D.HOSKIA
Module 2·55 min

ROS 2 Nodes and Topics

ROS 2 Nodes and Topics

ROS 2 is the middleware layer that connects robot hardware to high-level behavior. Understanding its communication primitives is essential for CatBot's software stack.

The Computation Graph

In ROS 2, software is organized into nodes — processes that perform specific tasks. Nodes communicate via:

  • Topics — asynchronous publish/subscribe (sensor data, state)
  • Services — synchronous request/response (configuration, queries)
  • Actions — long-running tasks with feedback (motion goals)
  • Parameters — runtime configuration values

Your First Publisher

import rclpy
from rclpy.node import Node
from std_msgs.msg import Float64

class JointCommandPublisher(Node):
    def __init__(self):
        super().__init__('joint_command_pub')
        self.pub = self.create_publisher(Float64, '/catbot/hip/command', 10)
        self.timer = self.create_timer(0.01, self.publish_command)  # 100 Hz
        self.get_logger().info('Joint command publisher started')

    def publish_command(self):
        msg = Float64()
        msg.data = 0.5  # radians
        self.pub.publish(msg)

def main():
    rclpy.init()
    node = JointCommandPublisher()
    rclpy.spin(node)
    rclpy.shutdown()

Your First Subscriber

from sensor_msgs.msg import JointState

class JointStateSubscriber(Node):
    def __init__(self):
        super().__init__('joint_state_sub')
        self.sub = self.create_subscription(
            JointState,
            '/catbot/joint_states',
            self.on_joint_state,
            10
        )

    def on_joint_state(self, msg: JointState):
        for name, pos in zip(msg.name, msg.position):
            self.get_logger().info(f'{name}: {pos:.4f} rad')

QoS Profiles

Quality of Service profiles control message delivery behavior:

from rclpy.qos import QoSProfile, ReliabilityPolicy, DurabilityPolicy

# For sensor data — use BEST_EFFORT (drop old messages)
sensor_qos = QoSProfile(
    reliability=ReliabilityPolicy.BEST_EFFORT,
    durability=DurabilityPolicy.VOLATILE,
    depth=1
)

For real-time control, use depth=1 and BEST_EFFORT to avoid queuing stale commands.