本节摘要:SOURCE 4.1:装配用 mate 约束(重合、同轴、距离)定义自由度;大型装配需实例化与简化表示。
设计一台两级减速器:箱体、两根轴、四个齿轮、若干轴承与端盖,加起来约三十个零件。真正困难的不是画零件,而是决定每个零件怎么装:齿轮与轴是"同轴 + 轴向定位",轴承外圈与箱体孔是"同轴 + 端面贴合",端盖与箱体是"同轴 + 面贴合 + 四个螺栓孔对中"。
如果把装配理解成"把零件摆到正确位置",就会靠拖动、靠肉眼——低速且易错。正确的心智模型是:装配 = 用约束消除自由度。每个零件在空间有 6 个自由度(3 平移 + 3 旋转),每加一个约束就消除若干个,直到所有零件的自由度被约束图固定。
| Mate | 消除 DOF | 典型零件关系 |
|---|---|---|
| 重合 | 3 平移 | 贴合面 |
| 同轴 | 2 平移+2 旋转 | 轴孔配合 |
| 距离 | 1 平移 | 间隙控制 |
| 角度 | 1 旋转 | 铰链 |
一个贴合面约束(重合)消除 3 个平移自由度;一个同轴约束消除 2 平移 + 2 旋转;两者组合后,零件只剩 1 个旋转自由度——正是轴的转动自由。这就是运动机构的设计语言:想让它怎么动,就保留对应的自由度;想固定它,就消到 0。
# 自由度审计:检查装配是否"过约束"或"欠约束" def dof_audit(assembly): free = 6 * len(assembly.parts) # 初始自由度 for mate in assembly.mates: free -= mate.removed_dof() # 每个约束消除若干 if free < 0: return f"过约束 {abs(free)}:存在冗余约束,需检查矛盾" if free > 0: return f"欠约束 {free}:零件仍可移动,需补定位约束" return "完全定义:装配可复现、可驱动" print(dof_audit(reducer)) # 输出: 完全定义:装配可复现、可驱动
装配体用树状结构组织:顶级装配 → 子装配 → 零件。树结构带来两个关键能力:
标准件库(螺栓、轴承、密封圈)以"实例"方式插入:同一螺栓在树中出现 12 次,内存中只存一份几何 + 12 个实例引用(变换矩阵)。实例化是大装配不卡顿的基石。
自上而下 vs 自下而上:前者从布局骨架插入零件;后者先建零件再组合。汽车/飞机多用混合策略。
| 策略 | 流程 | 优势 | 风险 |
|---|---|---|---|
| 自下而上 | 先建零件→逐个装配 | 零件独立、便于复用 | 装配时才发现配合不上的问题 |
| 自上而下 | 先建布局骨架→设计零件 | 整体协调、间隙可控 | 零件间强耦合、改动波及大 |
| 混合 | 骨架 + 复用库 | 兼得两者 | 需要成熟的规范支撑 |
大飞机项目普遍采用"骨架模型 + 区域划分"的混合策略:先定义机身外形与站位(骨架),再在骨架约束下设计各个舱段与设备,最后把成品装配为全机。
干涉检查与公差堆叠依赖装配层级正确;一个错误 mate 可导致全树更新失败。装配完成后必须执行两类检查:
装配完成后的产品结构(PS)可以直接导出 BOM:零件号、数量、材料、供应商。BOM 的正确性完全依赖装配树正确——漏插一个螺栓,BOM 就少一行,采购就漏一件。这就是为什么大型企业把"装配模型"当作 BOM 的唯一权威来源。
装配约束不只为固定零件,也为了保留该动的自由度。铰链约束保留 1 个旋转自由度,滑动副保留 1 个平移自由度,球铰保留 3 个旋转自由度。运动仿真正是利用这些保留的自由度:
以四连杆机构为例:四个铰链各保留 1 个旋转自由度,整机自由度按格鲁布勒公式计算:
其中 n 是杆件数(含机架),J 是运动副数。四连杆 n=4, J=4,得 DOF = 1——恰好一个自由度,说明机构能确定地运动。DOF 计算是机构设计的第一性检查。
def gruebler(n_links, joints, joints_dof): # joints_dof: 每个运动副限制的自由度数(转动=2,移动=2,球铰=0限制平移3?此处简化为平面情况) dof = 3 * (n_links - 1) - sum(joints_dof) return dof # 四连杆:4 根杆,4 个转动副,每个转动副限制 2 个自由度 print("四连杆 DOF:", gruebler(4, 4, [2, 2, 2, 2])) # 输出 1
大装配里一个 M8 螺栓可能出现 500 次。如果每个螺栓都存一份完整几何,内存会立刻爆炸。实例化(Instantiation) 的解法是:
class Instance: def __init__(self, part_id, transform): self.part_id = part_id # 引用零件几何 self.transform = transform # 4x4 变换矩阵:位置+姿态 def world_geometry(self): # 需要几何时,从零件库取共享几何再施加变换 base = part_library.load(self.part_id) return base.apply(self.transform)
渲染时 GPU 通过"实例化绘制"一次提交共享几何 + 变换列表,又省显存又省 CPU。理解实例化,是理解"10⁵ 零件装配为何还能流畅旋转"的关键。
大型项目装配建模的质量,取决于三条规范:
| 规范 | 内容 | 防止的问题 |
|---|---|---|
| 基准统一 | 所有零件从世界原点起步 | 装配时零件散落远处 |
| 引用受控 | 跨零件引用只指已发布版本 | 幽灵依赖、莫名爆红 |
| 层次清晰 | 子装配边界合理、标准件独立 | BOM 混乱、更新爆炸 |
公差堆叠(Tolerance Stack-up)沿尺寸链计算装配间隙的极值。以"轴 + 垫片 + 端盖"的轴向尺寸链为例:
| 尺寸链项 | 名义值 | 公差 |
|---|---|---|
| 箱体孔深 | 40.00 | ±0.10 |
| 垫片厚度 | 2.00 | ±0.05 |
| 端盖台阶 | 36.00 | ±0.15 |
| 装配间隙 | 2.00 | ±0.30 |
最坏情况法(WC) 把公差简单相加,得间隙 1.70~2.30mm;统计法(RSS) 按平方和开方,得约 ±0.187mm。设计规范往往同时给出 WC 与 RSS 两种结果:关键安全件用 WC,一般件用 RSS 以放宽公差、降低成本。
⚠️ 常见坑: circular reference(零件 A 依赖 B,B 又依赖 A)使求解器无法收敛。
💡 关键直觉:装配 = 约束图 + 实例管理。