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
| Pattern | Use Case | Example |
|---|---|---|
| Topic | Continuous data stream | Sensor readings, camera frames |
| Service | One-time request | Calculate 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: The Navigation Stack
Nav2 is the standard ROS 2 navigation framework. It handles:
- Localization: Where is the robot? (AMCL)
- Path Planning: How to get from A to B? (NavFn, Smac)
- Obstacle Avoidance: How to avoid hitting things? (DWB, MPPI)
- 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:
- A service computes the nearest charging station coordinate
- An action navigates the robot to that coordinate
- 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.