How Mass and Inertia Are Randomized in the Microduck RL Simulation
Microduck RL randomizes robot mass and inertia together using the dr.pseudo_inertia domain-randomization operation, applying a ±5% scale factor sampled once per environment at startup.
All Microduck reinforcement learning environments in the pollen-robotics/microduck_rl repository implement unified mass and inertia randomization through a single configuration flag and event registration pattern. This design ensures physics-consistent variations that improve policy robustness without destabilizing simulations. The implementation relies on mjlab's domain randomization API rather than direct parameter writes.
Configuration Flag and Range
Each environment exposes a boolean toggle ENABLE_MASS_INERTIA_RANDOMIZATION to control whether randomization is active. In microduck_velocity_env_cfg.py, this flag defaults to True for velocity tracking tasks:
# From microduck_velocity_env_cfg.py lines 35-53
ENABLE_MASS_INERTIA_RANDOMIZATION = True
The randomization magnitude is controlled by the MASS_INERTIA_RANDOMIZATION_RANGE constant set to (0.95, 1.05) at line 73, representing a symmetric ±5% variation around the nominal mass and inertia values.
Pseudo-Inertia Event Registration
When enabled, the environment registers a startup event named randomize_mass_inertia that invokes dr.pseudo_inertia. This operation is defined in microduck_velocity_env_cfg.py lines 60-68:
cfg.events["randomize_mass_inertia"] = EventTermCfg(
func=dr.pseudo_inertia,
mode="startup",
params={
"asset_cfg": SceneEntityCfg("robot", body_names=("trunk_base",)),
"alpha_range": (
math.log(MASS_INERTIA_RANDOMIZATION_RANGE[0]) / 2.0,
math.log(MASS_INERTIA_RANDOMIZATION_RANGE[1]) / 2.0,
),
},
)
The alpha_range parameter converts the desired mass-scale bounds using the relation e^{2α} ∈ [0.95, 1.05]. This logarithmic transformation ensures uniform sampling in scale space rather than in linear alpha space.
How Pseudo-Inertia Scaling Works
The dr.pseudo_inertia function computes a scalar α per environment and applies a joint transformation to both mass and inertia:
- Mass scaling: body mass multiplied by
e^{2α} - Inertia scaling: inertia tensor multiplied by
e^{2α} - Center of mass: remains unchanged
This coupling preserves the dynamic consistency of the rigid body—scaling mass and inertia together maintains the same natural frequency characteristics that would result from uniform density variations or added payload.
Startup Mode: Fixed Per-Environment Sampling
The event uses mode="startup" (line 64), meaning:
- The random scale is sampled once per environment at the beginning of training
- The same scale persists across all episode resets within that environment
- No accumulation or re-randomization occurs during execution
This matches standard "mass DR" behavior in mjlab and prevents numerical drift from repeated multiplicative updates.
Consistent Pattern Across All Microduck Environments
Every Microduck task implements identical mass and inertia randomization. The following environment configuration files repeat the same pattern with the same flag name and range constant:
microduck_standup_env_cfg.pylines 52-62microduck_spin_env_cfg.pymicroduck_sitstand_env_cfg.pymicroduck_roulade_env_cfg.pymicroduck_roller_crouch_env_cfg.pymicroduck_ground_pick_env_cfg.pymicroduck_ball_kick_env_cfg.py
Disabling Mass and Inertia Randomization
To disable randomization in a custom environment configuration, set the flag to False or omit the event registration entirely:
ENABLE_MASS_INERTIA_RANDOMIZATION = False
Legacy Implementation (Deprecated)
The repository contains an older helper randomize_mass_and_inertia in mdp.py lines 3243-3295 that directly wrote to body_mass and body_inertia. This implementation is deprecated and non-functional under mjlab 1.3.0 because those writes are not expanded per-environment, making the operation a no-op. The dr.pseudo_inertia method supersedes this legacy approach.
Complete Configuration Example
import math
from omni.isaac.lab.utils import configclass
from omni.isaac.lab.envs.mdp import EventTermCfg
from omni.isaac.lab.assets import SceneEntityCfg
import omni.isaac.lab.envs.mdp as dr
# Toggle and range
ENABLE_MASS_INERTIA_RANDOMIZATION = True
MASS_INERTIA_RANDOMIZATION_RANGE = (0.95, 1.05)
@configclass
class CustomMicroduckEnvCfg:
def __post_init__(self):
# ... other environment setup ...
if ENABLE_MASS_INERTIA_RANDOMIZATION:
self.events["randomize_mass_inertia"] = EventTermCfg(
func=dr.pseudo_inertia,
mode="startup",
params={
"asset_cfg": SceneEntityCfg(
"robot",
body_names=("trunk_base",)
),
"alpha_range": (
math.log(MASS_INERTIA_RANDOMIZATION_RANGE[0]) / 2.0,
math.log(MASS_INERTIA_RANDOMIZATION_RANGE[1]) / 2.0,
),
},
)
Summary
- Unified operation:
dr.pseudo_inertiarandomizes mass and inertia together usinge^{2α}scaling - Fixed range: ±5% variation controlled by
MASS_INERTIA_RANDOMIZATION_RANGE = (0.95, 1.05) - Startup sampling: Each environment gets one random scale at initialization, held constant across episodes
- Configuration flag:
ENABLE_MASS_INERTIA_RANDOMIZATIONboolean controls activation per environment - Consistent implementation: All Microduck tasks use identical patterns in their
*_env_cfg.pyfiles - Legacy superseded: Direct
body_mass/body_inertiawrites inmdp.pyare deprecated
Frequently Asked Questions
What is the exact randomization range for mass and inertia in Microduck RL?
The range is ±5% around nominal values, defined by MASS_INERTIA_RANDOMIZATION_RANGE = (0.95, 1.05) in each environment configuration file. Both mass and inertia tensor scale by the same factor within this interval.
Why does Microduck use dr.pseudo_inertia instead of direct mass writes?
dr.pseudo_inertia scales mass and inertia together while preserving center-of-mass location, maintaining physical consistency. Direct writes to body_mass and body_inertia (as in the deprecated mdp.py helper) are not expanded per-environment in mjlab 1.3.0 and produce no effect.
Is mass randomization resampled every episode?
No. The mode="startup" setting means each environment samples its mass/inertia scale once at training initialization and holds it fixed for all subsequent episodes. This prevents numerical accumulation while still providing inter-environment diversity for robust policy training.
How do I change the randomization strength in a custom Microduck environment?
Modify MASS_INERTIA_RANDOMIZATION_RANGE in your environment's configuration file. For example, (0.90, 1.10) would give ±10% variation. The alpha_range is automatically recomputed from your bounds using math.log(bound) / 2.0.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →