이 가이드는 인류와 AI가 함께 만드는 지식입니다.
이 콘텐츠는 Human + AI Partnership 철학 아래 모든 사람이 로봇·AI를 배울 수 있도록 무료로 제공됩니다. 당신의 질문과 기여가 다음 학생의 미래를 바꿉니다.
ROS 2 Humanoid Robots Guide 2026
Humanoids are the hardest robots to program — dozens of joints, dynamic balance, and coordinated locomotion plus manipulation. This guide covers the ROS 2 stack that makes it tractable: ros2_control, whole-body control, and MoveIt 2.
1. The Humanoid ROS 2 Stack
A humanoid needs a layered stack from hardware interface up to task planning:
sudo apt-get install -y ros-humble-ros2-control ros-humble-ros2-controllers ros-humble-moveit ros-humble-controller-manager ros-humble-joint-state-broadcaster ros-humble-joint-trajectory-controller
# Stack layers (bottom -> top):
# 1. Hardware interface (ros2_control HardwareInterface)
# 2. Joint controllers (effort / position / velocity)
# 3. Whole-body control (balance + task priorities)
# 4. Locomotion planner (footstep + gait generation)
# 5. Behavior / task (MoveIt 2, behavior trees)2. Describing the Robot: URDF for 25+ DOF
Humanoids have many kinematic chains. Structure the URDF with clear chains for legs, arms, and torso:
<!-- humanoid.urdf.xacro (excerpt) -->
<robot name="humanoid" xmlns:xacro="http://ros.org/wiki/xacro">
<xacro:include filename="leg.xacro"/>
<xacro:include filename="arm.xacro"/>
<link name="pelvis"/> <!-- floating base root -->
<!-- 6-DOF legs -->
<xacro:leg prefix="left" reflect="1"/>
<xacro:leg prefix="right" reflect="-1"/>
<!-- 7-DOF arms -->
<xacro:arm prefix="left" reflect="1"/>
<xacro:arm prefix="right" reflect="-1"/>
<ros2_control name="HumanoidSystem" type="system">
<hardware>
<plugin>humanoid_hw/HumanoidHardware</plugin>
</hardware>
<!-- each joint exposes command + state interfaces -->
</ros2_control>
</robot>3. ros2_control Joint Interfaces
Expose effort/position/velocity interfaces per joint so controllers can command torques for balance:
# controllers.yaml
controller_manager:
ros__parameters:
update_rate: 500 # Hz — humanoids need fast control loops
joint_state_broadcaster:
type: joint_state_broadcaster/JointStateBroadcaster
left_leg_controller:
type: joint_trajectory_controller/JointTrajectoryController
right_leg_controller:
type: joint_trajectory_controller/JointTrajectoryController
left_leg_controller:
ros__parameters:
joints:
- left_hip_yaw
- left_hip_roll
- left_hip_pitch
- left_knee
- left_ankle_pitch
- left_ankle_roll
command_interfaces: [effort]
state_interfaces: [position, velocity]4. Balance: ZMP & the Support Polygon
Static and dynamic balance both keep the Zero Moment Point inside the support polygon:
import numpy as np
def compute_zmp(com, com_accel, com_height, g=9.81):
"""Cart-table model ZMP from CoM state."""
zmp_x = com[0] - (com_height / g) * com_accel[0]
zmp_y = com[1] - (com_height / g) * com_accel[1]
return np.array([zmp_x, zmp_y])
def is_balanced(zmp, support_polygon):
"""ZMP must stay strictly inside the foot support polygon."""
return point_in_polygon(zmp, support_polygon)
# If ZMP approaches the polygon edge, the whole-body controller
# must adjust CoM trajectory or trigger a recovery step.5. Whole-Body Control (Task Priorities)
A whole-body controller solves a QP each cycle, honoring prioritized tasks (balance > posture > reaching):
# Prioritized task stack solved as a hierarchical QP
tasks = [
BalanceTask(weight=1000), # highest: keep ZMP in polygon
FootContactTask(weight=800), # maintain stance foot contact
CoMTask(target=com_ref, weight=500),
RightHandTask(target=grasp_pose, weight=100),
PostureTask(target=nominal_q, weight=10), # regularization
]
# Solve for joint accelerations subject to:
# - dynamics: M q'' + h = S tau + J_c^T f_c
# - torque limits: tau_min <= tau <= tau_max
# - friction cone: contact forces stay in cone
qdd, tau = wbc_solver.solve(tasks, robot_state)6. Bipedal Locomotion & Footstep Planning
Generate a walking gait from a footstep plan and a preview controller:
def plan_footsteps(start, goal, step_length=0.25, step_width=0.18):
steps, pos, side = [], np.array(start), 1
while np.linalg.norm(goal[:2] - pos[:2]) > step_length:
direction = (goal[:2] - pos[:2])
direction /= np.linalg.norm(direction)
pos[:2] += direction * step_length
foot = pos.copy()
foot[1] += side * step_width / 2 # alternate feet
steps.append({'pos': foot.copy(), 'foot': 'left' if side > 0 else 'right'})
side *= -1
return steps
# Feed the footstep sequence to a ZMP preview controller
# (Kajita's method) to produce a smooth CoM trajectory.7. Dual-Arm Manipulation with MoveIt 2
Plan coordinated two-arm motion while the lower body maintains balance:
from moveit.planning import MoveItPy
moveit = MoveItPy(node_name="humanoid_moveit")
both_arms = moveit.get_planning_component("both_arms")
both_arms.set_start_state_to_current_state()
both_arms.set_goal_state(configuration_name="carry_box")
plan = both_arms.plan()
if plan:
moveit.execute(plan.trajectory, controllers=[])
# The upper-body plan runs on top of the balance controller,
# which continuously corrects the CoM as the arms shift mass.8. Sim-to-Real: Isaac Sim & MuJoCo
Never tune a humanoid on hardware first. Train and validate in simulation:
# MuJoCo + ROS 2 bridge for fast dynamics
ros2 launch humanoid_sim mujoco_bringup.launch.py model:=humanoid.xml gui:=true
# Isaac Sim for photorealistic perception + RL locomotion policies
# Domain randomize mass, friction, and latency so a policy trained
# in sim survives the reality gap on Unitree G1 / Figure hardware.9. Real Hardware: Unitree G1 & Figure
- Unitree G1: ships an SDK with a ROS 2 bridge; 23–43 DOF depending on config, exposes joint state + high-level locomotion commands.
- Figure 03: enterprise units run proprietary control; ROS 2 typically wraps the perception layer rather than joint control.
- Booster / Fourier: increasingly ship ros2_control hardware interfaces out of the box.
- Always start with the manufacturer's damping/safe mode before enabling torque control.
10. Safety for Humanoids
- E-stop hierarchy: hardware e-stop > software watchdog > controller fault.
- Fall detection: monitor IMU + ZMP; trigger a protective crouch before impact.
- Torque ramping: never enable full torque instantly on startup.
- Workspace limits: constrain arm plans away from the robot's own head/torso.
- Human distance: a full-size humanoid is dangerous — enforce keep-out zones.
Key Takeaways
Build humanoids on ros2_control with a fast (500Hz+) loop, effort interfaces for the legs, and a whole-body QP that prioritizes balance above all tasks. Keep the ZMP inside the support polygon, plan footsteps with a preview controller, and use MoveIt 2 for dual-arm work layered on top of balance. Validate everything in MuJoCo or Isaac Sim before touching a Unitree G1 or Figure — and treat safety as the first controller, not the last.