molecule
AFS_Adom flight computer molecule
Public Unreviewedby ae007
Active fin stabilization flight computer for a sounding rocket, a clean-room AI redesign of the Rice Eclipse AFS board: RP2350B, ICM-45686, KX134-1211, MMC5983MA, MS5611, TMP117, INA219A, 8 servos, 2S LiPo, USB-C; 4-layer Adom molecule, designed end to end by Claude through KiCad and adom-aiflow
main
ae007
Project page: AFS_Adom rev A (Rice Eclipse AFS clean-room AI redesign): highlight reel and narrated process video with…
cbe460e
7d ago
"""Replace the two pre-existing texts the stitching vias ended up under: remove them by UUID and create shorter
replacements where the solver finds room ('Z out' beside the IMU axis arrows; the project link on the back)."""
import json, sys
sys.path.insert(0, '/tmp/claude-1001/-home-adom-project/8819fb5f-c2c6-4524-9528-99428cd6b88e/scratchpad/gen')
import silk
board = json.load(open(silk.OUT + '/board.json')); bounds = json.load(open(silk.OUT + '/bounds.json')); outline = board['outline']
old = {'9aff6aaa': 'F', 'd1920ed1': 'B'}
new = [('F', 'Z out', [165.0, 118.0], 10.0), ('B', 'wiki.adom.inc/ae007/afs-adom', [146.0, 150.0], 60.0), ('B', 'rev A 2026-10-15', [146.0, 150.0], 60.0)]
remove = [t['uuid'] for t in board['texts'] if t['uuid'][:8] in old]
create = []; applied_extra = []
for face in ('F', 'B'):
obs = [o for o in silk.obstacles_for(board, face, bounds) if not any(o['id'] == f'text:{k}' for k in old)]
groups = []
for ff, text, anchor, maxd in new:
if ff != face: continue
key = '%s|0.8' % text
if key not in bounds:
r = silk.bridge('kicad_text_bounds', dict(filePath=silk.BOARD_WIN, texts=[dict(id='0', text=text, x=146.0, y=134.0, height=0.8, width=0.8, stroke=0.15, align='center')]))
b = (r.get('texts') or [{}])[0].get('box'); bounds[key] = dict(w=b[2] - b[0], h=b[3] - b[1], native=True)
lab = dict(id=text, kind='block', face=face, texts=[dict(role='existing', text=text, height=0.8)])
cands = silk.block_candidates(lab, bounds, outline, grid=1.0)
groups.append(dict(id=text, anchor=anchor, candidates=cands, maxDistance=maxd))
if not groups: continue
bnd = [outline[0] + silk.EDGE_MARGIN, outline[1] + silk.EDGE_MARGIN, outline[2] - silk.EDGE_MARGIN, outline[3] - silk.EDGE_MARGIN]
silk.prefilter(groups, obs, bnd)
res = silk.run_solver(face + 'fix', bnd, obs, groups)
for pl in res['placements']:
if pl.get('unresolved'): print('UNRESOLVED', pl['id']); continue
ch = pl['children'][0]
create.append(dict(text=pl['id'], layer=f'{face}.SilkS', x=round(ch['x'], 3), y=round(ch['y'], 3), rotation=0, height=0.8, width=0.8, stroke=0.15, align='center', mirrored=(face == 'B')))
applied_extra.append(dict(label='fix:' + pl['id'], role='existing', text=pl['id'], x=ch['x'], y=ch['y'], size=0.8, layer=f'{face}.SilkS', box=[ch['x'] - ch['w'] / 2, ch['y'] - ch['h'] / 2, ch['x'] + ch['w'] / 2, ch['y'] + ch['h'] / 2], via='text'))
print('create', pl['id'], '->', ch['x'], ch['y'])
json.dump(dict(filePath=silk.BOARD_WIN, remove=remove, create=create), open(silk.OUT + '/apply_text_update.json', 'w'), indent=0)
ap = json.load(open(silk.OUT + '/applied.json')); ap += applied_extra; json.dump(ap, open(silk.OUT + '/applied.json', 'w')); json.dump(bounds, open(silk.OUT + '/bounds.json', 'w'))
print('remove', len(remove), 'create', len(create))