Tutorials 3 min read

Getting Started with ROS 2 for Humanoid Robotics

A practical guide to setting up ROS 2 Jazzy for humanoid robot simulation — from installation to your first walking controller in MuJoCo.

M
med Developer and robotics enthusiast tracking the open source humanoid robot ecosystem.
Getting Started with ROS 2 for Humanoid Robotics

ROS 2 has become the de facto middleware for humanoid robotics research. This guide gets you from zero to a simulated biped in MuJoCo as efficiently as possible.

Prerequisites

  • Ubuntu 24.04 LTS (ROS 2 Jazzy target)
  • Python 3.12+
  • 8GB RAM minimum (16GB recommended for MuJoCo)

Step 1: Install ROS 2 Jazzy

sudo apt install software-properties-common
sudo add-apt-repository universe
sudo apt update && sudo apt install curl -y
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key \
  -o /usr/share/keyrings/ros-archive-keyring.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] \
  http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | \
  sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null

sudo apt update
sudo apt install ros-jazzy-desktop ros-dev-tools

Add to your .bashrc:

source /opt/ros/jazzy/setup.bash

Step 2: Install MuJoCo

MuJoCo is now free (thanks DeepMind) and the best physics simulator for humanoid robotics:

pip install mujoco

Verify:

import mujoco
print(mujoco.__version__)  # should print 3.x.x

Step 3: Create a workspace

mkdir -p ~/humanoid_ws/src
cd ~/humanoid_ws
colcon build
source install/setup.bash

Step 4: Your first URDF model

Create a minimal biped model. For a real project, you’d load a proper URDF from the robot manufacturer, but here’s a minimal structure:

<!-- robot.urdf -->
<robot name="biped">
  <link name="base_link">
    <visual>
      <geometry><box size="0.3 0.2 0.5"/></geometry>
    </visual>
    <inertial>
      <mass value="5.0"/>
      <inertia ixx="0.1" iyy="0.1" izz="0.05" ixy="0" ixz="0" iyz="0"/>
    </inertial>
  </link>

  <link name="left_thigh"><!-- ... --></link>
  <joint name="left_hip" type="revolute">
    <parent link="base_link"/>
    <child link="left_thigh"/>
    <axis xyz="0 1 0"/>
    <limit lower="-1.5" upper="1.5" effort="50" velocity="5"/>
  </joint>
</robot>

Step 5: Publish joint states

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import JointState
import math, time

class SimpleController(Node):
    def __init__(self):
        super().__init__('simple_controller')
        self.pub = self.create_publisher(JointState, 'joint_states', 10)
        self.timer = self.create_timer(0.02, self.step)  # 50 Hz
        self.t = 0.0

    def step(self):
        msg = JointState()
        msg.header.stamp = self.get_clock().now().to_msg()
        msg.name = ['left_hip', 'right_hip', 'left_knee', 'right_knee']
        # Simple sinusoidal gait
        msg.position = [
            0.3 * math.sin(self.t),
            0.3 * math.sin(self.t + math.pi),
            -0.6 * abs(math.sin(self.t)),
            -0.6 * abs(math.sin(self.t + math.pi)),
        ]
        self.pub.publish(msg)
        self.t += 0.02 * 2 * math.pi * 0.5  # 0.5 Hz gait cycle

def main():
    rclpy.init()
    rclpy.spin(SimpleController())

Next Steps

This barely scratches the surface. The real work is in:

  1. Whole-body control — using libraries like pink (Pink Is Not Kinematics) for real-time IK
  2. State estimation — fusing IMU + leg odometry for robust pose estimation
  3. RL policies — training in Isaac Gym and transferring to MuJoCo/real hardware

The Open Duck Mini repository has a well-documented example of the full sim-to-real pipeline. Start there.

Share:

Newsletter

Weekly robotics digest, no spam.