How the 14 Dynamixel Servos of the Microduck Robot Map to Joint Indices

The 14 Dynamixel XL330 servos in the Microduck robot are indexed contiguously from 0 to 13, with indices 0–4 controlling the left leg, 5–8 controlling the neck and head, and 9–13 controlling the right leg.

The Microduck robot in the pollen-robotics/microduck_rl repository utilizes a fixed 14-servo actuation layout that remains consistent across all Isaac Lab environment variants. Understanding this standardized indexing scheme is essential for configuring reward functions, action rate penalties, and joint-specific control policies in reinforcement learning workflows.

Joint Index Layout Overview

The robot's articulation model assigns contiguous indices to each Dynamixel servo. The layout organizes the 14 degrees of freedom into three functional groups: the left leg, the neck and head assembly, and the right leg.

Index Joint Name Functional Group
0 left_hip_yaw Left Leg (0–4)
1 left_hip_roll Left Leg (0–4)
2 left_hip_pitch Left Leg (0–4)
3 left_knee Left Leg (0–4)
4 left_ankle Left Leg (0–4)
5 neck_pitch Neck/Head (5–8)
6 head_pitch Neck/Head (5–8)
7 head_yaw Neck/Head (5–8)
8 head_roll Neck/Head (5–8)
9 right_hip_yaw Right Leg (9–13)
10 right_hip_roll Right Leg (9–13)
11 right_hip_pitch Right Leg (9–13)
12 right_knee Right Leg (9–13)
13 right_ankle Right Leg (9–13)

Joint Index Conventions in the Codebase

The pollen-robotics/microduck_rl source code enforces these index conventions through explicit helper functions and constants. In src/mjlab_microduck/tasks/mdp.py, the codebase defines separate index lists for leg and neck joints to facilitate reward computations and action monitoring.

Leg joint indices are constructed by concatenating the left and right leg ranges:

leg_joint_indices = list(range(0, 5)) + list(range(9, 14))

This creates the list [0, 1, 2, 3, 4, 9, 10, 11, 12, 13], encompassing all hip, knee, and ankle servos while excluding the neck and head joints at indices 5–8.

Neck joint indices use a single contiguous range:

neck_joint_indices = list(range(5, 9))

This captures indices 5 through 8, corresponding to the neck pitch, head pitch, head yaw, and head roll servos.

According to the source code at line 1449 of mdp.py, these conventions are documented with the explicit comment: "left hip-ankle: 0-4, right hip-ankle: 9-13". The leg index list appears at line 54, while the neck index list is defined at line 62.

Home Pose Configuration

The same indexing scheme governs the robot's initial configuration. In src/mjlab_microduck/robot/microduck_constants.py (lines 81–94), the home pose array assigns default angles using this 0–13 index ordering. This ensures that initialization values align precisely with the servo layout used throughout the training environment.

Practical Code Examples

To retrieve the complete servo-only joint view in an environment, use the _servo_joint_ids helper function:


# Retrieve servo joint indices for the robot

servo_ids = _servo_joint_ids(env, env.scene["robot"])

# Returns: tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13])

When computing action-rate penalties specifically for leg movements, filter actions using the predefined leg indices:


# Isolate leg actions using the established index convention

leg_joint_indices = list(range(0, 5)) + list(range(9, 14))
leg_actions = env.action_manager.action[:, leg_joint_indices]

# Calculate action rate against previous step

action_rate = leg_actions - env._prev_leg_actions
penalty = torch.sum(torch.square(action_rate), dim=1)

Summary

  • The Microduck robot uses 14 Dynamixel XL330 servos indexed contiguously from 0 to 13.
  • Indices 0–4 control the left leg joints: hip_yaw, hip_roll, hip_pitch, knee, and ankle.
  • Indices 5–8 control the neck and head: neck_pitch, head_pitch, head_yaw, and head_roll.
  • Indices 9–13 control the right leg, mirroring the left leg joint configuration.
  • The leg_joint_indices and neck_joint_indices lists in src/mjlab_microduck/tasks/mdp.py enforce these groupings for reward calculations.
  • The home pose in src/mjlab_microduck/robot/microduck_constants.py confirms this ordering through initialization arrays.

Frequently Asked Questions

What type of Dynamixel servos does the Microduck robot use?

The Microduck robot uses Dynamixel XL330 servos for all 14 actuated joints. These compact, high-torque servos provide precise position control for the leg mechanisms and the active neck/head assembly.

How are the joint indices grouped in the Microduck robot?

Indices are grouped by anatomical function: 0–4 for the left leg, 5–8 for the neck and head, and 9–13 for the right leg. This grouping allows the reinforcement learning framework to apply specific reward modifiers—such as action rate penalties—selectively to the leg servos while excluding the neck joints.

Where is the joint index mapping defined in the source code?

The index mapping is defined in src/mjlab_microduck/tasks/mdp.py at lines 54 and 62, where leg_joint_indices and neck_joint_indices are explicitly constructed. The home pose configuration in src/mjlab_microduck/robot/microduck_constants.py (lines 81–94) further confirms this layout by indexing initial joint angles according to the same 0–13 scheme.

How do I access only the leg joints in the Microduck environment?

Filter the action tensor using the leg index list: list(range(0, 5)) + list(range(9, 14)). This excludes neck joints (indices 5–8) and returns a tensor containing only the 10 leg servo values (5 left + 5 right), which is the standard approach for computing leg-specific rewards in the MDP module.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →