3.2 接触动力学与约束求解


3.2 接触动力学与约束求解

本节摘要:接触是动力学里最不讲道理的部分——不光滑、多点耦合、力有单边性。MuJoCo 的解法是把接触写成带约束的优化问题:允许微小穿透,让接触力成为穿透深度与速度的光滑函数,用 solref 与 solimp 两组参数控制这层「软垫」的软硬与厚薄;摩擦用椭圆摩擦锥逼近库仑定律,condim 决定接触维度。理解这套软约束模型,接触参数从「玄学」变成「有物理含义的旋钮」,第六章的排错口诀全部有据可循。

上一节把运动方程支好了架子,唯独约束力一项挂着「待定」。全册最重要的一节就是现在:机器人与世界的交互几乎全走接触,接触力算得正不正,直接决定仿真可不可信。

一个抓不稳的杯子

先看现象再看原理。某项目用二指夹爪抓硬质水杯,仿真里杯子时不时「跳」一下就滑落,加大夹持力也没用;换成软一点的夹爪垫,反而抓得死死的。现象很反直觉——硬碰硬应该抓得最牢才对。

拆开看,杯子跳动是接触力高频振荡:硬碰硬时接触刚度极高,夹爪闭合的瞬间穿透量剧烈波动,法向力跟着剧烈波动,杯子被自己「弹」起来;等效摩擦力上限正比于法向力,于是摩擦也在波动,波动过零时杯子打滑。软夹爪垫压平了接触力的波动,摩擦上限稳定在高位,自然抓得稳。这个现象在真实世界同样存在——工程师给夹爪加橡胶垫不是为了温柔,是为了把接触动力学变「乖」。

MuJoCo 从模型层面就把这层「垫」内建了:它不追求绝对不穿透,而是让接触力随穿透深度平滑变化。要理解并调好它,得把软约束模型拆开看。

一、软约束:允许穿透,换取光滑

硬碰撞的立场是「穿透即违法」,发现相交立刻以冲量修正。数值上这等于要求力在碰撞瞬间从零跳到无穷大——数学上不可导,物理上不存在,工程上表现为高频抖动和不可复现。MuJoCo 换了个立场:把接触想象成一层薄薄的弹簧阻尼垫,穿透越深、接近速度越快,垫子的支撑力越大。力是状态的连续函数,可导、可积、可微,方程世界里它就是个守规矩的公民。

「软垫」的两个物理量——刚度与阻尼——被包装成两个面向用户的参数组,这就是所有接触排错绕不开的 solref 与 solimp。先记住各自的管辖范围:

参数组 管什么 直觉理解
solref 两参数 软垫的时间常数与阻尼比 多快把穿透弹回去、回弹时震不震
solimp 五参数 软垫的厚度剖面与刚度上下限 穿透多深开始「顶死」,刚度沿深度怎么爬坡
impratio 比值 摩擦锥相对法向的软硬比 摩擦「垫」比法向「垫」硬多少倍
condim 维数 该接触算几个方向的力 只算法向、还是带滑动摩擦、再加滚转扭矩

solref 默认值取「时间常数零点零二秒、阻尼比一」——含义是接触扰动约在二十毫秒内被平滑压回,且不过冲。这个默认值藏着一条通则:软垫的时间常数不应小于仿真步长。步长两毫秒的模型把 solref 时间常数设到一毫秒,等于要求引擎用两毫秒的刀工切一毫米的肉,数值上必然抖。第六章排接触抖动,第一刀就砍这里。

solimp 的五个数字初看吓人,日常只需要理解中间逻辑:它定义「刚度随穿透深度从 dmin 爬到 dmax、由低刚度爬向高刚度」的剖面。浅穿透时软、深穿透时硬,物体能微微陷入表面但绝不会被真的穿过去——这正是「看起来硬、算起来软」的实现方式。绝大多数场景用默认剖面就够,需要改的时机只有一个:软地面(沙地、垫子)把 dmax 调大,让可见形变合法化。

图 3-2 软接触模型:穿透、力与参数的对应关系

图 3-2 软接触模型:穿透、力与参数的对应关系

二、摩擦锥与接触维度:切向力怎么封顶

法向力管「压多紧」,摩擦管「滑不滑」。库仑定律说切向力不能超过摩擦系数乘法向力——把这条界限画在切平面坐标系里是一个圆锥。数值求解偏爱线性与二次约束,于是有了两条近似路线:金字塔近似把锥切成四棱锥,线性好解,但对角方向的真实摩擦上限被高估四成多,斜拖物体时「莫名打滑」;MuJoCo 默认走椭圆路线,二次锥任意方向的偏差在百分之几量级,代价是求解器要用非线性或精化技巧。实践结论:抓取、摩擦驱动这类对切向力敏感的任务,默认椭圆锥,别图省事换金字塔。

condim 决定每个接触算几个方向的力,它是被低估的性能与保真开关:condim 一只算法向,够滚球、够粒子;condim 三加两个切向滑动摩擦,是地面与抓取的常规配置;condim 四与六再加滚转与扭转摩擦,滑动的瓶子、拧动的螺丝才需要。把全场接触统一开到六是最常见的「性能自杀」——接触约束数直接决定 3.2 求解器的迭代开销,按需给不同 geom 配不同 condim,是第六章性能优化的保留节目。

三、求解器:把约束方程解出来

所有约束(接触、限位、等式、摩擦)最终汇成一个凸优化问题:在「约束力不违反单边性与摩擦锥」的前提下,最小化约束违反与力的某种加权组合。凸性是个金子招牌——局部最优即全局最优,解不挑初值,相邻两步的解高度连续,引擎用上一步的解热启动,几次迭代就能收敛。

用户侧的三个旋钮在 option 里:solver 选算法(Newton 精而快、PGS 稳而糙),iterations 是迭代预算,tolerance 是收敛阈值。诊断求解器健康有一组现成指标——每步结束后查看约束求解的残差与迭代数,残差迟迟压不到 tolerance,说明约束集病态:典型病因是 solref 与步长失配、condim 全场拉满、或者 equality 约束互相打架。看一段诊断代码:

mujoco.mj_step(model, data) print("本步接触数:", data.ncon) # 接触对数量 print("约束行数 nefc:", data.nefc) # 进求解器的约束总数 print("求解器迭代:", data.solver_niter[0]) # 实际迭代次数 print("对偶残差 gap:", data.solver_fwdinv[0]) # 收敛质量参考

这四个数字是接触仿真的「体检单」:接触数与约束行数解释了「为什么慢」,迭代数与残差解释了「为什么抖」。第六章的排错流程,第一站就是抄这张体检单。

四、案例回归:杯子为什么稳了

带着本节的模型回到开头的案例,现象全部有解。夹持力加大的做法错在「用力气对抗模型缺陷」——硬碰硬的力振荡幅度随夹持力一起放大,摩擦波动照样过零;软垫方案对在「直接压平力的波动源」。落实到参数:给夹爪指腹的 geom 单独配 solref 时间常数零点零五秒(比全局默认软一点)、impratio 提到十,摩擦垫比法向垫硬,同等法向波动下摩擦上限波动更小。复测:夹持成功率从六成七到接近满成,且夹持力均值反而降了四成——软约束不光稳,还省力。

变式推演:抓软包装(薯片袋)时, solref 再软一档,让可见形变成为保真的一部分;抓金属件对金属面,全局默认即可,别过度发软导致「手感虚浮」。参数没有万能值,与任务材料和步长匹配才是标准。

本节要点回顾

  • 软约束是内建的垫子:允许微穿透换来力对状态的光滑性,抖动的根源从模型层被拆除;
  • solref 管时间尺度:时间常数不小于步长是铁律,阻尼比一附近防过冲;
  • solimp 管深度剖面:浅软深硬,软地面才需要放宽 dmax;
  • 椭圆锥加 condim:摩擦敏感任务用默认椭圆锥,condim 按需配置,全场拉六是性能自杀;
  • 体检单四指标:接触数、约束行数、迭代数、残差——接触问题先抄单再动刀。

接触力算稳了,方程还是「连续时间」的;引擎真正执行的是离散小步。下一节讲时间的切法与积分器的选择。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U