# Microduck 的双足步态是怎么炼出来的?从 ZMP 到 PPO 的完整拼图
Meta Description: Microduck 的步态不是手写的,而是 PPO 在 MuJoCo 里自己”摸索”出来的。但 RL 不是凭空变魔术——奖励函数里藏着经典控制理论的影子。拆开从 ZMP 到 sim2real 的完整链路。
如果你玩过 Microduck 的模拟器,可能会觉得它走路的样子挺自然的——脚抬起来、重心平移、落地缓冲,每一步都像那么回事。
但这里有个反常识的事实:Microduck 的步态不是手写出来的。没有人在代码里写”左脚抬 15 度、前移 3 厘米、落地”这种硬编码轨迹。它走路的技能,是 PPO 在 MuJoCo 仿真里,通过 4096 个平行环境跑了上千万步,自己”摸索”出来的。
那问题来了——一个神经网络怎么就知道走路要抬脚、要前倾、要落地缓冲?
答案是:奖励函数里藏了经典控制理论的影子。
从 ZMP 说起:双足步态的”物理学铁律”
如果你研究过双足机器人,一定听过 ZMP(Zero Moment Point,零力矩点)。这是 Miomir Vukobratović 在 1968 年提出的概念,至今仍是双足步态规划的理论基石。
核心思想很简单:一个双足机器人要站住,它的压力中心必须落在脚掌范围内。ZMP 一旦跑到脚掌外面,机器人就倒了。传统步态规划的做法是:
- 预规划 ZMP 轨迹(通常走 S 型曲线)
- 用线性倒立摆模型(LIPM)反推 CoM 运动
- 通过逆运动学解出关节角度
- 走一步,再走下一步
ASIMO、Atlas(早期版本)、HRP 系列都是这条路线。效果好,但工程量巨大——每个步态参数都要手动调,遇到不平整地面就很容易翻车。
Microduck 走了完全不同的路。
不规划轨迹,改”教”神经网络走路
Microduck 的步态训练跑在 microduck_rl 仓库里,基于 mjlab(MuJoCo + Warp)和 PPO。核心任务叫 Mjlab-Velocity-Flat-MicroDuck,目标是:给定一个速度指令,让机器人往前走。
它的观测空间是 61 维——48 维本体感知(14 个关节的位置、速度、上一个动作 + 机身线速度/角速度/姿态)加上 13 维命令(前进/侧移/转向的 twist 3 维、头姿态 4 维、身体姿态 6 维)。
但真正体现”经典控制理论如何渗透到 RL 奖励设计”的,是奖励函数。
奖励函数里的”隐形倒立摆”
翻看 microduck_rl 的 mdp.py 和 microduck_velocity_env_cfg.py,你会发现一组精心设计的奖励项。如果把它们的核心意图翻译成控制理论的语言,大致是这样:
1. 前进追踪 — 开环激励
reward_tracking_lin_vel = exp(-(cmd_vx - actual_vx)² / σ²)
这是最大头的奖励。PPO 要最大化这个值,就必须让实际速度跟上指令速度。等于说:”往前走就是对的,走错了方向扣分。” 这是策略学习的主信号——没有这个,其他所有奖励都白搭。
有意思的是,前进速度是用足端触地传感器间接算出来的。Microduck 每只脚底有一个力传感器,通过检测”哪只脚着地、着地多久”来推断运动状态。这和 ZMP 里”压力中心必须在脚掌内”的物理约束是同源的——只不过 ZMP 用它规划轨迹,RL 用它作为学习的反馈信号。
2. 姿态跟踪 — 线性化控制
reward_tracking_body_pose = exp(-‖cmd_roll - actual_roll‖² / σ²)
要求机身保持水平,不要歪着走。这等价于传统控制里的姿态内环——经典方法用一个 PD 控制器维持机身水平,RL 则是让神经网络自己学会这个”保持水平”的行为。
在 microduck_rl 的 CLAUDE.md 里,开发团队特别强调了一个教训:Tracking Gaussian 的标准差不能太紧。Microduck 的脑袋占了整机重量的 38%,走路时必然晃动。如果头姿追踪奖励的 σ 设太小,策略会为了”脑袋不晃”而直接原地罚站。所以最终设了一个松紧合适的 σ——只惩罚 DC 偏移,允许高频振荡自然衰减。
3. 动作平滑 — 二阶低通约束
action_rate_penalty = -‖action_t - action_{t-1}‖
joint_acceleration_penalty = -‖joint_vel_t - joint_vel_{t-1}‖
这两项惩罚动作突变和关节加速度。翻译成控制语言:限制了策略的带宽和 slew rate。经典控制里用二阶低通滤波器做这件事,RL 用惩罚项达到同样的效果。
而且 microduck_rl 的实现更精细——它把腿部和颈部的动作平滑度分开惩罚。腿部动作允许更快变化(走路需要快速响应),颈部动作则要求更平滑(摄像头稳定)。这个区分在经典控制里对应不同关节的不同带宽需求。
4. 扭矩率 — 力控边界
torque_rate_penalty = -‖τ_t - τ_{t-1}‖
惩罚扭矩突变。在 XL330 这种微型舵机上,扭矩突变意味着齿轮冲击。这个奖励项的物理意义就是保护执行器。传统方法通过加速度规划来实现,RL 通过惩罚项让策略”自己学会”平缓发力。
从”手写步态”到”学出来的步态”——为什么更鲁棒?
传统 ZMP 步态规划的最大问题是什么?对模型精度极度敏感。
你的动力学参数(质量分布、摩擦系数、舵机响应延迟)差一点点,ZMP 轨迹就偏了,机器人就倒了。所以传统双足机器人花了大量时间做模型辨识和参数标定。
Microduck 的策略训练使用了 域随机化(Domain Randomization)——每次环境重置,电池电压、摩擦系数、舵机延迟、质量分布都在一定范围内随机变化。策略在”各种不同身体”上训练过,到了真机上自然就适应了偏差。
这就是为什么一个在 MuJoCo 里训练的神经网络,能在真实的 Microduck 上走路——它不是在执行一条死板轨迹,而是在处理一个61 维状态空间里的连续决策问题,而这个状态空间天然包含了各种不确定性的扰动。
两种路径,同一目标
说 Microduck 的步态完全是”RL 黑盒”也不对。奖励函数的设计大量借鉴了控制理论:
- 速度追踪 → 位置/速度环的反馈概念
- 姿态跟踪 → 姿态内环的等价表达
- 动作平滑 → 低通滤波器
- 扭矩率惩罚 → 力控的平滑约束
区别在于:经典控制把这些约束写成显式方程(PD 增益、截止频率、S 曲线规划),而 RL 把它们编码成奖励项的权重和分布参数。前者是”告诉机器人怎么做”,后者是”告诉机器人什么重要,让它自己摸索怎么做”。
最后的结果是同一个——Microduck 站稳了,走起来了。
写在最后
如果你正在复刻 Microduck(像我一样),理解这套奖励函数背后的控制理论,比直接抄参数更有用。因为在更换国产舵机、调整 BAM 参数后,原来的奖励权重可能全要重新调。知道为什么设这个项,比知道设多少重要得多。
参考来源:
- Pollen Robotics. microduck_rl 仓库. GitHub. CLAUDE.md, mdp.py, microduck_velocity_env_cfg.py. 2026.
- Rhoban Lab. BAM: Better Actuator Models for Sim-to-Real Transfer. ICRA 2025.
- Vukobratović, M., Borovac, B. Zero-Moment Point — Thirty Five Years of Its Life. International Journal of Humanoid Robotics, 2004.
- 复刻项目进度记录: duck.whatled.com
