Welcome to ROS 2 workshop! — ROS 2 workshop documentation

Robot Operating System

  • Each node in ROS is responsible for a single, module purpose
    • (e.g. one node for controlling wheel motors, one node for controlling laser range-finder, etc)
  • Each node sends/receives data to other nodes via topics, services, actions, or parameters

Topics

Element of the ROS graph that acts as a bus for nodes to exchange messages Nodes may publish data to any number of topics and simultaneously have subscriptions to any number of topics. Topics are how data is moved between nodes and therefore between different parts of the system

Some topic commands:

rqt_graph
ros2 topic list
ros2 topic list -t
ros2 topic echo <topic_name>
ros2 topic info <topic_name>
ros2 interface show <msg_type>
ros2 topic pub <topic_name> <msg_type> ‘<args>’
ros2 topic hz <topic_name>

Services

  • Services are based on call-response model (not the publisher-subscriber model of topics)
  • Services only provide data when they are specifically called by a client (as opposed to continual updates from subscriptions from topics)

Service commands:

ros2 service list
ros2 service type <service_name>
ros2 service list -t
ros2 service find <type_name>
ros2 interface show <type_name>.srv
ros2 service call <service_name> <service_type> <arguments>

Actions

  • intended for long running tasks. Have 3 parts (GOAL, FEEDBACK, RESULT)
  • Similar to services, but are preemptable (you can cancel them while executing).
    • Also provide steady feedback (as opposed to services that return a single response)
  • Actions use a client-server model
    • Action client node sends a goal to an action server node that acknowledges the goal and returns a stream of feedback and a result

Parameters

  • Configuration value of a node (node settings)
  • Each node has its own parameters

Commands:

ros2 param list
ros2 param get <node_name> <parameter_name>
ros2 param set <node_name> <parameter_name> <value>

Getting ROS parameters programmatically:

  • In a node, declare a parameter first
self.declare_parameter('my_param')
  • Then get a parameter
self.get_parameter('my_param')

Workspace

Defines context for the current workspace Creating a new workspace cd <your_workspace> $ rosdep install -i —from-path src —rosdistro foxy -y

1. What is the Publisher-Subscriber Model?

Publisher

  • A node that generates and sends data on a specific topic.
  • For example, a node could publish sensor data like LIDAR scans or images.

Subscriber

  • A node that listens to a specific topic to receive data.
  • For example, a navigation node could subscribe to odometry data to compute paths.

Topic

  • A named communication channel through which publishers send messages and subscribers receive them.
  • Think of it as a “mailbox” where data is delivered.

2. How Does it Work?

  1. A publisher node publishes messages to a topic.
  2. A subscriber node subscribes to the same topic.
  3. The ROS middleware (RMW) delivers messages from the publisher to all subscribers of the topic.

This decouples nodes:

  • The publisher doesn’t need to know which nodes are subscribing.
  • The subscriber doesn’t need to know which nodes are publishing.

3. Key Concepts

Messages

  • Data exchanged between nodes.
  • Defined in .msg files in ROS and can contain primitive types (e.g., integers, floats) or nested structures.
  • Example: std_msgs/String.msg (contains a single string).

Topics

  • Identified by a name (e.g., /scan, /cmd_vel).
  • Names should be unique to avoid conflicts.

QoS (Quality of Service)

  • ROS 2 introduces QoS policies to control message delivery:
    • Reliability: Reliable or Best Effort.
    • Durability: Volatile or Transient Local.
    • History: Keep Last or Keep All.

4. Example in ROS 2

Publisher

Here’s a simple Python publisher:

import rclpy
from rclpy.node import Node
from std_msgs.msg import String
 
class SimplePublisher(Node):
    def __init__(self):
        super().__init__('simple_publisher')
        self.publisher_ = self.create_publisher(String, 'chatter', 10)
        self.timer = self.create_timer(0.5, self.publish_message)
 
    def publish_message(self):
        msg = String()
        msg.data = 'Hello, ROS 2!'
        self.publisher_.publish(msg)
        self.get_logger().info(f'Publishing: {msg.data}')
 
def main(args=None):
    rclpy.init(args=args)
    node = SimplePublisher()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()
 
if __name__ == '__main__':
    main()
 
  • Topic: chatter.
  • Message Type: std_msgs/String.

Subscriber

Here’s a simple Python subscriber:

import rclpy
from rclpy.node import Node
from std_msgs.msg import String
 
class SimpleSubscriber(Node):
    def __init__(self):
        super().__init__('simple_subscriber')
        self.subscription = self.create_subscription(
            String,
            'chatter',
            self.callback,
            10
        )
 
    def callback(self, msg):
        self.get_logger().info(f'Received: {msg.data}')
 
def main(args=None):
    rclpy.init(args=args)
    node = SimpleSubscriber()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()
 
if __name__ == '__main__':
    main()
 
  • Subscribes to the chatter topic.
  • Processes messages received in the callback function.

Running the Nodes

  1. Launch the publisher:
    python3 simple_publisher.py

  2. Launch the subscriber in a separate terminal: python3 simple_subscriber.py

  3. The subscriber will print the messages sent by the publisher.