Files
2026-09-09 09:51:06 +08:00

297 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: altium-kicad
description: >
把 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 = 出错。
```powershell
$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,停了再想取就得重开桥接。所以顺序是:
1. 用 eda-agent 落盘基线到 `<target_dir>\_migration\altium_baseline\`:
`proj_get_stats` `proj_get_nets` `proj_get_bom` `pcb_get_board_statistics`
`pcb_get_layer_stackup` `pcb_get_design_rules`(存成 `pcb_design_rules.json`,
后面查 InPolygon clearance 要用)
2. `proj_export_netlist`(**tabular**)导到 `_migration\reference\netlist_tabular.csv`
—— 这是后面回填焊盘网络和比网表的**唯一真值**,别漏
3. 记下原理图页数和 PCB 数(`check_file_count` 要用)
然后转 ASCII:
```powershell
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。
跑完验证:
```powershell
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**(先干跑看量):
```powershell
$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 次)
```powershell
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:
```powershell
& $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`,必须包含:
1. 各阶段 PASS/FAIL 与关键数字(页数、元件数、节点数、走线/过孔匹配数)
2. **明确列出三项工具固有差异**(负片内电层 / 铺铜填充纹理 / 丝印字体)
及其根因,注明是容差项不是缺陷 —— 不写清楚,后面看报告的人会当成没做完
3. 证据文件索引
`--set report_path=E:\Kicad_design\FOO\_migration\verification_report.md`
回填后图结束,`ak_flow.py` 打印 `[DONE]`。
---
## 铁律速查
1. **原理图必须先转 ASCII**。AD26 二进制 `.SchDoc` 会让 KiCad 报
`Header already parsed`。PCB 侧没这问题,只有原理图。
2. **转 ASCII 之前先停 eda-agent**。Altium 一次只能跑一个脚本,桥接自己就是个脚本。
3. **基线快照要趁桥接活着做完**,尤其 tabular 网表 —— 后面回填网络和比网表都靠它。
4. **KiCad 导入只能人工点**,源必须选 `_ascii` 版。
5. **`kicad-cli pcb import` 不能替换主板**,那会切断原理图↔PCB 关联,只能当参考。
6. **zone 的本地 clearance 会盖过网络类**,只改 `.kicad_pro` 无效。
7. **网表比 partition 不比网络名**,且必须逐页导 kicadxml。
8. **跨工具像素级一致不可能**,判定基准是离散几何等价 + 三项固有容差。
9. **原始 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`