ROS 2 Topics - Asynchronous Communication in the Robotic Nervous System
What are ROS 2 Topics?
A Topic is a named bus over which nodes exchange messages asynchronously, forming a many-to-many communication pattern. Topics are the primary mechanism for asynchronous communication in ROS 2 and represent the "synapses" of the robotic nervous system, enabling nodes to share information without direct coordination.
Key Characteristics of Topics
Asynchronous Communication
- Publishers send messages without waiting for responses
- Subscribers receive messages when they are available
- No direct connection between publishers and subscribers
Many-to-Many Pattern
- Multiple publishers can send to the same topic
- Multiple subscribers can receive from the same topic
- Decouples publishers from subscribers in time and space
Message Type
- Each topic has a specific message type (e.g.,
std_msgs/String,sensor_msgs/LaserScan) - All publishers and subscribers on a topic must use the same message type
- Message types are defined using
.msgfiles
Creating Publishers and Subscribers
Publisher Example
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class TalkerNode(Node):
def __init__(self):
super().__init__('talker')
self.publisher_ = self.create_publisher(String, 'chatter', 10)
timer_period = 0.5 # seconds
self.timer = self.create_timer(timer_period, 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
Subscriber Example
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class ListenerNode(Node):
def __init__(self):
super().__init__('listener')
self.subscription = self.create_subscription(
String,
'chatter',
self.listener_callback,
10)
self.subscription # prevent unused variable warning
def listener_callback(self, msg):
self.get_logger().info(f'I heard: "{msg.data}"')
Quality of Service (QoS) Profiles
QoS profiles control how messages are delivered between publishers and subscribers:
Reliability
- Reliable: All messages are guaranteed to be delivered
- Best Effort: Messages may be lost, but higher throughput
Durability
- Transient Local: Late-joining subscribers receive the last message
- Volatile: No messages are stored for late joiners
History
- Keep Last: Store the most recent N messages
- Keep All: Store all messages (use with caution)
Example with QoS
from rclpy.qos import QoSProfile, ReliabilityPolicy, DurabilityPolicy
# Create a custom QoS profile
qos_profile = QoSProfile(
depth=10,
reliability=ReliabilityPolicy.RELIABLE,
durability=DurabilityPolicy.VOLATILE
)
self.publisher_ = self.create_publisher(String, 'chatter', qos_profile)
Topic Commands
Listing Topics
ros2 topic list
Getting Topic Information
ros2 topic info /chatter
Echoing Topic Data
ros2 topic echo /chatter std_msgs/msg/String
Publishing to a Topic (Command Line)
ros2 topic pub /chatter std_msgs/msg/String "data: 'Hello World'"
Message Types
Common Built-in Types
std_msgs: Basic data types (String, Int32, Float64, etc.)sensor_msgs: Sensor data (LaserScan, Image, PointCloud2, etc.)geometry_msgs: Geometric primitives (Point, Pose, Twist, etc.)nav_msgs: Navigation messages (Odometry, Path, OccupancyGrid, etc.)
Creating Custom Message Types
Custom message types are defined in .msg files in the msg/ directory of a package:
# Custom message example: MyMessage.msg
string name
int32 id
float64[] values
geometry_msgs/Point position
Advanced Topic Features
Latching
Latching allows publishers to send the last message to late-joining subscribers:
# This is now handled by Transient Local durability QoS
Publisher/Subscriber Count
Check how many publishers or subscribers are connected:
# Get number of publishers for a topic
publisher_count = self.publisher_.get_subscription_count()
# Get number of subscribers for a topic (from subscriber side)
# This is not directly available, but you can infer from message rates
Topic Remapping
Remap topic names at runtime:
# In Python launch file
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
package='my_package',
executable='talker',
name='talker',
remappings=[('chatter', 'custom_chatter')]
)
])
Topic Performance Considerations
Bandwidth
- High-frequency topics can consume significant bandwidth
- Use appropriate message types (e.g., compressed images)
- Consider throttling for high-bandwidth topics
Latency
- Choose appropriate QoS settings for your application
- Monitor message delay with tools like
ros2 topic hz
Memory Usage
- QoS history depth affects memory consumption
- Be careful with "Keep All" history policy
The Role of Topics in the Robotic Nervous System
Topics function as the primary communication mechanism in the robotic nervous system:
- Sensors: Publish sensor data (camera images, LIDAR scans, IMU readings)
- Controllers: Publish commands to actuators
- Perception: Publish detected objects, maps, or other processed data
- Behavior: Publish status, goals, or other coordination information
This asynchronous communication pattern allows for flexible, decoupled robot software architectures where nodes can be added, removed, or modified without affecting other parts of the system.
Common Patterns
Sensor Data Distribution
Multiple perception nodes can subscribe to the same sensor data without affecting the sensor node.
Command Distribution
A single controller can publish commands to multiple actuator nodes simultaneously.
Status Broadcasting
Nodes can broadcast their status to multiple monitoring or logging nodes.
Next Steps
Now that you understand ROS 2 Topics, continue to learn about:
- Services: Synchronous request-response communication
- Actions: Goal-oriented communication for long-running tasks
- Architecture: How nodes and topics work together in the ROS 2 graph