12 KiB
FreeCAD 3D 自动布线设计方案
本文档描述 QET / LightWork3D 与 FreeCAD 协同中的 3D 自动布线设计。
当前版本目标不是完整复刻 EPLAN Pro Panel 或 SOLIDWORKS Electrical,而是先完成一个可用的最小闭环:
工程端子
-> 路由路径网络
-> 自动求路
-> 生成 3D 折线导线
-> 可保存到 FreeCAD 文档
1. 设计边界
1.1 当前版本目标
当前版本只要求完成“能够自动布线”:
- 能识别 FreeCAD 文档中的工程端子。
- 能从用户指定的线槽、草图、面域创建路由网络。
- 能在两个端子之间自动生成 3D 折线导线。
- 能批量处理 QET 导入的导线任务。
- 能绕开或至少发现明显障碍碰撞。
- 默认禁止长距离悬空线。
1.2 当前版本不做
当前版本不做以下工程级能力:
- 不修改 FreeCAD C++ 源码。
- 不写入或依赖旧 3D 场景数据库表。
- 不把 3D 位姿、3D 路径点写入数据库。
- 不做完整线槽容量计算。
- 不做线径、弯曲半径、线束层叠排列。
- 不做强弱电隔离、EMC、屏蔽线等电气规则。
- 不保证达到 EPLAN / SOLIDWORKS Electrical 的完整工程级自动布线效果。
1.3 数据库约束
第一版严格遵守 docs/数据库设计.md:
- 设备绑定只依赖:
project_2d3d_symbol_binding:
project_uuid
element_uuid
instance_id
- 端子绑定只依赖:
project_2d3d_terminal_binding:
project_uuid
terminal_uuid
instance_id
- 3D 端子绑定唯一依据是:
terminal_uuid
- 3D 位姿、装配关系、布线几何以 FreeCAD 文档为准。
2. 总体方案
自动布线不直接在任意 3D 空间里找线,也不会把所有端子任意两两连接。它参考 EPLAN / SOLIDWORKS 的思路,先建立“可走路径网络”,再按 QET 导线任务中的起点端子和终点端子逐条求路。
端子出线段
-> 进入最近路由节点
-> 在线槽/路由路径网络中求最短路
-> 从路由网络出来
-> 进入目标端子
路由网络由 carrier 组成。一个 carrier 表示一段可走线中心线或辅助路由区域中的一条网格线。
2.1 路由优先级
当前版本按下面优先级处理:
WireDuct:线槽中心路径,最高优先级。RoutingPath:用户画的草图线、Draft Wire、明确选中的路由边。AuxiliaryPath:辅助路径,后续扩展使用。RoutingRange:选中面生成的辅助路由区域,成本较高,只用于过渡或没有线槽时兜底。
普通机柜、设备外壳、实体边默认不是路由路径。
3. FreeCAD 对象语义
3.1 工程端子
工程端子是可布线起点和终点,必须满足:
Role = "Terminal"
CanWire = true
QetTerminalUuid = <2D terminal_uuid>
QetInstanceId = <3D instance_id>
QetProjectUuid = <project_uuid>
端子空间位置来自 FreeCAD 文档。自动布线使用端子的全局坐标和方向。
3.2 路由路径 Carrier
路由路径对象使用以下语义属性:
QetRoutingRole = "RoutingCarrier"
QetRouteCarrierKind = "WireDuct" | "RoutingPath" | "AuxiliaryPath" | "RoutingRange"
CanRouteWire = true
QetProjectUuid = <project_uuid>
Points = [Vector, Vector, ...]
carrier 统一放在:
QETWiring
02_Carriers
3.3 自动导线
自动生成的导线放在:
QETWiring
04_Routed
自动导线语义:
RouteType = "AutoSuggested"
RouteMode = "Auto"
RouteStatus = "Routed" | "CollisionWarning"
QetStartTerminalUuid
QetEndTerminalUuid
QetAutoRouteAlgorithm
QetAutoRouteDiagnosticsJson
3.4 线槽实体
当用户选择线槽实体并执行“从线槽实体生成中心路径”后:
- 系统按包围盒长轴生成
WireDuct中心路径。 - 原线槽实体标记为可穿线路由源。
- 碰撞检测跳过该线槽实体本身,避免“线在槽内却撞到线槽外壳”的误报。
线槽实体属性:
QetRoutingSourceKind = "WireDuct"
QetRoutingObstacleMode = "PassThrough"
QetRouteCarrierName = <generated carrier name>
4. 算法设计
4.1 路由网络构建
模块:
src/Mod/FreeCADExchange/RoutingNetwork.py
构建步骤:
- 收集所有
QetRoutingRole = RoutingCarrier的对象。 - 读取 carrier 的
Points。 - 将相同或接近坐标的点合并为图节点。
- 将相邻点之间的线段建立为图边。
- 每条边记录所属 carrier,用于计算路径成本。
4.2 最短路算法
当前使用:
Dijkstra + bend_penalty
路径成本:
edge_cost = segment_length * carrier_kind_factor + bend_penalty
其中:
WireDuct = 1.0
RoutingPath = 1.0
AuxiliaryPath = 2.0
RoutingRange = 8.0
这使算法优先走线槽和明确路由路径,尽量少走辅助面域。
4.3 端子接入
模块:
src/Mod/FreeCADExchange/AutoRouting.py
流程:
- 读取起点端子和终点端子的全局坐标。
- 按端子方向生成短出线段。
- 找到距离起点出线点最近的路由节点。
- 找到距离终点出线点最近的路由节点。
- 在路由网络中执行 Dijkstra。
- 将端子出线段、网络路径、终点入线段拼成最终折线。
当前算法名:
network-dijkstra-v1
4.4 悬空线策略
当前版本默认:
allow_floating_fallback = false
也就是说,如果没有可用路由网络,系统不会生成长距离悬空线,而是提示用户先创建线槽路径、草图路径或辅助路由区域。
调试时可以显式启用 fallback,但正式使用不建议开启。
4.5 障碍物处理
当前版本使用 AABB 包围盒做碰撞诊断:
- 收集 FreeCAD 文档中的几何对象。
- 排除端子、carrier、已布线导线、原点辅助对象。
- 排除标记为
QetRoutingObstacleMode = PassThrough的线槽实体。 - 检查导线线段是否与障碍包围盒相交。
- 如果有碰撞,导线状态设为:
RouteStatus = "CollisionWarning"
当前版本是“碰撞诊断”,不是完整自由空间避障。
5. 当前已完成
5.1 Python 模块
已实现:
src/Mod/FreeCADExchange/RoutingNetwork.py
src/Mod/FreeCADExchange/AutoRouting.py
src/Mod/FreeCADExchange/AutoRoutingPanel.py
并已加入:
src/Mod/FreeCADExchange/CMakeLists.txt
src/Mod/FreeCADExchange/InitGui.py
5.2 路由网络功能
已完成:
- 从选中草图线、Draft Wire、明确选中的边创建
RoutingPath。 - 从选中线槽实体生成
WireDuct中心路径。 - 从选中面生成
RoutingRange辅助路由区域。 - 清除已生成路由路径。
- 扫描并统计路由网络。
5.3 自动布线功能
已完成:
- 两个选中端子之间自动布线。
- 根据导线任务批量自动布线。
- 使用 Dijkstra 求路。
- 支持转弯惩罚。
- 支持 carrier 类型成本。
- 默认禁止长距离悬空线。
- 碰撞检测和
CollisionWarning状态。 - 自动导线可见显示并保存到 FreeCAD 文档。
5.4 FreeCAD 面板
面板入口:
QET模板 -> 3D自动布线
当前按钮:
扫描端子/网络
从线槽实体生成中心路径
从线槽/草图创建路由路径
从选中面创建辅助路由区域
测试布线选中两个端子
按导线任务自动布线全部
清除自动布线
清除走线路径
保存
5.5 测试
已完成单元测试:
tests/python/freecad_exchange_auto_routing_test.py
覆盖:
- 无路由网络时默认拒绝悬空线。
- 显式调试 fallback 时生成正交路径。
- 优先使用用户路由网络。
- 优先使用
WireDuct,降低RoutingRange优先级。 - 从选中面生成辅助路由区域。
- 选中整个实体不会把所有外壳边转成路径。
- 从线槽实体生成中心路径。
- 线槽实体不作为自身路径碰撞障碍。
- 碰撞状态标记。
- 批量导线任务缺端子时跳过。
- 清除路由路径不删除已布线导线。
已完成 FreeCAD smoke:
tests/manual/freecad_auto_routing_smoke.py
6. 当前使用流程
6.1 单条导线自动布线
1. 打开 FreeCAD 工程 scene.FCStd
2. 进入 QET模板 -> 3D自动布线
3. 清除走线路径
4. 选中线槽实体
5. 点击“从线槽实体生成中心路径”
6. 必要时选草图线或 Draft Wire,点击“从线槽/草图创建路由路径”
7. 必要时选背板/门板面,点击“从选中面创建辅助路由区域”
8. 选中两个工程端子
9. 点击“测试布线选中两个端子”
6.2 批量导线自动布线
前提:
- QET 导出的
2d_to_3d.json中包含wires[]。 - 每条导线包含:
start_terminal_uuid
end_terminal_uuid
- FreeCAD 文档中存在对应
QetTerminalUuid的工程端子。
操作:
1. 创建线槽/路由网络
2. 点击“按导线任务自动布线全部”
注意:批量自动布线的依据是导线任务,不是“所有端子自动互连”。如果文档中只有端子而没有 wires[] 或 QETWiring_01_Tasks,系统不能判断哪些端子应该连接。
7. 当前限制
当前版本可完成自动布线原型,但仍有以下限制:
- 线槽实体中心线生成基于包围盒长轴,不理解真实线槽开口、盖板和内部空间。
- 多根线会沿同一路径生成,暂未做并行错位排列。
- 未计算线槽填充率和容量。
- 未考虑线径、最小弯曲半径。
- 未做强弱电分槽、线缆类型隔离。
- 障碍检测基于 AABB,存在误报和漏报。
- 辅助路由区域是网格近似,不等于专业软件的完整布线区域建模。
- 端子出线方向依赖端子 LCS 方向;如果模板端子方向不准,自动布线会受影响。
- 导线几何当前保存在 FreeCAD 文档,不作为第一版数据库字段回写。
8. 后续需要完成
8.1 近期优先级
- 线槽语义库
WireDuct:
centerline
width
height
inlet/outlet
usable_area
cover_state
- 多根线错位排列
同一路径上的多根导线按 lane_offset 排列
避免完全重叠
- 线槽容量和填充率
按线径估算截面积
计算 duct fill ratio
超过阈值给出警告
- 端子出线规则
根据端子 LCS 方向、设备安装面、接线孔方向生成更合理的短出线段
8.2 中期能力
- 真实几何碰撞检测
从 AABB 升级到更精确的 Shape / BRep 碰撞检测,降低误报。
- 弯曲半径约束
根据线缆类型和线径控制转弯半径。
- 线束对象
把多根同路导线抽象成 bundle,并支持展开显示。
- 规则约束
支持:
强电 / 弱电隔离
PE 线优先路径
屏蔽线规则
不同电压等级分槽
禁布区域
- 更智能的线槽识别
根据对象名称、尺寸比例、设备库语义自动识别线槽,而不完全依赖用户选择。
8.3 长期能力
- 接近 EPLAN / SOLIDWORKS 的工程级路由器。
- 完整导线长度统计。
- 自动生成线束报表。
- 2D / 3D 导线一致性校验。
- 自动推荐线槽路径和线槽容量。
- 多柜体、多门板、多安装板之间的跨区域路由。
- 可视化布线诊断面板。
9. 验收标准
当前版本验收只看“能否自动布线”:
- 文档中有至少两个工程端子。
- 文档中有至少一条
WireDuct或RoutingPathcarrier。 - 选择两个端子后执行单线测试布线,能生成
AutoSuggested导线。 - 存在导线任务时执行“按导线任务自动布线全部”,能批量生成
AutoSuggested导线。 - 生成导线在
QETWiring_04_Routed下可见。 - 没有路由网络时不生成长距离悬空线。
- 没有导线任务时,批量布线明确提示缺少连接关系。
- 明显碰撞时状态为
CollisionWarning。 - 保存 FreeCAD 文档后,自动导线和路由网络仍保留。
10. 开发验证命令
单元测试:
D:\FreeCAD-1.1.1\bin\python.exe -m unittest discover -s tests\python -p "freecad_exchange*_test.py"
真实 FreeCAD smoke:
D:\FreeCAD-1.1.1\bin\python.exe tests\manual\freecad_auto_routing_smoke.py
语法检查:
D:\FreeCAD-1.1.1\bin\python.exe -m py_compile src\Mod\FreeCADExchange\AutoRouting.py src\Mod\FreeCADExchange\RoutingNetwork.py src\Mod\FreeCADExchange\AutoRoutingPanel.py