Chapter 08: Bipedal Locomotion for Humanoid Robots
Learn how humanoids walk, run, and maintain balance on two legs. Master gait generation algorithms, Zero Moment Point (ZMP) theory, balance controllers, and whole-body control for stable locomotion on flat and uneven terrain.
What You'll Learn
By the end of this chapter, you'll be able to:
- ✅ Generate stable walking gaits using ZMP-based trajectory planning
- ✅ Implement balance control algorithms (
COMstabilization, ankle/hip strategies) - ✅ Design whole-body controllers for joint torque computation
- ✅ Handle locomotion on flat surfaces at 0.5 m/s walking speed
- ✅ Detect and recover from push perturbations within 1.5 seconds
- ✅ Implement gait state machines for transitions (stand → walk → run)
- ✅ Debug common locomotion failures (tipping, foot slip, oscillations)
- ✅ Integrate locomotion with perception and manipulation
Prerequisites
Before starting this chapter, you should:
- ✅ Complete Chapter 03: ROS 2 Fundamentals (topics, actions)
- ✅ Complete Chapter 04: URDF & Digital Twins (kinematics, dynamics)
- ✅ Understand basic control theory (PID, state feedback)
- ✅ Have Python 3.10+, ROS 2 Iron, NumPy/SciPy installed
- ✅ Have Isaac Sim 2025.1+ for simulation testing
Minimum: GTX 1660 (6 GB) for Isaac Sim locomotion sim Recommended: RTX 4060 Ti (16 GB) for real-time physics simulation Professional: RTX 4070 Ti+ (12-24 GB) for multiple humanoids
Why Bipedal Locomotion is Hard
Challenges unique to two-legged walking:
- Underactuated system: Fewer contact points than wheels/legs (unstable equilibrium)
- Hybrid dynamics: Continuous (swing phase) + discrete (foot contact) transitions
- Balance constraints: Center of Mass (
COM) must stay within support polygon - Impact forces: Foot strikes generate high forces (2-3x body weight)
- Terrain adaptation: Uneven surfaces require continuous adjustment
Why solve it anyway?
- Navigate human environments (stairs, narrow spaces)
- Energy efficiency (walking vs. wheeled on rough terrain)
- Social acceptance (human-like appearance)
- Manipulation while moving (whole-body coordination)
Gait Generation Fundamentals
Walking Cycle Phases
A complete walking cycle (stride) has 8 phases:
Key parameters:
- Step length: 0.3-0.6m (typical adult walking)
- Step width: 0.1-0.15m (lateral stability)
- Step height: 0.05-0.08m (foot clearance)
- Cycle time: 1.0-1.2s (walking), 0.6-0.8s (running)
- Double support ratio: 20% (walking), 0% (running - flight phase)
Zero Moment Point (ZMP) Theory
Definition: Point on the ground where the net moment from ground reaction forces is zero.
Physical intuition:
- If ZMP is inside the support polygon → robot is stable
- If ZMP reaches polygon edge → robot begins to tip
- If ZMP is outside polygon → robot is falling (unrecoverable)
Mathematical formulation:
For a humanoid with center of mass at position (x_com, y_com, z_com):
ZMP_x = x_com - (z_com / (g + z_com_ddot)) * x_com_ddot
ZMP_y = y_com - (z_com / (g + z_com_ddot)) * y_com_ddot
Where:
g = 9.81 m/s²(gravity)x_com_ddot,y_com_ddot,z_com_ddot=COMaccelerations
Stability condition:
ZMP ∈ Support Polygon
For single support (one foot): polygon is foot outline For double support (two feet): polygon is convex hull of both feet
ZMP-Based Gait Planning
Goal: Generate COM trajectory such that ZMP stays inside support polygon.
Linear Inverted Pendulum Model (LIPM):
Simplified humanoid dynamics:
x_com_ddot = (g / z_com) * (x_com - ZMP_x)
y_com_ddot = (g / z_com) * (y_com - ZMP_y)
This allows solving for COM trajectory that produces desired ZMP.
Gait Generator Implementation
See code-examples/locomotion/gait_generator.py for complete implementation.
Key algorithms:
- Footstep planner: Generate foot positions for N steps ahead
- ZMP reference: Define desired ZMP trajectory (center of support polygon)
- Preview controller: Solve for
COMtrajectory (quadratic optimization) - Swing foot trajectory: Polynomial interpolation for smooth foot motion
Expected outputs:
COMtrajectory: 100 Hz- Foot trajectories: 100 Hz
- Joint angles: via whole-body inverse kinematics
Balance Control
Center of Mass (COM) Stabilization
Problem: Real robot deviates from planned trajectory due to:
- Model errors (unmodeled dynamics)
- External disturbances (push, uneven terrain)
- Sensor noise (IMU drift, encoder backlash)
Solution: Feedback control to correct COM position/velocity.
COM PID controller:
# Position error
e_pos = com_desired - com_actual
# Velocity error
e_vel = com_vel_desired - com_vel_actual
# PID output
delta_com = Kp * e_pos + Kd * e_vel + Ki * integral(e_pos)
Typical gains for humanoid (mass ~50kg, height ~1.5m):
Kp = 200-400(position gain)Kd = 40-80(velocity gain)Ki = 5-15(integral gain)
Balance Recovery Strategies
1. Ankle Strategy (Small Perturbations)
When: Push force <50N, COM stays within support polygon
How: Adjust ankle torque to apply corrective moment
Ankle_torque = -K_ankle * (theta - theta_desired)
Advantages:
- Fast response (50-100ms)
- Minimal energy
- No foot movement
Limitations:
- Small workspace (ankle ROM ±15°)
- Cannot handle large disturbances
2. Hip Strategy (Medium Perturbations)
When: Push force 50-150N, COM approaching polygon edge
How: Generate large angular momentum with hip motion
Execution:
- Detect
COMnear stability boundary - Swing hip opposite to disturbance
- Generate counter-moment
- Return to nominal posture
Advantages:
- Larger workspace than ankle strategy
- No stepping required
Limitations:
- Slower than ankle (200-400ms)
- Higher energy cost
3. Stepping Strategy (Large Perturbations)
When: Push force >150N, COM exiting support polygon
How: Take step to create new support polygon under COM
Capture Point Theory:
- Capture point: Location where robot must step to stop
COMmotion - Formula:
x_capture = x_com + v_com / sqrt(g/z_com)
Execution:
- Compute capture point
- Plan foot placement at capture point
- Execute rapid step (swing time <0.3s)
- Stabilize in new support
Recovery time: 0.5-1.5 seconds (meets SC-004 requirement)
Whole-Body Control
Problem Formulation
Goal: Compute joint torques to achieve desired task-space motions (COM, feet, arms).
Humanoid has:
- n_q = 30-40 degrees of freedom (joints)
- n_c = 6-12 contacts (feet on ground)
- n_t = 12-18 task variables (
COM, swing foot, arms)
Equations of motion:
M(q) * q_ddot + C(q, q_dot) * q_dot + G(q) = τ + J_c^T * F_c
Where:
M(q)= inertia matrixC(q, q_dot)= Coriolis/centrifugal matrixG(q)= gravity vectorτ= joint torques (control input)J_c= contact JacobianF_c= contact forces
Quadratic Programming (QP) Controller
Formulate as optimization problem:
minimize: ||J * q_ddot - x_ddot_desired||² + λ * ||τ||²
subject to:
M(q) * q_ddot + h(q, q_dot) = τ + J_c^T * F_c
F_c_min ≤ F_c ≤ F_c_max (friction cone)
τ_min ≤ τ ≤ τ_max (joint limits)
Variables:
q_ddot= joint accelerations (n_q)τ= joint torques (n_q)F_c= contact forces (n_c)
Implementation: Use OSQP or quadprog solvers (10-20ms on CPU)
See code-examples/locomotion/whole_body_controller.py for complete QP formulation.
Task Hierarchy
Priority levels:
- High priority: Balance (
COMposition/velocity) - Medium priority: Swing foot trajectory
- Low priority: Arm posture
Hierarchical controller:
# Solve QP with task prioritization
def solve_wbc_hierarchical(tasks, contacts):
# Tasks sorted by priority (high → low)
tasks_sorted = sorted(tasks, key=lambda t: t.priority, reverse=True)
# Start with highest priority
qp_constraints = [contacts]
for task in tasks_sorted:
# Add task objective
qp_objective = task.jacobian @ q_ddot - task.desired_accel
# Solve QP
solution = solve_qp(qp_objective, qp_constraints)
# Add solution as constraint for next task (nullspace)
qp_constraints.append(solution)
return solution
Locomotion on Uneven Terrain
Terrain Sensing
Perception requirements:
- Elevation map (height field)
- Surface normals (slope estimation)
- Obstacle detection (step height)
- Friction coefficient estimation
Sources:
- Point clouds (from Chapter 07)
- Stereo depth
- Heightmap from SLAM
Adaptive Footstep Planning
Challenges on uneven terrain:
- Support polygon is not flat
- Foot orientation must match terrain
- Step height varies
COMtrajectory must account for elevation changes
Algorithm:
def plan_footstep_uneven(terrain_map, current_pose, target_velocity):
# Sample candidate foot positions
candidates = sample_foot_positions(current_pose, target_velocity)
# Evaluate each candidate
scores = []
for candidate in candidates:
# Check terrain height
height = terrain_map.get_height(candidate.x, candidate.y)
# Check slope
normal = terrain_map.get_normal(candidate.x, candidate.y)
slope = acos(normal.dot([0, 0, 1]))
# Check obstacles
clear = terrain_map.is_collision_free(candidate)
# Score = weighted sum
score = w1 * (1 - slope/max_slope) + \
w2 * clear + \
w3 * proximity_to_target
scores.append(score)
# Select best candidate
best_footstep = candidates[argmax(scores)]
return best_footstep
Balance on Slopes
ZMP on inclined terrain:
- Support polygon rotates with terrain
- Gravity projection changes
COMmust shift to maintain ZMP inside polygon
Modified ZMP calculation:
def compute_zmp_on_slope(com_pos, com_accel, terrain_normal):
# Rotate gravity to terrain frame
g_rotated = rotate_vector([0, 0, -9.81], terrain_normal)
# ZMP in terrain frame
zmp_x = com_pos[0] - (com_pos[2] / (g_rotated[2] + com_accel[2])) * com_accel[0]
zmp_y = com_pos[1] - (com_pos[2] / (g_rotated[2] + com_accel[2])) * com_accel[1]
return zmp_x, zmp_y
Gait State Machine
State Definitions
State transitions:
- Idle → Standing: Activate joint position control, lift
COM - Standing → Walking: Start gait generator, first step
- Walking → Running: Switch to dynamic walking (flight phase)
- Walking → Balancing: Disturbance detected (IMU, force sensors)
- Balancing → Walking:
COMstabilized, return to nominal gait
Implementation:
class GaitStateMachine:
def __init__(self):
self.state = GaitState.IDLE
self.transition_time = 0.3 # seconds
def update(self, dt, sensors, commands):
if self.state == GaitState.WALKING:
# Monitor balance
if self.detect_perturbation(sensors):
self.transition_to(GaitState.BALANCING)
# Check speed command
if commands.velocity > 1.0:
self.transition_to(GaitState.RUNNING)
elif self.state == GaitState.BALANCING:
# Attempt recovery
if self.is_stable(sensors):
self.transition_to(GaitState.WALKING)
# Timeout check
if self.time_in_state() > 1.5:
self.transition_to(GaitState.FALLING)
Performance Metrics
Success Criteria
1. Walking Speed: 0.5 m/s on flat terrain (SC-004)
- Measured: Average
COMvelocity over 10 steps - Target: 0.45-0.55 m/s
2. Balance Recovery: Within 1.5 seconds from perturbation (SC-004)
- Test: Apply 100N lateral push
- Measure: Time from push to stable
COM(< 5cm deviation)
3. Stability: No falls over 50 walking cycles
- Metric: Success rate > 95%
4. Energy Efficiency: Cost of Transport (COT)
COT = Energy / (Weight * Distance)
Target: COT < 0.2 (comparable to human walking)
Debugging Common Failures
1. Tipping Forward/Backward
Symptoms:
- Robot falls in sagittal plane
- Cannot recover balance
Causes:
- ZMP reaching front/back edge of foot
COMmoving too fast- Incorrect footstep timing
Solutions:
- Reduce walking speed
- Increase double support time
- Tune ZMP margin (keep 2cm from edge)
2. Lateral Instability
Symptoms:
- Swaying side-to-side
- Eventually tips laterally
Causes:
- Insufficient step width
COMnot centered over support polygon- Hip joint compliance
Solutions:
- Increase step width (0.1m → 0.15m)
- Add lateral
COMoffset during single support - Increase hip joint stiffness
3. Foot Slip
Symptoms:
- Foot slides on contact
- Loss of balance
- Jerky motion
Causes:
- Excessive ground reaction forces
- Low friction surface
- Incorrect contact detection
Solutions:
- Limit
COMacceleration - Use rubber foot pads
- Implement contact force sensing
4. Oscillations (Limit Cycles)
Symptoms:
- Robot bounces/oscillates
- Cannot settle to stable gait
Causes:
- PID gains too high
- Coupling between
COMand swing foot controllers - Unmodeled leg dynamics
Solutions:
- Reduce Kd gain (damping)
- Add low-pass filter on control output
- Increase simulation timestep resolution
Integration with Perception and Manipulation
Perception-Guided Walking
Use case: Navigate to table while avoiding obstacles
Pipeline:
- Perception: Generate occupancy grid from point cloud
- Path planning: A* or RRT to find collision-free path
- Footstep planning: Place feet along path, respecting obstacles
- Gait execution: Walk along planned footsteps
Code example:
# Perception provides obstacles
obstacles = perception_module.get_obstacles()
# Plan path to goal
path = path_planner.plan(robot_pose, goal_pose, obstacles)
# Convert path to footsteps
footsteps = footstep_planner.generate_from_path(path)
# Execute gait
gait_controller.execute_footsteps(footsteps)
Manipulation While Walking
Challenges:
- Arm motion affects
COM(dynamic coupling) - Reduced stability margin (arms not available for balance)
- Coordination of locomotion and manipulation timing
Whole-body coordination:
def walk_and_manipulate(walk_trajectory, arm_trajectory):
# Compute combined COM accounting for arm mass
com_total = (m_body * com_body + m_arm * com_arm) / (m_body + m_arm)
# Adjust ZMP reference to account for arm motion
zmp_adjusted = zmp_nominal + K_arm * (arm_accel - arm_accel_planned)
# Solve whole-body QP with both tasks
tasks = [
Task(type='COM', jacobian=J_com, priority=1),
Task(type='FOOT', jacobian=J_foot, priority=1),
Task(type='ARM', jacobian=J_arm, priority=2)
]
torques = whole_body_controller.solve(tasks)
return torques
Further Reading
Research Papers
- Preview Control of ZMP (Kajita et al. 2003) - IEEE Xplore
- Foundational ZMP-based gait generation
- Capture Point (Pratt & Tedrake 2006) - Paper
- Balance recovery using capture point theory
- Whole-Body Control (Sentis & Khatib 2005) - IJRR
- Task-space control with contact constraints
- Terrain-Aware Footstep Planning (Deits & Tedrake 2014) - Paper
- Mixed-integer optimization for footstep planning
- ATLAS Robot (Kuindersma et al. 2016) - Science Robotics
- Real-world humanoid locomotion on rough terrain
Open-Source Libraries
ROS 2 Packages
- Humanoid Common Msgs: humanoid_msgs
- Walking Controller: talos_walking
Summary
In this chapter, you learned:
- ✅ Gait generation using ZMP-based trajectory planning
- ✅ Balance control with
COMstabilization and recovery strategies - ✅ Whole-body control using quadratic programming
- ✅ Locomotion on uneven terrain with adaptive footstep planning
- ✅ Gait state machines for robust mode transitions
- ✅ Performance metrics for walking speed and balance recovery
- ✅ Debugging strategies for common locomotion failures
- ✅ Integration with perception and manipulation systems
Next steps:
- Chapter 09: Dexterous Manipulation (grasp planning, IK, force control)
- Chapter 13: Capstone Project (integrate locomotion + perception + manipulation)
Implement stable walking in Isaac Sim:
- Create humanoid URDF with 12-DOF legs
- Implement ZMP-based gait generator
- Add
COMbalance controller (PID) - Test walking at 0.5 m/s on flat terrain
- Apply lateral push (100N) and verify recovery < 1.5s
- Measure energy efficiency (Cost of Transport)
Time estimate: 4-6 hours Difficulty: Advanced Prerequisites: Control theory, dynamics, Isaac Sim