The router began as a port of FreeRouting and has grown its own engine (negotiated congestion, tree nets, exact checks, axis escapes), and 'freeroute' was one letter from the project it no longer follows. The package, module and command are now rpmroute; the freeroute command stays as an alias, and the RPMROUTE / RPMROUTE_ORACLE_JAVA variables fall back to the old FREEROUTE names. Version 2026.10.07. Routing is unchanged: a PCBench board routes to a byte-identical session either way.
2.7 KiB
FreeRouting → Python porting plan
Seed document. The routing agent expands this after studying the upstream Java source. Treat sections marked (TBD from source study) as the first research deliverable.
Ground truth: study the source
Port from the actual FreeRouting Java source, not from the Specctra spec alone. The algorithm details (rip-up-and-retry ordering, cost functions, 45°/free-angle geometry, autoroute vs. optimize passes) live in the code.
# Cloned into ./reference (gitignored — we don't vendor GPL source into history)
git clone --depth 1 https://github.com/freerouting/freerouting reference/freerouting
Key upstream packages to map first (verify paths against the clone):
app/freerouting/designforms/specctra/— DSN/SES read/write. This is the I/O boundary we must match byte-compatibly enough forkicad-clito import.app/freerouting/autoroute/— the maze/rip-up router core.app/freerouting/board/— the routing board data model (items, traces, vias, nets, clearance matrix).app/freerouting/geometry/planar/— points, lines, tile shapes, the 45°/free-angle geometry primitives.
The contract (fixed)
Input: Specctra .dsn. Output: Specctra .ses. kicad-cli pcb export specctra-dsn produces the input; kicad-cli pcb import specctra-ses consumes
the output. Match that I/O and the rest of kicad-mcp is unchanged.
Phased roadmap
- DSN parser — tokenize + parse the S-expression DSN into a typed board
model (layers, components, padstacks, nets, keepouts, rules/clearances).
First concrete, fully-testable module. Round-trip fixtures from
kicad-cli. - SES writer — emit a minimal valid session file KiCad imports cleanly, starting with an empty/no-op route to prove the I/O loop end to end.
- Board model + geometry — planar primitives and the item/net/clearance model the router operates on. (TBD from source study.)
- Autorouter core — maze routing with rip-up-and-retry. Start grid-based Manhattan/45° for an MVP; converge toward FreeRouting's approach. (TBD.)
- Optimize pass — via minimization, trace smoothing. (TBD.)
- CLI + kicad-mcp integration —
rpmroute board.dsn -o board.ses, then swap it in behindkicad_mcp/utils/freerouting_engine.py's JAR step.
Validation strategy
For any .dsn, FreeRouting's JAR gives a reference .ses. Diff our output
against it (connectivity first — every ratsnest resolved — then geometry).
The JVM stays available as an oracle during development even though the
shipped product has no Java dependency.
Conventions
uv for everything, src-layout, ruff, pytest. Author: Ryan Malloy. Keep
modules small and single-purpose. Tests alongside every parser/writer from
the first commit.