Chapter 5: ROS 2 Fundamentals
Overview
What You'll Learn
- Explain ROS 2 architecture and design philosophy
- Understand nodes, topics, services, and actions
- Configure DDS middleware for robot communication
- Use ROS 2 CLI tools for debugging
Estimated Time: 7-9 hours
Background
ROS 2 is the second generation of the Robot Operating System, redesigned for production robotics with real-time performance, security, and multi-robot support.
Key Improvements over ROS 1:
- DDS middleware (no roscore dependency)
- Real-time capable
- Native Windows/macOS support
- Security (SROS2)
- Better embedded support
Core Concepts
Concept 1: Nodes
Node = single-purpose executable in the ROS graph
import rclpy
from rclpy.node import Node
class MinimalNode(Node):
def __init__(self):
super().__init__('minimal_node')
self.get_logger().info('Node started')
def main():
rclpy.init()
node = MinimalNode()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
Concept 2: Topics (Pub-Sub)
Topic = named bus for asynchronous message passing
from std_msgs.msg import String
class Publisher(Node):
def __init__(self):
super().__init__('publisher')
self.pub = self.create_publisher(String, 'topic', 10)
self.timer = self.create_timer(1.0, self.callback)
def callback(self):
msg = String()
msg.data = 'Hello ROS 2'
self.pub.publish(msg)
Concept 3: Services (Request-Response)
Service = synchronous RPC pattern
from example_interfaces.srv import AddTwoInts
class ServiceNode(Node):
def __init__(self):
super().__init__('service_node')
self.srv = self.create_service(
AddTwoInts, 'add_two_ints', self.callback
)
def callback(self, request, response):
response.sum = request.a + request.b
return response
Concept 4: Actions (Long-Running Tasks)
Action = goal-based asynchronous pattern with feedback
from action_tutorials_interfaces.action import Fibonacci
from rclpy.action import ActionServer
class FibonacciServer(Node):
def __init__(self):
super().__init__('fibonacci_server')
self._action_server = ActionServer(
self, Fibonacci, 'fibonacci',
self.execute_callback
)
async def execute_callback(self, goal_handle):
# Long-running computation
feedback = Fibonacci.Feedback()
# ... computation ...
goal_handle.succeed()
result = Fibonacci.Result()
return result
Implementation
Setup: ROS 2 Workspace
# Create workspace
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src
# Create package
ros2 pkg create --build-type ament_python my_robot_pkg
# Build
cd ~/ros2_ws
colcon build
source install/setup.bash
Tutorial: Publisher-Subscriber
Create publisher.py:
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class MinimalPublisher(Node):
def __init__(self):
super().__init__('minimal_publisher')
self.publisher_ = self.create_publisher(String, 'topic', 10)
self.timer = self.create_timer(0.5, self.timer_callback)
self.i = 0
def timer_callback(self):
msg = String()
msg.data = f'Hello World: {self.i}'
self.publisher_.publish(msg)
self.get_logger().info(f'Publishing: "{msg.data}"')
self.i += 1
def main(args=None):
rclpy.init(args=args)
node = MinimalPublisher()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
Lab Exercises
Lab 1: Build Your First ROS 2 Package
Objective: Create functional pub-sub system
Tasks:
- Create ROS 2 workspace
- Implement publisher node
- Implement subscriber node
- Test communication
- Use ros2 CLI tools for debugging
Deliverables:
- Working package with publisher and subscriber
- Screenshot of
ros2 topic echooutput - Documentation of ROS 2 commands used
Validation:
# Terminal 1
ros2 run my_robot_pkg publisher
# Terminal 2
ros2 topic echo /topic
# Should see messages flowing
Summary
Key Takeaways
- Nodes are independent processes communicating via DDS
- Topics enable many-to-many async communication
- Services provide request-response patterns
- Actions handle long-running tasks with feedback
- Colcon builds ROS 2 workspaces