Chapter 1: Introduction to ROS2

What is ROS2?

ROS2 (Robot Operating System 2) is an open-source robotics middleware framework that provides:

  • Communication infrastructure between robot components
  • Tools and libraries for robot development
  • Hardware abstraction for sensors and actuators
  • Package management for code reuse

ROS2 vs ROS1

Feature ROS1 ROS2
Real-time Limited Yes (DDS)
Security No Built-in
Multi-robot Difficult Native
Platforms Linux only Linux, Windows, macOS
Communication Custom DDS standard

ROS2 Architecture

graph TB
    subgraph "ROS2 Application"
        N1[Node 1] -->|Topic| N2[Node 2]
        N2 -->|Service| N3[Node 3]
        N3 -->|Action| N4[Node 4]
    end
    
    subgraph "DDS Layer"
        DDS[Data Distribution Service]
    end
    
    N1 -.-> DDS
    N2 -.-> DDS
    N3 -.-> DDS
    N4 -.-> DDS
    
    style N1 fill:#C9B59C
    style N2 fill:#C9B59C
    style N3 fill:#C9B59C
    style N4 fill:#C9B59C
    style DDS fill:#EFE9E3

Installation

# Set locale
sudo apt update && sudo apt install locales
sudo locale-gen en_US en_US.UTF-8
sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
export LANG=en_US.UTF-8

# Add ROS2 repository
sudo apt install software-properties-common
sudo add-apt-repository universe
sudo apt update && sudo apt install curl -y
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null

# Install ROS2 Humble
sudo apt update
sudo apt upgrade
sudo apt install ros-humble-desktop

# Install development tools
sudo apt install ros-dev-tools

Verify Installation

# Source ROS2
source /opt/ros/humble/setup.bash

# Test with demo
ros2 run demo_nodes_cpp talker

Core Concepts

1. Nodes

Nodes are the basic building blocks - independent processes that perform computation.

import rclpy
from rclpy.node import Node

class MinimalNode(Node):
    def __init__(self):
        super().__init__('minimal_node')
        self.get_logger().info('Hello from ROS2!')

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

if __name__ == '__main__':
    main()

2. Topics

Topics enable publish-subscribe communication between nodes.

from std_msgs.msg import String

class PublisherNode(Node):
    def __init__(self):
        super().__init__('publisher_node')
        self.publisher = self.create_publisher(String, 'chatter', 10)
        self.timer = self.create_timer(1.0, self.timer_callback)
        self.counter = 0
    
    def timer_callback(self):
        msg = String()
        msg.data = f'Hello ROS2: {self.counter}'
        self.publisher.publish(msg)
        self.get_logger().info(f'Publishing: "{msg.data}"')
        self.counter += 1

3. Services

Services provide request-response communication.

from example_interfaces.srv import AddTwoInts

class ServiceNode(Node):
    def __init__(self):
        super().__init__('service_node')
        self.srv = self.create_service(
            AddTwoInts,
            'add_two_ints',
            self.add_two_ints_callback
        )
    
    def add_two_ints_callback(self, request, response):
        response.sum = request.a + request.b
        self.get_logger().info(f'{request.a} + {request.b} = {response.sum}')
        return response

Workspace Setup

Create ROS2 Workspace

# Create workspace
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws

# Build workspace
colcon build

# Source workspace
source install/setup.bash

Create Your First Package

cd ~/ros2_ws/src

# Python package
ros2 pkg create --build-type ament_python my_robot_pkg

# C++ package
ros2 pkg create --build-type ament_cmake my_robot_cpp

ROS2 Command Line Tools

Essential Commands

# List nodes
ros2 node list

# Node information
ros2 node info /node_name

# List topics
ros2 topic list

# Echo topic messages
ros2 topic echo /topic_name

# Topic information
ros2 topic info /topic_name

# Publish to topic
ros2 topic pub /topic_name std_msgs/msg/String "data: 'Hello'"

# List services
ros2 service list

# Call service
ros2 service call /service_name example_interfaces/srv/AddTwoInts "{a: 5, b: 3}"

# List parameters
ros2 param list

# Get parameter
ros2 param get /node_name parameter_name

Complete Example: Temperature Monitor

Publisher (Sensor Simulator)

import rclpy
from rclpy.node import Node
from std_msgs.msg import Float32
import random

class TemperatureSensor(Node):
    def __init__(self):
        super().__init__('temperature_sensor')
        self.publisher = self.create_publisher(Float32, 'temperature', 10)
        self.timer = self.create_timer(1.0, self.publish_temperature)
        self.get_logger().info('Temperature sensor started')
    
    def publish_temperature(self):
        msg = Float32()
        # Simulate temperature reading (20-30°C)
        msg.data = 20.0 + random.random() * 10.0
        self.publisher.publish(msg)
        self.get_logger().info(f'Temperature: {msg.data:.2f}°C')

def main(args=None):
    rclpy.init(args=args)
    sensor = TemperatureSensor()
    rclpy.spin(sensor)
    sensor.destroy_node()
    rclpy.shutdown()

Subscriber (Monitor)

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

class TemperatureMonitor(Node):
    def __init__(self):
        super().__init__('temperature_monitor')
        self.subscription = self.create_subscription(
            Float32,
            'temperature',
            self.temperature_callback,
            10
        )
        self.get_logger().info('Temperature monitor started')
    
    def temperature_callback(self, msg):
        temp = msg.data
        if temp > 28.0:
            self.get_logger().warn(f'High temperature: {temp:.2f}°C')
        elif temp < 22.0:
            self.get_logger().info(f'Low temperature: {temp:.2f}°C')
        else:
            self.get_logger().info(f'Normal temperature: {temp:.2f}°C')

def main(args=None):
    rclpy.init(args=args)
    monitor = TemperatureMonitor()
    rclpy.spin(monitor)
    monitor.destroy_node()
    rclpy.shutdown()

Launch Files

Manage multiple nodes with launch files:

from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription([
        Node(
            package='my_robot_pkg',
            executable='temperature_sensor',
            name='sensor'
        ),
        Node(
            package='my_robot_pkg',
            executable='temperature_monitor',
            name='monitor'
        ),
    ])

Run with:

ros2 launch my_robot_pkg temperature_system.launch.py

Key Takeaways

  1. ✅ ROS2 is the modern robotics middleware
  2. ✅ Nodes are independent processes
  3. ✅ Topics enable pub-sub communication
  4. ✅ Services provide request-response
  5. ✅ Workspaces organize your code
  6. ✅ Command-line tools for debugging

Review Questions

  1. What are the main improvements of ROS2 over ROS1?
  2. What is a ROS2 node?
  3. Explain the difference between topics and services
  4. How do you create a ROS2 workspace?
  5. What command lists all active topics?

Next Steps

In Chapter 2, we'll dive deeper into ROS2 communication patterns including actions, parameters, and quality of service (QoS) settings!

Complete Lab 1 to set up your environment and create your first ROS2 nodes!