126 lines
4.0 KiB
Markdown
126 lines
4.0 KiB
Markdown
# 矢量几何比对:Altium 侧 JSON 怎么导
|
||
|
||
`cmp_vec.py` 要两个目录:`kicad_vec/` 由 `dump_kicad_vec.py` 生成;
|
||
`altium_vec/` 得你在 Claude 会话里用 eda-agent 的 MCP 工具查出来再写盘 ——
|
||
LangGraph 进程里没有 MCP,这一步必须由会话来做。
|
||
|
||
---
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
_migration\gerber\
|
||
├── altium_vec\ meta.json vias.json pads.json tracks.json
|
||
├── kicad_vec\ meta.json vias.json pads.json tracks.json (dump_kicad_vec.py 生成)
|
||
└── layer_map.json
|
||
```
|
||
|
||
---
|
||
|
||
## altium_vec 各文件的格式
|
||
|
||
`cmp_vec.py` 的 `load()` 容忍三种外壳:裸 list、`{"vias": [...]}`、`{"objects": [...]}`,
|
||
所以直接把 MCP 返回的结果落盘一般就能用。字段名**区分大小写**,按下表来。
|
||
|
||
### meta.json
|
||
|
||
```json
|
||
{
|
||
"unit_note": "eda-agent 返回的是整数 mil,读数精度 ±0.5mil = 12.7um",
|
||
"scale_to_mm": 0.0254,
|
||
"counts": {"tracks": 10206, "arcs": 108, "pads": 3010, "vias": 2209}
|
||
}
|
||
```
|
||
|
||
`scale_to_mm` 是 `cmp_vec.py` 唯一会读的字段(也可以用 `--scale-to-mm` 覆盖)。
|
||
eda-agent 返回整数 mil,所以是 `0.0254`。
|
||
|
||
### vias.json — 来自 `pcb_get_vias`
|
||
|
||
小写字段:
|
||
|
||
```json
|
||
{"vias": [{"x": 22046, "y": 33005, "size": 20, "hole_size": 12,
|
||
"net": "VCC3V3", "low_layer": "TopLayer", "high_layer": "BottomLayer"}]}
|
||
```
|
||
|
||
`cmp_vec.py` 只用 `x` / `y`,其余留着供人核对。
|
||
|
||
### tracks.json — 来自 `obj_query`(PCB 文档,Track 对象)
|
||
|
||
**大写**字段(obj_query 原样返回 Altium 的属性名),值可以是字符串:
|
||
|
||
```json
|
||
{"objects": [{"Layer": "TopLayer", "X1": "21739", "Y1": "33141",
|
||
"X2": "21859", "Y2": "33141", "Width": "6", "Net": "PS232_RX"}]}
|
||
```
|
||
|
||
`cmp_vec.py` 用 `Layer` / `X1,Y1` / `X2,Y2`,按中点逐层匹配。
|
||
|
||
### pads.json — 来自 `obj_query`(Pad 对象)
|
||
|
||
```json
|
||
{"objects": [{"Name": "", "X": "22666", "Y": "32072", "Layer": "TopLayer",
|
||
"Net": "GND", "HoleSize": "0", "TopXSize": "59",
|
||
"TopYSize": "118", "Rotation": "90"}]}
|
||
```
|
||
|
||
用 `X` / `Y`。
|
||
|
||
---
|
||
|
||
## layer_map.json
|
||
|
||
Altium 层名 → KiCad 层名。**必须逐工程写,不能套公式** —— `MidLayerN` 到
|
||
`InN.Cu` 的对应取决于叠层顺序,想当然会全错。
|
||
|
||
```json
|
||
{
|
||
"TopLayer": "F.Cu",
|
||
"MidLayer1": "In2.Cu",
|
||
"MidLayer3": "In5.Cu",
|
||
"MidLayer2": "In7.Cu",
|
||
"BottomLayer": "B.Cu"
|
||
}
|
||
```
|
||
|
||
(上面是 GQ_EXCT7G_V1 的真实映射,注意 MidLayer2/3 是反的。)
|
||
|
||
怎么定:不带 `--layer-map` 跑一次 `cmp_vec.py`,它会打印两侧每层的走线条数,
|
||
按计数配对;再用 `pcb_get_layer_stackup`(Altium 侧)和 `get_layer_list`
|
||
(KiCad 侧)核对叠层顺序。内电层(负片平面)通常没有走线,不进 map。
|
||
|
||
---
|
||
|
||
## 跑一遍
|
||
|
||
```powershell
|
||
# 1) KiCad 侧(下面的 KiCad python 路径取自 ~/skills_env.md 的 KICAD_PYTHON)
|
||
& "D:\KiCad\10.0\bin\python.exe" dump_kicad_vec.py `
|
||
--board "E:\Kicad_design\FOO\FOO.kicad_pcb" `
|
||
--out "E:\Kicad_design\FOO\_migration\gerber\kicad_vec"
|
||
|
||
# 2) Altium 侧:在会话里用 eda-agent 查,按上面的格式写进 altium_vec\
|
||
|
||
# 3) 先不给 layer_map,看两侧每层走线数,定映射
|
||
python cmp_vec.py --altium-vec ...\altium_vec --kicad-vec ...\kicad_vec
|
||
|
||
# 4) 写好 layer_map.json 再跑完整比对
|
||
python cmp_vec.py --altium-vec ...\altium_vec --kicad-vec ...\kicad_vec `
|
||
--layer-map ...\layer_map.json --report ...\vec_result.json
|
||
```
|
||
|
||
退出码 0 = 全部图元匹配。
|
||
|
||
---
|
||
|
||
## 结果怎么读
|
||
|
||
- `unmatched_altium` 和 `unmatched_kicad` **都要是 0**。只看一边会漏掉
|
||
「KiCad 多出来的图元」。
|
||
- `residual mm` 的 max 应该在容差内且远小于容差(XMOD/GQ 实测中位数在 1um 量级)。
|
||
如果 max 贴着容差上限,多半是平移标定被拉偏了 —— 先查两侧过孔数是否相等。
|
||
- 两侧过孔数不同 → 质心标定必然偏。先查是导入丢了过孔,还是 Altium 侧
|
||
`obj_query` 漏了层,别硬比。
|
||
- 某一层大面积 unmatched,而其它层是 0 → 十有八九是 `layer_map.json` 配错了。
|