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

Microduck RL训练踩坑实录:奖励函数设计、PPO调参与策略部署

Build in Public admin 53分钟前 6次浏览 已收录 扫描二维码

Microduck RL训练踩坑实录:奖励函数设计、PPO调参与策略部署

Meta Description: 基于Pollen Robotics官方microduck_rl仓库的实战经验,拆解双足机器人RL训练中的奖励函数设计陷阱、PPO参数调优技巧,以及从仿真到真机部署的全流程。


双足机器人用强化学习训练步态,听起来很酷对吧?但真上手做一遍,你会发现大部分时间不是在调网络,而是在跟奖励函数打架。

Pollen Robotics 把 Microduck 的训练栈全开源了——microduck_rl 仓库基于 MuJoCo Warp(mjlab)和 PPO(rsl_rl),4096 个并行环境跑在 GPU 上,1-2 小时能训出一个可用的步态。但仓库里那个 AGENTS.md 文件,读一遍就知道他们踩了多少坑。

这篇文章不重复官方 README,而是把 AGENTS.md 里那些”每个规则都是用教训换来的”的经验,结合复刻过程中的实操,拆开来讲。

奖励函数设计的五个血泪教训

AGENTS.md 里有个专门章节讲奖励函数规则,每条后面都写着”learned the hard way”。这五个问题是在复刻中一定会遇到的。

1. 符号搞反,四轮训练白费

这是最容易被新手坑到的:Microduck 的 mdp.py 有两种惩罚风格。mjlab 基础的成本函数返回 ≥ 0,用负权重;而 Microduck 自有的 _penalty_l1 函数返回 ≤ 0(已经自带了负号),所以用正权重

如果你对一个返回 ≤ 0 的惩罚项用了负权重,那它就双负为正了——变成奖励这个违规行为。策略会疯狂利用它,比如 butt-hopping(屁股跳)或者 crash-sits(摔倒坐着)。

验证方法:在 wandb 上,每个 Episode_Reward/ 的值必须 ≤ 0。如果某个惩罚项是正数,那你的符号反了。

2. RL 优化的是奖励字面意思,不是你心里想的

原话:”RL optimizes the letter of the reward.”

每一个没明确约束的自由度都会被利用。你想让鸭子向前翻滚,它学会了 ballistic whip(弹射甩鞭)。你想让它站起来,它学会了用头做三角支撑。

解决方案:用硬的状态门控(state-based gates)来编码”什么算这个动作”,而不是用小惩罚来微调。比如检查特定脚掌的接触状态、躯干朝向角度、用 latch(锁存器)记录动作阶段。

3. 没有”Jackpot”

如果你设了一个”到达 X 位置就给奖励”的规则,而且到达后每步还继续拿奖励——这就是一个 jackpot,策略会为了拿这笔钱做出任何极端动作。

正确做法:对”到达 X”的奖励做 rate-limited 或 slewed(缓变)。对于指令转换任务,用一个 slewed 的内部目标(匀速插值),让策略跑在目标前面没有额外好处。

4. 观测空间必须和奖励测量同一个视图

这是 AGENTS.md 里的一条 invariant:

“If an obs is remapped to a sensor view (backlash encoder, bias), any tracking REWARD on the same quantity must measure the same view — otherwise the policy is punished for correcting what it sees.”

如果观测走的是 backlash 编码器视角,但奖励测量的是理想关节角度,策略会看到”我明明把读数纠正了,怎么还在扣分”,训练直接乱掉。

️5. 域随机化不能跨 episode 累积

mjlab 1.3.0 的 DR 操作符(add/scale)原生就是非累积的,但如果你写自定义 DR 函数,必须记住 restore-then-apply。

Pollen 团队踩过这个坑:一个累积的 CoM 随机化曾经导致连续几个月的训练退化——每次 reset 时 CoM 偏移量越积越大,策略面对的训练分布不断偏移。

PPO 训练的实际配置

从 microduck_rl 的源码和配置可以提取出 PPO 训练的典型参数:

环境配置

  • 并行环境数:4096(GPU 显存够的话)
  • 控制频率:50 Hz
  • 观测空间:61 维(48 本体感受 + 13 指令)
  • 动作空间:15 维(14 个舵机目标角度 + 1 个预留)

观测布局:61 维在所有任务族间共享,保证策略可以热切换。48 维本体感受包括关节角度、速度、IMU 姿态等。13 维指令块是 [twist(3), head_pose(4), body_pose(6)],这个顺序不能变。不用某个指令槽的就 ZERO-PAD 它,绝不删除槽位。

关节布局:14 个舵机,ctrl idx = joint idx:

  • 0-4:左腿(hip_yaw, hip_roll, hip_pitch, knee, ankle)
  • 5-8:脖子/头(neck_pitch, head_pitch, head_yaw, head_roll)
  • 9-13:右腿

策略导出:ONNX 导出时把观测归一化器(normalizer)一起烤进去。scripts/export.py 自动做这件事。如果用 in-sim play 测试看不出问题(因为 play 也加了归一化),但手转换 checkpint 就会在真机上翻车。

策略是 unfiltered 的:训练时不加动作低通滤波。加 EMA 滤波必须有匹配的运行时标志位和传输测试——训练时有、部署时没有,或者反过来,都会破坏 transfer。

构建新环境的正确流程

AGENTS.md 给了一个六步工作流,其中第二步是最多人跳过的:

  1. 选最接近的模板(不要从零开始)
  2. 在训练前先验证物理假设——这是最大的省时器
  3. 配置约定
  4. 写 cfg 测试
  5. 冒烟测试(64 envs,5 iters)
  6. 训练

第二点特别值得展开:一个目标/静止位必须是一个稳定平衡点。从随机初始状态保持 3 秒,检查倾斜角而不是只看高度——一个只看 z 的 settle test 会把已经摔倒的状态报告为”休息得很好”。

AGENTS.md 举了个例子:一个 5 mm 错误的 STANd_Z 曾经让训练目标变成了几天都达不到的 impossible target。

冒烟测试:95% 的配置错误都能逮住

64 个并行环境,5 次迭代,跑一次冒烟测试。这能抓住约 95% 的配置错误,花费几乎为零。

冒烟测试检查的内容:

  • 环境能构建成功
  • 步进过程没有 NaN
  • 观测是 61D
  • 每个奖励项都能计算
  • ONNX 能导出

规则:没有冒烟测试,不要跑长训。

从训练到真机部署的管线

训练完成后,流程是:

  1. uv run scripts/export.py 导出 ONNX(含归一化器)
  2. uv run publish 上传到 Hugging Face Hub
  3. 真机运行时通过 robotctl policy add 加载

在 CPU MuJoCo 里可以用 scripts/infer_policy.py 做部署演练——用和训练时一样的 BAM M6 执行器模型模拟。加 --no-bam 就回退到 XML PD 执行器。

真机运行时支持热切换策略:walk / recover / trick 共享 61 维观测契约,任何时刻可以互相接管。

在复刻场景下的实操建议

如果你像我一样用国产飞特舵机替换 XL330,有几个额外的注意点:

执行器模型替换后:BAM 的参数全变了,需要重新做执行器辨识(上篇文章的 6 阶段流程)。但 microduck_rl 的奖励函数和 PPO 配置不需要大改——因为奖励函数绑定的是”走路”这个任务,不是”某个舵机”。你只需要在 microduck_constants.py 里更新 BAM 执行器配置,训练脚本基本不动。

冒烟测试特别重要:换舵机后很多隐性的配置错误会在训练时暴露。先跑冒烟测试再跑长训,否则你会在 2 小时后才发现训练数据全是 NaN。

注意动作空间的边界:不同舵机的角度范围不同。飞特 HL-1910 的物理限位和 XL330 不一样,必须更新 action_scale 和关节限位配置,否则训练出来的策略可能在真机上撞限位。


从官方仓库的 commit 历史来看,microduck_rl 的奖励函数经历了多轮迭代。每一步迭代背后都是一个真实机器人摔倒的故事。如果你也在做双足机器人 RL 训练,AGENTS.md 是必读文档——里面的每一条规则都是用训练时间和硬件损耗换来的。

复刻项目的训练进度和实验记录持续更新在 duck.whatled.com。

数据来源:pollen-robotics/microduck_rl 仓库 AGENTS.md (2026)、microduck_rl README (2026)、pollen-robotics/microduck 官方仓库、mjlab (MuJoCo Warp) 文档。

喜欢 (0)
[🍬谢谢你请我吃糖果🍬🍬~]
分享 (0)
关于作者:
少将,关注Web全栈开发、项目管理,持续不断的学习、努力成为一个更棒的开发,做最好的自己,让世界因你不同。