Skip to main content

gantrix

A small framework for driving GRBL-based gantry devices with swappable tool heads — laser engraver today, whatever else you bolt to the carriage later (solenoid stamp, pen plotter, spray head, ...). Grew out of a one-off laser text-engraving script; generalized so the same motion/fill planning works for any tool, without being locked to the laser.

Layout

  • gantrix.transport — serial connection to GRBL, command/ack handshake, homes with the tool forced off first (a previous crashed run can leave a tool physically engaged even after the host process dies). A command that gets no reply at all (dead link, controller reset) raises GrblError rather than being silently swallowed; a mid-command controller reboot is detected from its boot banner instead of waiting out the full timeout. emergency_stop() sends GRBL's real-time soft-reset byte directly, bypassing the normal command queue, so it works even while another thread is blocked waiting on a stuck command.
  • gantrix.tools — the Tool plugin interface (engage/disengage + feed rates). LaserTool (M3/M5 with power) is the only concrete implementation shipped so far; new device types are added by subclassing Tool (see src/gantrix/tools/laser.py as the reference).
  • gantrix.design — turns a design into Shapes the planner can sweep. design.text is a small stroke font (rects + tapered diagonals). design.shapes.RasterShape is a generic bitmap-grid Shape, backing both design.qrcode (any QR-encodable data) and design.image (any image — logo, silhouette, photo — thresholded to black/white at a configurable resolution). True vector/SVG import (arbitrary curves, not just bitmaps) is the natural next addition here.
  • gantrix.planner.fill — generic boustrophedon (zigzag raster) fill: given anything exposing spans_at_y(y), sweeps scanlines and emits direction-alternating segments that minimize travel.
  • gantrix.job — wires a design + tool + transport into a runnable job. Accepts either a port string (opens/closes its own connection — CLI usage) or an already-connected transport (keeps it open — GUI usage).
  • gantrix.gui.app — preview a design as SVG, connect/disconnect a serial port, and run a job — all from the browser. gantrix.gui.connection holds the one live serial connection the process manages; gantrix.gui.job_runner runs a Job in a background thread (so the HTTP request returns immediately) and exposes progress + cancellation for the page to poll. Only one job at a time — it's a single physical device, not a queue. Two ways to stop: Cancel is cooperative (checked between fill segments — fine for "I want a different design," not fast enough to rely on if something's actually wrong); EMERGENCY STOP hits the hardware directly via emergency_stop() and works regardless of whether a command is stuck. Home manually re-homes ($H) when connected and no job is running.

Quickstart

pip install -e ".[dev,gui,design]"
pytest                                  # no hardware needed

# preview a design in the browser (no hardware needed)
uvicorn gantrix.gui.app:app --reload
# open http://127.0.0.1:8000

# run it for real
gantrix text HAND --port /dev/cu.usbserial-XXXXXX
gantrix qr "https://example.com" --port /dev/cu.usbserial-XXXXXX --cell-size 1.5
gantrix image logo.png --port /dev/cu.usbserial-XXXXXX --height 40 --cell-size 0.3

Adding a new device

Swapping tools without touching the design or planner is the point of the Tool split. To support a new actuator, subclass Tool and implement engage/disengage (see src/gantrix/tools/laser.py):

class MyTool(Tool):
    def engage(self, transport):
        transport.send("M62 P1")   # e.g. a GRBL digital output pin

    def disengage(self, transport):
        transport.send("M63 P1")

Then use it exactly like LaserTool — same layout_text/layout_qr output, same Job, just a different tool instance passed in.

Status

Early scaffold. Laser path is validated against a working engrave script. QR fill segments have been round-trip verified (reconstructing the module grid from planned segments reproduces the source matrix exactly) and rendered to confirm the code is well-formed. Only one concrete Tool (laser) ships so far — the interface is there for more, none built yet. Vector/SVG import and shape-drawing in the GUI (not just text/QR forms) are not built yet either. The GUI can connect/disconnect, run a job (text or QR), Cancel, Home, and hardware-level EMERGENCY STOP. A real incident during testing (the controller stopped responding mid-job) surfaced that failures weren't being surfaced at all — send() used to return False on a dead link and nothing checked it, so the job just kept retrying into the void with no visible error. Fixed: failures now raise and show up in the job's error field instead of hanging silently.

Release files for gantrix 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gantrix 0.1.0
File Size Uploaded
gantrix-0.1.0.tar.gz 24.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for gantrix 0.1.0
File Interpreter ABI Platform
gantrix-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 46.3 kB

Release files / gantrix-0.1.0.tar.gz

Download URL gantrix-0.1.0.tar.gz
Size 24.5 kB
Tags Source
SHA-256 checksum
How to use checksums
8d815fa2f470a7a98b4dc221c8b0cc9ee22f4c1d52110d922be9878812302a20
BLAKE2b-256 checksum
How to use checksums
0a2993adda2cdaac813460f8691bd82142a0f3cede88a465407a9cbd063a88cf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.0

Release files / gantrix-0.1.0-py3-none-any.whl

Download URL gantrix-0.1.0-py3-none-any.whl
Size 21.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0ad9d275f46506d8fc9c6c66e42162b80492bb82c42ea1f6a4e58be3147018a8
BLAKE2b-256 checksum
How to use checksums
dfda3ce605feeaa41c71b252da33b89db0b28654a9b632eb49371da1a66a0064
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.0

Release history Release notifications | RSS feed

0.1.1

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page