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

4.0 KiB
Raw Permalink Blame History

矢量几何比对: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

{
  "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

小写字段:

{"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 的属性名),值可以是字符串:

{"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 对象)

{"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 的对应取决于叠层顺序,想当然会全错。

{
  "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。


跑一遍

# 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 配错了。