# What Is the BAM Actuator Model in Microduck RL? Understanding the BAM M6 Implementation

> Explore the BAM actuator model in Microduck RL. Understand how it emulates Dynamixel servos for robot control and its M6 implementation.

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

---

**Microduck RL uses the BAM M6 actuator model to emulate the Dynamixel XL330 servos that power the robot.**

The Microduck RL repository from Pollen Robotics implements a physics-based reinforcement learning pipeline for a quadruped robot. At the heart of its simulation fidelity lies a specific actuator model that bridges the gap between idealized physics and real-world hardware behavior. This article explains the BAM M6 actuator model, its configuration, and how it integrates into the broader Microduck RL system according to the source code at `pollen-robotics/microduck_rl`.

## What Is the BAM M6 Actuator Model?

The **BAM M6** is a full-voltage-control actuator model designed to replicate the dynamics of the **XL330 servo motors** used on the physical Microduck robot. BAM stands for "Battery, Actuator, Motor" — a modeling framework that captures the interaction between power supply voltage sag, motor torque generation, and load-dependent friction.

According to the repository's constant definitions in [`src/mjlab_microduck/robot/microduck_constants.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/robot/microduck_constants.py), the M6 model is selected via the `model="m6"` parameter:

```python
_BAM_ACTUATOR_KWARGS = dict(
    motor_name="xl330",
    model="m6",                     # ← the BAM M6 model

    target_names_expr=(r"^(?!passive_).*",),
    kp_fw=200.0,
    vin_range=(6.5, 8.2),
    vin_drop_gain_range=(0.0, 0.2),
    vin_min=6.0,
    delay_min_lag=3,
    delay_max_lag=6,
)

```

The M6 designation refers to a specific firmware-calibrated parameter set derived from real XL330 test-bench measurements, stored in [`params/xl330/m6_new.json`](https://github.com/pollen-robotics/microduck_rl/blob/main/params/xl330/m6_new.json).

## Key Features of the BAM M6 Actuator

The BAM M6 actuator model incorporates several physical effects that distinguish it from ideal torque sources:

- **Voltage-controlled torque generation** — Torque is computed from commanded voltage using a proportional gain (`kp_fw=200.0`) rather than direct torque commands

- **Domain-randomized supply voltage** — Battery voltage varies per episode within `vin_range=(6.5, 8.2)` volts, with sag modeling via `vin_drop_gain_range`

- **Load-dependent friction randomization** — Per-joint friction scales are randomized each episode through the `FrictionDRBamActuatorCfg` class

- **Actuator delay modeling** — Response latency is simulated with `delay_min_lag=3` to `delay_max_lag=6` timesteps of delay

These features combine to create a **sim-to-real transferable** actuation model that matches the nonlinear, voltage-limited behavior of actual servo hardware.

## How the BAM M6 Actuator Is Instantiated in Microduck RL

The repository provides two actuator configurations built from the same M6 parameter kernel. Both use the `_BAM_ACTUATOR_KWARGS` dictionary defined above.

### Standard Friction-Randomized Configuration

```python
from mjlab_microduck.robot.microduck_constants import MICRODUCK_WALK_ROBOT_CFG

# The walk robot config embeds the BAM M6 actuator

robot_cfg = MICRODUCK_WALK_ROBOT_CFG

# Start a simulation with this configuration

import mujoco
spec = robot_cfg.spec_fn()
model = spec.compile()
data = mujoco.MjData(model)

```

The `actuators` object is created as:

```python
actuators = FrictionDRBamActuatorCfg(**_BAM_ACTUATOR_KWARGS)

```

### Backlash-Aware Configuration

For variants that model encoder backlash, the same M6 kernel is reused:

```python
backlash_actuators = BacklashEncoderBamActuatorCfg(**_BAM_ACTUATOR_KWARGS)

```

This design ensures consistent voltage-control dynamics regardless of which encoder model is active.

## Validating the BAM M6 Model Against Real Hardware

The repository includes a dedicated validation script that reproduces the BAM M6 kernel logic in a standalone MuJoCo rollout. This script compares simulation predictions against recordings from physical XL330 test-bench experiments.

Run the validation with:

```bash
uv run python3 scripts/validate_bam_testbench.py --max-files 3 --plot

```

The script loads [`params/xl330/m6_new.json`](https://github.com/pollen-robotics/microduck_rl/blob/main/params/xl330/m6_new.json) and exercises the identical voltage-control law, friction budget, and delay model used by the `FrictionDRBamActuatorCfg` class. This validation step confirms that the BAM M6 actuator accurately captures the hardware's dynamic response.

## Core Files for the BAM M6 Actuator Implementation

| File | Purpose |
|------|---------|
| [`src/mjlab_microduck/robot/microduck_constants.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/robot/microduck_constants.py) | Defines `_BAM_ACTUATOR_KWARGS` and instantiates `actuators` and `backlash_actuators` |
| [`src/mjlab_microduck/actuator/friction_dr_bam.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/actuator/friction_dr_bam.py) | Implements `FrictionDRBamActuatorCfg` with per-episode friction randomization |
| [`src/mjlab_microduck/actuator/backlash_encoder_bam.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/actuator/backlash_encoder_bam.py) | Implements `BacklashEncoderBamActuatorCfg` for backlash modeling |
| [`scripts/validate_bam_testbench.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/scripts/validate_bam_testbench.py) | Validates BAM M6 dynamics against real XL330 test-bench data |
| [`src/mjlab_microduck/tasks/mdp.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/tasks/mdp.py) | Contains `randomize_joint_friction_bam()` for episode-level friction sampling |

## Summary

- The **BAM M6 actuator model** is the core actuation model in Microduck RL, representing XL330 servo dynamics
- It uses **voltage-controlled torque generation** with `kp_fw=200.0` and domain-randomized battery voltage
- Two configurations exist: standard `FrictionDRBamActuatorCfg` and `BacklashEncoderBamActuatorCfg`, both sharing the same M6 parameter kernel
- The model is validated against real hardware via [`scripts/validate_bam_testbench.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/scripts/validate_bam_testbench.py)
- All definitions reside in [`src/mjlab_microduck/robot/microduck_constants.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/robot/microduck_constants.py)

## Frequently Asked Questions

### What does BAM stand for in the actuator model name?

BAM stands for **Battery, Actuator, Motor**. It describes a modeling framework that couples power supply dynamics (voltage sag), actuator control electronics, and motor physics into a unified simulation model. The M6 variant specifically refers to a parameter set calibrated for XL330 servos with firmware version M6.

### How does the BAM M6 model improve sim-to-real transfer?

The BAM M6 improves sim-to-real transfer by replicating **voltage-limited torque production**, **load-dependent friction**, and **battery voltage sag** — effects that dominate real servo behavior but are absent from ideal torque sources. Domain randomization over `vin_range`, `vin_drop_gain_range`, and per-joint friction scales during training ensures policies remain robust to these physical variations.

### Can I use the BAM M6 actuator with other motors besides the XL330?

While the `model="m6"` parameter is specifically calibrated for XL330 dynamics, the underlying `FrictionDRBamActuatorCfg` class can accept different motor parameter files. You would need to provide a compatible JSON parameter file with the same schema as [`params/xl330/m6_new.json`](https://github.com/pollen-robotics/microduck_rl/blob/main/params/xl330/m6_new.json) and update `motor_name` accordingly. The voltage-control architecture remains applicable to other low-impedance servo motors.