# Naming Convention for Unactuated Joints in Microduck RL: The `passive_` Prefix Standard

> Discover the `passive_` prefix naming convention for unactuated joints in Microduck RL. Learn how it simplifies actuator and observation pipelines for efficient filtering.

- Repository: [Pollen Robotics/microduck_rl](https://github.com/pollen-robotics/microduck_rl)
- Tags: best-practices
- Published: 2026-09-01

---

**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`, and `passive_RR_wheel` (Left-Front, Left-Rear, Right-Front, Right-Rear)
- **Backlash encoder hinges**: `passive_<joint>_backlash` components that sit in series with actuated servo joints to model mechanical play

According to [`AGENTS.md`](https://github.com/pollen-robotics/microduck_rl/blob/main/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`](https://github.com/pollen-robotics/microduck_rl/blob/main/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:

```python

# 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`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/robot/microduck_constants.py) defines the default joint selection regex for actuator-related operations as:

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

1. **Automatic Actuator Exclusion**: Control pipelines automatically ignore unactuated joints without maintaining manual exclusion lists
2. **Consistent Observation Spaces**: Reward functions and state estimators remain consistent across tasks, avoiding accidental penalization of passive components like backlash hinges
3. **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):

```python
servo_joint_cfg = SceneEntityCfg(
    "robot",
    joint_names=(r"^(?!passive_).*",)   # matches everything *except* passive_* joints

)

```

Selecting the four passive wheel joints for velocity tracking:

```python
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 the [`AGENTS.md`](https://github.com/pollen-robotics/microduck_rl/blob/main/AGENTS.md) specification
- 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.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/robot/microduck_constants.py) and 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`](https://github.com/pollen-robotics/microduck_rl/blob/main/AGENTS.md) at the repository root, specifically lines 55-58. Implementation details appear in [`src/mjlab_microduck/tasks/mdp.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/tasks/mdp.py) (filtering logic), [`src/mjlab_microduck/robot/microduck_constants.py`](https://github.com/pollen-robotics/microduck_rl/blob/main/src/mjlab_microduck/robot/microduck_constants.py) (default regex constants), and various `*_env_cfg.py` files (environment-specific joint selection).