• 欢迎访问少将全栈,学会感恩,乐于付出,珍惜缘份,成就彼此、推荐使用最新版火狐浏览器和Chrome浏览器访问本网站。
  • 吐槽,投稿,删稿,交个朋友
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏少将全栈吧

Microduck 的崎岖地形训练:1.5 厘米台阶为什么是这只鸭子的极限

Build in Public admin 7小时前 14次浏览 已收录 扫描二维码

Microduck 的崎岖地形训练:1.5 厘米台阶为什么是这只鸭子的极限

做过四足机器人 RL 的人可能习惯了这种地形配置:10 厘米高的台阶、20 度斜坡、碎石地面。MuJoCo 的标准地形库默认就是这些参数。但 Microduck 的训练配置里,台阶高度上限是 1.5 厘米,斜坡最大 5.7 度,随机网格高度差不超过 1 厘米。这不是保守,是物理约束。

一只 25 厘米高、800 克重的双足机器人,腿能抬起来的高度大概 1 到 2 厘米。台阶比脚抬高度还高,策略再怎么学也上不去。今天拆开看 Microduck 的崎岖地形训练配置,以及这些数字背后的物理逻辑。

四种地形各管什么

Microduck 的训练仓库里,崎岖地形配置定义在 velocity_env_cfg.py 中,叫 MICRODUCK_ROUGH_TERRAINS_CFG。它把一块 8 米见方的地形分成四种子地形,按比例分配:

平地(25%)——最基础的部分。策略在平地上学会基本步态,地形在这里不提供任何挑战。保留 25% 的平地比例是为了确保策略不会过度适应崎岖地形而丢失平地行走能力。

金字塔台阶(25%)——台阶高度从 0 到 1.5 厘米递增。注意这个上限。MuJoCo 默认的台阶地形配置是 10 厘米,那是给 ANYmal 那种体型的四足机器人用的。Microduck 的步态抬脚高度估计在 1-2 厘米,台阶设到 1.5 厘米已经是极限。再高策略学不会上去,训练信号变成纯粹的负反馈——每碰到台阶就摔——策略会学到”别走了”而不是”走上去”。

随机网格(30%)——模拟鹅卵石路面。把地面切成 45 厘米一格的网格,每格高度随机偏移 0 到 1 厘米。这个网格尺寸有讲究。最初试过 12 厘米的网格,8 米地形上就是 66×66=4356 个格子,总共约 26 万个碰撞体,MuJoCo 直接内存溢出。改成 45 厘米后变成 17×17=289 个格子,总量约 1.7 万,刚好跑得动。网格不能整除地形尺寸(0.45×17=7.65 米,不等于 8 米),否则接缝处会出现规律性的高度跳变。

金字塔斜坡(20%)——用高度场生成的金字塔形斜坡,坡度从 0.03 到 0.10(上升比),换算成角度大约 1.7 度到 5.7 度。斜坡看起来很缓,但对一只脚底面积只有几乎方厘米的鸭子来说,5.7 度的斜坡意味着重心投影偏移已经到了稳定边缘。高度场的垂直分辨率设到 1 毫米(vertical_scale=0.001),这样斜坡是平滑的而不是一阶一阶的楼梯——5 毫米的量化台阶对 Microduck 来说已经是需要跨过的障碍了。

为什么没有倒金字塔

细看配置会发现一个注释:BoxInvertedPyramidStairsTerrainCfg 被移除了。这不是设计选择,是修 bug。

倒金字塔地形——就是地面上挖坑——在 MuJoCo TerrainGenerator 里有一个实现细节:它把 env_origin_z 设成坑底的高度(负值)。Microduck 的站立高度大约 12 厘米,加上负的 env_origin_z,重置时 root_z ≈ 0.12 + (-0.10) = 0.02 米。这个位置在地面以下。机器人从地面以下出生,直接穿过地板掉进虚空。

这个问题在标准四足机器人上不会出现,因为它们的站立高度有 50-60 厘米,减去坑深还有 40 多厘米,不会跑到负数。但 Microduck 太矮了,任何向下的地形偏移都可能把出生点推到地面以下。所以所有向下延伸的地形都被砍掉了,只保留平地和向上凸起的地形。

同样的逻辑也适用于斜坡配置。注释里明确写了不使用倒置斜坡(HfInvertedPyramidSlopedTerrainCfg),原因跟倒金字塔一样——有坑底出生点在地面以下的风险。

接触面软化:不是改物理,是防 NaN

崎岖地形有一个隐藏的技术问题:盒子地形在高度变化处会产生硬边。相邻两个盒子高度不同,它们的接触面形成一个棱角。当脚正好落在这个棱角上时,MuJoCo 的接触求解器可能算出不稳定的法向量,产生脉冲式的异常力,进而传播成 NaN。

Microduck 的解法是 _soften_terrain_contacts 函数。它遍历 terrain body 下的所有几何体,把接触弹簧的时间常数从默认的 0.02 秒加倍到 0.04 秒,接触阻抗也稍微调软。效果是接触弹簧变软两倍,棱角处的脉冲被阻尼吸收,不会放大成数值爆炸。

这个改动对宏观行走物理几乎没有影响——0.04 秒的接触时间常数还在人类感知不到的范围内。但它把一个偶发但致命的 NaN 来源堵住了。在 4096 个并行环境里,每个环境每秒 50 步,一个 NaN 传播到梯度里就能废掉整个训练 batch。

推力扰动:0.3 的上限不是随便选的

除了静态地形,训练里还有动态扰动:VELOCITY_PUSH_RANGE。每隔 3 到 6 秒,给机器人一个随机的速度脉冲,范围 ±0.3 米/秒。这个数字原来是 ±0.5。

改到 0.3 的原因写在注释里,很直白:”an ADDITIVE kick larger than max walk speed (0.4) trains a permanently nervous fall-recovery gait”。Microduck 的最大行走速度命令是 0.4 米/秒。一个 0.5 的推力比最大行走速度还大,每 3 到 6 秒来一次。策略学到的不是”稳稳走”,而是”随时准备摔倒恢复”——步态变成防御性的低重心拖步,随时准备被推。

这个发现来自 2026 年 7 月的一次训练审计。把推力降到 0.3 以后——仍然占了最大速度的 75%,足以训练抗扰动能力——但不超过最大速度,策略可以学到正常的前进行走步态,同时保持对扰动的鲁棒性。

地形课程:从平地到崎岖

地形难度不是一开始就拉满的。Microduck 用 mjlab 的课程机制,地形难度随训练进度逐步提升。课程通过 CurriculumTermCfg 控制,在训练初期大部分环境是平地,少量简单地形。随着迭代推进,崎岖地形比例和难度逐渐增加。

这种渐进式策略的原因跟迁移学习里的逐步解冻类似:一开始就上全难度地形,策略会在最简单的地形上过拟合(站着不动不摔),无法学到有意义的步态。先在平地上学会走,再逐步加地形挑战,策略才能在已有步态基础上适应地形变化。

CoM 随机化也跟着课程走。初始范围 ±3 毫米,随训练进度提升到 ±8 毫米。一开始就把重心偏移拉到 8 毫米,策略连站都站不稳,什么也学不到。

尺寸决定一切

Microduck 的地形配置整体上可以用一句话总结:所有参数都按物理尺寸缩放。1.5 厘米台阶对应 1-2 厘米抬脚高度。5.7 度斜坡对应脚底面积和重心高度的比值。1 厘米网格高度差对应脚踝离地间隙。0.3 推力上限对应 0.4 最大行走速度。

这不是”保守调参”,是从物理约束反推训练配置。波士顿动力的 Atlas 身高 150 厘米,台阶高度可以设到 30 厘米——那是它腿长的 20%。Microduck 身高 25 厘米,1.5 厘米台阶是腿长的 6%——比例上比 Atlas 还保守,因为双足平衡在小尺寸上更难,重心偏移的容差更小。

对做小型机器人 RL 的人来说,这里有一个直接的参考:不要直接用 MuJoCo 或 mjlab 的默认地形配置。那些默认值是给中型四足机器人标定的。你的机器人抬脚高度多少,最大行走速度多少,脚底面积多大——从这些物理参数出发反推地形参数,比从默认值开始往下调要靠谱得多。

数据来源

  • GitHub: pollen-robotics/microduck_rl 仓库 src/mjlab_microduck/tasks/microduck_velocity_env_cfg.py
  • GitHub: pollen-robotics/microduck_rl 仓库 CLAUDE.md
  • mjlab TerrainGeneratorCfg 配置源码
  • MuJoCo 接触求解器文档(solref/solimp 参数)
喜欢 (0)赏
[🍬谢谢你请我吃糖果🍬🍬~]
分享 (0)
关于作者:
少将,关注Web全栈开发、项目管理,持续不断的学习、努力成为一个更棒的开发,做最好的自己,让世界因你不同。