app
Codex
Public Made by Adomby adom
Codex in Adom Hydrogen: ecosystem setup, dock dashboard and live engineering demos.
main
John Lauer
Astra ESC routing: independent planner, exact replay and narration handoff
2cc6a9e
23d ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
import planner as m
from planner import *
m.copper.clear()
plans=json.load(open('plan.json'))
for p in plans:
for path in p['paths']:register(p['net'],path,p['width'])
def search2(a,start,target,goalgeo,width=.25,plane=False):
goal=np.zeros((2,H,W),dtype=np.uint8)
if plane:goal[0]=1-a[2]
else:
for z,g in goalgeo:raster(goal[z],g.buffer(width/2-.04))
goal[a[:2]>0]=0
starts=np.zeros((H,W),dtype=np.uint8);raster(starts,start['g'].buffer(width/2-.04));starts[a[0]>0]=0
ids=np.flatnonzero(starts)
if not len(ids) or not np.any(goal):return None
a.tofile('mask.bin');goal.tofile('goal.bin');tx,ty=ij(*target)
r=subprocess.run(['./search2'],input=f'{W} {H} 0 {tx} {ty} {len(ids)} '+ ' '.join(map(str,ids)),capture_output=True,text=True)
raw=json.loads(r.stdout)
if not raw:return None
ps=compress(raw);out=[];curz=0
for i,j,z in ps:
x,y=xy(i,j)
if z!=curz:out.append(dict(x=x,y=y,layer='B.Cu' if z else 'F.Cu'))
elif [x,y]!=(out[-1] if out else None):out.append([x,y])
curz=z
return out
# Associate the connected pad groups using already planned native geometry.
def groups(net):
ps=by[net];nodes=[(p['g'],[0,1] if p['type']=='thru_hole' else [0]) for p in ps]+[(c['g'],c['zs']) for c in m.copper if c['net']==net]
parent=list(range(len(nodes)))
def find(i):
while parent[i]!=i:parent[i]=parent[parent[i]];i=parent[i]
return i
for i,(g,z) in enumerate(nodes):
for j,(h,zz) in enumerate(nodes[:i]):
if set(z)&set(zz) and g.distance(h)<.005:parent[find(i)]=find(j)
out=defaultdict(list)
for i,p in enumerate(ps):out[find(i)].append(p)
return list(out.values())
for net,layer in [('GND','In1.Cu'),('+3V3','In2.Cu')]:
plan=next(p for p in plans if p['net']==net)
for p in by[net]:
if p['type']=='thru_hole':continue
if any(c['net']==net and c['g'].intersects(p['g']) for c in m.copper):continue
route=search2(masks(net,.25),p,(p['x'],p['y']),[],plane=True)
if route:
e=route[-1];route.append(dict(x=e[0],y=e[1],layer=layer));register(net,route,.25);plan['paths'].append(route);print('plane repair',net,p['name'],flush=True)
for plan in plans:
net=plan['net'];width=plan['width']
if net in ['GND','+3V3']:continue
gr=groups(net);tries=set()
while len(gr)>1:
pairs=sorted((math.hypot(p['x']-q['x'],p['y']-q['y']),i,j,p,q) for i,pp in enumerate(gr) for j,qq in enumerate(gr[:i]) for p in pp for q in qq)
changed=False
for dist,i,j,p,q in pairs:
key=(p['name'],q['name'])
if key in tries:continue
tries.add(key);goals=[]
for t in gr[j]:goals.append((0,t['g']))
a=masks(net,width);route=search2(a,p,(q['x'],q['y']),goals,width)
if route:
register(net,route,width);plan['paths'].append(route);changed=True;print('repair',net,p['name'],q['name'],flush=True);break
if not changed:print('remaining',net,[[p['name'] for p in g] for g in gr],flush=True);break
gr=groups(net)
Path('plan-repaired.json').write_text(json.dumps(plans,indent=2))