Rename to rpmroute
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.
This commit is contained in:
@@ -1,14 +1,23 @@
|
||||
# freeroute
|
||||
# rpmroute
|
||||
|
||||
A native Python PCB autorouter: a Java-free reimplementation of the
|
||||
[FreeRouting](https://github.com/freerouting/freerouting) engine. Specctra DSN
|
||||
in, Specctra SES out, no JVM anywhere in the pipeline.
|
||||
A native Python PCB autorouter. Specctra DSN in, Specctra SES out, no JVM
|
||||
anywhere in the pipeline.
|
||||
|
||||
It began as a Java-free port of the
|
||||
[FreeRouting](https://github.com/freerouting/freerouting) engine and has grown
|
||||
its own router since: negotiated congestion before routing, multi-pin nets
|
||||
routed as trees, every route checked against exact pad and copper shapes, and
|
||||
pin escapes along the pad's own axis for parts placed at an angle. On dense
|
||||
boards it now finishes more connections than the FreeRouting JAR, with no
|
||||
rule violations.
|
||||
|
||||
It was called `freeroute` until 2026-10-07; that command still works.
|
||||
|
||||
## Why
|
||||
|
||||
Toolchains that autoroute (`kicad-mcp` among them) do it by shelling out to
|
||||
`freerouting.jar`, which drags a JVM into every install and container image.
|
||||
`freeroute` reimplements the routing engine in pure Python, with no dependencies
|
||||
`rpmroute` reimplements the routing engine in pure Python, with no dependencies
|
||||
beyond the standard library, so the JAR step becomes a `pip install`.
|
||||
|
||||
## The contract
|
||||
@@ -16,31 +25,31 @@ beyond the standard library, so the JAR step becomes a `pip install`.
|
||||
The entire integration surface is two Specctra files:
|
||||
|
||||
```
|
||||
board.dsn ──▶ freeroute ──▶ board.ses
|
||||
board.dsn ──▶ rpmroute ──▶ board.ses
|
||||
(unrouted) (routed session: traces + vias)
|
||||
```
|
||||
|
||||
`kicad-cli` already exports `.dsn` and imports `.ses`, so `freeroute` drops in
|
||||
`kicad-cli` already exports `.dsn` and imports `.ses`, so `rpmroute` drops in
|
||||
wherever `java -jar freerouting.jar` was invoked, and nothing else in the pipeline
|
||||
changes. The `-de` / `-do` / `-mp` flags are the JAR's, on purpose.
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
uv tool install freeroute # or: pipx install freeroute
|
||||
uv tool install rpmroute # or: pipx install rpmroute
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# a KiCad board: the exact engine, with the board's copper-to-edge rule
|
||||
freeroute board.dsn --engine exact --shove --edge-clearance 0.5 -do board.ses
|
||||
rpmroute board.dsn --engine exact --shove --edge-clearance 0.5 -do board.ses
|
||||
|
||||
freeroute -de board.dsn -do board.ses # the FreeRouting JAR spelling (grid engine)
|
||||
freeroute board.dsn --engine room --pack --shove -do board.ses
|
||||
rpmroute -de board.dsn -do board.ses # the FreeRouting JAR spelling (grid engine)
|
||||
rpmroute board.dsn --engine room --pack --shove -do board.ses
|
||||
```
|
||||
|
||||
With no `-do` / `-o`, the SES goes to stdout. Connections freeroute could not
|
||||
With no `-do` / `-o`, the SES goes to stdout. Connections rpmroute could not
|
||||
make are listed on stderr; the SES is still written and the exit code stays 0,
|
||||
as with the JAR. Connections whose two ends sit in one zone of their net are
|
||||
listed separately, as left to that zone's fill.
|
||||
@@ -99,7 +108,7 @@ What the opt-in passes buy you:
|
||||
- **`--diagonal`** (exact): a still-dropped 2-pin net is retried as a 45° trace
|
||||
covered by an exact integer octagon.
|
||||
|
||||
## What freeroute reads from a KiCad DSN
|
||||
## What rpmroute reads from a KiCad DSN
|
||||
|
||||
These were each checked against KiCad itself, pad by pad or with its DRC:
|
||||
|
||||
@@ -125,7 +134,7 @@ SES coordinates are written in resolution units, exactly as the JAR writes them.
|
||||
## Library use
|
||||
|
||||
```python
|
||||
from freeroute.route import route
|
||||
from rpmroute.route import route
|
||||
|
||||
ses_text = route(dsn_text, engine="exact", shove=True, edge_clearance_mm=0.5)
|
||||
```
|
||||
@@ -136,13 +145,13 @@ Alpha. Measured on two real KiCad 10 boards (the TerraHawk charge node's power
|
||||
stage and sense board, 2026-09-27), with every track stripped, then routed, then
|
||||
checked with `kicad-cli pcb drc --refill-zones`:
|
||||
|
||||
| board | freeroute exact | FreeRouting JAR | DRC errors from freeroute |
|
||||
| board | rpmroute exact | FreeRouting JAR | DRC errors from rpmroute |
|
||||
|---|---|---|---|
|
||||
| power stage (40 x 30 mm) | 7 unconnected, ~5 s | 12 | 0 |
|
||||
| sense board (55 x 25 mm, 0.5 mm pitch MCU) | 41 unconnected, ~2.5 min | 32 | 0 |
|
||||
|
||||
In the board owner's production flow (hand-routed power lanes kept, pours added
|
||||
after routing), freeroute completed the power stage with no unconnected items.
|
||||
after routing), rpmroute completed the power stage with no unconnected items.
|
||||
|
||||
What it is **not**, stated plainly:
|
||||
|
||||
@@ -164,7 +173,7 @@ What it is **not**, stated plainly:
|
||||
|
||||
For maximum completion on a dense board today, the JAR is still the stronger
|
||||
router. For routing without a JVM (CI, containers, an MCP server, a library
|
||||
call), freeroute routes legally and says what it could not do.
|
||||
call), rpmroute routes legally and says what it could not do.
|
||||
|
||||
## Development
|
||||
|
||||
|
||||
Reference in New Issue
Block a user