“拆一只开源鸭子”系列:(一)硬件、软件和部署 · (二)训练原理 · (三)仿真里鸭子为什么不走路 · (四)自己训一遍
这一篇记录我在本地把 Microduck 的仿真(simulation)跑起来、发现鸭子不走路、再一步步查出原因的过程。仿真用的是机器人上的同一套守护进程(daemon),见第一篇《硬件、软件和部署》;文中说到的 velstand、BAM 舵机(servo)模型和背隙(backlash),第二篇《训练原理》里有解释。
仿真怎么搭的
robotd --sim 把舵机总线(bus)换成一个 TCP 连接,另一头是 MuJoCo 进程(body_server)。控制循环(control loop)、策略(policy)、安全层、IPC 都是机器人上的同一份代码,它分不清对面是真身体还是仿真。
我的机器是 Intel Mac,踩了几个环境坑:
- Rust 要 ≥ 1.89,用
rustup toolchain install 1.94单独装一个,不动默认工具链。 - microduck_rl 锁定的 torch 2.9.1 没有 Intel Mac 的包,
uv sync装不上。好在body_server只依赖mujoco和numpy,单独建一个环境就行:mujoco==3.10.0(还有 Intel Mac 包的最新版)加onnxruntime。 - macOS 的 Unix socket 路径上限约 104 字符,状态目录别放太深,用默认的
~/.cache/duck-sim。 - 查看器要用
mjpython启动;挪过虚拟环境的话,记得改它的 shebang。
现象和排查
仿真起来后一切正常:1.00 倍实时,控制循环 50 Hz,鸭子能从坐姿站起来,头会东张西望。但发 0.15 m/s 的前进指令,8 秒只挪了 1 cm 左右。robotctl monitor 显示指令已经生效,腿却几乎不动。
我先怀疑是执行器(actuator)模型:训练用 BAM,而 body_server 只用 MJCF 里的简化位置执行器。装上 BAM(要用 uv.lock 锁定的 62bd8ce,分支最新的提交改了接口)、用官方参考脚本跑,鸭子照样不动,这个猜测就排除了。
真正的线索在策略集的 manifest.json 里:负责行走的是 velstand.onnx,而 duck-sim 脚本把行走槽写死成了旧的 alpha_walking.onnx。再加上 velstand 是在带背隙的模型上训练的,body_server 默认的 scene.xml 却不带背隙。
对照实验

| # | 运行方式(runner) | 策略(policy) | 执行器(actuator) | 场景(scene) | 结果(result,指令 0.15 m/s) |
|---|---|---|---|---|---|
| 1 | robotd + body_server | alpha_walking | 简化位置执行器 | scene.xml | 不走(8 s 约 1 cm) |
| 2 | 官方 infer_policy.py | alpha_walking | BAM | scene.xml | 不走(0.00 m/s) |
| 3 | 官方 infer_policy.py | velstand | BAM | scene_backlash.xml | 走,约 0.07 m/s |
| 4 | 官方 infer_policy.py | velstand | 简化位置执行器 | scene_backlash.xml | 走,约 0.08–0.09 m/s |
| 5 | robotd + body_server | velstand | 简化位置执行器 | scene.xml | 不走(10 s 5 mm) |
| 6 | robotd + body_server | velstand | 简化位置执行器 | scene_backlash.xml | 走,10 s 0.763 m |
实验 2 和 4 说明 BAM 不是关键,实验 5 和 6 说明 velstand 需要带背隙的场景。改两处就好:
- walk = "$POLICIES/alpha_walking.onnx"
- stand = "$POLICIES/alpha_stand.onnx"
+ walk = "$POLICIES/velstand.onnx"
RL=<microduck_rl 的路径>
DUCK_SIM_SCENE=$RL/src/mjlab_microduck/robot/microduck/scene_backlash.xml \
scripts/duck-sim
走起来以后,实际速度只有指令的一半左右(0.07~0.09 m/s)。我一开始以为是自己哪里还没配对,后来在官方基准里看到 0.4 m/s 也只能走到 0.17 m/s。看起来速度跟踪不足是策略本身的短板,不是配置问题。
上游已经有人报告了同样的问题(issue #498),修复的 PR #500 也做了这两处改动,写这篇的时候还没合并。
后来我自己从头训练了一遍走路策略和 velstand,还修了慢速不走的问题,见第四篇《自己训一遍》。
请我喝杯咖啡
