How Backlash Is Simulated in Microduck RL Environments: A Technical Deep-Dive
Backlash in Microduck RL environments is simulated through a three-layer system: passive hinge joints that model mechanical play, an actuator that reads encoder position through the backlash joint, and task configurations that retarget observations and rewards to preserve the original action space.
Microduck RL, developed by Pollen Robotics, implements realistic gearbox backlash simulation to bridge the gap between simulation and real-world hardware behavior. This article examines exactly how the microduck_rl repository achieves physically accurate backlash modeling without disrupting the learning pipeline's dimensionality.
The Three-Component Backlash Simulation System
The Microduck RL codebase implements backlash through three coordinated components: geometry modification, actuator feedback adjustment, and task configuration adaptation.
Geometry: Passive Backlash Joints via add_backlash.py
The foundation of backlash simulation lies in physical joint injection. The add_backlash.py script, located at src/mjlab_microduck/robot/microduck/add_backlash.py, processes the robot's MuJoCo XML to insert passive hinge joints for every actuated servo.
Each injected joint follows a strict naming convention: passive_<joint>_backlash. These joints receive a constrained rotational range—typically ±0.5° (±1° total play)—that directly models the mechanical gap between servo output shaft and robot link.
The passive_ prefix serves a critical purpose. All regex-based selections throughout the codebase—actuator targets, observation filters, reward computations—automatically exclude these joints. This preserves the original 14-DOF action space while adding physical realism.
python3 src/mjlab_microduck/robot/microduck/add_backlash.py \
src/mjlab_microduck/robot/microduck/robot_groundcontact.xml \
--backlash-deg 2.0
The --backlash-deg parameter controls total play magnitude. The script outputs modified XML files such as robot_groundcontact_backlash.xml, referenced in configuration constants.
Actuator: Encoder-Through-Backlash Feedback
The BacklashEncoderBamActuator class in src/mjlab_microduck/actuator/friction_dr_bam.py extends the standard BAM voltage-controlled actuator to handle realistic encoder behavior.
During each control step, the actuator computes encoder position as:
encoder_position = qpos[servo] + qpos[backlash]
This sum replicates real hardware where encoders mount on the output side of gear play. The servo joint angle and passive backlash joint angle combine to represent what the physical encoder actually measures.
Velocity commands (cmd.vel) remain unchanged, still targeting the motor side. This matches physical servo behavior where back-EMF-based velocity feedback operates at the motor rather than the output.
The actuator configuration class, BacklashEncoderBamActuatorCfg, enables clean swapping in environment configurations without modifying learning code.
Task Configuration: Observations and Rewards
The make_backlash_variant function in src/mjlab_microduck/tasks/backlash.py transforms standard Microduck environments into backlash-aware variants through three specific modifications:
- Observation retargeting: Swaps
joint_posandjoint_velforjoint_pos_rel_backlashandjoint_vel_rel_backlash. Policies observe the encoder-view (servo + backlash) while maintaining 14-dimensional vectors. - Reward boundary adjustment: Modifies
dof_pos_limitsreward to apply only to servo joints, preventing backlash joints from generating spurious penalties when hitting their ±1° hard limits. - Pose reward filtering: Updates joint selection regex to exclude
passive_*_backlashjoints, ensuring pose-tracking penalties compute on correct servo joints.
from mjlab_microduck.tasks.backlash import make_backlash_variant
from mjlab_microduck.robot.microduck_constants import MICRODUCK_BACKLASH_ROBOT_CFG
# base_cfg is any existing environment config
backlash_cfg = make_backlash_variant(base_cfg, robot_cfg=MICRODUCK_BACKLASH_ROBOT_CFG)
Robot Configuration Constants
The complete integration relies on constants defined in src/mjlab_microduck/robot/microduck_constants.py. Key backlash-enabled configurations include:
MICRODUCK_BACKLASH_ROBOT_CFG— Base robot with backlash jointsMICRODUCK_WALK_BACKLASH_ROBOT_CFG— Walking-optimized variant
These constants pair the appropriate XML model with the correct actuator configuration, enabling single-line environment customization.
How Backlash Simulation Preserves Learning Compatibility
A critical design requirement in Microduck RL is maintaining consistent state and action dimensions across simulation variants. The backlash simulation achieves this through:
| Mechanism | Implementation |
|---|---|
| Action space preservation | Passive joints excluded from actuator targets |
| Observation dimensionality | Relative-backlash functions output 14-DOF vectors |
| Reward stability | Joint-specific regex filtering |
| Configuration inheritance | make_backlash_variant wraps existing configs |
This architecture allows direct comparison between backlash-aware and ideal-servo policies without architectural changes to learning algorithms.
Summary
- Backlash simulation in Microduck RL uses passive hinge joints with constrained ranges to model mechanical gear play.
- The
add_backlash.pyscript injects geometry while preserving naming conventions that existing code ignores. BacklashEncoderBamActuatorreads encoder position as the sum of servo and backlash joint angles, matching real hardware behavior.make_backlash_variantretargets observations and rewards without changing vector dimensionality.- Robot constants in
microduck_constants.pyprovide pre-configured backlash variants for immediate use.
Frequently Asked Questions
What file adds physical backlash joints to the Microduck robot model?
The src/mjlab_microduck/robot/microduck/add_backlash.py script processes MuJoCo XML files to insert passive hinge joints. It outputs modified XML models with passive_<joint>_backlash joints representing mechanical play.
How does the actuator know to read position through the backlash joint?
The BacklashEncoderBamActuator class in src/mjlab_microduck/actuator/friction_dr_bam.py explicitly sums qpos[servo] + qpos[backlash] when computing encoder feedback. This replicates physical encoders mounted on the output side of gearbox play.
Why don't backlash joints appear in the action space?
All backlash joint names begin with passive_, which regex patterns throughout the codebase automatically exclude. This preserves the original 14-DOF action space while adding physical realism to dynamics.
Can existing environments be converted to backlash variants without code changes?
Yes. The make_backlash_variant function in src/mjlab_microduck/tasks/backlash.py wraps any existing configuration. It handles observation function swapping, reward retargeting, and robot configuration updating through a single function call.
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 →