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

Microduck 域随机化拆解:电压跌落、指令延迟和摩擦扰动怎么让仿真鸭子变真

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

域随机化(Domain Randomization)在 sim2real 里是个老话题了,但大多数文章讲到这就停了:”随机化一些参数,策略就泛化了。” 具体随机化什么?范围多大?为什么是这些参数?Microduck 的训练代码把这件事做到了很具体的程度——不是随便撒点噪声,而是对着 XL330 舵机的物理特性逐项建模。今天拆开看。

三个随机化维度,不是拍脑袋定的

Microduck_rl 的域随机化围绕三个核心参数展开:电池电压、指令延迟、摩擦系数。这三个不是随便选的,每一个都对应 sim2real 迁移时最痛的 gap。

电池电压:不只是 12V → 11V 那么简单

XL330 的控制律是电压控制——不是位置控制,不是速度控制,是直接给电压。这意味着电池电压直接决定舵机的力矩输出。满电 12V 和放电到 10V,同一个指令产生的力矩能差 20%。

Microduck 训练时用的 FrictionDRBamActuator(在 src/mjlab_microduck/actuator/ 里)对每个环境实例独立随机化电池电压。更关键的是,它还模拟了电压跌落(voltage sag)——当多个舵机同时出力时,电池内阻导致实际电压低于空载电压。一个 800g 的双足机器人,15 个舵机同时动作的瞬间,电池电压可能从 11.8V 跌到 10.5V。

这就是为什么 Microduck 不用理想 PD 控制器训练。用 BAM(Behavioral Actuator Model)建模到电压控制律这一层,域随机化才能在物理上有意义——你随机化的不是一个抽象的”力矩缩放因子”,而是”电池电压 × 电流 – 反电动势”这个真实的物理链路。

指令延迟:50Hz 循环里藏着的 20ms 不确定性

Microduck 的控制循环是 50Hz,也就是 20ms 一个 tick。但”50Hz”是个理想值。真实世界里,从策略推理出动作到舵机收到指令,中间有蓝牙传输延迟、串口通信延迟、舵机响应延迟。这些加起来可能从 5ms 到 25ms 不等。

训练时的域随机化对每个环境实例的指令延迟做了随机化。效果是策略学到了”不依赖即时反馈”——它不能假设上一 tick 发的指令这一 tick 就生效了。这对双足行走尤其关键:步态控制本质上是个延迟系统,策略如果对延迟过拟合,真机上稍微多 5ms 延迟就可能摔。

摩擦系数:Coulomb + Stribeck 不是常数

XL330 的摩擦不是简单的库仑摩擦。BAM 模型里用的是 Coulomb + Stribeck + 负载相关摩擦的三项模型。其中 Stribeck 效应(低速时摩擦系数反而更高)对双足机器人的低速精细动作影响很大——原地转向、微步调整这些动作,关节速度接近零,Stribeck 效应最显著。

域随机化对摩擦系数的扰动不是简单的 ±10% 乘个随机数,而是在 BAM 的物理框架内扰动 Stribeck 速度阈值和摩擦幅值。这意味着随机化后的摩擦曲线仍然物理合理——有 Stribeck 的形状,只是参数变了。

为什么不是更多参数?

一个自然的问题是:为什么不随机化质量、惯性、连杆长度?答案是优先级。Microduck 的 CAD 是从 Onshape 导出的,质量和惯量的几何来源是确定的。3D 打印件的公差(±0.2mm)对质量的影响大约 2-3%,远小于电压跌落 15% 和摩擦系数 30% 的变化范围。

换句话说,actuator gap >> body gap。在 800g 这个尺度上,舵机的不确定性远大于机械结构的不确定性。Pollen Robotics 的工程师在 AGENTS.md 里写得很直白:”At this scale — tiny servos driving a ~800 g biped — actuator fidelity is most of the sim2real gap.”

训练时怎么用:逐环境独立随机

域随机化的实现细节值得注意。MuJoCo Warp 支持 4096 个并行环境,每个环境实例在 reset 时独立采样一组 DR 参数。不是所有环境用同一组随机化——是 4096 个鸭子各自生活在各自的”平行宇宙”里。

这和早期 DR 论文的做法不同。早期做法是在一个环境里按 episode 切换参数,策略需要同时适应所有参数变体。Microduck 的做法更激进:4096 个环境同时跑,每个都有自己的电池电压、延迟和摩擦。PPO 的 batch 横跨所有这些变体,梯度更新自然地推动策略向”对所有变体都工作”的方向走。

实际训练 1-2 小时就能出可用的步态(4096 envs,单 GPU)。这个速度本身也是 MuJoCo Warp 的贡献——纯 Python 的 MuJoCo 环境跑 4096 并行不现实,Warp 的 GPU 并行才让这种”暴力 DR”变得可行。

去随机化验证:`–vin` 和 `–no-bam`

训练完怎么验证 DR 没有把策略搞废?microduck_rl 提供了几个诊断开关:

  • --vin:把电池电压钉到一个固定值
  • --vin-drop-gain:固定电压跌落增益
  • --kp-fw:固定 PD 增益
  • --no-bam:完全不用 BAM,退回到 MuJoCo XML 里的理想 PD 执行器

用 --no-bam 跑一遍,如果策略立刻摔了,说明策略确实依赖了 BAM 的物理建模——这不是坏事,说明 sim2real gap 被 DR 覆盖了。如果 --no-bam 还能走,说明策略学到了更鲁棒的步态,但也可能意味着 DR 范围不够大,真机上的表现可能不如仿真。

对复刻者的启示

如果你在复刻 Microduck 或做类似的小型双足机器人,域随机化的优先级应该是:

  1. 执行器物理 > 一切。先把 BAM 或等效的执行器模型搞对,DR 才有意义
  2. 电压和摩擦是前两个要随机化的参数,延迟排第三
  3. DR 范围从实测数据来,不是猜的。量一下满电/没电时的舵机力矩曲线,量一下通信延迟的分布
  4. 逐环境独立随机,不要偷懒用全局随机化

域随机化不是免费的午餐。随机化范围太大,策略会学得过于保守——走得很稳但很慢。范围太小,真机上摔。Microduck 目前的平衡点是在”能走”和”能泛化”之间,而这个平衡点是通过 BAM 的物理建模 + 实测参数范围找到的,不是调参调出来的。

数据来源:pollen-robotics/microduck_rl GitHub 仓库 README 及 actuator 模块源码,pollen-robotics/microduck 架构文档。

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