turtlebot3-burger_150.png
turtlebot3-waffle-pi_150.png
turtlebot3-arm_150.png
walking-y2_150.png
turbot3-multi_150.png
turbot3-dl-ros1_150.png
turbot3-ai.png
turbot3-dl-ros2_150.png
turbot3-slam_150.png
turbot3-arm_150.png
turtlebot4-lite_150.png
turtlebot4-pro_150.png
turbot4-dl_150.png
turbot4-ai_150.png
aidriving-racebot_150.png
aidriving-autodrive_150.png
turtlebot-arm_150.png
openmanipulator-x_150.png
Home » OpenDuckMini强化学习框架入门教程 » OpenDuckMini强化学习框架入门教程-域随机化

OpenDuckMini强化学习框架入门教程-域随机化

纠错,疑问,交流: 请进入讨论区请点击进入页面,扫码加入微信群或Q群进行交流

获取最新文章: 扫一扫加入“创客智造”公众号

欢迎加入我们的openduckmini交流群,微信扫描右侧二维码立即进群交流

群二维码

域随机化

  • 理解域随机化,包含核心函数,随机化参数,随机化范围分析,实现细节,域随机化的作用,与训练系统的集成等

概述

域随机化(Domain Randomization) 是强化学习中一种重要的泛化技术,通过在训练过程中随机变化仿真环境的物理参数,使得训练出的策略能够更好地迁移到真实环境(sim-to-real transfer)。Open Duck Playground 的域随机化在 playground/common/randomize.py 中实现。

核心函数

def domain_randomize(model: mjx.Model, rng: jax.Array):

该函数接受 MJX 模型和随机数生成器,返回随机化后的模型和参数变化掩码。每次环境 step 时调用,实现物理参数的在线变化。

随机化参数

1. 地面摩擦系数

随机变化机器人足部与地面的摩擦系数:

# 范围: 0.5 ~ 1.0(均匀分布)
geom_friction[FLOOR_GEOM_ID, 0] = uniform(0.5, 1.0)

这使策略学会在不同摩擦系数的地面上都能保持稳定——无论是光滑地板还是粗糙路面。

2. 关节摩擦

随机缩放执行器关节的静摩擦力:

# 范围: 0.9 ~ 1.1(乘积因子)
dof_frictionloss *= uniform(0.9, 1.1)

3. 关节惯性

随机缩放关节的 armature(旋转惯量):

# 范围: 1.0 ~ 1.05(乘积因子)
dof_armature *= uniform(1.0, 1.05)

4. 质心偏移

随机偏移躯干的质心位置:

# 范围: ±0.05 m
body_ipos[TORSO_BODY_ID] += uniform(-0.05, 0.05)

这模拟了机器人携带不同负载或重心变化的情况。

5. 质量变化

随机缩放所有连杆的质量:

# 范围: 0.9 ~ 1.1(乘积因子)
body_mass *= uniform(0.9, 1.1)

# 额外在躯干上 ±0.1 kg 的变化
body_mass[TORSO_BODY_ID] += uniform(-0.1, 0.1)

6. 关节零位偏移

随机偏移关节的初始零位(qpos0):

# 范围: ±0.03 rad
qpos0[joint_addr] += uniform(-0.03, 0.03)

7. 执行器 KP 增益

随机缩放位置控制器的 KP(比例增益):

# 范围: 0.9 ~ 1.1(乘积因子)
actuator_gainprm *= uniform(0.9, 1.1)
actuator_biasprm *= (-kp * factor)  # 同步更新偏置

这模拟了舵机性能差异或随时间老化的影响。

参数变化汇总

参数 变化方式 范围 仿真效果
地面摩擦 直接设置 [0.5, 1.0] 不同地面条件
关节静摩擦 乘积缩放 ×[0.9, 1.1] 关节灵活性变化
关节惯量 乘积缩放 ×[1.0, 1.05] 关节响应速度变化
质心位置 位置偏移 ±0.05 m 负载分布变化
连杆质量 乘积缩放 ×[0.9, 1.1] 整体重量变化
躯干附加质量 直接偏移 ±0.1 kg 额外负载
关节零位 角度偏移 ±0.03 rad 装配误差
执行器 KP 乘积缩放 ×[0.9, 1.1] 舵机性能差异

随机化范围分析

从简单到困难

easy ←─────────────────────────→ hard
平坦地形 + 小随机化      粗糙地形 + 大随机化
  (起始训练)                (高级泛化训练)

在训练策略时可以调整随机化范围:

  • 初始阶段:使用较小的随机化范围,让策略先学会基础运动
  • 后期阶段:逐步扩大范围,提高策略的鲁棒性
  • 最终部署:使用完整随机化范围训练,确保在真实环境的表现

与地形的协同作用

域随机化与地形选择相互配合:

地形 域随机化作用
平坦地形 + 随机化 策略学会应对不同地面条件
粗糙地形 + 随机化 策略学会在复杂地形上适应变化
回差模型 + 随机化 策略学会在真实机构误差下保持性能

实现细节

vmap 向量化

域随机化函数使用 @jax.vmap 实现的函数进行并行计算,支持 JAX 的自动向量化:

@jax.vmap
def rand_dynamics(rng):
    # 对每个参数生成随机变化
    # ... 7 种参数变化 ...
    return (friction, body_ipos, frictionloss, armature, body_mass, qpos0,
            actuator_gainprm, actuator_biasprm)

模型更新

使用 tree_replace 高效更新 MJX 模型参数:

model = model.tree_replace({
    "geom_friction": friction,
    "body_ipos": body_ipos,
    "dof_frictionloss": frictionloss,
    "dof_armature": armature,
    "body_mass": body_mass,
    "qpos0": qpos0,
    "actuator_gainprm": actuator_gainprm,
    "actuator_biasprm": actuator_biasprm,
})

变化掩码

同时返回 in_axes 参数变化掩码,指示哪些参数发生了变化:

in_axes = jax.tree_util.tree_map(lambda x: None, model)
in_axes = in_axes.tree_replace({
    "geom_friction": 0,         # 第一个维度变化
    "body_ipos": 0,
    # ...
})

这用于 JAX 的 vmap 映射机制,确保正确广播。

域随机化的作用

域随机化在 sim-to-real 迁移中发挥关键作用:

  1. 弥合仿真-现实差距:真实机器人存在制造公差、舵机性能差异、地面条件变化等
  2. 提高鲁棒性:策略学会适应各种物理参数变化,而不是过拟合到特定值
  3. 避免脆弱行为:防止策略利用仿真中的物理漏洞(如过大的摩擦力)
  4. 便于部署:策略在多种条件下训练,无需为每个机器人单独微调

与训练系统的集成

runner.py 中,域随机化函数作为参数传递给 PPO 训练器:

self.randomizer = randomize.domain_randomize

train_fn = functools.partial(
    ppo.train,
    randomization_fn=self.randomizer,  # 注入域随机化
    ...
)

PPO 训练器会在每个训练步调用此函数,随机化环境参数,使得策略在每次交互中面对略有不同的物理世界。

纠错,疑问,交流: 请进入讨论区请点击进入页面,扫码加入微信群或Q群进行交流

获取最新文章: 扫一扫加入“创客智造”公众号

欢迎加入我们的openduckmini交流群,微信扫描右侧二维码立即进群交流

群二维码

标签: OpenDuckMini强化学习框架