11 KiB
FreeCAD 电气自动布线设计
Goal
在 FreeCAD 中实现面向电气柜的第一版自动布线闭环。目标不是复刻 EPLAN Pro Panel 或 SOLIDWORKS Electrical 的完整工程级能力,而是让 QET 导出的 2D 导线任务可以在 FreeCAD 3D 工程中自动生成可见、可保存、可诊断的 3D 折线导线。
第一版验收目标:
- QET 输出的
wires[]能作为批量自动布线任务输入。 - FreeCAD 工程端子只以
terminal_uuid作为 2D/3D 端子绑定依据。 - FreeCAD 文档负责 3D 位姿、装配关系、线槽位置和导线几何。
- 系统能自动准备线槽/安装面/端子接入组成的布线布局空间。
- 系统能按导线任务逐条求路并生成
AutoSuggested导线。 - 失败时给出可操作诊断,而不是静默失败或生成长距离悬空线。
Scope
本设计覆盖:
- FreeCAD 侧自动布线路由网络。
- QET
2d_to_3d.json中wires[]到 FreeCAD 导线任务的消费方式。 - 工程端子检查和
local:*模板端子提升为真实 QET 端子的规则。 - 线槽、支撑面、端子接入路径的对象语义。
- 批量自动布线算法、诊断、状态和验收。
本设计不覆盖:
- FreeCAD C++ 核心修改。
- 完整自由空间避障。
- 完整线槽容量、填充率、线径、弯曲半径计算。
- 强弱电隔离、EMC、屏蔽线、PE 优先等完整规则库。
- 3D 导线路径写入数据库。
- 旧 3D 场景数据库表参与第一版协同。
Design Inputs
成熟软件参考给出的共同模式是:自动布线不是在任意 3D 空间里搜索,而是在已知的电气布局空间内工作。用户先完成 3D 装配、设备端子识别、线槽/布线路径准备,再触发批量路由。系统根据连接关系找端点,根据路径网络找可走通道,根据诊断结果提示缺路径、缺端子或碰撞。
当前项目已有基础:
src/Mod/FreeCADExchange/WiringImport.py可从wires[]导入导线任务。src/Mod/FreeCADExchange/RoutingNetwork.py已有 carrier 路由网络、线槽识别、支撑面网格、端子接入 carrier。src/Mod/FreeCADExchange/AutoRouting.py已有 Dijkstra 求路、端子绑定、批量布线、碰撞诊断。src/Mod/FreeCADExchange/AutoRoutingPanel.py已有“生成布线网络路径 / 生成布线布局空间 / 自动布线”的面板入口。- QET
sources/FreeCAD/FreeCADExchangeExportService.cpp已能导出wire_id、start_terminal_uuid、end_terminal_uuid、端子显示号和导线标注。
Data Contract
QET To FreeCAD
QET 继续通过 <ProjectRoot>/.qet_freecad/2d_to_3d.json 输出项目快照。
自动布线需要 wires[] 至少包含:
{
"wire_id": "direction:<net_uuid>:<index>",
"net_uuid": "string",
"group_uuid": "string",
"wire_mark": "string",
"wire_mark_is_manual": false,
"wire_style_id": 0,
"start_element_uuid": "string",
"start_instance_id": "string",
"start_terminal_uuid": "string",
"start_terminal_display": "string",
"end_element_uuid": "string",
"end_instance_id": "string",
"end_terminal_uuid": "string",
"end_terminal_display": "string"
}
wire_id 表示一条逻辑导线任务,来源应是 QET 的 DirectionInfo。start_terminal_uuid 和 end_terminal_uuid 是 FreeCAD 自动布线寻找工程端子的唯一正式依据。start/end_element_uuid、start/end_instance_id 和端子显示号只用于在 FreeCAD 中绑定或诊断端子,不作为数据库绑定字段扩张。
FreeCAD To QET
第一版保存时仍只回写最小绑定结果:
project_uuidelement_uuidinstance_idterminal_uuid
自动布线路径、线槽 carrier、导线点位、碰撞状态和装配状态保存在 scene.FCStd 中,不写入数据库绑定表。
FreeCAD Object Model
FreeCAD 文档中统一使用 QETWiring 分组:
QETWiring
QETWiring_01_Tasks
QETWiring_02_Carriers
QETWiring_03_Previews
QETWiring_04_Routed
QETWiring_05_Diagnostics
工程端子必须满足:
Role = "Terminal"
CanWire = true
QetProjectUuid = <project_uuid>
QetElementUuid = <element_uuid>
QetTerminalUuid = <terminal_uuid>
QetInstanceId = <instance_id>
路由 carrier 必须满足:
QetRoutingRole = "RoutingCarrier"
QetRouteCarrierKind = "WireDuct" | "TerminalAccess" | "RoutingRange" | "AuxiliaryPath"
CanRouteWire = true
QetProjectUuid = <project_uuid>
Points = [Vector, Vector, ...]
自动导线必须满足:
RouteType = "AutoSuggested"
RouteMode = "Auto"
RouteStatus = "Routed" | "CollisionWarning" | "Failed"
QetWireUuid = <wire_id>
QetStartTerminalUuid = <terminal_uuid>
QetEndTerminalUuid = <terminal_uuid>
QetAutoRouteAlgorithm = "network-dijkstra-v1"
QetAutoRouteDiagnosticsJson = <json>
Routing Layout Space
第一版正式入口是“准备布线布局空间”,而不是让用户手工给每条导线画辅助线。
布局空间由三类 carrier 组成:
WireDuct:线槽中心线,成本最低,优先使用。TerminalAccess:端子出线点到最近路由网络节点的短接入路径。RoutingRange:安装板、背板、门板等支撑面上的低优先级网格路径。
线槽识别规则:
- 优先读取对象语义。
- 其次按名称或标签识别
线槽、走线槽、wire duct、cable duct、trunking等关键词。 - 几何上必须呈明显细长比例。
- 机柜、门板、安装板、设备外壳不能被误判为线槽。
支撑面识别规则:
- 只接受具有安装板、背板、门板、panel、mounting plate 等语义的薄板对象。
- 支撑面生成
RoutingRange网格。 - 支撑面成本高于线槽,只作为过渡或兜底。
端子接入规则:
- 从端子 LCS 全局位置读取端子原点。
- 按端子方向生成短出线点。
- 找最近路由网络节点。
- 距离超过阈值则不生成接入,记录诊断。
- 接入路径使用正交折线,类型为
TerminalAccess。
Routing Algorithm
第一版使用图搜索:
carriers -> graph nodes/edges -> Dijkstra + bend_penalty
构图规则:
- 收集全部启用的 route carrier。
- 读取 carrier 的
Points。 - 将相同或接近坐标合并为节点。
- 识别轴向线段交点和重叠点,把线段切成可换向边。
- 边记录所属 carrier 和类型成本。
成本规则:
WireDuct 1.0
RoutingPath 1.0
TerminalAccess 2.0
AuxiliaryPath 2.0
RoutingRange 8.0
总成本:
edge_cost = segment_length * carrier_kind_factor + bend_penalty
避障规则:
- 收集障碍物 AABB。
- 排除工程端子、carrier、已布线导线、原点辅助对象。
- 排除
QetRoutingObstacleMode = "PassThrough"的线槽。 - 先从路由图中移除穿过障碍包围盒的边。
- 若仍能连通,生成安全路径。
- 若无法连通,退回原图求路,并把最终导线标记为
CollisionWarning。
默认禁止:
allow_floating_fallback = false
没有可用路由网络时不能生成长距离悬空线。
User Workflow
正式面板流程:
1. 打开 scene.FCStd
2. 进入 QET模板 -> 3D自动布线
3. 点击 生成布线网络路径
4. 点击 生成布线布局空间
5. 点击 自动布线
6. 查看状态和诊断
7. 保存 FreeCAD 文档
也允许简化为:
1. 打开 scene.FCStd
2. 点击 自动布线
此时系统自动执行:
识别线槽
识别支撑面
生成端子接入
检查/绑定工程端子
按导线任务批量求路
如果线槽无法自动识别,用户可选中线槽实体后执行“生成布线网络路径”补充中心线。
Diagnostics
诊断是第一版的核心能力。每次批量布线报告至少包含:
- 总导线任务数。
- 成功布线数量。
- 碰撞警告数量。
- 缺失端子数量。
- 自动绑定端子数量。
- 自动创建端子数量。
- 缺失端子样例。
- 路由网络 carrier、线段、节点数量。
- 首个可操作错误提示。
必须明确区分这些失败:
- 没有
wires[]或QETWiring_01_Tasks。 - 导线任务引用的
terminal_uuid在 FreeCAD 中不存在。 - 模板端子仍是
local:*,但无法按设备和端子显示号绑定。 - 端子离路由网络太远。
- 文档里没有可用
WireDuct或RoutingRange。 - 有路由网络但起点和终点不连通。
- 生成路径与障碍物碰撞。
错误信息应直接显示在 FreeCAD 面板状态中,同时写入 QetAutoRouteDiagnosticsJson 或诊断分组,方便复盘。
Phased Delivery
Phase 1: Routing Network Closure
目标:让单柜体样例稳定完成批量自动布线。
交付:
- 线槽中心线自动识别。
- 支撑面低优先级网格。
- 端子接入 carrier。
- Dijkstra 路由。
- AABB 诊断。
- 批量报告。
Phase 2: Electrical Practicality
目标:让布线结果更像电气柜实际布线。
交付:
- 同一路径多根导线 lane offset。
- 导线长度统计。
- 线槽基础容量估算和超限警告。
- 线缆颜色/线号显示。
- 手动调整自动路径后锁定。
Phase 3: Rule-Aware Routing
目标:支持基础电气规则,但仍保持轻量。
交付:
- 强弱电路径偏好。
- PE 线路径偏好。
- 禁布区域。
- 设备类型出线方向规则。
- 更精确的 BRep 碰撞检查。
Testing
单元测试覆盖:
- 无路由网络时拒绝正式自动布线。
- 线槽优先于支撑面。
- 端子接入 carrier 自动生成。
- 相交线槽可换向。
- 障碍边被过滤。
- 无替代路径时标记
CollisionWarning。 wires[]缺端子时跳过并报告。local:*端子可按任务提升为真实 QET 端子。- 清除路由路径不删除已布线导线。
- 保存后 carrier 和导线仍在 FreeCAD 文档中。
手工 smoke 覆盖:
- 单柜体、两层 DIN 导轨、横向线槽、安装板。
- QET 导出至少 10 条导线任务。
- 点击“自动布线”后可生成多条
AutoSuggested导线。 - 关闭并重新打开
scene.FCStd后导线仍存在。 - 故意删除一个端子后,报告缺失端子而不是崩溃。
Acceptance Criteria
第一版完成的判断标准:
- FreeCAD 文档中有真实工程端子和 QET 导线任务。
- 自动布线能准备
WireDuct、RoutingRange、TerminalAccess网络。 - 批量自动布线能为可连通任务生成
AutoSuggested导线。 - 没有路径时不生成悬空长线。
- 缺端子、缺任务、缺路径、碰撞都有中文诊断。
- 生成结果保存在
scene.FCStd,不写入旧 3D 数据库表。 - 第一版数据库绑定仍只依赖
project_uuid / element_uuid / terminal_uuid / instance_id。
Deferred Defaults
为避免第一版范围漂移,下面三项采用明确默认值,后续阶段再扩展:
- 第一版读取
wire_style_id仅用于诊断和后续扩展,不强制映射 FreeCAD 导线颜色和线宽。 - 第一版只在 FreeCAD 中保存和显示自动布线长度,不导出正式长度报表。
- 第一版不提供
AutoSuggested转锁定确认导线的完整工作流;用户需要固定路径时,先使用已有手动布线能力重新创建正式手动导线。