本节摘要:MuJoCo 对「非刚体」的支持哲学是「为动力学影响而简化」:流体用附加阻力项近似而非解流体方程,颗粒用大量小刚体加椭圆锥摩擦拼凑集体行为,柔体用离散自由度换形变能力。三条路线都到不了影视级保真,但都足够改变机器人的受力与交互结果——本节给出三档建模的决策依据、参数入口与验证方法,帮你在「够用的简化」与「错误的简单」之间划清界限。
第三章的引擎内幕掀开了主干道的机盖,本节开进特殊路况:水、沙、布。这些对象共同点是「形状不老实」,而 MuJoCo 的应对是统一的实用主义——只建模「对机器人动力学有影响的那部分行为」。
表面看是三种东西,在仿真视角下是同一个问题的三种答案:自由度爆炸怎么办。流体的真实现象由亿万分子的集体行为涌现,颗粒堆由无数接触耦合,布料由网状质点系统构成——全都超出刚体引擎的舒适区。MuJoCo 的做法不是硬解,而是问一个工程问题:「机器人感知到的部分是什么?」水下机械臂感受到的是阻力与浮力,不是分子热运动;推沙子的手臂感受到的是阻力突变与陷落,不是每颗沙粒的轨迹;抓布料的手指感受到的是柔顺回缩,不是纤维纠缠。把感受建模到位,把其余的物理省略——这是本节三条路线共同的灵魂,也是判断「MuJoCo 行不行」的尺子。
MuJoCo 内置的流体模型粒度是「每个物体一个阻力项」:给 geom 配上流体形状系数,引擎按相对速度计算线性与二次阻力,外加附加质量与粘性矩的简化项。配置在 geom 的 fluidshape 属性与若干系数里,语义是「这个物体在流体里运动时会受到这样的反作用」。
它能正确回答的问题:水下机器臂拖动时的阻力量级、球体在水中的下沉与摆动节奏、螺旋桨推力与阻力的平衡点。它不能回答的问题:涡激振动、空化、两物体间被扰动的流场耦合——任何「场」级别的水动力学效应都不在场。某水下抓取项目用内置阻力项做控制器预验证,抓取成功率趋势与水池实测一致;换到「水流冲击下的姿态保持」任务,仿真说稳、水池里翻——涡旋力不在模型里,仿真当然看不见。结论有条清晰的分界线:物体在静止流体里动,内置项够用;流体本身在动且形状复杂,另请专业流体求解器做联合仿真。
沙堆、豆子、碎料这类对象,MuJoCo 的路线是「不加新机制,用现有机制拼」:成百上千个小球刚体、椭圆锥摩擦、关掉不需要的碰撞对。没有专门的颗粒求解器,但刚体框架天然支持「大量小物体的密集接触」——3.2 的软约束求解就是为这种场景调的。
颗粒建模的成败手筋在摩擦与性能两处。摩擦侧:颗粒的「表观内摩擦」由球间摩擦系数与滚动行为共同涌现,椭圆锥摩擦(3.2 的主角)在这种场合对「休止角」的还原明显好于金字塔近似——某农业分拣项目里,同样的摩擦系数,椭圆锥堆出的料堆坡度与实测差不到两度,金字塔版本溜坡严重。性能侧:颗粒数的开销主要在接触对数量,工程惯例是三件套——控制颗粒半径别太细、用 contype 规则关掉「颗粒与颗粒之外」的无谓配对、必要时把远处颗粒「冻结」(冻结的自由度不进方程)。
一段生成颗粒场的惯例代码:
import mujoco import numpy as np model = mujoco.MjModel.from_xml_path("sandbox.xml") data = mujoco.MjData(model) # 找到颗粒组的 geom id 区间,统一设置摩擦与接触配对 grain_ids = [i for i in range(model.ngeom) if model.geom_group[i] == 3] for gid in grain_ids: model.geom_friction[gid] = np.array([0.9, 0.004, 0.002]) mujoco.mj_forward(model, data) print("初始接触对:", data.ncon) # 落地前应当很少 for i in range(2000): mujoco.mj_step(model, data) print("堆积后接触对:", data.ncon) # 观察接触规模是否在预算内
接触数就是颗粒场景的油表:起步几百、堆积后几千都在正常区间;一步冲到几万,先查碰撞配对规则再谈优化。
布料、绳缆、软体夹爪,MuJoCo 的方案是把柔性离散成自由度:物体拆成许多小刚体,之间用平等的「弹性连接」(equality 约束的柔化版或专用弹性件)拼起来。形变不是连续介质力学解出来的,而是这些离散件的集体行为——布的垂坠、绳的甩尾、软爪的包覆,都能呈现;应力分布、精确的材料本构,则不在表达范围。
这条路线的关键取舍是离散精度对自由度的平方级放大:柔性件数量翻倍,接触与约束的组合近乎平方增长。实操上有两条经验线:一是「柔性件数量按视觉与力学需求的最小值取」,一根绳十二段就够像,别上四十段;二是「给柔性件配 condim 一」,法向接触为主,切向摩擦交给关键部位,自由度预算立刻松一半。软体夹爪这类「柔体本身是研究对象」的任务,MuJoCo 版本适合做控制逻辑验证;要做材料级设计(硬度曲线、疲劳),数据不可信,请回有限元。

简化建模最大的风险不是「算不出」,而是「算出的看起来像那么回事」。三道关把侥幸筛掉:
关一:量级关。 阻力对不对,先看数量级——手持任何物体在水中横扫,阻力应当在几牛到几十牛的量级,仿真给出五百牛就是参数写错了。关二:形状关。 颗粒堆出休止角、绳垂出悬链线、布盖出褶皱轮廓,形状不对说明摩擦或离散参数失真。关三:极限关。 把速度、质量推到任务上限的百分之五十余量,行为仍平稳才算过关——只用「轻拿轻放」验证过的沙堆模型,机械臂真甩起来就会穿模。
三道关都不难,难的是养成习惯:凡用了本章的简化档位,就配一个对应的验证小实验。这套习惯在第五章会升值——Sim-to-Real 的成败,一半压在「简化模型到底简化了多少」的透明度上。
内置近似不够用时,轮到插件出场。下一节看引擎的扩展接口怎么在不破坏内核的前提下接进自定义力学。