How to Configure Head COM Randomization in Microduck RL: A Complete Guide

Enable ENABLE_HEAD_COM_RANDOMIZATION, adjust HEAD_COM_RANDOMIZATION_RANGE for magnitude, and customize HEAD_BODY_NAMES to control which head bodies receive randomized center-of-mass offsets each episode.

Head center-of-mass (COM) randomization is a critical domain-randomization technique in the Microduck RL repository that improves sim-to-real transfer by varying the mass distribution of the robot's head assembly every episode. This training-time randomization forces the policy to become robust to manufacturing tolerances and assembly variations in the real Pollen Robotics Microduck platform.

Understanding Head COM Randomization in Microduck RL

Microduck RL implements non-accumulating head COM randomization through a five-part configuration system in microduck_velocity_env_cfg.py. Unlike physics parameters that drift over time, each episode applies fresh random offsets, ensuring stable long-term training behavior.

Key Implementation Files

Step 1: Enable Head COM Randomization

The boolean flag ENABLE_HEAD_COM_RANDOMIZATION located at src/mjlab_microduck/tasks/microduck_velocity_env_cfg.py#L30-L33 controls whether the feature is active.


# Default configuration (enabled)

ENABLE_HEAD_COM_RANDOMIZATION: bool = True

Setting this to False completely disables the randomization pipeline, useful for deterministic debugging or ablation studies.

Step 2: Configure the Randomization Range

HEAD_COM_RANDOMIZATION_RANGE at src/mjlab_microduck/tasks/microduck_velocity_env_cfg.py#L58-L66 specifies the ± range in meters applied to each head body's COM. The default value is ±0.003 m (3 mm).


# Default 3mm range

HEAD_COM_RANDOMIZATION_RANGE: float = 0.003

# Increased robustness: 5mm range

HEAD_COM_RANDOMIZATION_RANGE: float = 0.005

This value serves as the initial range; curriculum learning typically expands it during training.

Step 3: Specify Affected Head Bodies

HEAD_BODY_NAMES at src/mjlab_microduck/tasks/microduck_velocity_env_cfg.py#L66-L72 defines which bodies undergo COM randomization using regex patterns.


# Default: comprehensive head assembly coverage

HEAD_BODY_NAMES: tuple[str, ...] = (
    "neck",
    "neck_pitch",
    "yaw_roll_motion",
    "(bottom_head_shell|jaw_soft)",
)

Each regex matches body names in the MJCF model. The tuple structure allows precise control over which mechanical components experience mass distribution shifts.

Step 4: Wire Randomization into Episode Events

The EventTermCfg named randomize_head_com at src/mjlab_microduck/tasks/microduck_velocity_env_cfg.py#L420-L426 hooks the randomization into the environment's event system, triggering at episode start.

Step 5: Ramp with Curriculum Learning

The CurriculumTermCfg named head_com_range at src/mjlab_microduck/tasks/microduck_velocity_env_cfg.py#L870-L878 progressively increases randomization difficulty:

  • Start: ±0.003 m at step 0
  • End: ±0.01 m at step 500,000

This curriculum schedule prioritizes early policy stability before introducing challenging mass distributions.

Complete Configuration Example


# Custom microduck_velocity_env_cfg.py excerpt

from mjlab_microduck.tasks.microduck_velocity_env_cfg import (
    ENABLE_HEAD_COM_RANDOMIZATION,
    HEAD_COM_RANDOMIZATION_RANGE,
    HEAD_BODY_NAMES,
)
from mjlab.managers import CurriculumTermCfg, EventTermCfg

# 1. Enable feature

ENABLE_HEAD_COM_RANDOMIZATION = True

# 2. Set 5mm randomization range

HEAD_COM_RANDOMIZATION_RANGE = 0.005

# 3. Restrict to neck and rigid head components

HEAD_BODY_NAMES = (
    "neck",
    "neck_pitch",
    "yaw_roll_motion",
    "bottom_head_shell",  # note: removed jaw_soft for this variant

)

# 4. Custom curriculum: faster ramp to 10mm

head_com_curriculum = CurriculumTermCfg(
    name="head_com_range",
    start_step=0,
    end_step=300_000,      # faster progression

    start_val=0.003,
    end_val=0.010,
    event_name="randomize_head_com",
)

Disabling Head COM Randomization

For reproducible debugging or hardware validation:


# Deterministic configuration

from mjlab_microduck.tasks.microduck_velocity_env_cfg import (
    ENABLE_HEAD_COM_RANDOMIZATION,
)

ENABLE_HEAD_COM_RANDOMIZATION = False

# Remove or comment out the curriculum entry to prevent warnings

Advanced: Multi-Task Randomization Strategies

Different Microduck variants implement head COM randomization with task-specific defaults:

Task File Default Range Curriculum End Range
microduck_velocity_env_cfg.py ±3 mm ±10 mm
microduck_velocity_rollers_env_cfg.py ±3 mm ±10 mm
microduck_standup_env_cfg.py ±3 mm ±8 mm

Copy configuration patterns between these files when developing new locomotion behaviors requiring robust head control.

Summary

  • Enable/disable head COM randomization via ENABLE_HEAD_COM_RANDOMIZATION boolean flag
  • Control magnitude through HEAD_COM_RANDOMIZATION_RANGE (meters) and head_com_range curriculum
  • Select bodies by editing HEAD_BODY_NAMES regex tuple to match specific MJCF body names
  • Verify implementation in microduck_velocity_env_cfg.py lines 30–33, 58–72, 420–426, and 870–878
  • Leverage non-accumulating behavior for stable long-duration training runs

Frequently Asked Questions

What happens if I increase HEAD_COM_RANDOMIZATION_RANGE too aggressively?

Excessive range values (above ±15 mm) can destabilize the head control policy, causing training failures or erratic behaviors. The default curriculum smoothly ramps from 3 mm to 10 mm over 500k steps to avoid this. Monitor the head_pose tracking error in TensorBoard when adjusting ranges.

Does head COM randomization affect all Microduck RL tasks?

According to the source code, the walking (microduck_velocity), roller (microduck_velocity_rollers), and stand-up (microduck_standup) tasks all implement head COM randomization. New tasks must explicitly configure randomize_head_com in their event tables and optionally add head_com_range curricula.

Can I randomize COM for other body parts using the same mechanism?

Yes. The mdp.py helper functions support arbitrary body lists. Create a new EventTermCfg with your custom body regex tuple and wire it through a corresponding curriculum term. The head-specific implementation serves as the reference pattern.

How do I verify my head COM randomization configuration is active?

Run the unit test in tests/test_swizzle_head_cfg.py which validates the head_pose command presence and confirms ENABLE_HEAD_COM_RANDOMIZATION is properly honored. Additionally, enable Isaac Sim's visualization to observe COM markers shifting at episode boundaries.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →