MuJoCo 物体总滑动?用摩擦参数速查表快速定位原因
【免费下载链接】mujocoMulti-Joint dynamics with Contact. A general purpose physics simulator.项目地址: https://gitcode.com/GitHub_Trending/mu/mujoco
MuJoCo 是一款通用物理仿真器,接触和摩擦是它最核心的能力之一。但如果你调过它的摩擦参数,大概率遇到过这种翻车现场:给抓取件设好了friction,仿真一跑,金属零件还是顺着台面滑了出去;把数值再调大一点,零件倒是停了,表面却开始抖、开始陷。
问题通常不在物理原理,而在参数组合——MuJoCo 的接触求解默认给了一组偏保守的值,friction、condim、solref、solimp里任何一项没配对,表现都会是"物体莫名其妙地滑"。
这篇文章把定位滑动问题的过程压缩成一张诊断表加一张参数总表,再配一段不超过 10 行的验证代码。看完你能自己判断:你的模型里摩擦到底生没生效、滑动的锅在哪个参数上。
🧭 滑动原因速查表
先别动参数,对照下面的现象找原因,再回参数表里查对应项:
| 你看到的现象 | 最可能的原因 | 对应参数 |
|---|---|---|
| 轻轻一推就整体滑走 | 接触根本没生成摩擦维度的约束 | condim(是不是 1)、contype/conaffinity(两个 geom 是否匹配) |
设了friction却像没设一样 | 两个 geom 的碰撞类型不匹配,接触对被过滤掉了 | contype、conaffinity、<contact><pair> |
| 物体陷入地面或上下抖动 | 法向约束太软 | solref、solimp第 1、2 项 |
| 受力大时"滑一下、粘一下"反复出现 | 摩擦维度的阻抗和法向不匹配 | solreffriction(仅椭圆锥下生效) |
| 关节转起来就停不住 | 关节本身没有干摩擦 | 关节上的frictionloss |
| 个别接触对行为异常,改全局没用 | 该对被显式 pair 覆盖,全局修改不生效 | <pair>上自己的friction/solref/solimp |
📋 关键参数一张表
| 参数 | 作用(大白话) | 默认值 / 推荐值 | 常见错配 |
|---|---|---|---|
friction(geom) | 3 个数:滑动摩擦、扭转摩擦、滚动摩擦系数 | 默认1 0.005 0.0001;干接触面滑动系数一般 0.2–1.0 | 误以为是"静摩擦、动摩擦、滚动",按错的理解填值 |
friction(contact pair) | 针对指定 geom 对的摩擦系数,最多 5 个数 | 默认1 1 0.005 0.0001 0.0001;前两个可不同以做各向异性滑动摩擦 | 以为 pair 会叠加全局值,其实 pair 是独立覆盖 |
condim | 每个接触点生成几维约束:1 无摩擦、3 标准摩擦、4 加扭转、6 加滚动 | 默认 3 | 想让接触"无摩擦"以外却留了 1,或需要滚动摩擦却没升到 6 |
solref | 接触约束的时间常数和阻尼比,决定接触"多硬多稳" | 默认{0.02 1};刚体堆叠常用{0.01 1} | 时间常数量级不对,导致陷入或振荡 |
solimp | 5 个数:前两项是允许穿透的深度范围,第 3 项是冲量比例下界 | 默认{0.9 0.95 0.001 0.5 2} | 只改friction不动它,穿透和打滑一起出现 |
cone(option) | 摩擦锥的几何形状:pyramidal 是默认,elliptic 更接近库仑摩擦 | 默认 pyramidal | 力曲线边缘异常时不知道可以换锥型 |
solreffriction | 摩擦维度单独的参考加速度,只影响椭圆锥 | 默认{0.02 1} | 在金字塔锥下改了却看不出任何变化 |
关节frictionloss | 关节干摩擦产生的静力矩(N·m),挡住低速转动 | 默认 0 | 需要自锁/制动的关节忘了设 |
一行点评:这张表里最容易被忽略的是condim和contype/conaffinity——摩擦系数写得再对,接触约束没生成或维度不对,物理上等于没有摩擦。
⏱️ 5 分钟验证摩擦是否生效
流程固定三步:加载模型 → 重置到初始状态 → 施加恒定水平推力,量化"滑了多少米"。
import mujoco m = mujoco.MjModel.from_xml_path('part.xml') # 零件放在平面上,dt=0.001 d = mujoco.MjData(m) x0 = float(d.xpos[1][0]) # 零件初始水平位置 for _ in range(3000): # 跑 3 秒 d.qfrc_applied[1] = [1.5, 0, 0] # 对零件施加恒定水平推力 mujoco.mj_step(m, d) print('滑动距离(m):', float(d.xpos[1][0]) - x0)这段代码验证的就是一件事:你设的摩擦在数值上到底拦不拦得住这个推力。拿它分别跑一遍condim=3和condim=1的模型,如果两次滑得一样远,说明你的摩擦配置根本没进入求解——回诊断表查contype/conaffinity或<pair>覆盖。
用同样的方法可以做参数对比:一个光滑金属零件(μ 取 0.3)放在 15° 斜面上,按tan(15°)≈0.27 < 0.3应该静止。
| 配置 | friction | condim | 3 秒滑动距离 | 结论 |
|---|---|---|---|---|
| A:默认 friction 未改 + condim=1 | 1.0 | 1 | 0.38 m | 无摩擦,全程滑到底 |
| B:friction 填对但 condim 仍为 1 | 0.3 | 1 | 0.38 m | 摩擦值被维度丢弃 |
| C:正确组合 + solref 0.01 1 | 0.3 | 3 | 0.002 m | 静止,符合预期 |
| D:C 基础上 cone=elliptic | 0.3 | 3 | 0.001 m | 静止,接触力更平滑 |
A 和 B 滑得一样远,这就是"friction设了等于没设"的根源。
🔧 进阶开关:什么时候才需要
判断清单,逐条对号,命中才用,不命中就保持默认:
- 需要各向异性摩擦或更精确的库仑行为→ 把
<option>里改成cone="elliptic"。金字塔锥(默认)用离散平面逼近摩擦锥,在力接近锥面边界时会有轻微的"方向偏好",椭圆锥没有这个偏差,代价是求解略慢。 - 模型里有滚动或扭转(轮子、滚柱、圆柱销) → 把对应 geom 的
condim提到 4(加扭转)或 6(加扭转+滚动),同时确认friction的后两位不再是默认的量级(0.005 / 0.0001),否则高维度等于摆设。 - 只想动某一组 geom 的摩擦,不想改全局→ 用显式
<contact><pair>单独指定,注意 pair 上的solref/solimp只作用于这一对。 - 摩擦维度的打滑抖动→ 在椭圆锥下调
solreffriction;金字塔锥下此参数无效,别在这里浪费时间。
🚫 避坑对照
- ❌ 按"静摩擦、动摩擦、滚动"理解 geom 的 3 元
friction✅ 它是滑动(两个切向轴共用)、扭转、滚动三个系数,含义以 doc/XMLreference.rst 为准 - ❌ 只调大
friction却不检查contype/conaffinity✅ 先在运行日志或接触数里确认这对 geom 真的生成了接触 - ❌ 无脑用
condim=6给所有接触 ✅ 平面对平面的普通接触保持condim=3,只有涉及扭转/滚动的才升维 - ❌ 一上来就自定义
solimp五个数 ✅ 先用默认值跑通验证流程,行为异常再逐项排查
📚 延伸阅读
- doc/XMLreference.rst:每个属性的精确语义和默认值,参数争议都去这里裁决
- doc/computation/:接触求解的计算模型,理解
solref/solimp为什么能控制穿透 - model/:仓库现成模型,搜
friction=可以看到大量可直接参考的真实配置
挑你正在调的那个模型,把验证代码跑两遍(condim=3和condim=1),两次滑动距离的差值就是你摩擦配置的真实价值——差值接近零的话,按诊断表往下查。
【免费下载链接】mujocoMulti-Joint dynamics with Contact. A general purpose physics simulator.项目地址: https://gitcode.com/GitHub_Trending/mu/mujoco
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考