15 KiB
name, description
| name | description |
|---|---|
| altium-kicad | 把 Altium Designer 的 PCB 设计工程整体搬到 KiCad,并验证搬完的板与原设计电气 等价、制造等价。驱动 E:\LangGraph_Design\Altium-Kicad 里的 LangGraph 工作流 (11 节点 / 4 个判定回环),进程内 + SQLite 持久化,不用 langgraph dev。图在每 个需要 MCP、CLI 或人在 GUI 里点的地方 interrupt 回到 Claude 会话,由本 skill 执行真实动作再回填结论推进。附带把两次真实迁移里反复重写的脚本通用化:ASCII 转换脚本生成、BGA 平面焊盘网络回填、覆铜 zone clearance 批改、逐页网表 partition 比对、走线/过孔矢量等价比对。 只要用户提到 Altium 转 KiCad、AD 转 KiCad、把 PrjPCB 导入 KiCad、迁移/搬移 PCB 工程、altium-kicad 工作流、"Header already parsed"、原理图转 ASCII、 导入后 DRC 一堆短路、BGA 焊盘丢网络、铺铜避让变大、网表比对、Gerber 比对、 或者说 "启动 altium-kicad"、"跑迁移流程"、"继续上次那个迁移"、"convert my Altium project to KiCad"、"import PrjPCB into KiCad"、"migrate PCB from Altium",就必须用这个 skill —— 哪怕他们没说 skill、没提 LangGraph,只说了 "把这块板转成 KiCad"、"这板子迁移到一半,接着弄"。 |
Altium → KiCad 工程迁移
这个 skill 是什么
一次完整迁移 = 5 个阶段:桥接 → 转 ASCII 并导入 → 修 PCB → 网表对齐 → 几何对齐 → 验收。 这些步骤有严格的先后依赖、有失败要退回重做的回环、单次会话跑不完(用户要去 Altium 和 KiCad 里手动点很多次)。所以状态由 LangGraph 图持久化在 SQLite 里, 你负责把图停下来的每一步翻译成真实动作,做完回填结论让它往下走。
MCP 边界(必须理解,否则会白折腾):eda-agent(altium MCP)和 KiCAD-MCP-Server
跑在你这个 Claude 会话进程里,不在 LangGraph 的 Python 进程里。所以图不可能
自己去 ping Altium、自己去数文件、自己去改板 —— 它只做编排,凡是要碰真实世界的
地方一律 interrupt() 交回给你。这是设计,不是缺陷。
环境
| 项 | 值 |
|---|---|
| 图工程根 | E:\LangGraph_Design\Altium-Kicad(可用 --project-root 或 AK_PROJECT_ROOT 改) |
| Python | conda env langgraph(~\skills_env.md 的 CONDA_LANGGRAPH_PYTHON) |
| KiCad python | ~\skills_env.md 的 KICAD_PYTHON,本机 D:\KiCad\10.0\bin\python.exe |
| checkpoint | <图工程根>\runs\skill_checkpoint.sqlite,按 thread 隔离 |
| thread 命名 | 由 target_dir 目录名推导,如 E:\Kicad_design\XMOD_V1p0 → ak-xmod-v1p0 |
| 驱动脚本 | %USERPROFILE%\.claude\skills\altium-kicad\scripts\ak_flow.py |
需要的 MCP:eda-agent(Altium 侧取数)、kicad(可选,KiCad 侧大多走
kicad-cli 和 pcbnew 更稳)。
驱动命令
统一用 conda run -n langgraph python 跑 ak_flow.py。退出码 2 = 停在
interrupt 等你回填(不是错误),0 = 图跑完,1 = 出错。
$AK = "$env:USERPROFILE\.claude\skills\altium-kicad\scripts\ak_flow.py"
# 新建 / 续跑(同一个 target-dir 重复跑就是续跑,不会重置)
conda run -n langgraph python $AK start `
--source-prj "E:\Altium_design\FOO\FOO.PrjPCB" `
--target-dir "E:\Kicad_design\FOO"
# 看现在停在哪
conda run -n langgraph python $AK status --target-dir "E:\Kicad_design\FOO"
# 回填结论、推进(--set 免转义,true/false 转 bool,纯数字转 int)
conda run -n langgraph python $AK resume --target-dir "E:\Kicad_design\FOO" `
--set bridge_ok=true
# 列出所有迁移线程 / 清掉某个线程重来
conda run -n langgraph python $AK list
conda run -n langgraph python $AK reset --target-dir "E:\Kicad_design\FOO"
--set 的值含空格要整体加引号:--set "report_path=E:\My Board\report.md"。
start 还可以调回环的重试上限(默认 桥接/导入 3 次、网表/几何 5 次,超限走 safety_end):
--max-bridge-retry N --max-import-retry N --max-netlist-retry N --max-gerber-retry N。
[INTERRUPT] 后面的 JSON 里 action 字段告诉你该做哪一步,下面逐个说。
回填不能是空的。langgraph 把 falsy 的 resume 当作「没提供」,会在同一个 节点再中断一次,看起来像卡住。至少给一个键。
逐步执行
开始之前先问清楚两件事(没有默认值,猜错了会把工程写到别处):
源 .PrjPCB 的绝对路径、目标 KiCad 目录的绝对路径。
prompt_altium_mcp — 让用户开启 Altium 桥接
告诉用户在 Altium 里:DXP/Preferences → Scripting System → Global Projects → Install 选 Altium_API.PrjScr,然后 File → Run Script → Dispatcher.pas → StartMCPServer → Run,状态窗显示 MCP: idle 即通。
提醒两条脾气:桥接约 10 分钟空闲自停,一次只能跑一个脚本。
用户确认后:--set acknowledged=true
check_altium_bridge — 验证桥接
调 eda-agent 的 app_ping。通了 --set bridge_ok=true,不通就 false
(图会回到上一步让用户重开,最多 3 次)。
convert_ascii — 转 ASCII(顺带做基线快照)
先做基线快照,趁桥接还活着。 后面 check_file_count 要页数、rebuild_rules
要设计规则、网表比对要真值网表,这些全都只能从 Altium 侧取;而转 ASCII 的第一步
就是停掉 eda-agent,停了再想取就得重开桥接。所以顺序是:
- 用 eda-agent 落盘基线到
<target_dir>\_migration\altium_baseline\:proj_get_statsproj_get_netsproj_get_bompcb_get_board_statisticspcb_get_layer_stackuppcb_get_design_rules(存成pcb_design_rules.json, 后面查 InPolygon clearance 要用) proj_export_netlist(tabular)导到_migration\reference\netlist_tabular.csv—— 这是后面回填焊盘网络和比网表的唯一真值,别漏- 记下原理图页数和 PCB 数(
check_file_count要用)
然后转 ASCII:
python "$env:USERPROFILE\.claude\skills\altium-kicad\scripts\stage_ascii.py" stage `
--source-prj "E:\Altium_design\FOO\FOO.PrjPCB" `
--migration-dir "E:\Kicad_design\FOO\_migration"
它把整个工程复制到 <工程目录>_ascii staging(原始工程一个字节都不动),
枚举出实际的 .SchDoc 并生成 convert_to_ascii.pas。
接着让用户:先停掉 eda-agent(不停会和 StartMCPServer 脚本冲突挂起),再在
Altium 里 File → Run Script → 选生成的 .pas → ConvertSchToAscii → Run。
跑完验证:
python ...\stage_ascii.py verify --staging-dir "E:\Altium_design\FOO_ascii"
verify 通过了再回填:--set ascii_ok=true --set ascii_staging_dir=E:\Altium_design\FOO_ascii
⚠️
convert_ascii后面没有判定回环,回填ascii_ok=false图照样往下走。 没转干净就进 KiCad 导入必然报Header already parsed,白跑一轮。
prompt_kicad_import — 用户在 KiCad 里手动导入
这一步没有任何 CLI/MCP 通道,只能人点。给用户精确路径:
打开 KiCad 主程序(工程管理器) → File → Import Non-KiCad Project → Altium Project...
- 源:staging 里的
_ascii版.PrjPCB(选错成原始工程就前功尽弃) - 目标:target_dir
- 点 OK 等待,十几页 + 多层 PCB 要几十秒到几分钟
导完常见现象:报告里只有 IEEE_SYMBOL 未处理记录(无害);结构是扁平的,
可能多出重复的 .kicad_sch(确认无引用后删掉)。
用户确认导完:--set imported=true
check_file_count — 文件数核对
Altium 侧基线(原理图页数 + 1 块 PCB)对比 target_dir 下
*.kicad_sch + *.kicad_pcb 的计数。payload 里的 kicad_glob_hint 是图那侧
glob 出来的预填值(-1 表示它数不到),你要自己核实。
--set altium_count=16 --set kicad_count=16
不一致会退回重导(最多 3 次)。不一致时先看是不是多了重复页,或者某页导入失败。
rebuild_rules — 设计规则重建 + PCB 修复
三件事,顺序不能反:
1) 改 .kicad_pro 的规则:按基线 pcb_design_rules.json 设间隙/线宽/过孔/
孔/网络类。导入只搬几何,规则用的是 KiCad 默认(比 Altium 严),不改的话 DRC
会有几千条误报。
2) 回填焊盘网络 + 批改 zone clearance(先干跑看量):
$KP = "D:\KiCad\10.0\bin\python.exe" # ~\skills_env.md 的 KICAD_PYTHON
& $KP "...\scripts\fix_pcb.py" --board "E:\Kicad_design\FOO\FOO.kicad_pcb" `
--netlist-csv "E:\Kicad_design\FOO\_migration\reference\netlist_tabular.csv" `
--zone-clearance-mm 0.254 --dry-run
--zone-clearance-mm 要去基线 pcb_design_rules.json 查 InPolygon 规则的
polygon clearance,别照抄 0.254。确认后去掉 --dry-run 真改(会自动备份板文件)。
3) 重填铺铜:让用户在 KiCad GUI 里按 B,或走 IPC 后端。
大板不要用 SWIG/pcbnew refill,会超时甚至段错误。
跑一次 DRC 确认数字降下来了(run_drc 或 kicad-cli pcb drc),
然后 --set rules_ok=true。
这两个坑的根因写在
references/playbook.md§4,值得先读: BGA 平面焊盘丢网络(假短路的真凶,Altium 靠负片内电层隐式连接)、 zone 本地 clearance 被写成 0.5mm 且会盖过网络类(只改网络类完全无效)。rebuild_rules后面同样没有回环,别在没修好的时候回填 true。
compare_netlist — 网表对齐(可回环 5 次)
conda run -n langgraph python "...\scripts\netcmp.py" `
--kicad-dir "E:\Kicad_design\FOO" `
--netlist-csv "E:\Kicad_design\FOO\_migration\reference\netlist_tabular.csv" `
--out "E:\Kicad_design\FOO\_migration\netcmp"
脚本会逐页导出 kicadxml(扁平结构下整体导出会漏页)、剥掉 KiCad 网名的前导
/、去掉 Altium 的 net=? 重复行,然后按 net partition 比等价类 —— 不比
网络名,两个工具命名规则不同,逐名比必然一片红。
一致(退出码 0)→ --set netlist_identical=true。
不一致 → 看 diff.json 改 KiCad 对齐,--set netlist_identical=false 会回到这一步
再来一轮。改不动的时候,节点级差异往往不是真错,先按 playbook §5 的三条归一化
自查。超过 5 轮会走 safety_end。
payload 里写的是「调
/goal让 Claude Code 或 Codex 自主迭代」。愿意的话可以 那样做;直接用netcmp.py+ 自己改板通常更快也更可控。
compare_gerber — 几何等价(可回环 5 次)
判定基准先说死:逐层制造几何等价。离散铜(走线/过孔/焊盘/孔/板框)要零差异; 铺铜纹理、丝印字形、负片内电层是工具固有容差项,不是缺陷、修不掉。
决定性证据走矢量比对,不是栅格 XOR:
& $KP "...\scripts\dump_kicad_vec.py" --board "...\FOO.kicad_pcb" `
--out "...\_migration\gerber\kicad_vec"
# Altium 侧用 eda-agent 导同名 JSON 到 altium_vec\(格式见 references\vector-compare.md)
python "...\scripts\cmp_vec.py" --altium-vec ...\altium_vec --kicad-vec ...\kicad_vec `
--layer-map ...\layer_map.json --report ...\vec_result.json
TOTAL unmatched primitives: 0 → --set gerber_aligned=true。
要出 Gerber 图片证据的话:KiCad 侧 kicad-cli pcb export gerbers/drill;
Altium 侧 eda-agent 生不了 Gerber(工程没有 OutJob,proj_run_output 是空操作),
必须让用户在 File → Fabrication Outputs → Gerber Files 手动导,参数见
playbook §7。
acceptance_report — 验收报告
写 <migration_dir>\verification_report.md,必须包含:
- 各阶段 PASS/FAIL 与关键数字(页数、元件数、节点数、走线/过孔匹配数)
- 明确列出三项工具固有差异(负片内电层 / 铺铜填充纹理 / 丝印字体) 及其根因,注明是容差项不是缺陷 —— 不写清楚,后面看报告的人会当成没做完
- 证据文件索引
--set report_path=E:\Kicad_design\FOO\_migration\verification_report.md
回填后图结束,ak_flow.py 打印 [DONE]。
铁律速查
- 原理图必须先转 ASCII。AD26 二进制
.SchDoc会让 KiCad 报Header already parsed。PCB 侧没这问题,只有原理图。 - 转 ASCII 之前先停 eda-agent。Altium 一次只能跑一个脚本,桥接自己就是个脚本。
- 基线快照要趁桥接活着做完,尤其 tabular 网表 —— 后面回填网络和比网表都靠它。
- KiCad 导入只能人工点,源必须选
_ascii版。 kicad-cli pcb import不能替换主板,那会切断原理图↔PCB 关联,只能当参考。- zone 的本地 clearance 会盖过网络类,只改
.kicad_pro无效。 - 网表比 partition 不比网络名,且必须逐页导 kicadxml。
- 跨工具像素级一致不可能,判定基准是离散几何等价 + 三项固有容差。
- 原始 Altium 工程只读,所有写操作只作用于 staging 副本和 target_dir。
排错
| 症状 | 处理 |
|---|---|
| resume 后又停在同一个节点 | 回填是空的或全 falsy。langgraph 把它当没提供。加一个非空键。 |
app_ping 突然不通 |
桥接空闲 10 分钟自停了。让用户重跑 StartMCPServer。 |
| Altium 脚本跑起来卡死 | eda-agent 没停,两个脚本冲突。停掉再跑。 |
导入报 Header already parsed |
ASCII 没转干净,或者源选成了原始工程。stage_ascii.py verify 查。 |
| 导入后 DRC 几千条 | 正常。先按基线改 .kicad_pro 规则,再回填焊盘网络、重填铺铜。 |
| 一堆 "GND vs 空网络" 短路 | BGA 平面焊盘丢网络。fix_pcb.py 回填。playbook §4.1。 |
| 改了网络类但铺铜避让没变 | zone 本地 clearance 盖过了。fix_pcb.py --zone-clearance-mm。playbook §4.2。 |
| refill 超时/段错误 | 大板别用 SWIG。GUI 里按 B,或 IPC 后端。 |
| 网表比对差一堆节点 | 多半是某页 kicadxml 没导出成功,看 netcmp.py 的 [export] N/M。 |
| 矢量比对某层全 unmatched | layer_map.json 配错了。不带 --layer-map 跑一次看两侧每层走线数。 |
[SAFETY-END] |
某个回环超了重试上限,图优雅退出了。修好卡住的那步再 start --restart 重跑;确实需要更多轮次就加 --max-netlist-retry 8 这类参数。 |
kicad-cli 输出 UnicodeDecodeError |
别用 text=True 收 kicad-cli 的输出,中文 Windows 会按 GBK 解 UTF-8。netcmp.py 已处理。 |
ModuleNotFoundError: langgraph |
conda run -n langgraph pip install langgraph langgraph-checkpoint-sqlite |
ImportError: pcbnew |
fix_pcb.py / dump_kicad_vec.py 必须用 KiCad 自带 python 跑,不是 conda 的。 |
深入
references/playbook.md— 每个坑的根因、XMOD/GQ 两次迁移的实测数字、 各阶段该有的判定基准和证据目录约定。卡住了先读这个。references/vector-compare.md—altium_vec/各 JSON 的字段格式、layer_map.json怎么定、结果怎么读。- 图的拓扑与 interrupt 契约:
E:\LangGraph_Design\Altium-Kicad\Notes\Task04.md