Gscrib is a powerful Python library for generating G-code for CNC machines, 3D printers, and other automated devices. It provides a comprehensive set of tools for creating, transforming, and optimizing toolpaths, empowering creators to write clean, efficient, and highly customizable G-code programs.
- Core G-code Generation: Linear and rapid moves, coordinate transformations, and more.
- Advanced Path Interpolation: Trace arcs, splines, helices, parametric curves, and more.
- Temperature & Tool Control: Manage spindle speed, laser power, fan speed, and more.
- State Management: Track machine state for safe and consistent operations.
- Transformation Utilities: Apply rotations, scaling, reflections, and more.
- Customizable Hooks: Add custom logic to modify parameters dynamically.
- Live Sensor Data: Read temperatures, positions, and more from connected devices.
- Multiple Output Options: Write G-code to files, serial ports, or network sockets.
- Error Handling: Built-in validation and error handling.
Documentation for the latest version of the project can be found at Read the Docs.
from gscrib import GCodeBuilder
g = GCodeBuilder(output="output.gcode"):
g.set_axis(x=0, y=0, z=0) # Set initial position
g.rapid(z=5) # Rapid move up to Z=5
g.rapid(x=10, y=10) # Rapid move to (10, 10)
g.tool_on("clockwise", 1000) # Start tool at 1000 RPM
g.coolant_on("flood") # Enable flood coolant
g.move(x=20, y=20, F=1500) # Linear move with feed rate
g.coolant_off() # Turn off coolant
g.tool_off() # Turn off tool
g.teardown() # Flush file changes
Generated G-code:
G92 X0 Y0 Z0 ; Set axis position
G0 Z5
G0 X10 Y10
S1000 M03 ; Start tool, clockwise
M08 ; Turn on coolant, flood
G1 X20 Y20 F1500
M09 ; Turn off coolant
M05 ; Stop tool
# Clockwise arc
g.set_direction("clockwise")
g.trace.arc(target=(10, 0), center=(5, 0))
# Counterclockwise arc
g.set_direction("counter")
g.trace.arc(target=(0, 0), center=(0, -10))
# Spline curve through a series of control points
control_points = [(0, 0), (5, 10), (10, -5), (15, 0)]
g.trace.spline(control_points)
# Helix
g.trace.helix(target=(10, 0, 10), center=(-10, 0), turns=3)
# Spiral
g.trace.spiral(target=(10, 0), turns=2)
# Thread
g.trace.thread(target=(10, 0, 5), pitch=1)
Use mathematical functions to generate parametric curves and complex shapes dynamically.
import numpy as np
# Custom parametric circle function
def circle(thetas):
x = 10 * np.cos(2 * np.pi * thetas)
y = 10 * np.sin(2 * np.pi * thetas)
z = np.zeros_like(thetas)
return np.column_stack((x, y, z))
# Estimate path length
length = g.trace.estimate_length(100, circle)
# Interpolate the path
g.set_resolution(0.1)
g.trace.parametric(circle, length)
Hooks allow you to dynamically modify movement parameters, such as adding extrusion for 3D printing.
import math
# Custom extrusion hook function
def extrude_hook(origin, target, params, state):
dt = target - origin
length = math.hypot(dt.x, dt.y, dt.z)
params.update(E=0.1 * length) # Add extrusion parameter
return params
g.add_hook(extrude_hook)
g.move(x=10, y=0) # Will add E=1.0
g.move(x=20, y=10) # Will add E=1.414
g.move(x=10, y=10) # Will add E=1.0
g.remove_hook(extrude_hook)
Matrix transformations allow you to manipulate toolpaths by applying translations, rotations, scaling, reflections, or mirroring.
# Save current transformation state
g.transform.save_state()
# Translate 10 units along X and Y
g.transform.translate(x=10, y=10)
# Change the pivot point for the next transformation
g.transform.set_pivot(point=(5, 5, 0))
# Rotate 45 degrees around Z-axis
g.transform.rotate(angle=45, axis="z")
# Trace an arc in the transformed coordinate system
g.trace.arc(target=(10, 0), center=(5, 0))
# Restore original state before transformations
g.transform.restore_state()
By default, transformations are pushed to and popped from a stack, but you can assign names to them to reuse your custom coordinate systems.
# Save a transformation state with a name
g.transform.save_state("my_transorm")
# Rotate and scale the coordinate system
g.transform.rotate(angle=90, axis="z")
g.transform.scale(2.0)
g.move(x=10, y=10)
# Restore the transformation state
g.transform.restore_state("my_transorm")
# Trace an arc in the restored coordinate system
g.trace.arc(target=(10, 0), center=(5, 0))
Easily track and manage the machine's state during operations, including tool activity, position, feed rates, and more. The state is updated automatically as actions are performed.
# Set the initial position and feed rate
g.set_axis(x=0, y=0, z=0)
g.set_distance_mode("relative")
g.set_feed_rate(1200)
# Activate the tool and move to a position
g.tool_on("cw", 1000)
g.move(x=10, y=10)
# Access and print the current state
print(f"Tool Active: { g.state.is_tool_active }") # True
print(f"Tool Power: { g.state.tool_power }") # S=1000
print(f"Feed Rate: { g.state.feed_rate }") # F=1200
print(f"Position: { g.state.position }") # X=10, Y=10, Z=0
# Move again with an updated feed rate
g.move(x=20, y=20, F=800)
# State automatically reflects the changes
print(f"Feed Rate: { g.state.feed_rate }") # F=800
print(f"Position: { g.state.position }") # X=30, Y=30, Z=0
# Attempt to change the spindle direction while the tool is active
g.tool_on("ccw", 2000) # This will raise a ToolStateError
Safe operating ranges for key machine parameters can be set using
set_bounds()
. This helps prevent invalid or potentially dangerous
values during runtime. Once bounds are set, any command that violates
them will raise an exception.
# Define safety bounds for different machine parameters
g.set_bounds("bed-temperature", min=0, max=200)
g.set_bounds("chamber-temperature", min=0, max=60)
g.set_bounds("hotend-temperature", min=0, max=200)
g.set_bounds("feed-rate", min=100, max=7000)
g.set_bounds("tool-number", min=1, max=5)
g.set_bounds("tool-power", min=0, max=100)
# You can also constrain motion in 3D space
g.set_bounds("axes", min=(0, 0, -10), max=(20, 20, 10))
# These will raise exceptions due to being out of bounds
g.set_feed_rate(10000) # Exceeds max feed rate
g.move(x=5, y=5, F=10) # Below min feed rate
g.move(x=-100) # Outside defined X-axis range
In direct write mode, machine data such as temperature, position, and other sensor values can be read from the device. This enables G-code to be adjusted based on the latest readings.
g.query("position") # Request position data
X = writer.get_parameter("X") # Get X position
Y = writer.get_parameter("Y") # Get Y position
Z = writer.get_parameter("Z") # Get Z position
E = writer.get_parameter("E") # Get extruder position
g.query("temperature") # Request temperature data
T = writer.get_parameter("T") # Get tool temperature
B = writer.get_parameter("B") # Get bed temperature
Context managers provide a convenient way to temporarily modify settings, apply transformations, or add hooks during operations, automatically restoring the previous state when the context ends.
# Switch to absolute positioning for a specific operation
with g.absolute_mode():
g.rapid(x=0, y=0)
# Switch to relative positioning for a specific operation
with g.relative_mode():
g.move(x=10)
g.move(y=10)
# Apply a transformation within a specific context
with g.current_transform():
g.transform.rotate(angle=45, axis="z")
g.trace.arc(target=(10, 0), center=(5, 0))
# Restore and apply a named transformation
with g.named_transform("my_transorm"):
g.transform.rotate(angle=45, axis="z")
g.trace.arc(target=(10, 0), center=(5, 0))
# Add a custom hook for the duration of the operation
with g.move_hook(temporary_hook):
g.move(x=10, y=10)
Vpype-Gscrib: A vpype plugin that extends vpype’s capabilities with a powerful command-line interface for converting SVG files into G-code. It provides a flexible and efficient toolkit for plotter and CNC workflows. See Vpype-Gscrib's Documentation
Here is how to clone the project for development:
$ git clone https://github.com/joansalasoler/gscrib.git
$ cd gscrib
Create a virtual environment:
$ python3 -m venv venv
$ source venv/bin/activate
Install gscrib
and its dependencies:
$ pip install --upgrade pip
$ pip install -e .
$ pip install -r requirements.txt
$ pip install -r requirements.dev.txt
Run tests:
pytest
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
Gscrib is an independent project that was initially forked from Mecode, a lightweight Python library for G-code generation originally developed at the Lewis Lab at Harvard University. The development of Gscrib was heavily influenced by Mecode’s design, and we are grateful for the foundational work done by its original author and contributors. Additionally, Gscrib includes code developed by the authors of Printrun, a Python-based suite for controlling 3D printers.
As Gscrib continues to evolve with new features, optimizations, and expanded capabilities, we recognize and appreciate the importance of this early work in shaping its foundation.
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the LICENSE file for more details.