Chapter 3: The Digital Twin (Gazebo & Unity)
Learning Objectives
By the end of this chapter, you will be able to:
- Understand the ROS 2 architecture and its core components
- Create and manage ROS 2 nodes, topics, and services
- Write basic publisher/subscriber programs in Python
- Navigate the ROS 2 ecosystem and command-line tools
Introduction
Robot Operating System (ROS 2) is the industry-standard middleware for building robot software. It provides tools, libraries, and conventions for developing modular, reusable robot applications.
ROS 2 is a complete redesign of ROS 1, with improvements in real-time performance, security, and multi-robot support. It's used in research labs, startups, and production systems worldwide.
Core Concepts
ROS 2 Architecture
ROS 2 uses a distributed architecture where independent programs (nodes) communicate over well-defined interfaces.
Key Components:
- Nodes: Independent processes that perform specific tasks
- Topics: Named channels for asynchronous message passing
- Services: Synchronous request-response communication
- Actions: Long-running tasks with feedback
- Parameters: Configuration values for nodes
Nodes
A node is a single executable that performs one function (e.g., reading a camera, controlling a motor, planning a path).
Design Philosophy: One node = one responsibility
Example nodes in a mobile robot:
camera_driver: Publishes camera imagesobject_detector: Detects objects in imagesnavigation: Plans paths and sends velocity commandsmotor_controller: Converts velocity to motor commands
Topics and Messages
Topics enable publish-subscribe communication:
- Publishers send messages to a topic
- Subscribers receive messages from a topic
- Messages are typed (e.g.,
sensor_msgs/Image,geometry_msgs/Twist)
┌─────────┐ Topic: /camera/image ┌─────────┐
│ Camera │ ──────────────────────────────────> │ Detector│
│ Node │ (sensor_msgs/Image) │ Node │
└─────────┘ └─────────┘
Services
Services provide synchronous request-response communication:
- Client sends a request and waits for a response
- Server processes the request and returns a result
Use cases: Query robot state, trigger one-time actions
# Service call example (pseudocode)
response = client.call_async(request)
result = response.result()
Actions
Actions are for long-running tasks that need:
- Goal: What to achieve
- Feedback: Progress updates
- Result: Final outcome
Example: "Navigate to position (x, y)" with periodic position feedback.
Practical Application
Example 1: Simple Publisher (Python)
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(1.0, self.timer_callback)
self.count = 0
def timer_callback(self):
msg = String()
msg.data = f'Hello World: {self.count}'
self.publisher_.publish(msg)
self.get_logger().info(f'Publishing: "{msg.data}"')
self.count += 1
def main(args=None):
rclpy.init(args=args)
node = MinimalPublisher()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
Explanation:
- Create a node called
minimal_publisher - Create a publisher on the
topictopic with a queue size of 10 - Use a timer to publish a message every 1 second
rclpy.spin()keeps the node running
Example 2: Simple Subscriber (Python)
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class MinimalSubscriber(Node):
def __init__(self):
super().__init__('minimal_subscriber')
self.subscription = self.create_subscription(
String,
'topic',
self.listener_callback,
10)
def listener_callback(self, msg):
self.get_logger().info(f'Received: "{msg.data}"')
def main(args=None):
rclpy.init(args=args)
node = MinimalSubscriber()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
Explanation:
- Create a subscriber on the
topictopic - Register
listener_callbackto handle incoming messages - Print received messages to the console
Running the Example
# Terminal 1: Run publisher
ros2 run my_package publisher
# Terminal 2: Run subscriber
ros2 run my_package subscriber
# Terminal 3: Inspect topics
ros2 topic list
ros2 topic echo /topic
Command-Line Tools
# List all nodes
ros2 node list
# List all topics
ros2 topic list
# Get info about a topic
ros2 topic info /camera/image
# Echo messages from a topic
ros2 topic echo /camera/image
# Call a service
ros2 service call /service_name service_type "{request_data}"
# View node graph
ros2 run rqt_graph rqt_graph
Summary
ROS 2 provides a powerful framework for building modular robot systems. Its pub-sub architecture enables loose coupling between components, making systems easier to develop, test, and scale.
Understanding nodes, topics, and services is essential for working with any ROS 2-based robot platform, from academic research robots to commercial humanoids.
Key Takeaways:
- ROS 2 uses a distributed architecture with independent nodes
- Topics enable asynchronous publish-subscribe communication
- Services provide synchronous request-response patterns
- Python and C++ are the primary languages for ROS 2 development
Further Reading
-
Official Documentation:
-
Books:
- A Concise Introduction to Robot Programming with ROS 2 by Francisco Martín Rico
- Programming Robots with ROS by Morgan Quigley et al.
-
Online Courses:
-
Community: