Naming Convention for Unactuated Joints in Microduck RL: The `passive_` Prefix Standard
All unactuated joints in Microduck RL use the passive_ prefix, enabling automatic filtering via negative lookahead regex patterns like ^(?!passive_).* in actuator and observation pipelines.
The pollen-robotics/microduck_rl repository enforces a strict naming convention for unactuated joints to maintain clean separation between servo-driven mechanisms and free-spinning components. Every joint without an actuator must adhere to the passive_ prefix rule, allowing the simulation framework to automatically exclude these degrees of freedom from torque-controlled pipelines while selectively including them in observations when needed.
The passive_ Prefix Rule
Unactuated joints—those not driven by motors or servos—must begin with the string passive_. This applies to:
- Free-spinning wheel hinges:
passive_LF_wheel,passive_LR_wheel,passive_RF_wheel, andpassive_RR_wheel(Left-Front, Left-Rear, Right-Front, Right-Rear) - Backlash encoder hinges:
passive_<joint>_backlashcomponents that sit in series with actuated servo joints to model mechanical play
According to AGENTS.md in the repository root: "Unactuated joints are all named passive_* (wheels, backlash hinges). Every actuator/obs/reward selector uses ^(?!passive_).* — keep the prefix convention when adding joints, and new passive_ regexes must not accidentally match backlash joints (^passive_.*wheel, not ^passive_.*)."
Implementation Across the Codebase
The convention is hard-coded in three critical areas to ensure unactuated joints never receive torque commands.
Actuator Filtering in MDP Definitions
In src/mjlab_microduck/tasks/mdp.py, the code explicitly filters out passive joints when building actuator-related observations. The implementation uses string prefix checking to separate active from passive components:
# Filtering passive joints out of a full joint list
full_names = asset.joint_names
active_names = [n for n in full_names if not n.startswith("passive_")]
This ensures that reinforcement learning observations and rewards calculated from joint states only consider controllable degrees of freedom unless explicitly configured otherwise.
Robot Constants Configuration
The file src/mjlab_microduck/robot/microduck_constants.py defines the default joint selection regex for actuator-related operations as:
(r"^(?!passive_).*",)
This negative lookahead pattern matches any joint name that does not start with passive_, effectively creating a whitelist of actuated joints for torque commands and position control loops.
Environment Configuration Files
Individual task configurations in src/mjlab_microduck/tasks/*_env_cfg.py (such as microduck_velocity_env_cfg.py) leverage the same regex patterns to selectively include or exclude passive components:
- Exclude passive joints:
joint_names=(r"^(?!passive_).*",)selects only actuated joints for control - Include wheel joints:
joint_names=(r"^passive_.*wheel",)specifically targets the four free-spinning wheels for velocity observations
Why the Naming Convention Matters
Strict adherence to the passive_ prefix provides three architectural benefits:
- Automatic Actuator Exclusion: Control pipelines automatically ignore unactuated joints without maintaining manual exclusion lists
- Consistent Observation Spaces: Reward functions and state estimators remain consistent across tasks, avoiding accidental penalization of passive components like backlash hinges
- Selective Inclusion: Researchers can explicitly target wheel velocities or ignore them using simple regex modifications rather than hard-coded joint indices
Practical Configuration Examples
When configuring scenes and observations in Microduck RL, use these patterns:
Selecting only actuated joints (excluding passive_ components):
servo_joint_cfg = SceneEntityCfg(
"robot",
joint_names=(r"^(?!passive_).*",) # matches everything *except* passive_* joints
)
Selecting the four passive wheel joints for velocity tracking:
wheel_joint_cfg = SceneEntityCfg(
"robot",
joint_names=(r"^passive_.*wheel",) # matches passive_LF_wheel, passive_LR_wheel, …
)
Summary
- Unactuated joints in Microduck RL must use the
passive_prefix per theAGENTS.mdspecification - Wheel joints follow the pattern
passive_{LF,LR,RF,RR}_wheel - Backlash hinges use
passive_<joint>_backlash - The regex
^(?!passive_).*filters out all passive joints from actuator pipelines src/mjlab_microduck/robot/microduck_constants.pyand task configuration files encode this convention for automatic enforcement
Frequently Asked Questions
How do I add a new unactuated joint to Microduck RL?
Prefix the joint name with passive_ in your MJCF/URDF model definition. Update any environment-specific regex patterns if you need to include this joint in observations, using patterns like ^passive_.*wheel for wheels or ^passive_.*backlash for backlash mechanisms. Never use ^passive_.* alone, as this would match both wheels and backlash joints indiscriminately.
Why does Microduck RL use regex patterns instead of explicit joint lists?
Regex patterns provide flexibility across different robot model variations while maintaining safety constraints. The negative lookahead ^(?!passive_).* automatically adapts when joints are added or removed from the model, ensuring that unactuated degrees of freedom never accidentally receive torque commands without requiring code changes in multiple files.
What is the difference between passive wheel joints and passive backlash joints?
Passive wheel joints (passive_LF_wheel, etc.) are free-spinning rotational degrees of freedom that allow the robot to roll without motor resistance. Passive backlash joints (passive_<joint>_backlash) are zero-mass, zero-inertia hinges inserted in series with actuated joints to simulate mechanical compliance and encoder play. Both use the passive_ prefix but serve different physical purposes in the simulation.
Where is the naming convention documented in the source code?
The primary documentation resides in AGENTS.md at the repository root, specifically lines 55-58. Implementation details appear in src/mjlab_microduck/tasks/mdp.py (filtering logic), src/mjlab_microduck/robot/microduck_constants.py (default regex constants), and various *_env_cfg.py files (environment-specific joint selection).
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 →