ROS 2 and the robotics stack
Nodes, topics, services, actions, TF and how robotics teams are organized.
Day 10 · 45 min
After this lesson
- You can explain ROS 2 nodes, topics, services, actions and QoS.
- You can sketch a node graph for the course robot.
- You can present the robot as a portfolio project.
How professional robots are wired together in software
What ROS 2 is
ROS 2 (Robot Operating System 2) is not an operating system. It is middleware plus a toolbox: you split a robot's software into nodes, each with one job, and they talk over a publish-subscribe bus built on DDS. A long-term-support release ships every two years in May; Humble Hawksbill (2022) is supported to 2027 and Jazzy Jalisco (2024, on Ubuntu 24.04) to 2029. Nodes are written in C++ with rclcpp or Python with rclpy and driven from the ros2 command line.
Topics, services, actions, parameters and launch files
- Topics: named, typed, many-to-many streams for continuous data.
/cmd_velcarries geometry_msgs/msg/Twist (linear.x in m/s, angular.z in rad/s);/scancarries sensor_msgs/msg/LaserScan. - Services: request and response, like a function call across the network, for short operations such as enabling the motors.
- Actions: long-running goals with feedback and cancellation, built from topics and services. Nav2's NavigateToPose streams the distance remaining and can be cancelled when a person steps in front.
- Parameters: typed per-node settings such as
wheel_base: 0.12, loaded from YAML at launch or changed live withros2 param set. - Launch files: Python, XML or YAML files that start a set of nodes with their parameters, remappings and namespaces, so one command brings up the whole robot.
DDS and quality of service
Underneath, the RMW layer maps ROS 2 onto a DDS implementation: eProsima Fast DDS by default, or Eclipse Cyclone DDS; Zenoh is a newer non-DDS option. Discovery is automatic over UDP multicast, and ROS_DOMAIN_ID keeps two robots on one network apart. Every endpoint carries a QoS profile: reliability (RELIABLE retransmits lost samples, BEST_EFFORT does not), durability (VOLATILE, or TRANSIENT_LOCAL, which replays the last messages to late joiners and is used for maps), history depth (KEEP_LAST 10), plus deadline and liveliness. Publishers offer, subscribers request, and a connection forms only when the offer satisfies the request. Camera and lidar drivers usually publish with the sensor-data profile, BEST_EFFORT with depth 5, so a subscriber left on the RELIABLE default receives nothing, with one warning as the only clue.
TF, URDF, RViz and bags
TF2 keeps a time-stamped tree of coordinate frames. By REP 105 the chain is map → odom → base_link: odometry publishes odom → base_link (smooth, drifts), localization publishes map → odom (corrects drift, may jump), and robot_state_publisher reads the URDF to publish base_link → sensor frames. Any node can then ask where the sonar was in the map frame at 12.304 s and get an interpolated answer. RViz2 draws it all live: robot model, frames, scans, maps, planned paths. ros2 bag record captures topics to MCAP files so a field failure can be replayed at your desk.
The big packages
- Nav2: AMCL localization, costmaps that inflate obstacles, global planners (NavFn, Smac), local controllers (DWB, Regulated Pure Pursuit, MPPI) and recovery behaviors, orchestrated by behavior trees.
- MoveIt 2: motion planning for arms: inverse kinematics, collision checking, OMPL planners and trajectory execution.
- ros2_control: a hardware abstraction with standard controllers such as diff_drive_controller.
- micro-ROS: ROS 2 on microcontrollers such as the ESP32 over XRCE-DDS, with an agent on a computer that bridges serial or Wi-Fi into the graph. That is how the course robot would publish
/odomand obey/cmd_vel.
How robotics teams are organized
Robotics companies usually split work into perception, localization and mapping, planning and controls, manipulation, embedded firmware, electrical, mechanical, simulation and test, and infrastructure for fleets, logs and CI. Startups hire generalists who cover several of these; larger companies such as Boston Dynamics, Amazon Robotics or Agility Robotics hire specialists. Firmware and controls meet at the motor driver, perception and planning meet at the costmap, and everyone meets in the logs.
Presenting the robot as a portfolio project
A reviewer gives a project about two minutes, so lead with a 60 to 90 second video of the robot finishing a lap with telemetry overlaid. Then a README with a block diagram, the bill of materials and cost, the schematic or KiCad board, the firmware and simulator code, and measured results: "a UMBmark square test cut return error from 41 cm to 6 cm", "bulk capacitance cut the 5 V dip from 1.1 V to 0.08 V". Add a section on what went wrong; it is the part interviewers ask about.
Roles and interview expectations
Embedded robotics interviews probe interrupts, PWM and H-bridges, encoders, PID tuning, power integrity and bring-up. Robotics software interviews probe C++ and Python, ROS 2 (QoS, TF, executors and callback groups), coordinate frames, state estimation such as Kalman filters, and planning such as A* and sampling-based planners. Expect a live or take-home exercise: A* on a grid, a PID class with anti-windup, or transforming points between frames.
Interactive: a node graph you can break
A ROS 2 node graph
Messages flow from the camera to the motors. Click a node or a topic for its message types, then change the detector's QoS and watch the graph break the way real ones do.
Click or tab to a node (rounded) or a topic (square) to see what it publishes, subscribes to and its message types.
images published 1 · delivered 0 · dropped 0 · retransmitted 0
Connected: the QoS profiles are compatible and images flow.
In practice
Practice
Sketch the node graph for your robot, then install ROS 2
Assume the ESP32 runs micro-ROS over Wi-Fi and a laptop runs everything else. List the nodes, the topics with their message types and rates, and the QoS you would choose for each. Then install ROS 2 and reproduce this lesson's QoS bug on purpose.
Worked answer: the node graph
| Node | Runs on | Publishes | Subscribes |
|---|---|---|---|
| /robot_base (micro-ROS) | ESP32 | /odom (nav_msgs/msg/Odometry, 20 Hz, best effort), /range (sensor_msgs/msg/Range, 16 Hz, sensor data), /battery (sensor_msgs/msg/BatteryState, 1 Hz, reliable) | /cmd_vel (geometry_msgs/msg/Twist, reliable), with a 300 ms watchdog |
| /micro_ros_agent | laptop | Bridges XRCE-DDS over Wi-Fi UDP into DDS | none |
| /robot_state_publisher | laptop | /tf_static and /robot_description (transient local) | /joint_states |
| /odom_to_tf | laptop | /tf (odom → base_link) | /odom |
| /behavior (your state machine) | laptop | /cmd_vel (10 Hz) | /range, /odom |
| /teleop_twist_keyboard and rviz2 | laptop | /cmd_vel when you drive by hand | /tf, /odom, /range |
The design choices to defend in an interview: the speed loops and encoder interrupts stay on the ESP32, only setpoints and state cross Wi-Fi; sensor streams are best effort because a late reading is worthless; commands are reliable and guarded by a watchdog so a dropped link stops the robot.
Install and the QoS experiment
# Ubuntu 24.04 with ROS 2 Jazzy (add the ROS 2 apt repository first, as in docs.ros.org)
sudo apt install ros-jazzy-desktop
source /opt/ros/jazzy/setup.bash
# macOS or Windows: run it in a container instead
docker run -it --rm osrf/ros:jazzy-desktop
# smoke test, in two terminals
ros2 run demo_nodes_cpp talker
ros2 run demo_nodes_py listener
# look at the graph and the QoS of every endpoint
ros2 node list
ros2 topic list
ros2 topic info -v /chatter
# reproduce this lesson's scenario: a QoS mismatch
ros2 topic pub /test std_msgs/msg/String "{data: hello}" --qos-reliability best_effort
ros2 topic echo /test --qos-reliability reliable # silence, plus an incompatible-QoS warning
ros2 topic echo /test --qos-reliability best_effort # messages arriveReal-world scenario
Real-world scenario
The publisher works, the subscriber never hears it
A new team member writes a C++ node that subscribes to /camera/image_raw to count people in the hallway. The camera driver is clearly running: ros2 topic hz reports 30 Hz and RViz shows the live image. The new node builds, starts, logs that it has subscribed, and then its callback never fires, not once, for an entire afternoon of debugging.
Symptoms
- ros2 topic list shows /camera/image_raw and ros2 topic hz reports 30 Hz
- RViz and ros2 topic echo display the images normally
- The new node's callback counter stays at zero, with no errors and no crashes
- A single warning at startup says a new publisher on /camera/image_raw is offering incompatible QoS and that no messages will be received from it
Interview questions
screenExplain topics, services and actions, with an example of when you would use each.
screenWhat does TF do, and what are the map, odom and base_link frames?
screenHow would you present a hobby robot in an interview so that it counts as real experience?
deepA subscriber receives nothing even though the topic is publishing. How do you debug it?
deepHow would you connect a microcontroller-based robot like the course robot to a ROS 2 system?
Quiz
References and further reading
Where the ideas in this lesson come from, and what to read next. Books are the standard texts; papers are the original sources; standards are what employers work to.
- Paperfree online
Read: The original ROS design.
- Paper
Steven Macenski, Tully Foote, Brian Gerkey, Chris Lalancette and William Woodall (2022). Robot Operating System 2: Design, Architecture, and Uses in the Wild. Science Robotics 7(66).doi:10.1126/scirobotics.abm6074
Read: Why ROS 2 changed the architecture and who runs it in production.