CATIA 装配二次开发:实例、引用与可追溯 BOM,怎样避免数量翻倍


一个装配里有两个相同支架组件,每个组件装三颗螺钉。脚本遍历一次就输出三颗,是少算;先展开六个螺钉实例,再乘组件数量二得到十二颗,是多算。两种程序都可能在小样件上“运行正常”,直到采购数量对不上才暴露问题。

BOM 工具最重要的部分是数据模型。本文讨论 CATIA V5 装配数据采集与独立聚合逻辑,示例中的数据为人工构造,不是对用户模型的实测结果。

一、先决定你需要哪一种物料表

层级 BOM 保留父子关系,例如总装下有两个支架组件;展开 BOM 则把采购叶子聚合成总数量。制造 BOM 还可能把虚拟组件展开、将装配工艺件另行处理。导出前必须确定规则,否则一个“数量”字段会同时承担多种含义。

CATIA 的 Product 模型区分引用产品与它在树中的组件实例;某些属性只适用于其中一种对象。因此,不能把树节点名称直接当作唯一零件身份。Product 对象说明

至少分开保存下面四层标识:

标识 解决的问题 不适合作为什么
本次导出中的实例路径 这颗螺钉出现在哪里 跨修订永久主键
CAD 引用标识 哪些实例共享设计定义 企业料号的唯一替代
料号与修订 业务上是否允许合并 唯一的几何状态判断
配置或有效性条件 本次交付采用哪个状态 可以随意忽略的备注

例如 Wheel.1 与 Wheel.2 可引用同一零件定义,实例名称不同并不意味着不同物料;反过来,两份不同文档可能错误地拥有同一料号,盲目合并会掩盖数据冲突。聚合键应来自明确的业务契约,而不是“选一个最像 ID 的字符串”。

二、展开数量和引用缓存要分开

有两种正确的数量计算方法。第一种直接遍历实例树,每遇到一个应计入的叶子就加一;第二种遍历引用结构,在边上保存局部数量,根到叶的数量取路径上的乘积,再对等价叶子求和。二者可以得到相同结果,但数据结构不能混用。

对于两组支架,每组三颗螺钉,实例树会出现六个叶子;引用结构只有一个支架定义和一个螺钉定义,边权分别为二与三。若导出的输入已经包含六个叶子,就不应再次乘二。

“已经访问过这个引用,所以不再遍历”的全局 visited 集合也很危险。它适合缓存零件属性,避免同一份文档读取六次,却不适合跳过实例计数。可以建立两套结构:referenceCache 用来复用设计属性;occurrenceRows 用来保留每一个出现位置。需要检测意外循环时,用当前递归路径的祖先引用集合,而不是把所有曾出现的引用永久排除。

Products 集合提供子产品访问,但索引与包装层行为要对照本机 Automation 帮助。采集层不应把某个动态 COM 对象直接塞进后续并行计算队列;先读取成普通字符串、数字和状态,再交给无 COM 依赖的聚合器。Products 集合接口

三、先定义叶子,再计算数量

没有子节点不一定代表已完整加载的采购零件。它还可能是缺失引用、未加载的表示、被配置排除的组件,或按业务规则需要展开的虚拟总成。建议把“能否解析”“是否计入”“节点种类”存成独立字段。

本例采用严格规则:只有解析成功、明确属于采购叶子且未排除的实例进入正式数量;解析失败使报告进入“不完整”状态,不能静默当作数量零。被排除实例要另列表明原因,便于工程人员核对本次配置。

这些规则应由采集适配层判断并传给聚合层。不要在聚合器中猜测:文件扩展名是 CATPart 就一定采购,或者节点名字含有 Screw 就一定螺钉。外购件、焊接组件、虚拟装配可能有完全不同的管理方式。

四、把聚合核心写成可单独验证的纯逻辑

下面的 Python 3 示例不访问 CATIA。输入约定是“已经展开的实例叶子”,因此每行贡献一个数量。reference 与 revision 的组合只作为本例聚合键,实际项目可以改成企业料号、修订和配置的组合。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from collections import Counter

def aggregate(rows):
seen_occurrences = set()
counts = Counter()
trace = {}
for row in rows:
occurrence = row["occurrence"]
if occurrence in seen_occurrences:
raise ValueError(f"重复实例路径: {occurrence}")
seen_occurrences.add(occurrence)
if not row["resolved"]:
raise ValueError(f"引用未解析: {occurrence}")
if row["excluded"]:
continue
if row["kind"] != "purchased_leaf":
raise ValueError("本聚合器只接受已经展开的采购叶子")
key = (row["reference"], row["revision"])
counts[key] += 1
trace.setdefault(key, []).append(occurrence)
return counts, trace

真实工具还应区分“结构采集失败”与“物料属性缺失”,并支持一次汇总所有错误,而不是永远只看到第一项。这里抛异常是为了让最小示例拒绝不可靠结果,不代表生产工具必须在 UI 上立刻中断整个报告。

trace 很重要:当螺钉数量从六变七时,用户需要知道多出来的是哪个实例。只有汇总表而没有来源路径,就很难区分设计修改、重复导出和聚合算法错误。

五、装配变换和物料数量不要绑在一起

若进一步输出安装坐标,需要明确每个实例的局部变换与根坐标之间的关系。采用列向量约定时,根到叶的变换可写成 T_root_leaf=T_root_parent×T_parent_leaf。交换乘法顺序通常会产生错误结果;必须先约定矩阵排列、左右乘与长度单位,不能直接照搬另一套 CAD 库的数据排列。

但即使两个实例的位置重合,也不能凭坐标相同就去重:它们可能是建模错误,也可能是不同配置或不同业务对象。数量统计基于结构与计入规则,空间重叠属于另外一项几何质量检查。把这两种检查混成一个“自动清理”,会悄悄改变设计数据。

六、用六组小装配验证规则,而不是只跑大模型

第一组只有一个零件,确认根节点本身与子节点边界。第二组同一零件出现三次,预期数量三、引用缓存读取一次。第三组两个相同子装配各含三颗螺钉,预期六。第四组同料号不同修订,确认是否分行。第五组引入一个缺失链接,报告应标为不完整。第六组排除一个配置实例,确认数量和排除清单同步变化。

再加一次顺序不变性测试:打乱输入行次序后,聚合数量不应变化;追溯列表排序可以变化,正式导出时统一排序即可。若重复导入同一实例行,程序应报告重复,不能默默把数量加倍。

导出文件还应包含模型版本、配置标识、采集时间、过滤规则版本和错误清单。“数量一致”只能说明当前规则下结果一致;如果规则从采购叶子改为全部 CATPart,必须生成新的规则版本,不能把两次报告当作同口径直接比较。

七、COM 连接只是适配层的一部分

Windows COM 互操作有自己的生命周期和线程边界。把所有异常都转成“空子节点”,会让断开的会话看起来像一个没有零件的装配。采集失败应保持为失败,不要伪装成有效业务数据。Microsoft COM 互操作概述

本文没有给出通吃所有 CATIA 安装的会话连接器,也没有声称在真实装配中完成验证。上线时先用本机帮助核对引用属性、加载模式和集合遍历,再把得到的数据送进这类可独立测试的聚合核心。这样,版本差异被限制在适配层,数量规则则可以持续维护。

参考资料


 上一篇
LightTools 二次开发:把参数扫描做成可恢复、可追踪的仿真任务 LightTools 二次开发:把参数扫描做成可恢复、可追踪的仿真任务
批量仿真的难点不只是循环修改参数。本文从会话绑定、数据键失效、仿真完成判据、任务身份和失败恢复出发,设计一个隔离版本差异的 LightTools 自动化执行框架。
下一篇 
CATIA V5 参数驱动开发:把单位、依赖更新与失败隔离做成契约 CATIA V5 参数驱动开发:把单位、依赖更新与失败隔离做成契约
从一组带孔板参数出发,拆解 CATIA V5 自动建模中的单位转换、输入契约、更新依赖与失败隔离。通过参数敏感性算例和 C# 核心片段,建立可以审计的批量生成流程。
  目录