域随机化¶
本页仅描述仓库中那些已经注册、且已经接入 DR provider 的任务的当前状态。所有结论都来自代码;不从设计意图推断任何内容。
当前统一的入口点位于 NpEnv._init_domain_randomization() 和 DomainRandomizationManager:
init 路径:task provider 产生一个
InitRandomizationPlan;manager 在 env 初始化期间调用后端的apply_init_randomization(...)reset 路径:task provider 产生一个
ResetPlan;manager 验证能力,然后调用后端的set_state(..., randomization=...)interval 路径:task provider 产生一个
IntervalRandomizationPlan;manager 在 step 之前按需调用后端的apply_interval_randomization(...)
这三条路径对应三个生命周期类别:
init 生命周期 DR:改变模型 identity 或模型几何的项;只能在 env/backend 初始化和 materialization 期间生效,例如 Sharpa 手物体的
geom_size缩放。reset 生命周期 DR:不改变模型 identity,只在同一模型内改变参数或 reset 状态的项,例如
base_mass_delta、base_com_offset、gravity、kp、kd。interval 生命周期 DR:step 之间的外部扰动,例如 push。
状态结论¶
当前所有接入 DR provider 的任务都使用统一的 DR 入口点;没有任何任务绕开
DomainRandomizationManager在reset()内部运行单独的 DR 流程。它们的结构都大致相同:task 文件定义一个
domain_rand配置 dataclass、一个DomainRandomizationProvider和一个ResetPlan;G1WalkFlat复用G1Walk的 provider。今天所”统一”的主要是入口点和执行流程,而不是每一个随机化项本身。共享辅助函数
build_common_reset_randomization()目前生成base_mass_delta、base_com_offset、gravity、kp、kd;共享的 interval 辅助函数目前只生成 push。ResetRandomizationPayload已经可以表达gravity、body_iquat、body_inertia、kp、kd,并且MuJoCoBackend已声明支持。这些是否实际被使用,仍取决于 task provider 是否对它们进行采样和 dispatch。MotrixBackend目前支持base_mass_delta、base_com_offset、kp、kd和 interval push;并且它要求在初始化期间所有模型 actuator 都是 position actuator。geom_size不是 reset 生命周期字段;Sharpa 手物体的 geom 缩放由 init 生命周期的模型 materialization 处理。
统一性评估表¶
Task |
使用统一 DR 入口? |
结构化形式? |
reset 形式 |
interval 形式 |
Code |
|---|---|---|---|---|---|
|
是 |
是: |
task 状态采样 + common payload |
push |
|
|
是 |
是: |
task 状态采样 + common payload |
push |
|
|
是 |
是: |
task 状态采样 + common payload |
push |
|
|
是 |
是:复用 |
task 状态采样 + common payload |
push |
|
|
是 |
是: |
大量 task 专属的 reset 采样 + common payload |
push |
|
|
是 |
是: |
task 专属的 reset 采样 + common payload |
无 |
|
|
是 |
是: |
grasp cache 采样 + common payload |
物体 |
|
|
是 |
是:复用 Sharpa rotation provider 并 override reset 采样 |
grasp 收集 reset + common payload |
无 |
|
各任务域随机化清单¶
Task |
当前已实现的 reset 域随机化 |
当前已实现的 interval 域随机化 |
默认状态 |
|---|---|---|---|
|
base xy;base yaw;base qvel;command 采样; |
|
|
|
base xy;base yaw;base qvel;command 采样; |
|
kp/kd 默认启用;common payload 和 push 默认禁用 |
|
base xy;base yaw;由 |
|
kp/kd 默认启用;common payload 和 push 默认禁用 |
|
与 |
|
kp/kd 默认启用;common payload 和 push 默认禁用 |
|
动作帧采样;root 位姿扰动 |
|
|
|
若存在 grasp cache,则随机采样一个 grasp;否则对手部关节施加 |
无 |
若 grasp cache 路径可用则默认采样; |
|
grasp cache 按 |
物体 |
|
|
手部位姿 reset;物体位姿 / quat reset;收集成功的 grasp 并按 |
无 |
默认用于生成 Sharpa grasp cache;cache 文件名包含单个 scale 值;common payload 默认禁用 |
当前统一 DR 的能力与边界¶
1. 统一入口点是完整的¶
统一入口点由 NpEnv 和 DomainRandomizationManager 保证:
任务只需注册一个 provider
manager 统一执行能力验证
后端统一负责实际施加随机化 payload
因此从执行路径的角度看,这些任务已经是统一的。
2. 共享辅助函数仍然较窄¶
dr_utils.py 目前只有两类共享辅助函数:
reset common payload:
base_mass_delta、base_com_offset、gravity、kp、kdinterval common payload:push
这意味着:
尽管运动控制任务都走统一入口点,但它们的 base xy、yaw、qvel、command 和 gait phase 仍然直接在各自的 provider 内部采样
G1MotionTracking的 pose / velocity / joint 噪声也是 task 专属逻辑Allegro 的 grasp / 物体初始状态采样完全是 task 专属逻辑
Sharpa 的
geom_size缩放是 init 生命周期的模型 materialization,不属于 reset common payload
所以今天的”统一性”更多是关于 contract 和调用约定,而不是”所有任务共享同一套随机化项 schema”。
3. 后端能力已经超出任务当前使用的范围¶
ResetRandomizationPayload 现在包含:
base_mass_deltabase_com_offsetgravitybody_iquatbody_inertiakpkd
当前的后端能力:
MuJoCoBackend:支持上述 7 个 reset 项,外加 interval push 和 interval body forceMotrixBackend:支持base_mass_delta、base_com_offset、kp、kd,外加 interval push;要求在初始化期间 actuator 全部为 position actuator
说明:
当前的
IntervalRandomizationPlan支持push_perturbation_limit、body_linear_velocity_delta和body_force;其中body_force表达热路径上的直接外力扰动,而不暴露后端私有的xfrc_applied细节。当前 MuJoCo 后端的 interval push 和 interval body force 都通过
xfrc_applieddispatch;Sharpa 手物体扰动已切换为直接力扰动。Motrix 后端目前仍不支持直接 body-force 扰动,因此这类 owner 配置必须继续显式禁用。
但在任务侧,当前的现实是:并非每个 provider 都构造这些字段。后端 contract 是能力边界;task 配置和 provider 是否 dispatch 一个 payload,才决定了某个任务是否实际启用对应的 DR 项。
Reset gravity 用法¶
gravity 是一个 reset 生命周期 DR:在每次 reset 时,会按 env 子集采样一个完整的 MuJoCo gravity 向量 (gx, gy, gz),并通过 ResetRandomizationPayload.gravity dispatch 到后端。该向量同时表达方向和大小:
方向:由
(gx, gy, gz)的方向决定。大小:由向量范数
sqrt(gx^2 + gy^2 + gz^2)决定。生命周期:仅在 reset 时采样和写入;env 会保留该重力,直到下一次 reset 重新采样。
后端:当前在 UniLab 中,只有 MuJoCo 后端声明支持该 reset 项;Motrix 后端不支持。一些任务按能力过滤并跳过它;另一些任务在 validate 阶段抛出错误。
配置入口在每个任务的 env.domain_rand 下:
env:
domain_rand:
randomize_gravity: true
gravity_range:
- [-0.2, -0.2, -10.5]
- [0.2, 0.2, -8.5]
字段语义:
randomize_gravity:是否启用 gravity reset DR;默认为false。gravity_range:一个形状为(2, 3)的逐维采样范围;第一行和第二行给出每个分量的上界和下界。在每次 reset 时,每个维度在
[min(row0, row1), max(row0, row1)]内均匀采样。方向不会自动归一化,重力范数也不固定。
如果你只想随机化大小而保持竖直向下的方向,只开放 z 分量:
uv run train --algo ppo --task g1_walk_flat --sim mujoco \
env.domain_rand.randomize_gravity=true \
'env.domain_rand.gravity_range=[[0.0,0.0,-10.5],[0.0,0.0,-8.5]]'
如果你想同时随机化方向和大小,开放 x/y/z:
uv run train --algo ppo --task g1_walk_flat --sim mujoco \
env.domain_rand.randomize_gravity=true \
'env.domain_rand.gravity_range=[[-0.3,-0.3,-10.5],[0.3,0.3,-8.5]]'
说明:
gravity_range必须可转换为(2, 3)数组;否则 reset 在构造 payload 时会抛出错误。该项不调用
mj_setConst;MuJoCo step / forward 直接读取mjModel.opt.gravity。不要在 Motrix 后端下启用该项;当前 Motrix 能力不包含
gravity。如果你当前的环境仍安装了不包含
gravity字段的mujoco-uni包,MuJoCo reset 会抛出 unsupported field;你需要使用包含该字段的mujoco-uni构建/发布版本。在训练期间,建议从较小的倾斜范围开始;否则在早期采样到过大的水平重力,可能会使任务退化为不可学习。
Interval push 用法¶
支持 interval push 的任务在 env.domain_rand 下配置它:
env:
domain_rand:
push_robots: true
push_interval: 750
max_force: [1.0, 1.0, 0.5]
push_body_name: null
push_robots:是否启用 push。push_interval:每 N 个 env step 触发一次。max_force:一个长度为 3 的外力上限;每个维度在[-max_force, max_force]内采样。push_body_name:施加力的目标 body / link。默认为null,表示使用后端的base_name。
uv run train --algo ppo --task g1_walk_flat --sim mujoco \
env.domain_rand.push_robots=true \
env.domain_rand.push_interval=500 \
'env.domain_rand.max_force=[20.0,20.0,5.0]' \
env.domain_rand.push_body_name=torso_link
说明:
MuJoCo 按 body name 解析,Motrix 按 link name 解析;缺失的 name 会在 env/backend 初始化期间抛出错误。
push_body_name是一个 init 配置;在 env 创建之后修改它不会改变已经解析的目标。热路径只采样和施加外力;它不解析 XML / asset,也不探测后端私有能力。
MuJoCo push 通过
xfrc_applied外力实现,不直接覆盖 base 速度。
geom_size 生命周期边界¶
geom_size 明确不属于 ResetRandomizationPayload,并且不得在热路径上通过 BatchEnvPool.reset(..., randomization=...) 修改。
原因在于 geom_size 会改变模型几何和模型 identity;正确的生命周期是:
task provider 在
build_init_randomization_plan(...)中生成模型变体以及 env 到模型的分配。MuJoCo 后端在冷路径上使用
MjSpec修改 geom size,并编译 scale 专属的MjModel。后端使用长度为
num_envs的模型序列构造BatchEnvPool。
reset 阶段只在同一模型 identity 内执行状态和参数扰动;它不处理
geom_size。
这条边界存在的目的是遵循冷路径 asset/model-metadata 访问原则:step()、reset() 和热路径 DR 不解析 XML、不读取 asset,也不在运行时基于 asset 元数据进行分支。
相关任务¶
G1 Motion Tracking:开启 DR 前先确认 motion 资产和 replay。
Sharpa Inhand:scale / grasp cache / DR 边界更敏感。
Go2 Rough Terrain:常见的是 mass、COM、friction、push。
有关配置示例,请参阅 配置。有关开发者 provider 接口和后端能力边界,请参阅 编写 Provider 和 Domain Randomization Contract。