Python ROS 2 for Robotics — Core Concepts
What ROS 2 Is
ROS 2 (Robot Operating System 2) is an open-source middleware framework for building robot applications. It provides communication primitives, hardware abstraction, device drivers, visualization tools, and a massive ecosystem of reusable packages. Maintained by Open Robotics (now part of Intrinsic, an Alphabet company), ROS 2 is the successor to ROS 1, redesigned for production use in commercial robotics.
ROS 2 is not an operating system. It runs on top of Linux, macOS, or Windows and provides the “plumbing” that connects different parts of a robot software system.
Core Architecture: Nodes and Communication
A ROS 2 application is a graph of nodes — independent processes that each handle one responsibility. A typical robot might have nodes for:
- Camera image processing
- LIDAR point cloud filtering
- Path planning and navigation
- Motor control
- Speech recognition
- Battery monitoring
Nodes communicate through three patterns:
Topics (Publish-Subscribe)
Topics are named channels for streaming data. A node publishes messages to a topic, and any number of nodes can subscribe. This is the most common communication pattern.
# Publisher: camera node publishes images
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Image
class CameraNode(Node):
def __init__(self):
super().__init__('camera_node')
self.publisher = self.create_publisher(Image, '/camera/image', 10)
self.timer = self.create_timer(0.033, self.publish_frame) # 30 fps
def publish_frame(self):
msg = Image()
# Fill image data from camera
self.publisher.publish(msg)
self.get_logger().debug('Published frame')
# Subscriber: detection node reads images
class DetectionNode(Node):
def __init__(self):
super().__init__('detection_node')
self.subscription = self.create_subscription(
Image, '/camera/image', self.detect_objects, 10)
def detect_objects(self, msg):
# Process image and detect objects
self.get_logger().info('Detected objects in frame')
Services (Request-Response)
Services handle one-shot requests that need a reply. Think of asking the robot a question and waiting for the answer:
from example_interfaces.srv import AddTwoInts
class CalibrationService(Node):
def __init__(self):
super().__init__('calibration_service')
self.srv = self.create_service(
AddTwoInts, 'calibrate_sensor', self.calibrate_callback)
def calibrate_callback(self, request, response):
response.sum = request.a + request.b
self.get_logger().info(f'Calibration result: {response.sum}')
return response
Actions (Long-Running Tasks)
Actions handle tasks that take time and provide progress feedback. Navigating to a waypoint is a classic example — you send the goal, receive periodic progress updates, and eventually get a result.
Message Types
ROS 2 uses strongly typed messages defined in .msg files. The ecosystem provides hundreds of standard message types:
- std_msgs — Primitives like String, Int32, Float64
- geometry_msgs — Pose, Twist, Point, Quaternion
- sensor_msgs — Image, LaserScan, PointCloud2, Imu
- nav_msgs — OccupancyGrid, Path, Odometry
You can also define custom messages for your specific application.
The Python Client Library: rclpy
rclpy (ROS Client Library for Python) is the official Python interface to ROS 2. A minimal node:
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, 'chatter', 10)
self.timer = self.create_timer(1.0, self.timer_callback)
def timer_callback(self):
msg = String()
msg.data = 'Hello, robot world!'
self.publisher.publish(msg)
def main():
rclpy.init()
node = MinimalPublisher()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
Packages and Workspaces
ROS 2 code is organized into packages — self-contained units with their own dependencies, launch files, and configuration. Packages live in a workspace — a directory where you build and run your robot software:
# Create a workspace
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src
# Create a Python package
ros2 pkg create --build-type ament_python my_robot --dependencies rclpy std_msgs
# Build the workspace
cd ~/ros2_ws
colcon build
# Source the workspace
source install/setup.bash
# Run a node
ros2 run my_robot my_node
Launch Files
Real robots need many nodes running simultaneously. Launch files start and configure multiple nodes:
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(package='my_robot', executable='camera_node'),
Node(package='my_robot', executable='detection_node'),
Node(package='my_robot', executable='motor_node',
parameters=[{'max_speed': 1.5}]),
])
Common Misconception
Many people think ROS 2 is only for physical robots. In practice, a significant portion of ROS 2 development happens in simulation (Gazebo, Isaac Sim) before any hardware is involved. The same nodes, topics, and messages work identically whether the robot is real or simulated. This is one of ROS 2’s greatest strengths for development and testing.
One thing to remember: ROS 2 turns complex robot systems into manageable pieces — each node does one job, communicates through typed messages, and can be developed, tested, and replaced independently.
See Also
- Python Behavior Trees Robotics How robots make decisions using a tree-shaped rulebook that keeps them organized, like a flowchart that tells a robot what to do in every situation.
- Python Bluetooth Ble How Python connects to fitness trackers, smart locks, and wireless sensors using the invisible radio signals all around you.
- Python Circuitpython Hardware Why CircuitPython makes wiring up LEDs, sensors, and motors as easy as plugging in a USB drive.
- Python Computer Vision Autonomous How self-driving cars use cameras and Python to see the road, spot pedestrians, read signs, and understand traffic — like giving a car human eyes and a brain.
- Python Home Assistant Automation How Python turns your home into a smart home that reacts to you automatically, like a helpful invisible butler.