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

> Learn how to configure head COM randomization in Microduck RL. Adjust range and body names for effective episode randomization. Get started with our complete guide.

- Repository: [Pollen Robotics/microduck_rl](https://github.com/pollen-robotics/microduck_rl)
- Tags: how-to-guide
- Published: 2026-09-02

---

**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](https://github.com/pollen-robotics/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`](https://github.com/pollen-robotics/microduck_rl/blob/main/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

- [`src/mjlab_microduck/tasks/microduck_velocity_env_cfg.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/tasks/microduck_velocity_env_cfg.py) — main walking task configuration (lines 30–33, 58–66, 66–72, 420–426, 870–878)
- [`src/mjlab_microduck/tasks/microduck_velocity_rollers_env_cfg.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/tasks/microduck_velocity_rollers_env_cfg.py) — roller variant with identical randomization setup
- [`src/mjlab_microduck/tasks/microduck_standup_env_cfg.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/tasks/microduck_standup_env_cfg.py) — stand-up task configuration
- [`src/mjlab_microduck/tasks/mdp.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/tasks/mdp.py) — low-level helper functions for MJCF model manipulation
- [`tests/test_swizzle_head_cfg.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/tests/test_swizzle_head_cfg.py) — unit tests verifying configuration integrity

## 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`](https://github.com/pollen-robotics/microduck_rl/blob/develop/src/mjlab_microduck/tasks/microduck_velocity_env_cfg.py#L30-L33) controls whether the feature is active.

```python

# 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`](https://github.com/pollen-robotics/microduck_rl/blob/develop/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).

```python

# 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`](https://github.com/pollen-robotics/microduck_rl/blob/develop/src/mjlab_microduck/tasks/microduck_velocity_env_cfg.py#L66-L72) defines which bodies undergo COM randomization using regex patterns.

```python

# 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`](https://github.com/pollen-robotics/microducks/microduck_rl/blob/develop/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`](https://github.com/pollen-robotics/microduck_rl/blob/develop/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

```python

# 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:

```python

# 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`](https://github.com/pollen-robotics/microduck_rl/blob/main/microduck_velocity_env_cfg.py) | ±3 mm | ±10 mm |
| [`microduck_velocity_rollers_env_cfg.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/microduck_velocity_rollers_env_cfg.py) | ±3 mm | ±10 mm |
| [`microduck_standup_env_cfg.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/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`](https://github.com/pollen-robotics/microduck_rl/blob/main/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`](https://github.com/pollen-robotics/microduck_rl/blob/main/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`](https://github.com/pollen-robotics/microduck_rl/blob/main/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.