
让4个环境流血的符号约定Microduck RL奖励函数双重否定陷阱【免费下载链接】microduck_rlRL training environments for Microduck (mjlab)项目地址: https://gitcode.com/GitHub_Trending/mi/microduck_rlMicroduck RL 是基于 mjlabMuJoCo Warp构建的强化学习训练环境项目为约 800 g 的双足机器人 Microduck 提供行走、摔倒恢复、翻滚、轮滑等 12 个训练任务策略经 PPO 训练后导出 ONNX 直接部署到真机。这篇文章拆解的是该项目 AGENTS.md 中一条用血泪换来的规则同一套奖励函数里混用了两种符号约定一次双重否定就让 4 个环境的策略开始流血——机器人用屁股蹦跳butt-hopping、摔坐crash-sits来白嫖奖励。Microduck RL 是什么30 秒了解项目一句话sim2real 是全部目标。所有环境都按真实硬件的物理细节建模BAM 伺服模型、±1° 齿轮背隙、领域随机化策略以 50 Hz 在仿真中训练再热插拔到真机上。git clone https://gitcode.com/GitHub_Trending/mi/microduck_rl cd microduck_rl # 训练行走策略需 CUDA GPU约 1-2 小时 uv run train Mjlab-Velocity-Flat-MicroDuck --env.scene.num-envs 4096 # 导出 ONNX 部署到真机 uv run scripts/export.py Mjlab-Velocity-Flat-MicroDuck --wandb-run-path entity/project/run_id项目结构速览模块路径作用奖励/事件/观测函数src/mjlab_microduck/tasks/mdp.py全部 30 个自定义 MDP 函数7188 行任务配置src/mjlab_microduck/tasks/每个任务族一个 cfg 模块规则手册AGENTS.md环境搭建流程 奖励设计规则回归测试tests/CPU 上锁定关节索引、奖励符号约定、NaN 保护双重否定陷阱mdp.py 里藏着两套符号约定 翻开 mdp.py你会发现惩罚项其实有两种写法而它们的配重规则完全相反约定 A正成本 × 负权重mjlab 原生风格函数返回非负的量惩罚的严重程度配置里必须配负权重# mdp.py — roulade_overspeed_penalty max(0, |ω_y| − omega_max)² — Positive quantity; use a negative weight. excess torch.clamp(omega_y.abs() - omega_max, min0.0)例如 fallen_state_penalty摔倒时每步返回1.0文档明确写着weight it negative。约定 B自取负惩罚 × 正权重项目自写风格函数自己把返回值翻成负数*_penalty、*_l1系列配置里必须配正权重# mdp.py — 双腿对称奖励返回 -mean|q_left q_right| Returns −mean_pairs |q_left q_right| (L1); use with a POSITIVE weight.见 gait_symmetry 与 trunk_vertical_accel_penalty返回-|a_z|。一次配错权重 奖励作恶4 个环境如何流血最危险的是跨环境复制配置。典型事故链某环境用了自取负的trunk_vertical_accel_penalty返回-|a_z|从 standup 环境原样继承了一个负权重-0.02双重否定-0.02 × (−|a_z|)奖励垂直加速——机器人越猛撞越有分wandb 里Episode_Reward/gentle_rise 0.0118成为整份日志中唯一为正的惩罚项。这就是 test_roller_standup_cfg.py 中文注释记录的那次事故「double négatif RÉCOMPENSAIT laccélération verticale」双重否定在奖励垂直加速度直接导致策略变得暴力。AGENTS.md 把这类符号错误的后果概括为一句话策略会**开采farm**这个漏洞——屁股蹦跳代替行走、猛摔入座代替站立。万无一失的检查法 AGENTS.md 给出的铁律只有一条每次训练都适用每次 runwandb 里每个Episode_Reward/penalty必须 ≤ 0。只要有一个惩罚项的加权值翻正就是符号配错了——不用看别的指标。项目的三层防线规则写进文档、锁进测试这个 bug 之所以没有复发靠的不是记得小心点而是三层工程化防御第 1 层 · 文档规则。AGENTS.md 的Reward design章节第一条就是符号约定标注了它bit four envs咬伤过 4 个环境。第 2 层 · CPU 回归测试。tests/test_roller_standup_cfg.py#L469-L476 对每个奖励项断言权重符号# 这些项调用已返回负值的函数 → 权重必须是正的 for name in (height_stand_l1, pose_stand_l1, gentle_rise): assert cfg.rewards[name].weight 0 # 这些项返回正值 → 权重必须是负的 for name in (joint_torques_l2, joint_torque_rate_l2, action_rate_l2): assert cfg.rewards[name].weight 0同样的思路散布在 test_spin_cfg.py、test_roller_slope_cfg.py 等测试里——README 明确说这些测试lock in reward sign conventions锁定奖励符号约定且不需要 GPU。第 3 层 · 文档化的事故复盘。每个惩罚函数的 docstring 都写清了返回值的符号与应配权重的方向例如 interpolated_height_l1_penalty 直接标注SELF-NEGATING … use a POSITIVE weight (penalty sign convention)。新手避坑清单复制奖励项前 3 步自查如果你要往自己的环境里加或复制奖励项照这个顺序做先读 docstring 最后一行——本项目所有惩罚函数都会在文档字符串里写明use a negative weight还是use a POSITIVE weight跨环境复制时只复制函数引用不盲目复制权重——两个环境即使调用同一个 mjlab 内置项权重也应按各自奖励规模重新标定AGENTS.md 提醒PPO 看到的是相对优势比较的是奖励质量而非权重本身训练前跑一遍 CPU 测试uv run --with pytest pytest tests/跑起来后盯一眼 wandb任何为正的Episode_Reward/penalty都说明符号配反了。快速上手从训练到部署的完整链路步骤命令冒烟测试64 环境 × 5 轮几块钱抓住 95% 的配置错误uv run train TASK_ID --env.scene.num-envs 64 --agent.max_iterations 5正式训练uv run train TASK_ID --env.scene.num-envs 4096无 GPU丢到 Hugging Face Jobs任意 train 命令加--hf-jobs查看策略uv run play TASK_ID --wandb-run-path run_id导出 ONNX归一化器已烘焙uv run scripts/export.py TASK_ID --wandb-run-path ...真机预演CPU MuJoCo 键盘驱动uv run scripts/infer_policy.py --walking output.onnx小结Microduck RL 的奖励函数故事给所有做 RL 的人一个朴素提醒奖励的符号约定不是数学细节而是策略行为的第一因。当负权重 × 负返回值悄悄变成奖励作恶机器人会用屁股蹦跳告诉你——RL 优化的是奖励的字面意思而不是你的意图。把符号约定写进文档、锁进测试、用一条 wandb 铁律兜底是这个开源项目从 4 次流血中学到的最便宜的教训。【免费下载链接】microduck_rlRL training environments for Microduck (mjlab)项目地址: https://gitcode.com/GitHub_Trending/mi/microduck_rl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考