Development Guide
Welcome to the development guide for Vpype-Gscrib. This guide will walk you through the process of setting up your development environment and extend the project with new features.
Introduction
Vpype-Gscrib is a plugin for vpype, an extensible command-line tool designed for generating, optimizing, and processing vector graphics for plotters. Vpype simplifies working with SVG paths, provides powerful transformation capabilities, manages multi-layer compositions, and optimizes toolpaths for efficient execution.
This plugin enables the generation of G-code programs directly from vpype documents, making it possible to control CNC machines, pen plotters, and other G-code-compatible devices. To achieve this, it leverages Gscrib, a Python library that provides a set of tools for G-code generation.
By combining the flexibility of Vpype with the G-code generation capabilities of Gscrib, Vpype-Gscrib serves as a versatile tool for translating vector-based designs into precise machine instructions. Whether you’re an artist, maker, or engineer, this tool empowers you to bring intricate designs to life with precision and efficiency.
Getting Started
Prerequisites
Before you start, make sure you have the following installed on your machine:
Python (3.10 or newer)
Pip (Python package manager)
Git (Version control tool)
If you need help installing any of these, check out their official installation guides:
Setting Up the Development Environment
Follow these steps to set up your development environment:
Clone the repository:
git clone https://github.com/joansalasoler/vpype-gscrib.git
cd vpype-gscrib
Create and activate a virtual environment:
python3 -m venv venv
source venv/bin/activate # On Windows, use: venv\Scripts\activate
Install dependencies:
pip install --upgrade pip # Upgrade pip
pip install -e . # Install in development mode
pip install -r requirements.txt # Install additional dependencies
pip install -r requirements.dev.txt # Install development dependencies
Check the plugin is working:
vpype gscrib --help
Project Structure
Here’s a brief overview of the vpype-gscrib project structure:
vpype-gscrib/
├── vpype_gscrib/ # Main package directory
│ ├── __init__.py # Package initialization
│ ├── vpype_gscrib.py # Command line interface (CLI)
│ ├── vpype_options.py # Command line options
│ ├── renderer # Generates G-code from documents
│ └── ... # Other module files
├── tests/ # Tests directory
└── docs/ # Documentation builder
Documentation and Testing
To build the documentation locally run the following commands. This will
generate the documentation in the ./docs/html directory. Open index.html
in a web browser to view it.
cd docs
pip install -r requirements.txt
python -m sphinx . ./html
To run the test suite, use pytest. This will automatically discover
and run all the tests in the project. You can also run specific tests
by referring to the pytest documentation.
python -m pytest
Extending the Plugin
Adding Configuration Parameters
Configuration parameters allow users to customize the behavior of
various components within the system. These parameters can be set via
command-line options or TOML configuration files, and are tipically
accessed through the rendering context (GContext).
The following steps outline how to add a new parameter.
Define the Option:
Open
vpype_gscrib/vpype_options.py.Add an option with a name, type, and short help message.
Use the correct type (e.g., LengthType for lengths).
ConfigOption(
option_name='length-units',
help="Choose the unit of measurement for the output G-Code.",
type=LengthUnits,
)
Store the Option:
Open
vpype_gscrib/config/renderer_config.py.Add a property to
RendererConfigwith the same name as the option.Use pydantic for validation (ensure correct type and range of values).
@dataclass
class RenderConfig(BaseModel, BaseConfig):
length_units: LengthUnits = Field(LengthUnits.MILLIMETERS)
Adding New Renderer Components
This is the fun part! GRenderer delegates specific machine operations
to specialized components in order to generate a G-code program. This
modular approach allows different strategies to be swapped without
modifying the renderer’s core logic. Each type of component has multiple
implementations, giving users flexibility in configuring their
machine’s behavior.
Currently, the system supports the following component types:
Tool — Handles tool operations (activation, deactivation).
Head — Controls machine movements (travel, plunge, retract).
Coolant — Manages the coolant system (flood, mist).
Fan — Manages the machine fans (on, off ).
Rack — Manages tool changes and rack operations.
Bed — Manages the machine bed or table.
The renderer coordinates these components to process the document hierarchy and create the G-code program. They are instantiated from their respective factory classes based on user choices. For example, combining the following components for a standard milling setup:
A spindle tool (
SpindleTool)Manual tool changes (
ManualRack)Flood coolant (
FloodCoolant)
Here’s how to add a new component.
Implement the Component:
Define a new component by extending the appropriate abstract base class
(BaseTool, BaseHead, BaseCoolant, BaseFan, BaseRack, BaseBed).
Each method receives a GContext, which holds the configuration for the
specific document layer or the entire document being rendered.
class CustomHead(BaseHead):
def safe_retract(self, ctx):
ctx.g.rapid(z=ctx.safe_z)
def retract(self, ctx):
ctx.g.rapid(z=ctx.safe_z)
def plunge(self, ctx):
ctx.g.move(z=ctx.plunge_z, F=ctx.travel_speed)
ctx.g.move(z=ctx.work_z, F=ctx.plunge_speed)
def travel_to(self, ctx, x, y):
ctx.g.move(x=x, y=y, F=ctx.travel_speed)
def trace_to(self, ctx, x, y):
ctx.g.move(x=x, y=y, F=ctx.work_speed)
def park_for_service(self, ctx):
ctx.g.rapid(z=ctx.park_z)
ctx.g.rapid_absolute(0, 0)
Define a New Type for the Component:
Each renderer component is associated with a type, which defines the available options for that component. These types are stored in an enum —a predefined list of valid options that users can choose from. To register your component, add a corresponding type to the enum.
class HeadType(BaseEnum):
STANDARD = 'standard'
CUSTOM = 'custom' # New type
Map the Type to the Implementation:
Now that the system recognizes your new type, you need to specify which class should be instantiated when that type is selected. This is done in the component’s factory, which maps each type to its implementation.
class HeadFactory:
@classmethod
def create(cls, head_type: HeadType) -> BaseHead:
providers = {
HeadType.STANDARD: StandardHead,
HeadType.CUSTOM: CustomHead, # Register new component
}
return providers[head_type]()
Test your component:
vpype read input.svg gscrib --head-type=custom --output=output.gcode
Generating G-code Inside Renderer Components
All renderer component methods receive a GCodeBuilder
instance through the ctx.g attribute. This object, provided by the
Gscrib library, is your main interface for generating G-code. Instead
of writing raw G-code strings, you’ll use high-level methods that handle
syntax, state management, and safety for you.
GCodeBuilder makes it easier to build G-code programs by abstracting
away low-level details. It helps you keep track of things like the machine’s
position, feed rate, tool state, and more. It also supports advanced
features such as path interpolation, and built-in safety checks.
For example, a retract and plunge sequence could be written like this:,
ctx.g.rapid(z=ctx.safe_z)
ctx.g.move(z=ctx.work_z, F=ctx.plunge_speed)
You can also use it to generate more complex toolpaths like arcs and splines, apply transformations like scaling or rotation, and insert comments or conditional logic using standard Python syntax.
Using Gscrib has several advantages:
Safety: It automatically validates commands to prevent unsafe operations.
Flexibility: Use Python control structures to build dynamic, reusable routines.
Efficiency: It simplifies repetitive tasks and reduces human error.
Readability: It produces clean, structured code that’s easier to maintain.
To dive deeper into everything Gscrib can do, check out the official Gscrib Documentation.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Fork the repository on GitHub.
Create your feature branch:
git checkout -b feature/your-new-feature
Make your changes and commit them:
git commit -m "Add a detailed description of your feature"
Push your changes to the branch:
git push origin feature/your-new-feature
Open a Pull Request on GitHub.
Please ensure your code follows a style consistent with the project’s own and includes tests for any new functionality.
Getting Help
If you need help or have questions, feel free to:
Check out the documentation.
Open an issue on GitHub.
Happy coding, and don’t forget to have fun! We hope you enjoy working with vpype-gscrib as much as we do. Feel free to contribute, experiment, and bring your creative ideas to life!