Skip to main content

Nodes and Topics

Introduction

Nodes and topics form the backbone of ROS 2 communication. Nodes are independent programs that publish or subscribe to topics to exchange data asynchronously.

Learning Objectives:

  • Create ROS 2 nodes in Python
  • Publish messages to topics
  • Subscribe to topics and process data
  • Understand Quality of Service (QoS)

What are Nodes?

A node is an executable that uses ROS 2 to communicate with other nodes. Each node should have a single, well-defined purpose:

  • Camera driver node
  • Motor controller node
  • Path planning node

What are Topics?

A topic is a named bus for transmitting messages. Nodes publish to topics and subscribe to topics:

  • /camera/image - camera images
  • /cmd_vel - velocity commands
  • /odom - odometry data

Publisher-Subscriber Pattern

Publisher Node → Topic → Subscriber Node(s)

Multiple subscribers can listen to one topic. One publisher is typical, but multiple publishers are allowed.

Creating a 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(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()

if __name__ == '__main__':
main()

Creating a 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'I heard: "{msg.data}"')

def main(args=None):
rclpy.init(args=args)
node = MinimalSubscriber()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()

if __name__ == '__main__':
main()

Running Nodes

# Terminal 1: Run publisher
python3 publisher.py

# Terminal 2: Run subscriber
python3 subscriber.py

# Terminal 3: Inspect topics
ros2 topic list
ros2 topic echo /topic
ros2 topic hz /topic
ros2 topic info /topic

Quality of Service (QoS)

QoS policies control message delivery reliability and performance:

  • Reliability: RELIABLE (guaranteed) vs BEST_EFFORT (fast)
  • Durability: VOLATILE (current) vs TRANSIENT_LOCAL (late joiners get history)
  • History: Keep last N messages
from rclpy.qos import QoSProfile, ReliabilityPolicy

qos = QoSProfile(depth=10, reliability=ReliabilityPolicy.RELIABLE)
self.publisher_ = self.create_publisher(String, 'topic', qos)

Exercises

  1. Create a publisher node that sends robot position data
  2. Create a subscriber that receives and prints the position
  3. Use ros2 topic hz to measure message frequency
  4. Experiment with different QoS settings

Summary

Nodes communicate via topics using the publish-subscribe pattern. Publishers send messages asynchronously, and subscribers receive them. QoS policies control delivery guarantees.

Further Reading