Domain Randomization Contract¶
Domain randomization is an env-owner provider contract plus backend capability application. User configuration examples live in Domain Randomization.
Lifecycle Classes¶
Init lifecycle: changes model identity or geometry. These changes run during env/backend initialization, materialization, or cache construction.
Reset lifecycle: changes state or parameters within the same model identity. Providers dispatch a reset randomization payload through
ResetPlan.Interval lifecycle: applies perturbations between steps, such as push or body force plans.
Hot paths must not parse XML/assets or probe backend private methods with
getattr or hasattr.
Provider Minimum¶
A task that uses DR should define:
A task-owned domain-randomization config dataclass.
A
DomainRandomizationProvider.Reset behavior returning
ResetPlanstate and randomization payloads.Interval behavior through
IntervalRandomizationPlanwhen needed.Env construction that calls
self._init_domain_randomization(...).
Shared types live in src/unilab/dr/types.py, and manager behavior lives in
src/unilab/dr/manager.py.
Backend Capability Boundary¶
Backend support is explicit. A reset or interval item only counts as a unified DR item when three pieces exist together:
ResetRandomizationPayloadorIntervalRandomizationPlanhas an explicit field.The backend declares and implements the capability.
The task config/provider samples and dispatches that field.
MuJoCo and Motrix differences stay in backend capability declarations, backend implementations, and owner YAMLs.
MuJoCo BatchEnvPool Snapshot¶
Current MuJoCo reset randomization uses BatchEnvPool.reset(..., randomization=...) with a fixed field whitelist. Indexed reads and writes are
available through get_field_indexed(...) and set_field_indexed(...). This
interface lives in the mujoco-uni package (mujoco.batch_env), not in this
repository; the reset-term constants that map onto it are in
src/unilab/dr/types.py.
The supported reset fields and their per-env block shapes are below. The leading
dimension is always len(env_ids); the trailing block size is the field’s full
flat width in a single mjModel.
Field |
Per-env block shape |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Refresh behavior is fixed by the backend: body_mass, body_ipos,
body_iquat, body_inertia, and dof_armature trigger an mj_setConst
refresh after the write, while gravity, geom_friction, kp, and kd do
not.
Two caveats:
geom_sizeis not inSUPPORTED_FIELDS. Geometry size is expressed through init-lifecycle model materialization (seeGeomSizeOverride/ModelVariantSpecinsrc/unilab/dr/types.py), not reset randomization.gravityreset randomization requires amujoco-unibuild that ships it. This repository pinsmujoco-uni==3.8.0, whoseSUPPORTED_FIELDSincludesgravity; older packages such as3.6.0.post6do not.
Motor Control Extension¶
Motor-actuator tasks that do not map policy output directly to backend position
actuators should keep conversion in the env owner layer. Register a pre-step
callback through SimBackend.set_pre_step_control(...); the backend calls it
before physics substeps and refreshes sensors after stepping.
Go2W is the current all-motor actuator example: its env owner combines leg position targets and wheel torque, while kp/kd randomization stays in the env owner cache rather than leaking MuJoCo position-actuator mechanics into shared payloads.
Evidence In Repo¶
DR types:
src/unilab/dr/types.pyDR manager:
src/unilab/dr/manager.pyBackend interface:
src/unilab/base/backend/base.pyExample providers:
src/unilab/envs/locomotion/g1/joystick.py,src/unilab/envs/motion_tracking/g1/tracking.py,src/unilab/envs/manipulation/sharpa_inhand/rotation.py