Domain Randomization¶
This page only describes the current domain randomization status of registered tasks in the repo. All conclusions come from the code; nothing is inferred from design intent.
Two DR declaration paths exist today:
Manager-Based (Compatible) tasks: reset / interval randomization is declared through Hydra
events:manager terms in the owner YAML; reset-lifecycle events sample at reset, interval-lifecycle events perturb between steps. See theevents:block ofsrc/unilab/conf/ppo/task/go1_joystick_flat/base.yamlfor an example.Task-level provider path: custom tasks (including tasks hosted in external repos) may declare
env.domain_rand.*configuration through aDomainRandomizationProvider+DomainRandomizationManager. No in-repo task currently uses this path.
The unified entry point of the legacy provider path lives in NpEnv._init_domain_randomization() and DomainRandomizationManager:
init path: the task provider produces an
InitRandomizationPlan; the manager calls the backend’sapply_init_randomization(...)during env initializationreset path: the task provider produces a
ResetPlan; the manager validates capability and then calls the backend’sset_state(..., randomization=...)interval path: the task provider produces an
IntervalRandomizationPlan; the manager calls the backend’sapply_interval_randomization(...)as needed before step
These three paths correspond to three lifecycle classes:
init-lifecycle DR: items that change the model identity or model geometry; can only take effect during env/backend initialization and materialization, e.g. object
geom_sizescaling via model variants.reset-lifecycle DR: items that do not change model identity, only change parameters or reset state within the same model, e.g.
base_mass_delta,base_com_offset,gravity,kp,kd.interval-lifecycle DR: external perturbations between steps, e.g. push.
Status Conclusions¶
Manager-Based tasks do not register a DR provider; their reset/interval randomization consists of
events:manager terms in the owner YAML, executed uniformly by the manager lifecycle. Custom tasks on the provider path instead go through theDomainRandomizationManagerunified entry point.Provider-path owners define a
domain_randconfig dataclass, aDomainRandomizationProvider, and aResetPlan; Manager-Based owners declare reset behavior through Hydra command/event terms. G1 motion reset perturbations belong toMotionCommandCfg, while WBT addsEventTermCfgreset and interval terms.What is “unified” today is mainly the entry point and execution flow, not every randomization item itself. The legacy path’s shared helper
build_common_reset_randomization()currently generatesbase_mass_delta,base_com_offset,gravity,kp,kd.ResetRandomizationPayloadcan already expressgravity,body_iquat,body_inertia,kp,kd, andMuJoCoBackendhas declared support. Whether these are actually used still depends on whether the task provider samples and dispatches them.MotrixBackendcurrently supportsbase_mass_delta,base_com_offset,kp,kd, and interval push; and it requires all model actuators to be position actuators during initialization.geom_sizeis not a reset-lifecycle field; object geom scale is handled by init-lifecycle model materialization.
Uniformity Assessment Table¶
Task |
Declaration path |
Structured form? |
reset form |
interval form |
Code |
|---|---|---|---|---|---|
|
Hydra |
Yes: owner YAML declares reset/interval events |
root-state reset + base mass/COM + |
|
|
|
Hydra |
Yes: owner YAML declares reset events |
root-state reset + |
none |
|
|
Hydra |
Yes: Hydra |
root-state reset + kp/kd via |
none |
|
|
Hydra |
Yes: same Manager-Based event terms as |
root-state reset + kp/kd via |
none |
|
|
Hydra command term |
Yes: Hydra |
motion frame, root pose/velocity, and joint-position sampling |
none |
|
|
Hydra |
Yes: same motion command + Hydra |
motion reset plus mass/COM/PD/friction/encoder-bias events |
interval velocity kick |
|
|
Hydra |
Yes: Hydra |
entity-scoped hand/ball reset |
none |
|
|
Hydra |
Yes: reuses the rotation reset event + |
noisy hand reset + grasp collection |
none |
|
Per-task Domain Randomization List¶
Task |
Currently implemented reset domain randomization |
Currently implemented interval domain randomization |
Default state |
|---|---|---|---|
|
base xy/yaw and base qvel via |
|
all listed event terms are declared and enabled by default in |
|
base xy/yaw and base qvel via |
none |
event terms declared and enabled by default in |
|
base xy/yaw and base qvel via |
none |
kp/kd enabled on mujoco owners by default; disabled on motrix/mjwarp owners |
|
Same as |
none |
Same defaults as |
|
Motion-command frame sampling; root pose perturbation |
none |
|
|
Same motion reset plus base mass, base COM, PD gain, foot friction, and encoder-bias event terms |
|
The WBT owner explicitly enables all listed event terms; unsupported capabilities raise rather than fall back |
|
Entity-scoped hand/ball reset; an explicitly configured grasp cache is sampled, otherwise |
none |
owner YAML explicitly selects the home pose and zero reset noise; a configured missing or malformed cache fails closed |
|
Reuses the rotation reset with |
none |
generates the 50k-row Allegro grasp cache and raises |
Current Unified DR Capabilities and Boundaries¶
1. The Legacy Provider Entry Point Is Unified¶
The unified entry point of the legacy provider path is guaranteed by NpEnv
and DomainRandomizationManager:
Tasks only need to register a provider
The manager uniformly performs capability validation
The backend is uniformly responsible for actually applying the randomization payload
So from an execution-path perspective, provider-path tasks are unified;
Manager-Based tasks instead execute the events: terms declared in the owner
YAML through the manager lifecycle.
3. Backend Capabilities Already Exceed What Tasks Currently Use¶
ResetRandomizationPayload now contains:
base_mass_deltabase_com_offsetgravitybody_iquatbody_inertiakpkd
Backend capability today:
MuJoCoBackend: supports the 7 reset terms above, plus interval push, interval body velocity delta (linear and world-frame angular), and interval body force/torqueMotrixBackend: supportsbase_mass_delta,base_com_offset,kp,kd, plus interval push; requires actuators to all be position actuators during initialization
Notes:
The current
IntervalRandomizationPlansupportspush_perturbation_limit,body_linear_velocity_delta,body_angular_velocity_delta,body_force, andbody_torque; among these,body_force/body_torqueexpress hot-path direct external-wrench perturbations without exposing the backend-privatexfrc_applieddetails.The current MuJoCo backend’s interval push and interval body force are both dispatched through
xfrc_applied.The Motrix backend currently still does not support direct body-force disturbance, so such owner configs must continue to be explicitly disabled.
But on the task side, the current reality is: not every provider constructs these fields. The backend contract is the capability boundary; whether the task config and provider dispatch a payload is what determines whether a given task actually enables the corresponding DR item.
Reset gravity Usage¶
gravity is a reset-lifecycle DR: on each reset, a full MuJoCo gravity vector (gx, gy, gz) is sampled per env subset and dispatched to the backend via ResetRandomizationPayload.gravity. This vector expresses both direction and magnitude:
Direction: determined by the direction of
(gx, gy, gz).Magnitude: determined by the vector norm
sqrt(gx^2 + gy^2 + gz^2).Lifecycle: only sampled and written at reset; the env retains that gravity until the next reset re-samples it.
Backend: currently in UniLab, only the MuJoCo backend declares support for this reset term; the Motrix backend does not. Some tasks filter it by capability and skip it; others raise an error in the validate stage.
The config entry lives under env.domain_rand in provider-path task owners;
Manager-Based tasks have no env.domain_rand:
env:
domain_rand:
randomize_gravity: true
gravity_range:
- [-0.2, -0.2, -10.5]
- [0.2, 0.2, -8.5]
Field semantics:
randomize_gravity: whether to enable gravity reset DR; defaults tofalse.gravity_range: a(2, 3)-shaped per-dimension sampling range; the first and second rows give the upper and lower bounds of each component.On each reset, each dimension is uniformly sampled within
[min(row0, row1), max(row0, row1)]. The direction is not automatically normalized, and the gravity norm is not fixed.
If you only want to randomize the magnitude while keeping the vertical-down direction, only open up the z component; to randomize both direction and magnitude, open up x/y/z. Enable it from the CLI with env.domain_rand.randomize_gravity=true and a env.domain_rand.gravity_range=[...] override on a provider-path task owner.
Notes:
gravity_rangemust be convertible into a(2, 3)array; otherwise reset will raise an error when constructing the payload.This term does not call
mj_setConst; MuJoCo step / forward readsmjModel.opt.gravitydirectly.Do not enable this term under the Motrix backend; the current Motrix capability does not include
gravity.If your current environment still has a
mujoco-uni-runtimepackage installed that does not include thegravityfield, MuJoCo reset will raise unsupported field; you need to use amujoco-uni-runtimebuild/release that includes the field.During training it is recommended to start from a small tilt range; otherwise sampling a too-large horizontal gravity early on may degrade the task into being unlearnable.
Interval push Usage¶
Manager-Based tasks configure interval push through the env.events.push_robot
term. For example, src/unilab/conf/ppo/task/go1_joystick_flat/base.yaml uses
push_by_setting_velocity with a 15-second interval and per-axis velocity ranges.
uv run train --algo ppo --task go1_joystick_flat --sim mujoco \
'env.events.push_robot.interval_range_s=[10.0,10.0]'
geom_size Lifecycle Boundary¶
geom_size is explicitly not part of ResetRandomizationPayload, and must not be modified on the hot path via BatchEnvPool.reset(..., randomization=...).
The reason is that geom_size changes model geometry and model identity; the correct lifecycle is:
The task provider generates the model variants and env-to-model assignment in
build_init_randomization_plan(...).The MuJoCo backend modifies geom size on the cold path using
MjSpecand compiles scale-specificMjModels.The backend constructs
BatchEnvPoolwith a model sequence of lengthnum_envs.
The reset stage only performs state and parameter perturbations within the same model identity; it does not handle
geom_size.
This boundary exists to honor the cold-path asset/model-metadata access principle: step(), reset(), and hot-path DR do not parse XML, do not read assets, and do not branch at runtime based on asset metadata.