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, andankle. - Indices 5–8 control the neck and head:
neck_pitch,head_pitch,head_yaw, andhead_roll. - Indices 9–13 control the right leg, mirroring the left leg joint configuration.
- The
leg_joint_indicesandneck_joint_indiceslists insrc/mjlab_microduck/tasks/mdp.pyenforce these groupings for reward calculations. - The home pose in
src/mjlab_microduck/robot/microduck_constants.pyconfirms 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →