@huaqiu/dsh-kicad 0.4.13 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/lib/index.mjs +5 -0
  2. package/package.json +2 -2
  3. package/skills/hardware-design-brief/SKILL.md +65 -31
  4. package/skills/hardware-design-brief/agents/openai.yaml +3 -3
  5. package/skills/hardware-design-brief/references/design-brief-guide.md +84 -11
  6. package/skills/hardware-design-brief/references/examples/hardware-solution-example.md +442 -0
  7. package/skills/hardware-design-brief/references/hardware-prd-guide.md +53 -10
  8. package/skills/hardware-design-brief/references/mrd-guide.md +45 -10
  9. package/skills/hardware-design-brief/references/multi-board-guide.md +51 -0
  10. package/skills/hardware-design-brief/references/project-controls.md +45 -0
  11. package/skills/hardware-design-brief/references/solution-deliverable.md +55 -0
  12. package/skills/hardware-design-brief/references/stage-boundaries.md +32 -0
  13. package/skills/pcb-initial-placement/SKILL.md +343 -0
  14. package/skills/pcb-initial-placement/agents/openai.yaml +4 -0
  15. package/skills/pcb-initial-placement/references/algorithm.md +317 -0
  16. package/skills/pcb-initial-placement/scripts/apply_via_ipc.py +211 -0
  17. package/skills/pcb-initial-placement/scripts/board_geometry.py +368 -0
  18. package/skills/pcb-initial-placement/scripts/kipy_common.py +80 -0
  19. package/skills/pcb-initial-placement/scripts/pack.py +576 -0
  20. package/skills/pcb-initial-placement/scripts/placement_config.example.json +116 -0
  21. package/skills/pcb-initial-placement/scripts/placement_view.py +340 -0
  22. package/skills/pcb-initial-placement/scripts/pose_table.py +86 -0
  23. package/skills/pcb-initial-placement/scripts/projpaths.py +160 -0
  24. package/skills/pcb-initial-placement/scripts/sexpr.py +180 -0
  25. package/skills/pcb-initial-placement/scripts/suggest_modules.py +420 -0
  26. package/skills/pcb-initial-placement/scripts/verify_placement.py +226 -0
  27. package/skills/pcb-initial-placement/scripts/write_board_file.py +109 -0
  28. package/src/skills.ts +11 -0
@@ -0,0 +1,51 @@
1
+ # 多 PCB:整机、单板与板间互连
2
+
3
+ 当产品包含多种 PCB、多块同型板、分体探头/显示/电源/执行模块,或已有需求需决定分板时使用。先区分物理单元、功能模块、采购模块与自研 PCB;一张功能框图不自动代表一块 PCB。
4
+
5
+ ## 各阶段如何拆分
6
+
7
+ | 阶段 | 必需处理 |
8
+ | --- | --- |
9
+ | MRD/立项说明 | 写整机及附件/分体单元、使用位置、距离、供电/安装/维护边界;已知多 PCB 时记录其组成与来源。板数未定时明确待方案决策,不为市场文档强造硬件架构 |
10
+ | 产品/硬件 PRD | 建整机需求与板级分配视图,已有板卡逐块列职责、供电/功能/接口/环境/成本边界和验收;尚未定的分板提案列状态和决策条件。没有独立市场需求时不为每块板编造 MRD |
11
+ | 硬件方案 | 比较必要的集中/分板路线并选主方案;落实每种 PCB、实例数、板内电路/核心件/预算,以及整机互连和装配关系;将确定的分板/接口分配回填 PRD,保持版本可追溯 |
12
+ | 原理图/PCB 交接 | 每块自研 PCB 对应独立电路/PCB 设计输入,共享接口契约;区分单板自测和整机联调,注明依赖接口版本 |
13
+
14
+ 用户在 MRD 阶段已指定多板时不得省略;尚无分板依据时也不能把猜测当冻结事实。允许 MRD→PRD→方案迭代细化,而不是要求市场阶段就完成全部 PCB 设计。
15
+
16
+ ## 稳定编号和需求分配
17
+
18
+ 用 `B01`、`B02` 标识不同 PCB 设计类型;同型板重复使用写 `B02 × 4` 并给实例/地址区分,不生成四份矛盾方案。编号跨文档保持稳定。采购模块单列型号/版本和宿主 PCB;模块内自带 PCB 不算本项目新增的自研设计,但必须覆盖其互连和成本。
19
+
20
+ | 板号/名称 | 类型及每机数量 | 模块/安装位置 | 承担的 H- 需求 | 电源/性能/成本分配 | 对外/板间接口 | 状态/方案位置 |
21
+ | --- | --- | --- | --- | --- | --- | --- |
22
+
23
+ 沿用已有 `H-` 编号,以“分配板号”关联,不为拆文档随意重编需求。跨板需求(例如端到端延迟或整机续航)保留整机判据,并分配各板预算与联调责任,不能仅靠各板局部通过就宣称满足整机目标。
24
+
25
+ ## 文档组织
26
+
27
+ 默认总方案 `03-design-brief.md` 写系统架构、板卡清单、统一供电/信号拓扑、整机预算、风险及集成验证;每块自研 PCB 的具体方案放在 `boards/B01-名称.md` 等文件,公共板间契约放在 `interfaces/board-interconnects.md`。路径相对于项目 `docs/`。
28
+
29
+ 若要求单文件或项目很小,保留独立的“B01 单板方案”“B02 单板方案”“板间互连”章节,不强制增加文件。无论文件数,每块板均按 [方案交付结构](solution-deliverable.md) 展开:不能总方案很详细,子板只留一句功能描述。共享选型和接口可以引用唯一位置,不复制多份主数据。
30
+
31
+ ## 板间连接必须能接线
32
+
33
+ 为每组连接给 `IF-01` 等稳定编号。输出连接总表及逐针映射:
34
+
35
+ | 连接编号 | A端板/实例/连接器型号 | B端板/实例/配对型号 | 线束/FPC/背板规格及长度 | 供电方向/最大负载 | 信号/地/屏蔽 | 版本/责任 |
36
+ | --- | --- | --- | --- | --- | --- | --- |
37
+
38
+ | 连接编号 | A端针号/信号 | B端针号/信号 | 电气类型与方向 | 电压域/电流/速率 | 默认/断电/插拔行为 | 端接/上拉/保护归属 |
39
+ | --- | --- | --- | --- | --- | --- | --- |
40
+
41
+ 说明针序的观察方向、连接器 Pin 1 和锁扣/防呆定义,避免相同序号实际镜像。差分对、参考地、备用脚、屏蔽连接与禁止连接脚应明确。连接器未定而又影响针序/电流/结构时属于交接阻塞,不能留给两位单板工程师各自决定。
42
+
43
+ 核查:两端的驱动/接收方向和电压兼容;隔离域不经地线/测试线短接;上拉/终端不遗漏或重复;总线地址/片选/实例可区分;线缆压降和峰值电流可接受;未上电板不会反灌;带电插拔是否允许及其保护/顺序已定义。
44
+
45
+ 多板 I²C、SPI、模拟信号等不能仅因板内可用就直接延伸到线缆。依实际长度、负载、带宽、环境和共模条件论证,必要时改变收发、隔离或通信方式,并回写两端方案。
46
+
47
+ ## 汇总与变更
48
+
49
+ 按每机实例数量汇总功耗、端到端性能、成本、尺寸及接线;采购模块不要同时累计其整模块价格与内部器件价格。单板测试分别列板端条件,整机测试覆盖接线错误、通信失联、供电顺序和适用故障。
50
+
51
+ 板间契约更改时同时检查两端单板的选型/引脚/电路、固件、线束和测试;记录版本兼容性。只能完成一侧更新时将另一侧和整机兼容性标为待复核,不能宣称接口已闭合。
@@ -0,0 +1,45 @@
1
+ # 文档一致性与验证检查
2
+
3
+ 本指南用于模型内部自检,不是审批流程。默认不生成独立决策日志、决策编号或签核表。保持方案的技术深度,减少重复记录和对用户的确认请求。
4
+
5
+ ## 信息放在对应位置
6
+
7
+ - 产品目标、来源和验收条件放在 PRD;选型、电路取舍、参数依据和预算放在方案的对应章节;实测证据引用实际试验记录。不要把同一结论再抄入决策文件。
8
+ - 假设直接注明在受影响参数或方案旁,足以解释适用条件即可。关键未决项在相关文档末尾简短列“缺什么—影响哪部分—下一步怎么解决”;无实质未决项时不建空表。
9
+ - 需求/板号/接口编号沿用已有规则,保留需求→板卡/电路→验证的对应关系,不再额外建立 `D-001` 决策条目。
10
+ - 每份文档保留版本/日期和输入依据。用来源与证据说明用户要求、工程建议、假设、计划和实测结果,不为每项添加等待用户签核的状态。
11
+
12
+ 用户明确要求独立决策日志,或已提供的团队规范明确要求时再使用;不因“企业项目”“受监管产品”或旧日志存在而自动增加审批。已有日志保留历史和必要引用,新内容默认写回对应文档,不擅自删除旧文件或要求用户批准迁移。
13
+
14
+ ## 什么时候才需要问用户
15
+
16
+ 先看已有输入、优先级和授权能否回答,再查资料或计算;只有关键取舍确实无法代决时提问。
17
+
18
+ | 情况 | 处理方式 |
19
+ | --- | --- |
20
+ | 用户已给过信息、已选择或已授权模型决定 | 直接沿用;无新矛盾不再次询问 |
21
+ | 常规选型、引脚/外围计算、文档组织、资料可查的事实 | 自行核实并决定推荐基线,说明依据,继续实施方案 |
22
+ | 可逆、影响有限且可作合理假设的缺口 | 明示假设后继续,不要求每条都被确认 |
23
+ | 待查手册、供应商资料或待实测项目 | 作为工程待办,记录取得证据的方法;用户回复“确认”不能替代证据 |
24
+ | 核心需求冲突或缺少关键外部条件,且无既定取舍依据 | 尽量合并提问,给推荐及影响;只限制依赖该答案的部分,其他工作继续 |
25
+ | 用户明确要求阶段审批 | 按用户规定的节点暂停,不追加其他审批节点 |
26
+
27
+ 未回复不代表批准;也不意味着已经授权的独立工作都要停下。涉及供电、隔离或其他关键电气边界而无可靠依据时,不用随意默认值掩盖缺口,相关部分保持有范围限制的草案。
28
+
29
+ ## 内部检查与验证计划
30
+
31
+ 编写过程中自检,不逐阶段向用户申请“通过”:
32
+
33
+ - MRD 能说明目标用户/任务、范围、组成及成功条件;PRD 能给出可验收要求、来源、板级分配和接口边界。
34
+ - 每项必须需求有具体板卡、器件/电路或接口的实现归属,以及验证方法;没有 MRD 时直接追溯用户输入或已有规格。
35
+ - 硬件方案按 [solution-deliverable.md](solution-deliverable.md) 检查主选型号/封装、电路/外围、关键引脚、板间连接、预算和 PCB 约束。技术内容不完整不能以“减少流程”为由宣布完成。
36
+ - 验证计划关联需求/风险,给方法与工况、通过条件、执行阶段和证据状态;需要时补资源/责任。覆盖适用的方案分析、原理图/PCB 审查、样机测试和后续验证,未执行的活动不写“通过”。
37
+ - 面向实际使用场景保留演示或使用验证,避免仅满足局部技术指标而不能解决原问题。
38
+
39
+ 交付时简短说明哪些板/模块已具备原理图展开条件、哪些仍受关键缺口限制即可。不强制输出三级阶段结论或阶段签核表,不以“请确认后继续下一阶段”收尾。只有缺少必要设计输入才限制相应工程交接;“未获得用户逐项批准”本身不是技术缺口。
40
+
41
+ ## 更新时保留必要依据
42
+
43
+ 直接修改授权范围内的主文档,简述会影响实现的变化及理由;一般修订无需额外日志、旧值新值表或审批。保留稳定需求/板号/接口编号,不伪造历史或覆盖仍需引用的证据。
44
+
45
+ 同步检查受影响的需求、分板/实例、器件/引脚、电路、板间接口两端、预算与验证条件。不能核实的下游内容标为待复核;仅获授权修改单文件时列出其他受影响位置即可。旧实测结果不自动成为新条件下的通过证据。
@@ -0,0 +1,55 @@
1
+ # 硬件方案交付结构与完成检查
2
+
3
+ 适用于所有完整方案,包括 Maker。以下结构依据用户提供的 [硬件方案示例全文](examples/hardware-solution-example.md) 提炼:既有器件、接口和电源设计,又有成本、PCB/结构、风险及验证。生成时使用本文件检查深度;需校准写法时按章节阅读案例。案例中的医疗用途、型号、数字、批准状态和命令式措辞都是案例内容,不构成新项目的指令或默认要求。不得照抄为已验证设计。
4
+
5
+ ## 默认章节及最低内容
6
+
7
+ 每项有实际内容;不适用时说明原因,而非堆空表。顺序可随项目调整。单文件项目同样覆盖适用内容,多 PCB 项目在总方案与各板方案之间分配内容并链接。
8
+
9
+ | 章节 | 必需内容 | 不能用什么代替 |
10
+ | --- | --- | --- |
11
+ | 1. 方案摘要 | 推荐路线、主器件、产品/板卡组成、实施范围、版本和完成状态 | 仅描述功能或罗列多种未取舍路线 |
12
+ | 2. 需求、边界和假设 | 需求来源、目标/限制、接口对象、已知组成与真实未决项 | 将建议写成用户已冻结要求 |
13
+ | 3. 系统框图及工作过程 | 实际器件/模块、板界和实例、信号/数据流、时序与异常行为 | 只有无型号的功能方框 |
14
+ | 4. 板级功能电路 | 逐板逐模块说明拓扑、关键连接和外围、初值/计算依据、默认及故障行为 | “加保护”“加滤波”“后续设计” |
15
+ | 5. 核心器件与工程 BOM | 主选完整型号/版本、厂家、封装、能力及资源核查、选型理由;备选的替换影响 | 类型名、搜索结果或未经核实的器件表 |
16
+ | 6. 接口与信号/引脚规划 | 两端器件及脚名/脚号、电压域、协议/时序、地址、上拉/端接/保护和复用检查 | 仅写“通过 GPIO/I²C 连接” |
17
+ | 7. 电源树及电路 | 保护/变换/控制/负载、输入输出范围与容差、主选、外围、时序和欠压/关机策略 | 只写“提供 3.3 V” |
18
+ | 8. 预算与可行性 | 电流/功率/续航、资源/存储、性能及相关热/空间预算;数值、来源、公式和余量 | 全部留为公式或默认“足够” |
19
+ | 9. 成本和采购依据 | 数量、单价区间/报价及日期、按板与整机汇总、口径/遗漏、可信器件和资料入口 | 无来源价格、算错总价、检索入口冒充库存证明 |
20
+ | 10. PCB 与结构约束 | 每板尺寸/层数等约束或建议、分区/靠近关系、回流/噪声/热规则、板间物理实现、测试可达性 | “注意 EMC/DFM”或宣称已完成 PCB |
21
+ | 11. 风险与验证 | 对具体电路/器件/板间连接的风险、应对;原理图/PCB/样机和适用后续检查 | 与本方案无关的通用测试清单或伪造通过结果 |
22
+ | 12. 交接结论 | 哪些板/模块可展开原理图、剩余关键缺口、下一步及输入版本 | 将“有框图”判为全方案完成 |
23
+
24
+ ## 接近案例、并加强可实现性的写法
25
+
26
+ 案例的“关键器件建议”要落实成项目的**主选基线**。例如不能仅输出“外接 EEPROM 存 30 条记录”;应选具体料号与容量,列记录大小×条数,再加校准参数、双副本、CRC、索引与元数据,核对总容量及寿命。每个数字都需来自需求、手册或明确的工程推算。
27
+
28
+ 案例的“接口与信号规划”应覆盖中间驱动芯片两侧。例如使用显示驱动器时,控制器到驱动器的控制线、驱动器到显示屏的 COM/SEG、模式和映射都要交代,不能只画 MCU→LCD 的箭头。所选型号的实际通信接口和封装需核实,不能从器件类别推断。
29
+
30
+ 案例的“电源设计要点”应落实成拓扑及连接。采用按键锁存关机时,说明启动触发、自保持、复位默认、撤销保持及各状态电流路径;给主器件和关键外围依据。开机、掉电和调试供电均要检查,不能只写“完全断电所以没有功耗”。
31
+
32
+ PCB/结构段保留案例中这类具体指导:开关电源关键环路及器件靠近关系、探头与热源隔离、线束入口的保护位置、接地和测试入口。按实际项目论证,不将案例中的所有规则或数字变成通用强制要求。
33
+
34
+ ## 交付前逐项检查
35
+
36
+ ### 方案落实
37
+
38
+ - 已为各必需模块选出主器件/模块及封装/版本,或明确标出真实阻塞;“待选”不能覆盖已经具备决策条件的全部核心件。
39
+ - 有逐板电路说明、关键外围参数/依据和信号路径;原理图人员无需重做主方案取舍。
40
+ - 完整型号、封装、脚号、外设实例和接口类型在原厂资料中对应;备选的封装/软件差异已记录。
41
+ - 器件正常工作范围与电源容差、掉电状态、阈值一致;检查保护/锁存/驱动/复位的真实行为。
42
+ - 资源、非易失存储(含副本/元数据)、通信容量和性能预算有计算,不能超出主选能力;尚待测试的估计有状态。
43
+
44
+ ### 图表、分板与经济性
45
+
46
+ - 整机、板卡、模块边界明确;多板每种 PCB 有独立方案,每个实例/数量可查。
47
+ - 板间连接两端针脚、供电方向、地/屏蔽、连接器配对、线缆和异常状态一致;没有只在一块板上定义的接口。
48
+ - 框图、电源树、信号表、器件表和预算采用同一推荐版本,无旧候选混入。
49
+ - 各电源轨与实例数量统计正确,功率损耗不漏计/重复计;BOM 行小计、上下界与总计可复算,成本口径一致。
50
+
51
+ ### 深度和状态
52
+
53
+ - Maker 与企业均满足以上电路深度;Maker 可删商业管理章节或用模块替代自研电路,但模块的具体接口仍需落实。
54
+ - 真正尚未知的外部条件、未完成的核查或实物验证明确标注,关键缺口存在时交付“方案草案/部分可展开”,不虚构确定性。
55
+ - 已完成输入的板/模块和暂缓范围分别说明。原理图与 PCB 后续负责展开、校核和实现,不能被迫重新发明电源、接口和连接方案。
@@ -0,0 +1,32 @@
1
+ # 阶段边界:先完成电路方案,再展开详细设计
2
+
3
+ 硬件方案是原理图及 PCB 的主要依据。本阶段不直接绘制完整 EDA 文件,不代表核心选型、接口电路、关键参数及模块连接也应后置。先保证后续工程师能依据文档实现,不必重新做主要方案决策。
4
+
5
+ ## 同一话题在各阶段的深度
6
+
7
+ | 话题 | PRD:要求与分配 | 硬件方案:应完成的设计输入 | 原理图/PCB/制造:后续落实 |
8
+ | --- | --- | --- | --- |
9
+ | 产品与多板 | 整机边界、已有板卡组成、各板职责和要求;未知分板标提案 | 确定 PCB 类型/数量/实例、板级方案、板间接口和供电,回填 PRD | 每板独立设计文件、版本与整机装配配置 |
10
+ | 核心器件 | 性能、成本、环境及用户指定约束 | 厂家、完整型号/版本、封装、主选依据、兼容性与资源核查 | 建库、全引脚接线、全量物料核验和采购放行 |
11
+ | 电源/保护/驱动 | 输入、负载、功耗、异常行为 | 具体拓扑、器件、关键外围/初值、使能/复位/锁存、阈值及预算依据 | 完整电路、全部阻容位号、仿真/实测调优;验证不后移方案必需计算 |
12
+ | 信号与引脚 | 协议/速率/电气条件、兼容对象 | 核心信号逐项连接、外设实例及引脚映射、地址/上下拉/端接/隔离、默认及故障状态 | 补齐非关键接线、ERC/网络核验、由实现调整并回写基线 |
13
+ | 板间互连 | 两端职责、安装/线缆和供电要求 | 连接器配对型号、针序/映射、线缆/FPC、地/屏蔽、功率和保护、插拔与顺序 | 完整线束图、机械装配图、详细应力及工艺确认 |
14
+ | PCB 与结构 | 固定机壳、接口位置、包络及制造能力 | 板尺寸/层数/板厚的约束或建议、功能分区、热/回流/噪声布局规则及阻抗等目标 | 最终叠层及制造参数、求解线宽/间距/等长、精确布局布线、Gerber |
15
+ | 装配与测试 | 数量、手焊/外协、维修/校准目标 | 可焊封装、接口可达性、烧录/测试信号与连接、定制件配合和关键装配约束 | 全部测试点坐标、治具结构、钢网、拼板、回流工艺和工艺卡 |
16
+ | 安全与合规 | 地区、用途、环境及适用目标 | 核实影响设计的适用条件,完成隔离/保护方案和所需设计目标,未决项列动作 | 详细规则验证、专项试验及正式合规证据 |
17
+ | 物料与成本 | 预算与批量口径 | 核心器件清单/工程 BOM、主要外围与成本估算、采购核实状态 | 带全部位号、封装的完整 BOM 和生产放行 |
18
+
19
+ ## 如何处理尚未确定的参数
20
+
21
+ - **用户或既有产品的硬约束**:原样继承并查冲突,不因“属于后期”删除。
22
+ - **可由手册和计算决定**:本阶段给推荐值/范围、依据和适用条件,例如分压、上拉、滤波、反馈、限流;不要一概写待定。
23
+ - **需布局或试验收敛**:本阶段先给目标、初值/范围和验证方法,后续调优并回写方案。
24
+ - **缺少会改变路线的外部条件**:只阻塞受影响模块,可交付条件化草案;核心电路未闭合时不能宣称整板方案完成。
25
+
26
+ 例如手焊项目需要本阶段选能焊的封装;高速接口需要先有主选器件、连接和布线目标;固定外壳项目需要落实可用包络与连接器方向。不能在方案期仅说“后续考虑”,也不能将尚无依据的参数写成冻结结论。
27
+
28
+ ## 交接含义
29
+
30
+ “可进入原理图”意味着主选器件与封装、电源/接口/关键外围、引脚资源、板间连接和约束已足以展开电路。可以有不影响路线的细节待优化,但不能留下迫使绘图人员重新选主控、供电或接口的关键空白。
31
+
32
+ “可用于 PCB 设计”意味着方案已给 PCB 约束和设计目标;实际布局布线还依赖完成的原理图、封装与机械协调。“可投板/装配”则需要后续设计检查与制造数据。三者不能混用。
@@ -0,0 +1,343 @@
1
+ ---
2
+ name: pcb-initial-placement
3
+ description: "给只有网表、还没布局的 KiCad PCB 做 Phase-1 初始布局:功能分块、锚点定位、分区摆放、无重叠校验与交付报告;结果优先通过 KiCad IPC API 应用到打开的板子上,IPC 不可用时才离线生成新板文件。适用于 20–200 器件、单板、以单面为主的初始布局。"
4
+ ---
5
+
6
+ # PCB 初始布局(Phase 1)
7
+
8
+ 把一块"器件散落在板外、零布局"的板子,变成"定位准确、核心合理、分组集中、可以接手"的初始布局。器件不动原理图、不布线、不改网表。
9
+
10
+ 产出的不是"好看的图",而是一次**可评审、可接手、可一键撤销**的布局决策:每个器件有明确的功能归属,每个模块有明确的核心器件和落位区域,机械件保持原样,模块内器件聚在核心旁边。
11
+
12
+ ## 边界:这个技能不做什么
13
+
14
+ - 不布线、不铺铜、不做等长/阻抗/试布线/拥塞预测。
15
+ - 不做 SI / PI / 热 / EMC 分析,不做 3D 机械干涉检查(只能标注风险,不能验证)。
16
+ - 不做 HPWL 或任何"目标函数最优"的承诺——这是 Phase 1,目标是**合理且可接手**,不是最优。
17
+ - 不修改原理图、不新建网络、不改封装、不替换器件。
18
+ - 不覆盖用户的原始板文件。
19
+
20
+ ## 与 kicad-ipc 的关系
21
+
22
+ **读**:用 `get_pcb_board` 拿权威语义快照(器件、焊盘、网络、板框),不要靠肉眼或猜测。
23
+
24
+ **写**:**优先走 KiCad IPC API**。摆放结果通过 `scripts/apply_via_ipc.py` 一次性提交到打开的板子上,KiCad 自己维护对象、UUID、连通性和撤销栈,整个布局是**一个 undo 步骤**。`.kicad_pcb` 不是可以随手改写的中间格式。
25
+
26
+ 先读 `kicad-ipc` 技能再动手。本技能不重复它的连接、版本路由和事务规则。
27
+
28
+ 只有 IPC 确实不可用、且用户明确接受"给我一个新板文件"时,才退回 `scripts/write_board_file.py` 离线写盘——那条路没有撤销栈,写完还要用户手动重新打开。
29
+
30
+ ## 输出目录约定(硬性)
31
+
32
+ **这次运行产生的每一个文件都放进项目下的 `placement/`**——与板文件同级,不存在就新建。技能目录里只有代码,cwd 和临时目录里不留任何产物。
33
+
34
+ ```
35
+ <项目>/
36
+ board.kicad_pcb
37
+ placement/ <- 本次布局唯一的落盘位置
38
+ geometry.json # 步骤 1:courtyard 占用矩形 + 板框
39
+ placement_config.json # 步骤 2/3:模块、锚点、定位件、禁布区
40
+ placement_plan.json # 步骤 5:每个器件的位姿
41
+ placement_pose_table.csv # 步骤 6:交接位姿表
42
+ placement_view.svg # 步骤 6:模块彩色视图 + 评估面板(必出)
43
+ placement_view.png # 可选:同一张图的位图
44
+ verify_placement.txt # 步骤 6:独立校验报告
45
+ apply_via_ipc.txt # 步骤 6:IPC 提交与回读日志
46
+ <board>-placed-preview.kicad_pcb # 仅离线退回方案才产生
47
+ ```
48
+
49
+ 规则:
50
+
51
+ - **不要写进技能目录**(`scripts/` 是只读代码,不是工作区),也不要散落在 cwd、桌面或 `%TEMP%`。
52
+ - **中间脚本也算产物**:为这块板临时写的连通性提取、模块顺序扫描、兜底几何脚本,同样放 `placement/`,取能看懂的名字。收尾时要么留作复现证据,要么明确删掉,不要留在半路。
53
+ - **脚本默认就落在那里**:知道 `--board` 的用 `<板目录>/placement/`,其余用输入文件(geometry / plan)所在目录。想换地方用 `--outdir`;要精确指定文件名才用 `--out`。
54
+ - **报告里的路径要和磁盘一致**。写完报告回头核对一遍:`placement/` 之外不该有任何本次产物。
55
+
56
+ ## 六步流程
57
+
58
+ ### 步骤 1 读取与预检
59
+
60
+ 1. `kicad_ipc_diagnose` 确认环境。
61
+ 2. **不要为了"看一眼板子"去读整板快照。** `get_pcb_board` 会返回每个焊盘、每条走线的完整
62
+ JSON——63 器件的板子实测 **194 KB**,其中 95% 是步骤 1 根本不需要的焊盘细节。步骤 1
63
+ 要的四个数字(器件数、板框、courtyard 来源、器件在不在板内)**全都能从板文件离线算出**,
64
+ 成本约 **0.5 KB**:
65
+
66
+ ```
67
+ python scripts/board_geometry.py --board <board>.kicad_pcb --brief
68
+ ```
69
+
70
+ 一次给全:器件数、板框顶点/尺寸、**真实多边形面积**(不是包围盒)、courtyard 总面积与
71
+ 密度、`bbox_src` 逐来源计数、现存角度直方图、器件 X/Y 范围、**有多少器件原点落在板框内**,
72
+ 以及所有必须写进报告的警告。`geometry.json` 里同时存了 `preflight` 与 `board_area_mm2`
73
+ 字段供后续步骤引用。
74
+
75
+ `get_pcb_board` 仍然是**写入时**的权威接口——只是它不是一把量尺。
76
+ 3. **判断这块板值不值得自动布局**:器件数 20–200、单板、以单面为主。`--brief` 的
77
+ `device origins inside` 一行直接给出判据:
78
+ - `N of N` → 作者手工调过,只做局部调整,**不要整板重排**;
79
+ - `0 of N`(全部在板框外)→ 源布局是"停机坪"导入态,没有价值,整板重排;
80
+ - 介于两者之间 → 混合态,先问用户。
81
+ 4. 确认原点/单位/层叠;确认器件都有 courtyard。非 `CrtYd` 的来源会逐件标在 `bbox_src` 里,
82
+ `--brief` 会直接点名,**必须在报告里复述**。`bbox_src` 为 `none` 的件没有任何东西保护
83
+ 它不被压叠,只能人工处理。
84
+ 5. **先核对板框与器件坐标是否自洽。** 如果 `--brief` 报"器件原点全部在板框外",那通常不是
85
+ 布局问题,而是**板框本身错了**。这是必须停下来问用户的分叉点:把 N 个器件塞进一个小矩形,
86
+ 还是把矩形改对,后续代价差一个数量级。不要自己猜。
87
+
88
+ 需要改板框时走 `kicad-ipc` 的图形创建能力(`kipy.board_types.BoardRectangle` +
89
+ `create_items`,一个 commit),**不要手改 `.kicad_pcb` 的 Edge.Cuts**。注意连带影响:
90
+ 板框一改,先前"在板外"的定位件(安装孔等)坐标全部失效,要一起重定位,并在报告里写明
91
+ 这是随板框变动的连带修改,不是布局算法的输出。
92
+
93
+ 6. 这一步的产物:`placement/geometry.json`(每个器件的 courtyard 占用矩形 + 板框多边形 +
94
+ preflight 摘要)。
95
+
96
+ > `board_geometry.py` 的占用框优先级是 CrtYd → Fab → 焊盘 → 丝印。丝印兜底是为只有丝印的
97
+ > 美术件(logo、基准点)准备的:这类件既没有 courtyard 也没有焊盘,早期版本会直接崩在汇总行上。
98
+ > 现在它会正常出框,并把 `bbox_src` 标成 `silk`,在 stdout 里点名。真正没有任何几何的件会拿到
99
+ > 零面积框并被单独警告——**这种件没有任何东西保护它不被压叠**,必须人工处理。
100
+ >
101
+ > Edge.Cuts 支持 `gr_line` / `gr_rect` / `gr_poly` / `gr_circle`。整块板只用一个
102
+ > **`gr_rect`** 描述是很正常的写法(KiCad 自己的板子就这么做),不要以为必须有四段
103
+ > `gr_line`;旧版解析器只认 start/end,遇到 `gr_rect` 会报 "does not form a closed
104
+ > polygon",那是解析器缺口,不是板子的问题。
105
+
106
+ ### 步骤 2 功能分块
107
+
108
+ **每个电气器件恰好属于一个模块,或者被显式标为"未分组"。**没有重复、没有遗漏,这一点要用
109
+ 断言守住。
110
+
111
+ **先把草稿跑出来再改,不要从零手写。** 手写 12 个模块的成员表是本流程最贵的一步(实测
112
+ 127 s 的纯推理,且极易出错——本次手写就漏了一个器件、重复了一个器件)。让脚本做机械部分:
113
+
114
+ ```
115
+ python scripts/suggest_modules.py --board <board>.kicad_pcb
116
+ # -> placement/placement_config.json(可直接喂给 pack.py 的草稿)
117
+ ```
118
+
119
+ 它按可靠性顺序做四件事:非电源/非单脚网络做并查集聚类 → 把只挂在电源上的器件(去耦、
120
+ 滤波)按电源域归给对应模块 → 把孤立单件并回邻居最多的模块 → 锚点按模块面积比例排成横向带。
121
+ 它**只做机械部分**:`fixed` 与 `keepouts` 一律留空,因为那是只有用户知道的物理事实。
122
+ 最后它会**断言分块是一个真划分**(无重复、无遗漏),这正是本步骤要求"用断言守住"的那件事。
123
+
124
+ 拿到草稿后人工做四件事,这才是真正需要判断力的部分:
125
+
126
+ 1. **改名字**:`dip_8_c4` 这类机器名要改成"VPP 升压"这类能评审的名字。
127
+ 2. **拆过大的簇**:脚本在超过 `器件数/4` 的簇后面标 `<- too big`。那说明有一条跨模块总线把
128
+ 两个功能块粘住了,机器分不开,只能人拆。
129
+ 3. **补 `fixed`**:所有有机械约束的器件。
130
+ 4. **补 `keepouts`**:插座倾斜体积、天线净空等。
131
+
132
+ 分块依据,按可靠性从高到低:
133
+
134
+ 1. **网表连通性**:谁和谁连得最多,谁就是一组。这是最硬的证据。
135
+ 2. **网名的原理图 sheet 前缀**(如 `/buspci.sch/`、`/graphic/`):同一张子图的网络聚在一起,
136
+ 是作者本人的功能划分意图。
137
+ 3. **功能常识**:视频输入/输出、总线接口、帧缓存、图形逻辑、板边连接器。
138
+
139
+ **电源网络必须降权**:GND 上挂着 115 个器件、+5V 上 70 个,如果按连通性聚类,整板会被并成
140
+ 一个巨大的"电源模块"。脚本已按三个条件降权(网名命中电源黑名单 / 扇出超过 `--fanout`
141
+ 默认 8 / 器件只连电源)。聚类完成后再把**只通过电源/地连接的器件**按电源域分配给对应模块。
142
+
143
+ **总线网络也要降权,但门槛要稳。** `/DATA-RB7` 这类总线从连接器穿过缓冲器一直拉到 ZIF 座,
144
+ 把它当分组证据会把半个板子并成一块。脚本的判据是"**抽掉这条网,它的脚还能不能连在一起**":
145
+ 能,说明这条网没提供新的分组信息,是总线;不能,说明它是真正的局部连线。两个门槛缺一不可:
146
+
147
+ - `min_pins>=4`:3 脚网络"缓冲器输出→串联电阻→指示灯"是真实子电路,不是总线;
148
+ - `max_frac<=0.5`:抽掉后还有一半脚连着的网,硬拆只会把一个完整模块剁成碎件。
149
+
150
+ **只放宽 `--fanout` 不解决问题**——总线的问题从来不是扇出大,而是它跨越功能块。
151
+
152
+ 每个模块要指定**核心器件**(1–3 个),它是这个模块的摆放锚点,也是评审时的抓手。
153
+ 找不到核心的模块,说明分块本身有问题。
154
+
155
+ 产出:`placement/placement_config.json` 里的 `modules`。
156
+
157
+ ### 步骤 3 锚点与定位件
158
+
159
+ 先钉死不动的,再谈摆放。
160
+
161
+ | 类别 | 处理 |
162
+ | --- | --- |
163
+ | 已存在的安装孔 / 定位孔 | **保持原坐标**,只登记为障碍物 |
164
+ | 位置已定、有结构约束的连接器 | **保持位置、角度、朝向** |
165
+ | 只要求"靠板边"的连接器 | 在指定板边上给一个合法位置即可 |
166
+ | 用户锁定的核心器件 | 保持不动 |
167
+ | PCI 金手指、板边支架连接器 | 从板框几何**反推**原点(见下) |
168
+
169
+ 两个必须掌握的推导:
170
+
171
+ - **金手指**:找一个已知该落在板边的焊盘(如 PCI 的 A1),用它的局部坐标反推封装原点,`origin = 板边目标点 − 焊盘局部坐标`。这样金手指一定贴合板边斜边。
172
+ - **支架连接器**:封装名常带结构偏移(如 `EdgePinOffset14.56mm`),原点 = 板边坐标 + 偏移量。
173
+
174
+ 产出:`placement/placement_config.json` 里的 `fixed`。
175
+
176
+ ### 步骤 4 分区(floorplan)
177
+
178
+ 1. 先把**固定件**、**禁布区**(keep-out)在占用栅格上盖章。顺序不能反,否则自由器件会先占掉禁布区。
179
+ 2. 按"贴边模块优先、面积大的模块优先"分配粗区域:大模块(FPGA、RAMDAC、SIMM 阵列)先落地,小模块(去耦、端接电阻)后填缝。
180
+ 3. 分区是**粗网格**级别,不是把每个模块锁进一个死框——模块边界处的自由空间应该被相邻模块共享,否则会出现大块空洞和远处的"飞地"。
181
+ 4. 机械禁布区要显式登记:SIMM/DIMM 模块插上后会倾斜,倾斜体积要预留。**这块区域必须在步骤 1 就识别出来**,否则后期无法收拾。
182
+
183
+ ### 步骤 5 模块内摆放
184
+
185
+ 对每个模块的每个器件:
186
+
187
+ 1. **核心器件和"二级核心"(晶振、时钟、配置 EEPROM、电位器)先摆**——它们比去耦电容更需要贴着自己的芯片。
188
+ 2. 大器件(courtyard 面积 ≥ 阈值)先于小器件,否则大器件会找不到整块空地。
189
+ 3. 从模块的锚点向外做**环形搜索**:以锚点为中心,半径按步进增长,每圈按角度采样,找到第一个合法位置。多个锚点时,取"离任一锚点最近"的那个解。
190
+ 4. 一个器件这一轮找不到位置时,**不要把它甩到板子另一头**,而是下一轮给它更大的搜索半径。突然跳到远处会把功能分组彻底打散。
191
+ 5. 模块之间**轮流占位**(round-robin),让共享区域的分配对各个模块公平。模块的处理顺序会影响结果:先处理的模块拿到sought-after的近处空间。**顺序要试,不要拍脑袋**——用"每个器件到本模块核心的距离中位数/总和"作为评分比较几种顺序。
192
+ 6. 收尾:**疏散修复 + 向核心压实**
193
+ - 还有器件放不下时,找一个"驱逐代价最小"的合法位置(被挤走的器件 courtyard 总面积最小),把它换进去,被挤走的重新排队。
194
+ - 全部落地后,反复把每个器件拉向"离自己核心更近的合法位置"。这一步只会让分组更紧,不会破坏可行性。
195
+
196
+ 产出:`placement/placement_plan.json`(由 `scripts/pack.py` 生成,含 `positions` / `unplaced` / `modules` / `anchors` / `fixed` / `keepouts`)。
197
+
198
+ ### 步骤 6 校验、出图与交付
199
+
200
+ **校验**:跑 `scripts/verify_placement.py`——**独立校验,不共用 packer 的代码**,否则只是把同样的算术再算一遍。它顺手把整份报告写进 `placement/verify_placement.txt`:这份文件是交接证据,不要只留在终端里。
201
+
202
+ **出图**:跑 `scripts/placement_view.py`,产出 `placement/placement_view.svg`。**每次布局都要出这张图**——评审时它是唯一能一眼看全局的东西,也是"板子到底摆成什么样"最省事的答复:
203
+
204
+ ```powershell
205
+ python <skill>/scripts/placement_view.py --geometry placement/geometry.json `
206
+ --plan placement/placement_plan.json --config placement/placement_config.json
207
+ # -> placement/placement_view.svg
208
+ ```
209
+
210
+ 图上有什么:真实板框(含缺口、圆角、异形边)、禁布区(斜线填充,面板里写清为什么禁)、按模块着色的 courtyard(**固定件实心、算法摆放的半透明**,一眼分得清"决定的"和"推出来的")、模块锚点、比例尺;下方是评估面板——板面积、courtyard 占比、重叠对数、出板数、未摆放数、stand-in 警告。它只用标准库,不依赖 KiCad、浏览器或光栅化库,任何跑得动 packer 的机器都出得来。
211
+
212
+ 面板里的门槛数字只用于**显示**;真正的判据是 `verify_placement.py`。两者不一致时以校验脚本为准。
213
+
214
+ 需要位图或真实铜箔视图时再补(可选):
215
+
216
+ ```powershell
217
+ # 位图(有 ImageMagick / Inkscape 时)
218
+ magick -density 96 placement/placement_view.svg placement/placement_view.png
219
+ # 3D 渲染(kicad-cli;用离线副本或已保存的板子)
220
+ kicad-cli pcb render --output placement/board-3d.png --side top --quality high <board>.kicad_pcb
221
+ # 真实铜箔/丝印分层 SVG —— 注意 --output 是目录,不是文件名
222
+ kicad-cli pcb export svg --output placement/board-svg/ --layers F.Cu,F.Silkscreen,Edge.Cuts <board>.kicad_pcb
223
+ ```
224
+
225
+ 交付物(全部在 `placement/` 下):
226
+
227
+ | 文件 | 说明 |
228
+ | --- | --- |
229
+ | `placement_config.json` | 布局决策本身:模块划分、锚点、定位件、禁布区、模块顺序 |
230
+ | `placement_plan.json` | 每个器件的位姿(x, y, rot) |
231
+ | `placement_pose_table.csv` | 交接位姿表(模块、位号、值、封装、原点、角度、courtyard 尺寸、fixed/placed) |
232
+ | `placement_view.svg` | **模块彩色视图 + 评估面板**(必出) |
233
+ | `verify_placement.txt` | 独立校验报告(重叠/间距/出板/分组/密度) |
234
+ | `apply_via_ipc.txt` | IPC 提交与回读日志 |
235
+ | 板文件 | IPC 提交后的板子;离线方案才多一个 `<board>-placed-preview.kicad_pcb` |
236
+ | `REPORT.md` | 分组清单(模块→器件→核心)、待确认清单、运行统计、复现命令 |
237
+
238
+ ## 把结果放进 KiCad:优先 IPC
239
+
240
+ ```
241
+ python scripts/apply_via_ipc.py --plan placement/placement_plan.json --dry-run # 先看要动哪些
242
+ python scripts/apply_via_ipc.py --plan placement/placement_plan.json # 提交为一个 undo 步骤
243
+ python scripts/apply_via_ipc.py --plan placement/placement_plan.json --save # 用户满意后落盘
244
+ ```
245
+
246
+ 每次运行都会留下 `placement/apply_via_ipc.txt`(提交了多少个、回读有没有不一致),这份日志是"确实提交过、且和计划一致"的唯一凭证。
247
+
248
+ **`--include-fixed` 是这一节最常见的坑。** 脚本默认**不动** `fixed` 里的器件,因为它假设这些定位件本来就在正确位置(真实的机械约束场景)。但板子如果是"全部散落在板外"的导入态,定位件也在停机坪上,默认行为会**静默漏掉**它们——计划里 28 个定位件,板子上一个都没动。判断方法只有一个:提交后从编辑器**实时读回**,比对计划里的全部位号,而不是只看 `parts to move` 的数字。凡是从零布局的板子,都要带 `--include-fixed`。
249
+
250
+ 脚本遵守 kicad-ipc 的规则:
251
+
252
+ - 先 `kicad_ipc_diagnose`,环境不通就不要往下走。
253
+ - 连接后**先定位再改**:按 reference 重新取封装对象,保留 KiCad 的 UUID;引用缺失、重复或**被锁定**的封装直接报错退出,不做部分应用。
254
+ - **整批一个 commit**:`begin_commit()` → 设 position/orientation → `update_items([...])` → `push_commit()`;任何异常 `drop_commit()`。用户在 KiCad 里只看到一步撤销。
255
+ - **提交后重新读回**,逐个比对坐标和角度。`update_items()` 没抛异常不等于板子已经变成计划的样子。
256
+ - `board.save()` 只在用户要求落盘时调用。
257
+ - 失败时给出可执行的诊断(编辑器没开 / API 服务没启用 / 沙盒不是 Full Access / 项目管理器占了 socket),而不是丢一个 traceback,更不是转去手改文件。
258
+
259
+ 注意 `orientation` 的 setter 会 `normalize180()`,270° 会存成 −90°:**几何等价,比较时要按最短路角度差**,不要按字符串比。
260
+
261
+ ## 质量门槛(硬性)
262
+
263
+ | 检查 | 门槛 |
264
+ | --- | --- |
265
+ | 完整性 | 板上每个器件都有位姿;计划里没有板上不存在的位号 |
266
+ | courtyard 重叠 | **0 对**(这是硬门槛,不是"尽量少") |
267
+ | courtyard 来源 | 非 `CrtYd` 的器件必须在报告里点名;`bbox_src` 为 `none` 的件**没有任何保护**,必须人工处理 |
268
+ | 最小间距 | 用户给的设计规则,或 ≥ 0.2 mm 兜底 |
269
+ | 出板 | 只有"本体本来就要伸出板外"的连接器允许;其它出板都是 bug |
270
+ | 分组 | 每个器件到本模块核心的距离中位数、最大值;报告有多少器件离别的模块核心更近 |
271
+ | 密度 | courtyard 总面积 / 真实板面积。> 75% 就属于密板,预期会出现溢出和挤占 |
272
+ | 出图 | `placement_view.svg` 已生成,且面板数字与 `verify_placement.txt` 一致 |
273
+ | 可读性 | 板文件能被 kicad-cli 正常解析(`pcb export svg` / `pcb render`) |
274
+ | 产物位置 | 本次所有产物都在 `placement/` 下;技能目录与 cwd **零新增文件** |
275
+
276
+ 密度这一条要**主动算给用户看**:板子放不下时,不要偷偷降低间距或把器件塞进不该塞的地方,而要说清楚"这是板面密度的硬约束",并给出选项。
277
+
278
+ ## 最要命的几个坑
279
+
280
+ - **不要整板重排已经手工调过的板子。** 先判断源布局有没有价值。
281
+ - **不要用 int() 截断网格索引。** `int(-0.3)` 是 0 不是 −1,会把板外一格当成板内,器件就会挂在板边外面。用 `math.floor()`。
282
+ - **板框要做半格腐蚀。** 单元格的**中心和四个角**都在板内才算可用,否则 courtyard 会压到板边外。
283
+ - **盖章和判空必须用同一套取整。** 一方用 `round` 一方用 `+0.5` 取整,膨胀后的矩形会溢进邻居的格子,把邻居的所有权改掉,随后在疏散修复里报 `KeyError`。
284
+ - **所有权 id 要回收。** 每 commit 一次就新分配一个 id,bytearray 存 255 个就溢出(`byte must be in range(0,256)`)。
285
+ - **模块顺序决定成败,要实测**。同一个算法换一下模块顺序,某个模块的位置中位数能从 43 mm 变成 156 mm。
286
+ - **courtyard 是唯一的重叠判据。** 没有 courtyard 的封装要用 Fab 层、焊盘或丝印推出来,并且**在报告里点名**——一个错误的 courtyard 会安静地毁掉整个布局。
287
+ - **2D 通过不等于机械通过。** 插座类器件(SIMM/DIMM)的倾斜体积必须显式登记为禁布区,并把"有没有器件落在里面"写进待确认清单。
288
+ - **别把"全固定"的模块当成空模块。** 安装孔、板边端子这类模块成员可以全是定位件,于是它的 `anchors` 是空表。按锚点算距离/离群时如果直接取 `anchors[k][0][0]`,会在这块板的第一个全固定模块上 `IndexError`。做距离统计前先筛掉没有锚点的模块。
289
+ - **产物别乱放。** 技能目录是只读代码区,cwd 是用户的。中途替换用的兜底脚本(几何、校验、出图)也该进 `placement/`,否则下一个人既找不到它们,也不敢删。
290
+ - **别用 `get_pcb_board` 做步骤 1 的"看一眼"。** 实测 63 器件的板子返回 **194 KB**,占整轮
291
+ 输入 token 的 ~89%,而那些焊盘细节步骤 1 一个都不用。用 `board_geometry.py --brief`(0.5 KB)。
292
+ 整板快照是**写入**路径的权威,不是量尺。
293
+ - **别假设板的网表是 `(net 12 "GND")` 格式。** 经导入器产生的板子写的是 `(net "GND")`,
294
+ 没有数字码。按下标 2 取网名会拿到空串,于是 111 条网络变成 0 条,**下游所有按连通性做的
295
+ 分组全部静默失效**——不报错,只是结论全错。统一走 `sexpr.net_name(pad)`。
296
+ - **别假设板框是四段 `gr_line`。** 整块板用一个 `gr_rect` 是合法且常见的写法。解析器只认
297
+ start/end 时会报"不闭合",那是在冤枉板子。`gr_poly` / `gr_circle` 同理。
298
+ - **器件值里的非 ASCII 字符能杀掉一整轮运行。** `100µF` 在 GBK/cp1252 控制台上让 `print()`
299
+ 抛 `UnicodeEncodeError`——脚本干完了活,却死在最后一行汇总上。`projpaths.make_console_safe()`
300
+ 会把 stdout/stderr 重配成 `utf-8/errors=replace`,报告文件仍是 UTF-8。
301
+ - **板框和器件坐标不自洽时,先怀疑板框。** "全部器件原点在板框外"通常不是布局问题,是板框
302
+ 被改小了而器件没跟着走。这是要停下来问用户的分叉点,不要自己猜着往小矩形里塞。
303
+ 改板框后,安装孔一类"在板外"的定位件坐标会一起失效,**必须连带重定位并写进报告**。
304
+ - **改板框走 IPC,不要手改 Edge.Cuts。** `BoardRectangle` + `create_items` 一个 commit 就能
305
+ 换掉整条板框,用户在 KiCad 里一次 Ctrl+Z 撤销。
306
+ - **位姿变换要用真实数据验,不要"看起来对"。** courtyard 局部框 + 原点 + 旋转能否复现 KiCad
307
+ 的世界坐标,是整个布局的地基:转错一个方向,所有间距数字全错却依然自洽。用一次
308
+ `get_pcb_board` 的焊盘坐标做交叉验证(247 个焊盘,误差应为 0.000000 mm),验一次,
309
+ 省掉后面所有返工。
310
+
311
+ ## scripts/ 索引
312
+
313
+ | 脚本 | 作用 |
314
+ | --- | --- |
315
+ | `board_geometry.py` | 只读提取 courtyard 占用矩形 + 板框多边形 → `geometry.json`;`--brief` 额外打印步骤 1 的完整判据(面积/密度/角度/在板内计数/警告) |
316
+ | `suggest_modules.py` | **步骤 2/4 的草稿器**:按网表连通性自动分块(电源与总线降权、电源专挂件归域、孤立件并回),给核心与按面积铺开的锚点,并断言真划分 → `placement_config.json` |
317
+ | `pack.py` | 核心摆放算法,读 config,输出 `placement_plan.json` |
318
+ | `verify_placement.py` | 独立校验(重叠/间距/出板/分组/面积),硬门槛不过就非零退出,报告落 `verify_placement.txt` |
319
+ | `placement_view.py` | **出图**:模块彩色视图 + 评估面板 → `placement_view.svg`(纯标准库) |
320
+ | `apply_via_ipc.py` | **首选**:整批一个 undo 步骤提交到打开的板子,日志落 `apply_via_ipc.txt` |
321
+ | `write_board_file.py` | 退回方案:离线写一个新板文件,源文件不动 |
322
+ | `pose_table.py` | 生成交接用位姿表 CSV |
323
+ | `projpaths.py` | `placement/` 输出目录解析 + 报告 Tee(报告一律 UTF-8)+ `make_console_safe()` 防终端编码炸掉整轮运行——所有脚本共用 |
324
+ | `sexpr.py` / `kipy_common.py` | s-expression 只读解析器(含 `net_name()` 双方言取网名)/ KiCad IPC 连接与事务助手 |
325
+ | `placement_config.example.json` | 完整可跑示例(KiCad video 示范板,189 器件) |
326
+
327
+ 所有脚本都接受 `--outdir`(换输出目录)与 `--out`(精确指定文件名);不给就落在 `<板目录>/placement/`。
328
+
329
+ 跑通示例:先生成草稿配置,再人工改写模块与定位件(技能目录只读,不要就地改
330
+ `placement_config.example.json`)。以下假定板子是 `C:\proj\video\video.kicad_pcb`,
331
+ 命令在任何 cwd 下都能跑;除 `--board` 外一次 `--out` 都不给,产物自动落进 `placement/`:
332
+
333
+ ```
334
+ python board_geometry.py --board C:\proj\video\video.kicad_pcb --brief
335
+ python suggest_modules.py --board C:\proj\video\video.kicad_pcb # 然后人工复核/改名/补 fixed
336
+ python pack.py --geometry C:\proj\video\placement\geometry.json --config C:\proj\video\placement\placement_config.json --board C:\proj\video\video.kicad_pcb
337
+ python verify_placement.py --geometry C:\proj\video\placement\geometry.json --plan C:\proj\video\placement\placement_plan.json
338
+ python placement_view.py --geometry C:\proj\video\placement\geometry.json --plan C:\proj\video\placement\placement_plan.json
339
+ python pose_table.py --geometry C:\proj\video\placement\geometry.json --plan C:\proj\video\placement\placement_plan.json
340
+ python apply_via_ipc.py --plan C:\proj\video\placement\placement_plan.json --dry-run
341
+ ```
342
+
343
+ 算法细节、坐标变换的推导和每个坑的复现过程见 [references/algorithm.md](references/algorithm.md)。
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "PCB 初始布局"
3
+ short_description: "为只有网表、零布局的 KiCad PCB 做 Phase-1 初始布局(功能分块、锚点定位、分区摆放、无重叠校验),优先经 KiCad IPC 应用到打开的板子"
4
+ default_prompt: "使用 $pcb-initial-placement,为当前板子完成 Phase-1 初始布局:功能分块、锚点与定位件、分区摆放、无重叠校验与出图,结果优先通过 KiCad IPC 应用为一步撤销;仅在 IPC 不可用且用户明确接受时离线生成新板文件。"