app
KiCad - the KiCad Bridge
Public Made by Adomby adom
Reference implementation of the KiCad bridge: multi-instance Python server, forward path via kicad-cli, reverse path via in-process plugin. Most complex of the three bundled bridges.
master
John Lauer
0.9.340: routing tests, demo runner + evidence (arav-rog 2026-09-07), vendoring and overlay tools, release notes
25dcdaf
1mo ago
"""Create a small, entirely unrouted two-layer routing regression board."""
from pathlib import Path
import json
import uuid
def make(directory):
directory = Path(directory)
directory.mkdir(parents=True, exist_ok=True)
base = Path(__file__).resolve().parents[2] / 'templates/blank-board.kicad_pcb'
text = base.read_text()
blocks=[]
def footprint(ref,x,y,pads):
body=f'(footprint "RoutingFixture:{ref}" (layer "F.Cu") (uuid "{uuid.uuid4()}") (at {x} {y})\n'
body+=f'(property "Reference" "{ref}" (at 0 -3) (layer "F.SilkS") (effects (font (size 1 1) (thickness 0.15))))\n'
body+=f'(property "Value" "ROUTING_TEST" (at 0 -5) (layer "F.Fab") (effects (font (size 1 1) (thickness 0.15))))\n'
body+='(attr through_hole exclude_from_pos_files exclude_from_bom)\n'
for number, px, py, net in pads:
body+=f'(pad "{number}" thru_hole circle (at {px} {py}) (size 2 2) (drill 1) (layers "*.Cu" "*.Mask") (net "{net}") (uuid "{uuid.uuid4()}"))\n'
blocks.append(body+')\n')
footprint('J1',105,85,[(str(i),0,(i-1)*5,f'NET_{i}') for i in range(1,7)])
footprint('J2',145,85,[(str(i),0,(i-1)*5,f'NET_{i}') for i in range(1,7)])
footprint('J3',125,116,[('1',0,0,'NET_6')])
blocks.append(f'(gr_rect (start 98 78) (end 152 122) (stroke (width 0.05) (type default)) (fill none) (layer "Edge.Cuts") (uuid "{uuid.uuid4()}"))\n')
output=directory/'live-routing.kicad_pcb'
output.write_text(text[:text.rfind(')')]+''.join(blocks)+')\n')
plan=[]
for i in range(1,7):
y=85+(i-1)*5
points=[f'J1.{i}',[112,y],[138,y],f'J2.{i}']
if i==3:
points=[f'J1.{i}',{'x':112,'y':y,'layer':'B.Cu'},{'x':138,'y':y,'layer':'F.Cu'},f'J2.{i}']
row={'net':f'NET_{i}','width':0.25,'points':points}
if i==6:
row.pop('points'); row['paths']=[points,[[125,y], [125,113], 'J3.1']]
plan.append(row)
(directory/'plan.json').write_text(json.dumps(plan,indent=2)+'\n')
return output
if __name__=='__main__':
import sys
print(make(sys.argv[1] if len(sys.argv)>1 else Path(__file__).parent/'fixture'))