kicad:EasyEDA→KiCad 工程(Board1/Board2)、库、脚本与评审文档(IC 引脚、风扇、热、EDL 供电、布局规则)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
这个提交包含在:
@@ -0,0 +1,61 @@
|
||||
"""Inject measurement-route faults in memory without saving the production PCB."""
|
||||
import argparse
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import pcbnew as pcb
|
||||
|
||||
from kelvin_checks import check_measurement_branches
|
||||
from schematic_maintenance import ROOT
|
||||
|
||||
|
||||
def run_case(case):
|
||||
path = ROOT / 'PhoneRail-Board1/PhoneRail-Board1.kicad_pcb'
|
||||
branches = json.loads((ROOT / 'pcb-routing-rules.json').read_text(encoding='utf-8'))['measurement_branches']
|
||||
board = pcb.LoadBoard(str(path))
|
||||
tracks = {t.m_Uuid.AsString(): t for t in board.GetTracks()}
|
||||
track = tracks[branches[0]['track_uuids'][0]]
|
||||
if case == 'missing_segment':
|
||||
board.Remove(track)
|
||||
elif case == 'load_branch_on_sense_trace':
|
||||
a, b = track.GetStart(), track.GetEnd()
|
||||
mid = pcb.VECTOR2I((a.x+b.x)//2, (a.y+b.y)//2)
|
||||
branch = pcb.PCB_TRACK(board)
|
||||
branch.SetStart(mid)
|
||||
branch.SetEnd(pcb.VECTOR2I(mid.x+pcb.FromMM(1), mid.y))
|
||||
branch.SetWidth(pcb.FromMM(.5))
|
||||
branch.SetLayer(track.GetLayer())
|
||||
branch.SetNet(track.GetNet())
|
||||
board.Add(branch)
|
||||
result = check_measurement_branches(board, branches)
|
||||
if case == 'baseline':
|
||||
assert not result['errors'] and len(result['branches']) == 10, result
|
||||
elif case == 'missing_segment':
|
||||
assert any(e['kind'] == 'kelvin_missing_items' for e in result['errors']), result
|
||||
else:
|
||||
assert any('branch_join_outside_shunt_land' in e.get('issues', []) for e in result['errors']), result
|
||||
return {'case': case, 'passed': True, 'detected_errors': result['errors']}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--case', choices=('baseline', 'missing_segment', 'load_branch_on_sense_trace'))
|
||||
args = parser.parse_args()
|
||||
folder = ROOT / 'out/local-routing-r3'
|
||||
if args.case:
|
||||
result = run_case(args.case)
|
||||
(folder / f'kelvin-probe-{args.case}.json').write_text(json.dumps(result, indent=2)+'\n', encoding='utf-8')
|
||||
return
|
||||
results = []
|
||||
# Isolate native KiCad object ownership for each destructive in-memory probe.
|
||||
for case in ('baseline', 'missing_segment', 'load_branch_on_sense_trace'):
|
||||
subprocess.run([sys.executable, __file__, '--case', case], check=True, timeout=60)
|
||||
results.append(json.loads((folder / f'kelvin-probe-{case}.json').read_text(encoding='utf-8')))
|
||||
out = folder / 'kelvin-probe.json'
|
||||
out.write_text(json.dumps({'passed': True, 'cases': results}, indent=2)+'\n', encoding='utf-8')
|
||||
print(json.dumps(results))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
在新工单中引用
屏蔽一个用户