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.1

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.1
File Size Uploaded
gantrix-0.1.1.tar.gz 26.1 kB Details

Built distribution (wheel)

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

Total release size: 49.0 kB

Release files / gantrix-0.1.1.tar.gz

Download URL gantrix-0.1.1.tar.gz
Size 26.1 kB
Tags Source
SHA-256 checksum
How to use checksums
9c17b809acba5060fa0779c9815b9f7a422c31712b834b67825d7ce690dd671f
BLAKE2b-256 checksum
How to use checksums
6b8eb60d0b87e1947d4a1ac262f1670628b78715076a49a52f7a204fdf65744b
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.1-py3-none-any.whl

Download URL gantrix-0.1.1-py3-none-any.whl
Size 22.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5b42c46fd0507af6ef2e09d1ebdbcc4aeca3285dbe4229be4e7f9266b1c2f379
BLAKE2b-256 checksum
How to use checksums
c15952a11ec9dc9e5754de47c56801b7019e329dd71b4a98cb6f3149114dbdf9
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

This release

0.1.1 This release

2 release files

0.1.0

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