解读 184 · 域随机化细讲
解读对象:
microduck_velocity_env_cfg.py的随机化开关与范围(L48–89)+tasks/mdp.py的 randomize_* 函数
需要的前置:解读 183(同一课包上一篇)· 解读 125(函数逐个版)
在有风的天气练投篮,正式比赛时反而觉得球场安静——域随机化(domain randomization,DR)
就是这句话的工程版:训练时故意把虚拟世界的参数抖开,让同一条策略见过千万个"略不相同
的世界",真机那个世界只是其中之一。反直觉:仿真明明可以很精确,我们偏要把它做糙。
1. 为什么要故意做糙
物理引擎永远不是现实。摩擦模型近似、通信延迟、传感器装歪、齿轮间隙……每一项单看都小,
叠在一只 737 g、靠 14 个关节动态平衡的鸭子上,足以让仿真满分策略在真机第一步摔跤
(sim2real gap)。DR 的答案是:与其假装差距不存在,不如把每种差距都变成训练科目。
2. 随机化什么:这张鸭子的真实清单
velocity 配置里开着的(L48–89 逐行核对):
| 抖什么 | 范围 | 备注 |
|---|---|---|
| 躯干质心 | ±3 mm 起,课程爬到 ±15 mm | 曾想爬到 ±30 mm 被砍:脚跟只在踝后 20 mm,质心会被抖出支撑面,后向平衡直接没法训 |
| 头部质心 | ±3 mm → ±10 mm | 头是大杠杆臂 |
| 质量+惯量 | (0.95, 1.05) 倍 | 必须同因子,独立随机会造出非法惯量张量 |
| BAM 摩擦预算 | (0.9, 1.1) 倍 | 走执行器的 friction_scale,不是 MuJoCo 字段 |
| 转子反射惯量 | (0.9, 1.1) 倍 | BAM 的 armature 照常生效 |
| 编码器偏置 | ±0.015 rad(±0.86°) | 每环境恒定,模拟标定误差 |
| IMU 安装误差 | 随机轴最大 6° | 零中心;真板 ~5° 俯仰偏移在运行时源头修,不靠 DR |
| 推搡 | 每 3–6 s,±0.3 m/s | 从 ±0.5 收紧:大脚会训出"神经质的救步步态" |
| 电池电压 | (6.5, 8.2) V+负载压降 (0, 0.2) | 官方超压特例,换舵机别照抄 |
| 指令延迟 | 3–6 控制步 | 通信+固件滞后 |
关着但留了范围的也值得看:kP (0.85,1.15)/kD (0.9,1.1) 注释写着 "Was True",初始姿态
±10°/±5° 也关着——DR 清单是开关面板,不是常量协议。
3. 怎么抖才科学:四条工程卫生
读 randomize_* 函数(mdp.py)能总结出统一纪律:一,先恢复标称、再采新值——
randomize_delayed_actuator_gains 每次先 reset_gains 再 set_gains,否则随机值逐回合
累积,世界越练越歪;二,物理量成对动:质量与惯量同一因子;三,传感器错装用每环境
恒定偏置,不搞每步噪声——装歪的 IMU 不会每 20 ms 换个方向;四,抖到正确的边界:
BAM 自己管摩擦,DR 就得写进执行器接口(friction_scale),MuJoCo 的 dof_frictionloss
早被清零了。彩蛋:expand_bam_friction_fields 是带装饰器的空函数,装饰器本身就是
注册副作用——让 mjlab 把摩擦字段按环境展开。
4. 范围怎么定:覆盖实测误差,不是想象最坏
指南原话:DR 要覆盖实测误差,不是想象中的最坏情况。范围开太大,策略为了"所有虚构机器人
都不倒"会学成紧张、保守、迈不开腿的折中动作(±30 mm 质心被砍就是活例)。每个范围的
依据只能是你台架实测的离散度;DR 有没有用,用扰动测试验:exp001b 给 IMU 加扰动扫描,
开随机化的 A 组最大衰减 -4.6%、关掉的 B 组 -6.0%——方向对,但 1–2% 在单种子噪声内,
诚实结论是"待长训练复测"。故意做糙是手段,知道糙了多少才是本事。
你带走的收获
- DR = 把 sim2real 差距变成训练科目:质心、质量、摩擦、延迟、电压、传感器误差、推搡。
- 范围有出处(±30 mm 被砍的脚跟几何、±0.5 推搡的神经质步态),不是拍脑袋。
- 四条卫生:先恢复再采样、成对量同因子、传感器误差用恒定偏置、抖到执行器边界内。
- 开关面板思维:留范围不等于开;kp/kD 现在就是关的。
- 验证靠扰动测试看"被打时掉多少",不看训练分数。