Skip to main content

Advanced ROS 2

Learning Objectives:

  • Implement request-response communication with services
  • Use actions for long-running tasks with feedback
  • Understand lifecycle nodes for managed startup and shutdown
  • Navigate a robot using the Nav2 stack

Prerequisites: Chapter 1: ROS 2 Foundations

Estimated Reading Time: 50 minutes


Services: Request-Response

While topics are great for streaming data, sometimes you need a synchronous request-response pattern. That's what services provide.

A service has a server (processes requests) and a client (sends requests):

from example_interfaces.srv import AddTwoInts

class AddServer(Node):
def __init__(self):
super().__init__('add_server')
self.srv = self.create_service(
AddTwoInts, 'add_two_ints', self.add_callback
)

def add_callback(self, request, response):
response.sum = request.a + request.b
self.get_logger().info(f'{request.a} + {request.b} = {response.sum}')
return response
class AddClient(Node):
def __init__(self):
super().__init__('add_client')
self.client = self.create_client(AddTwoInts, 'add_two_ints')
while not self.client.wait_for_service(timeout_sec=1.0):
self.get_logger().info('Waiting for service...')

async def call(self, a, b):
request = AddTwoInts.Request()
request.a = a
request.b = b
result = await self.client.call_async(request)
return result.sum

When to Use Topics vs Services

PatternUse CaseExample
TopicContinuous data streamSensor readings, camera frames
ServiceOne-time requestCalculate path, get parameter

Actions: Long-Running Tasks

Actions extend services for tasks that take time to complete. They provide:

  • Goal: What you want the robot to do
  • Feedback: Progress updates during execution
  • Result: Final outcome when the action completes
from nav2_msgs.action import NavigateToPose
from rclpy.action import ActionClient

class NavigationClient(Node):
def __init__(self):
super().__init__('navigation_client')
self.action_client = ActionClient(
self, NavigateToPose, 'navigate_to_pose'
)

def send_goal(self, x, y):
goal = NavigateToPose.Goal()
goal.pose.pose.position.x = x
goal.pose.pose.position.y = y
self.action_client.wait_for_server()
future = self.action_client.send_goal_async(
goal, feedback_callback=self.feedback_callback
)
return future

def feedback_callback(self, feedback_msg):
distance = feedback_msg.feedback.distance_remaining
self.get_logger().info(f'Distance remaining: {distance:.2f}m')

Lifecycle Nodes

Lifecycle (managed) nodes follow a state machine:

Unconfigured → Inactive → Active → Finalized

Active

This enables coordinated startup:

from rclpy.lifecycle import Node as LifecycleNode

class ManagedSensor(LifecycleNode):
def __init__(self):
super().__init__('managed_sensor')

def on_configure(self, state):
self.get_logger().info('Configuring sensor...')
# Load parameters, allocate resources
return TransitionCallbackReturn.SUCCESS

def on_activate(self, state):
self.get_logger().info('Sensor active — publishing data')
self.timer = self.create_timer(0.1, self.publish_data)
return TransitionCallbackReturn.SUCCESS

def on_deactivate(self, state):
self.get_logger().info('Sensor deactivated')
self.destroy_timer(self.timer)
return TransitionCallbackReturn.SUCCESS

Nav2 is the standard ROS 2 navigation framework. It handles:

  1. Localization: Where is the robot? (AMCL)
  2. Path Planning: How to get from A to B? (NavFn, Smac)
  3. Obstacle Avoidance: How to avoid hitting things? (DWB, MPPI)
  4. Recovery: What to do when stuck? (Spin, backup)

Launching Nav2

# Launch Nav2 with a robot in Gazebo
ros2 launch nav2_bringup tb4_simulation_launch.py \
world:=warehouse.sdf

Sending Navigation Goals

# Send a goal via CLI
ros2 action send_goal /navigate_to_pose \
nav2_msgs/action/NavigateToPose \
"{pose: {pose: {position: {x: 2.0, y: 1.0}}}}"

Exercise: Service-Action Pipeline

Build a system where:

  1. A service computes the nearest charging station coordinate
  2. An action navigates the robot to that coordinate
  3. Feedback reports distance remaining every second
tip

You can test this entirely in simulation. Launch TurtleBot 4 in Gazebo and use the Nav2 action interface.

Summary

In this chapter you learned:

  • Services provide synchronous request-response communication
  • Actions handle long-running tasks with goals, feedback, and results
  • Lifecycle nodes enable coordinated startup and shutdown
  • Nav2 is the complete navigation stack for autonomous robot movement

Next: Module 2: The Digital Twin — simulate your robot in Gazebo.