ROS 2 Guide

ROS 2 is the free software framework behind most research robots and many hobby robots. This guide starts with a plain summary of what it is and who needs it. It then covers releases, hardware, how the parts of a robot program talk to each other, and the main tools and libraries. The later sections go deep into middleware, quality of service, executors, real-time control and security, with example robots that run ROS 2 throughout.

ROS 2 in brief

ROS stands for Robot Operating System, but it is not an operating system. It is a set of libraries and tools that runs on top of Linux (and to a lesser degree Windows and macOS). Its main job is to let many small programs share data inside a robot. One program reads the lidar, another builds a map, a third plans a path and a fourth drives the wheels. ROS 2 connects them, so each piece can be written, tested and swapped on its own.

The bigger draw is the ecosystem. Thousands of free packages already handle mapping, navigation, arm motion planning, camera drivers and simulation. A robot that "supports ROS 2" can usually use all of them without new code. That is why a $300 education rover and a $50,000 research robot often run the same navigation software.

Good fit

  • Robots that map rooms, navigate, or plan arm motion
  • Robots with a Linux computer such as a Raspberry Pi or Jetson
  • Projects that mix many sensors and motors
  • Anyone aiming for robotics research or a robotics job

Poor fit

  • A first robot programmed in blocks or simple Python
  • Small microcontroller robots with no Linux computer
  • Quick one-off scripts, where the setup outweighs the gain
  • Toy and companion robots with closed software

ROS 2 has a difficult learning curve. Learning it means learning Linux, the command line, a build system and a new way of structuring programs. Most people need a few weeks before it clicks. The payoff is that skills carry over from one ROS 2 robot to the next, from a classroom TurtleBot 4 to a Stretch or Go2 EDU.

ROS 1 and ROS 2

The original ROS began at Stanford in 2007 and grew up at Willow Garage, a robotics research lab that released ROS 1.0 in 2010. It became the standard in university labs, but it had limits that mattered outside them. Every system depended on one central program, the ROS master, and its networking assumed a reliable wired network. It had no security and little support for real-time control.

ROS 2 was a rewrite rather than an update. It replaced the custom networking with an industrial standard called DDS, removed the central master, and added security, quality-of-service settings and support for Windows and microcontrollers. The first full release came in December 2017. The last ROS 1 release, Noetic, reached end of life in May 2025, so all new work should use ROS 2.

ROS is open source under the Apache 2.0 license and is maintained by the nonprofit Open Source Robotics Foundation, with funding from member companies through the Open Source Robotics Alliance. It is not only for small robots. The Autoware self-driving stack, the Open-RMF system for managing robot fleets in hospitals and warehouses, and the ROS-Industrial packages for factory arms are all built on it.

ROS 1ROS 2
StatusEnded May 2025Current, with new releases every May
Central serverROS master requiredNone, programs find each other
NetworkingCustom TCP protocolDDS or Zenoh, chosen by a setting
Network tuningNoneQuality-of-service settings per connection
SecurityNoneEncryption and access control (SROS2)
Build toolcatkincolcon with ament
Launch filesXMLPython, XML or YAML
PlatformsUbuntuUbuntu, Windows, RHEL, macOS (limited), microcontrollers

Some older kits still ship with ROS 1. The JetTank runs ROS Melodic, the JetHexa is tied to a Jetson Nano with Melodic, and the AiNex humanoid has no ROS 2 image yet. These still work, but tutorials and packages for them are shrinking. A bridge package (ros1_bridge) can link old ROS 1 code to a ROS 2 system during a move.

Releases

A new ROS 2 release, called a distribution or distro, comes out every year on May 23 (World Turtle Day). Each gets a two-word name with a turtle theme, moving through the alphabet one letter a year. Releases in even-numbered years are long-term support (LTS) releases with five years of fixes. Odd-year releases get about 18 months and mainly serve people who want newer features.

ReleaseReleasedMain UbuntuGazeboSupport ends
Lyrical Luth (LTS)May 202626.04JettyMay 2031
Kilted KaijuMay 202524.04IonicDecember 2026
Jazzy Jalisco (LTS)May 202424.04HarmonicMay 2029
Humble Hawksbill (LTS)May 202222.04FortressMay 2027
Rolling RidleyOngoingLatestLatestNone, it keeps moving

Each ROS 2 release is built for one Ubuntu version, and mixing them is the most common install problem. The Ubuntu version decides the ROS 2 release, and on a Jetson the JetPack version decides the Ubuntu version (see the Jetson Guide). Different releases can share a network for simple messages, but this is not officially supported.

Computers and operating systems

ROS 2 needs a computer that runs Linux. On a robot that usually means a Raspberry Pi, an NVIDIA Jetson or a small x86 PC. Microcontrollers such as an Arduino or ESP32 cannot run full ROS 2, but they can join a ROS 2 system through micro-ROS (see Microcontrollers and micro-ROS).

PlatformSupportNotes
Ubuntu LinuxTier 1The main platform, with ready-made packages from apt. Each release has its own Ubuntu version.
WindowsTier 1Official binaries, but many community packages are Linux-only. WSL2 (Ubuntu inside Windows) is the easier route.
Red Hat Enterprise LinuxTier 2Mainly used by companies.
macOSTier 3Builds from source with effort. Most Mac users run a Linux virtual machine, Docker or the community RoboStack (conda) packages.
DebianTier 3Raspberry Pi OS is Debian-based but not officially supported, so robot kits often run ROS 2 inside Docker on it instead.

Docker is popular because it pins the exact Ubuntu and ROS 2 versions inside a container, whatever the host runs. The official ros images on Docker Hub cover every current release.

Core concepts

A ROS 2 robot is a collection of programs called nodes. Each node does one job, such as reading the IMU or planning a path. Nodes find each other automatically on the network and form the ROS graph, the live picture of who is sending what to whom.

Communication

Communication is the heart of ROS 2. Nodes exchange data in four main ways, each suited to a different kind of task.

MethodPatternTypical useExample
TopicsMany senders to many receivers, continuous streamSensor data, motor commands, robot stateLidar scans on /scan
ServicesOne request, one replyQuick questions and one-off commandsReset odometry, save a map
ActionsA goal with progress updates and a final result, can be cancelledTasks that take seconds or minutesDrive to the kitchen, move the arm
ParametersSettings stored in each nodeConfiguration and tuningMaximum speed, camera frame rate

Topics

A topic is a named channel such as /cmd_vel or /camera/image_raw. Nodes publish messages to it and other nodes subscribe. Neither side knows or cares who is on the other end. A lidar driver publishes to /scan, and the map builder, the obstacle avoider and a visualizer on a laptop can all subscribe at once. Swapping in a different lidar only means a different driver publishing to the same topic.

Topics carry most of the data in a robot. Some names are conventions that nearly every robot follows, which is what lets standard packages work across robots.

TopicMessage typeContents
/cmd_velgeometry_msgs/Twist or TwistStampedSpeed and turn rate commands for a mobile base
/odomnav_msgs/OdometryThe robot's estimated position and speed from wheel odometry
/scansensor_msgs/LaserScanDistances from a 2D lidar
/imusensor_msgs/ImuOrientation, rotation rate and acceleration from an IMU
/camera/image_rawsensor_msgs/ImageCamera frames
/joint_statessensor_msgs/JointStateAngles and speeds of arm or leg joints
/tftf2_msgs/TFMessagePositions of the robot's parts relative to each other (see Coordinate frames)

At the lowest level, driving any ROS 2 rover works the same way. A node publishes a forward speed and a turn rate to /cmd_vel, and the base driver turns them into wheel speeds. This one convention is why a keyboard teleop node, a gamepad node and the Nav2 planner can all drive the same robot.

Services

A service is a function call between nodes. One node offers it, another sends a request and waits for the reply. Services suit short tasks with a clear answer, such as asking for the current map or switching a camera mode. They are a poor fit for anything slow, because the caller cannot see progress or cancel. A service that takes more than a second or two is usually better as an action.

Actions

An action is a long-running task with feedback. A client sends a goal, such as a position to drive to. The server accepts or rejects it, streams progress (distance remaining, for example), and finally returns a result. The client can cancel at any time. Navigation, arm motions and docking are all actions. Under the hood an action is built from three services and two topics.

Parameters

Each node has its own named settings, such as max_speed or frame_rate. They are usually loaded from a YAML file at launch and can be read or changed while the node runs. A node can reject a change it considers unsafe. Parameters are how the same Nav2 code is tuned for a small TurtleBot and a heavy outdoor robot.

Messages and interfaces

Every topic, service and action has a fixed data type defined in a short text file. A .msg file lists the fields of a message. A .srv file has a request and a reply, separated by three dashes. An .action file has a goal, a result and feedback.

# BatteryAlert.msg
builtin_interfaces/Time stamp
float32 voltage
uint8 percent
bool charging

At build time, ROS 2 turns these files into C++ and Python classes. Standard packages define the common types, such as std_msgs, geometry_msgs, sensor_msgs and nav_msgs. Reusing a standard type is almost always better than inventing a new one, since existing tools then understand the data.

Names, namespaces and remapping

Every node, topic, service and parameter has a name, and names can be grouped under a namespace. With two robots on one network, each runs under its own namespace, so their commands arrive on /robot1/cmd_vel and /robot2/cmd_vel rather than colliding on /cmd_vel. The same trick keeps a robot's front and rear cameras apart.

Remapping renames things when a node starts, without touching its code. A keyboard teleop node that publishes to /cmd_vel can be pointed at a second robot from the command line.

ros2 run teleop_twist_keyboard teleop_twist_keyboard --ros-args -r cmd_vel:=/robot2/cmd_vel

Remapping is what makes third-party packages reusable. A driver that publishes images on image_raw can be remapped to whatever name the rest of the system expects.

Discovery and domains

With no central server, nodes find each other by announcing themselves on the network. Any ROS 2 computer on the same network sees the others automatically. That is convenient on a wired network and a common headache on Wi-Fi (see Middleware).

The last two settings apply only to the DDS middleware. Zenoh ignores them and is configured through its own router settings instead.

Coordinate frames and tf2

A robot is full of positions measured from different places. The lidar reports distances from itself, the arm's camera sees objects relative to the gripper, and the map is fixed to the room. The tf2 library tracks how all these frames relate over time, so any point can be converted from one frame to another with one call.

Mobile robots follow a standard chain of frames set out in the ROS conventions (REP 105).

The localization node publishes the map to odom link, the base driver publishes odom to base_link, and the robot's description supplies the fixed links to each sensor. Distances are in meters and angles in radians, with x forward, y left and z up (REP 103). Most "the robot thinks the wall is behind it" bugs come from a wrong frame or a missing link in this chain.

Robot description (URDF)

A URDF file describes the robot's body as links (rigid parts) joined by joints, with shapes, masses and joint limits. Most are written in xacro, a macro language that adds variables and reusable pieces to the raw XML. The robot_state_publisher node reads the URDF and the /joint_states topic and publishes every part's position to tf2.

The same file drives RViz, the simulator, MoveIt and collision checking. Many makers publish a URDF for their robot, including Waveshare for the RoArm-M3, Dobot for the Magician E6 and Unitree for the Go2. The robot pages in this guide note where a model exists in each simulator. Lyrical adds URDF 1.2, with acceleration and jerk limits on joints.

Everyday tools

Simulation

A simulator runs a virtual copy of the robot that publishes the same topics as the real one. The same navigation or arm code runs in both, so most bugs get caught before anything can crash into a wall.

Major libraries

Most of the value of ROS 2 is in a few large, well-tested projects. When a robot "supports ROS 2", it usually means it works with these.

Nav2 is the standard navigation system. Given a map and a goal, it plans a route, follows it, avoids obstacles that appear on the way and recovers when stuck. A localization node (AMCL) tracks the robot on a known map, and costmaps mark where the robot may drive. Planner plugins find a path and controller plugins follow it. A behavior tree runs the whole task and decides what to do when things go wrong, such as backing up or spinning in place to clear a blocked path. Every part is a plugin, so wheeled, legged and car-like robots swap in the pieces that suit them.

Nav2 runs on robots throughout this guide, from the $300 MentorPi A1 to the Jackal, Husky and ROSbot.

Mapping and localization

The Robot Vision page compares the lidars, depth cameras and stereo cameras these packages use.

Arm motion (MoveIt 2)

MoveIt 2 plans arm movements. Given a target pose for the gripper, it solves the inverse kinematics and plans a path that avoids obstacles and the robot itself. It then sends a smooth trajectory to the arm. MoveIt Servo adds real-time steering from a joystick or a tracking program. Most arms in this guide with ROS 2 support include MoveIt setups, such as the myCobot 280, PiPER, xArm 6, UR5e and Kinova Gen3.

Motor control (ros2_control)

ros2_control is the layer between high-level commands and the motors. A hardware interface plugin talks to the real motors over serial, CAN bus or EtherCAT and exposes each joint's command and state values. Controllers then run in a fixed-rate loop on top. The diff_drive_controller turns /cmd_vel into wheel speeds, and the joint_trajectory_controller follows MoveIt's arm paths. A controller manager loads, starts and switches controllers while the robot runs.

Because simulators and fake hardware provide the same interface, the same controllers work in Gazebo and on the real robot. Writing a hardware interface is usually the main task when bringing up a custom robot in ROS 2.

Cameras and perception

AI and language models

ROS 2 has no built-in AI, but it is the usual way to connect one to a robot. A node runs a vision model or LLM and turns its output into goals, actions or /cmd_vel messages. Hiwonder's JetAuto and JetAcker courses include LLM voice-control chapters. The Mini Pupper 2 connects to ChatGPT, Gemini and Claude on top of its ROS 2 stack. The Mars home robot runs Python skills and LLM agents on a ROS 2 base. Robot-learning projects such as LeRobot often skip ROS 2 entirely, though the ALOHA 2 code uses it.

A first node

A ROS 2 node in Python is a class that extends Node. This one publishes a short drive command ten times a second, which would make a rover drive slowly in a circle.

import rclpy
from rclpy.node import Node
from geometry_msgs.msg import Twist

class Circler(Node):
    def __init__(self):
        super().__init__('circler')
        self.pub = self.create_publisher(Twist, 'cmd_vel', 10)
        self.declare_parameter('speed', 0.1)
        self.create_timer(0.1, self.tick)

    def tick(self):
        msg = Twist()
        msg.linear.x = self.get_parameter('speed').value
        msg.angular.z = 0.5
        self.pub.publish(msg)

def main():
    rclpy.init()
    rclpy.spin(Circler())

if __name__ == '__main__':
    main()

The 10 in create_publisher is the queue depth, the simplest form of a QoS setting. rclpy.spin hands control to an executor, which calls tick on schedule. The same steps from the command line look like this.

mkdir -p ~/ws/src && cd ~/ws/src
ros2 pkg create --build-type ament_python --node-name circler circler --dependencies rclpy geometry_msgs
# replace the generated circler/circler.py with the code above
cd ~/ws && colcon build
source install/setup.bash
ros2 run circler circler --ros-args -p speed:=0.2
ros2 topic echo /cmd_vel     # in a second terminal

C++ nodes follow the same pattern with rclcpp, and need a CMakeLists.txt using ament_cmake. C++ is the norm for drivers, controllers and anything time-critical, while Python suits high-level logic and quick tools.

Real robots start many nodes at once, so they use launch files rather than ros2 run. A launch file in Python lists the nodes to start, with their parameters and remappings, and ros2 launch starts and stops them together. This one starts the node above at a different speed.

from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription([
        Node(package='circler', executable='circler',
             parameters=[{'speed': 0.2}]),
    ])

Launch files can include other launch files, so a robot's main launch file often pulls in the base driver, the sensors and Nav2 from their own packages. Launch files can also be written in XML or YAML.

Software layers

The rest of this guide covers the lower layers. They matter for tuning performance, fixing network problems and building products. ROS 2 is a stack of libraries, each hiding the one below.

LayerWhat it does
User codeNodes written by the robot's developers
Client librariesrclcpp (C++) and rclpy (Python), plus community ones for Rust, C#, Java and Node.js
rclShared C library with the logic common to every language, such as names, parameters, time and logging
rmwThe ROS middleware interface, a thin C layer every middleware plugin implements
MiddlewareFast DDS, Cyclone DDS, Connext DDS or Zenoh, which actually move the bytes
TransportUDP, TCP or shared memory

Because every language sits on the same rcl core, a Python node and a C++ node behave the same way. Because every middleware sits behind rmw, switching middleware is a single environment variable with no code changes.

DDS and Zenoh middleware

DDS (Data Distribution Service) is a standard for publish-subscribe networking used in military, aerospace and industrial systems. ROS 2 adopted it to avoid writing networking from scratch. Each DDS vendor ships its own implementation, and ROS 2 picks one through the RMW_IMPLEMENTATION environment variable.

MiddlewareRMW_IMPLEMENTATION valueNotes
eProsima Fast DDSrmw_fastrtps_cppThe default in most releases, including Lyrical. Has shared-memory transport and a discovery server.
Eclipse Cyclone DDSrmw_cyclonedds_cppPopular for its simple behavior on busy networks. It was the default in Galactic and is common on Nav2 robots.
RTI Connext DDSrmw_connextddsCommercial, with certified versions for safety-critical products. Free for research.
Eclipse Zenohrmw_zenoh_cppNot DDS. Uses a small router instead of multicast discovery. Tier 1 since Kilted.

DDS discovery sends multicast packets so every participant can find every other. On Wi-Fi this works badly. Many routers drop or slow multicast, and with dozens of nodes the discovery traffic alone can swamp a link. The classic symptom is a laptop that sees a robot's topics in ros2 topic list but receives no data, or receives it in bursts.

All nodes in a system should use the same middleware. Different DDS vendors can talk to each other in principle, but mixed setups are a frequent source of subtle bugs. Zenoh cannot talk to DDS at all without a bridge.

Quality of service (QoS)

Every publisher and subscriber carries a QoS profile that controls how messages are delivered. ROS 1 had nothing like it. QoS lets a camera stream drop stale frames while a map is delivered reliably to late joiners, over the same network.

PolicyOptionsMeaning
ReliabilityReliable, best effortReliable resends lost messages. Best effort drops them, which is better for fast sensor data where only the newest reading matters.
History and depthKeep last N, keep allHow many unsent or unread messages to queue
DurabilityVolatile, transient localTransient local keeps the last messages for nodes that join later. Maps and the robot description use it.
DeadlineA time periodRaises an event if messages arrive further apart than this
LifespanA time periodMessages older than this are discarded unread
LivelinessAutomatic, manual, with a lease timeHow a subscriber detects that a publisher has died

ROS 2 ships preset profiles. The default is reliable, volatile, keep last 10. The SensorDataQoS preset is best effort with a small queue, and most lidar and camera drivers use it.

The most common QoS trap is an incompatible pair. A reliable subscriber will not connect to a best-effort publisher, and a transient-local subscriber will not connect to a volatile publisher. No messages flow, and the only sign is a warning in the logs. ros2 topic info -v /scan shows each side's QoS, which usually reveals the mismatch at once.

Executors and callback groups

A node does its work in callbacks, small functions that run when a message arrives, a timer fires or a service is called. An executor owns the threads that run those callbacks. Calling spin hands the node to one.

Callback groups control which callbacks may run in parallel under a multi-threaded executor. Callbacks in a mutually exclusive group never overlap, which protects shared data. Callbacks in a reentrant group can run at the same time, even with themselves.

A classic deadlock comes from calling a service and waiting for the reply inside a callback, while the reply needs the same blocked thread to be processed. The fixes are an asynchronous call, a separate callback group for the client, or in Python the new AsyncNode class in Lyrical, which works with Python's asyncio.

Lifecycle nodes

A normal node begins working the moment it is launched. A lifecycle node (or managed node) moves through set states instead, so a system can bring itself up in a controlled order and restart parts cleanly.

Transitions such as configure, activate, deactivate and cleanup each run a callback where the node can succeed or fail. Nav2 is built entirely from lifecycle nodes, and its lifecycle manager starts the map server, localization, planner and controller in order and stops them all if one fails. Hardware drivers benefit the most, since a motor driver can stay inactive until every safety check has passed.

Components and zero-copy

By default each node runs as its own process, and messages between nodes are serialized and passed through the middleware even on the same computer. With large data such as images and point clouds, that copying takes noticeable time.

Components are nodes built as shared libraries, which can be loaded into one process called a component container, at launch or while running. Nodes in the same process can use intra-process communication. A publisher hands over a pointer to the message and no copy is made. Camera pipelines gain the most, where one node resizes each frame, another detects objects and a third tracks them.

Across processes, shared-memory transports in Fast DDS and Cyclone DDS (through Eclipse iceoryx) avoid network copies. Some support loaned messages, where the middleware allocates the message directly in shared memory. Lyrical's new rosidl::Buffer extends the zero-copy idea to GPU memory, so images can pass between GPU-accelerated nodes without a trip through the CPU. It works only with Fast DDS so far.

Real-time control

A balancing robot or a walking leg needs its control loop to run on time every time, often at 500 to 1,000 times a second. A late cycle can mean a fall. ROS 2 was designed so real-time use is possible, but it is not real-time out of the box.

The tightest control loops usually run below ROS 2 entirely. Legged robots such as the Go2 EDU, G1 and Booster T1 run their balance and gait loops on dedicated controllers or in the maker's SDK. ROS 2 sits on top for higher-level commands, mapping and planning.

Microcontrollers and micro-ROS

micro-ROS brings ROS 2 to microcontrollers with only kilobytes of memory. Code on the board uses rclc, a C client library, to create nodes, publishers and subscribers much like full ROS 2. The board talks to a micro-ROS agent running on a Linux computer over serial, USB, Wi-Fi or Ethernet, using a lightweight protocol (DDS-XRCE). The agent relays its topics into the main ROS 2 system.

A common design pairs a Raspberry Pi or Jetson running Nav2 with a microcontroller reading wheel encoders and driving motors, both on the same ROS 2 graph. Supported boards include the ESP32, Raspberry Pi Pico, STM32 and Teensy families, and the Arduino Portenta H7 and Nano RP2040 Connect (see the Arduino Guide). The Yahboom ESP32 camera car has micro-ROS lessons, and community projects run the Maqueen through micro-ROS. Drones use the same link. PX4 flight controllers expose their sensors and commands as ROS 2 topics over XRCE-DDS, which is how most ROS 2 drone research talks to the autopilot.

Security

By default, any computer on the network can read every topic and publish commands to the robot, including /cmd_vel. That is fine in a lab and risky on a shared or public network.

SROS2 uses the DDS Security standard to add three protections. Authentication proves each node's identity with certificates. Access control limits which topics each node may publish or subscribe to. Encryption hides the data on the network. The ros2 security commands create a keystore and per-node keys. Setting ROS_SECURITY_ENABLE=true turns security on, and ROS_SECURITY_STRATEGY=Enforce makes nodes without valid keys fail instead of falling back to plain traffic. Zenoh has its own TLS encryption and access-control settings. Products should also limit network exposure in the usual ways, such as a firewall and not exposing rosbridge to the internet.

Build system and packages

Robots that run ROS 2

Many robots in this guide list ROS 2 support, but the depth varies a lot. Some run ROS 2 as their main software with full source code. Others offer a driver that publishes a few topics, and some only have community ports. Each robot's page states what its maker provides.

Learning kits

Education rovers with a lidar and a camera are the cheapest way into full ROS 2 with real navigation. Most come with long courses and pre-installed images. The TurtleBot 4 and TurtleBot 3 are the reference robots used in official tutorials. The TurtleBot 4 is built on the Create 3 base, which runs ROS 2 in its own firmware.

Legged robots and humanoids

Legged robots with ROS 2 range from the open-source Mini Pupper 2 and Pupper V3 to the EDU versions of Unitree's robots. The CyberDog 2 has an open ROS 2 stack, and the ROSpider and JetHexa2027 are ROS 2 hexapods. Among humanoids, Booster's K1 and T1, Unitree's G1 and H1 and ROBOTIS's OP3 provide ROS 2 interfaces.

Research platforms and mobile manipulators

Clearpath's Jackal, Husky and Dingo ship with ROS 2 Jazzy. Mobile manipulators such as Stretch, TIAGo, Reachy 2 and the Galaxea R1 combine Nav2 and MoveIt-style arm control on one robot.

DIY builds

Several of the DIY robot blueprints use ROS 2. They include the RoboRacer (F1TENTH) and MuSHR race cars, the Mini Pupper and Pupper V3 quadrupeds, and the PAROL6, Thor and OpenArm robot arms. Arms built with Dynamixel smart servos have ready-made ROS 2 drivers (see the Servo Guide).

Learning path

  1. Linux and Python first. Comfort with the terminal, files, environment variables and basic Python saves weeks of confusion.
  2. Install Jazzy on Ubuntu 24.04, natively, in a virtual machine or in Docker. Work through the official beginner tutorials with the turtlesim simulator.
  3. Learn the command-line tools on a running system. Exploring with ros2 topic, ros2 node and rqt_graph teaches more than reading about them.
  4. Simulate a mobile robot in Gazebo, such as the TurtleBot 3 or 4, then map a world with SLAM Toolbox and navigate it with Nav2.
  5. Move to real hardware, either a kit with a ready-made ROS 2 image or a custom robot with ros2_control and micro-ROS.

The Online Robotics Courses page compares ROS 2 courses, from the free official tutorials to video courses and university classes.

Common problems