ROS 2 Jazzy Tutorial for Beginners: Setup, Nodes & First Robot (2026)
In just 60 seconds, you’ll get a beginner‑friendly ROS 2 Jazzy tutorial — covering setup, nodes, and building your first robot, enhanced with Bird’s‑Eye‑View sensor fusion and spatiotemporal transformers.
TL;DR — Quick Insights
- ROS 2 Jazzy is the LTS: Released May 2024, Jazzy Jalisco is the long-term support distribution of ROS 2 — the version you should learn in 2026 for any serious robotics project.
- Ubuntu 24.04 is required: Jazzy runs natively on Ubuntu 24.04 LTS (Noble Numbat). If you are on Windows, WSL2 or Docker both work well.
- Nodes are the building blocks: Every ROS 2 application is a graph of nodes — small, focused processes that communicate by publishing and subscribing to named topics.
- Python first, then C++: Start with Python (rclpy) for speed of learning. Migrate to C++ (rclcpp) once you need real-time performance in production systems.
- Simulation before hardware: Use Gazebo Harmonic or Webots to simulate your robot before touching physical hardware — cheaper, faster, and endlessly repeatable.
- Introduction: Why ROS 2 and Why Jazzy?
- Prerequisites: What You Need Before You Start
- Step 1: Installing ROS 2 Jazzy on Ubuntu 24.04
- Step 2: Core Concepts — The ROS 2 Architecture
- Step 3: Creating Your First ROS 2 Workspace and Package
- Step 4: Writing a Publisher Node
- Step 5: Writing a Subscriber Node
- Step 6: Building and Running Your Nodes
- Step 7: Visualising the ROS 2 Graph
- Step 8: Running Gazebo Harmonic Simulation
- From UDHY’s Robotics Platform: Applying ROS 2 in Production
- Lessons Learned
- UDHY Learning Path: From Beginner to Job‑Ready Robotics Engineer
- FAQs on ROS 2 Jazzy
- References & Authoritative Sources
Introduction: Why ROS 2 and Why Jazzy?
If you want to build autonomous robots in 2026 — whether that is a warehouse delivery drone, a surgical assistance arm, or a self-driving campus shuttle — there is one framework you need to know: ROS 2. The Robot Operating System 2 is not an operating system in the traditional sense. It is an open-source middleware and toolchain that provides everything a robotics developer needs: communication infrastructure, hardware abstraction, simulation tools, visualisation, and a rich ecosystem of ready-made packages for navigation, perception, and control.

ROS 2 was rebuilt from scratch compared to ROS 1, addressing every major limitation of its predecessor: real-time support, multi-robot networking, improved security through DDS (Data Distribution Service), and production-grade reliability. ROS 1 is now in maintenance-only mode. If you are starting today, you start with ROS 2.
Within ROS 2, the current long-term support (LTS) distribution is Jazzy Jalisco, released in May 2024 and supported until May 2029. Jazzy introduces native support for Ubuntu 24.04 LTS, improved DDS performance through Zenoh transport layer experiments, enhanced Nav2 navigation stack with better path smoothing, and tighter integration with Gazebo Harmonic. Learning Jazzy means your knowledge is stable, supported, and directly applicable to production robotics for the next five years.
Prerequisites: What You Need Before You Start
Before installing ROS 2 Jazzy, ensure you have the following:
- Ubuntu 24.04 LTS (Noble Numbat) — either natively installed, in WSL2, or in a virtual machine.
- Basic Python knowledge — you should understand variables, functions, classes, and loops.
- Basic Linux terminal comfort — navigating directories (cd, ls), running commands, and editing files.
- 8 GB RAM minimum, 16 GB recommended for running Gazebo simulation alongside ROS 2 nodes.
⚠️ Windows Users: ROS 2 Jazzy does not natively support Windows. Use WSL2 (Windows Subsystem for Linux) with Ubuntu 24.04, or run Ubuntu in VirtualBox/VMware. The experience is nearly identical to native Ubuntu.
Step 1: Installing ROS 2 Jazzy on Ubuntu 24.04
Open a terminal and follow these steps exactly. Each command is explained so you understand what it does — not just what to type.
1.1 Set Up Locale
ROS 2 requires UTF-8 locale support. Run:
locale # check for UTF-8
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
1.2 Add the ROS 2 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
1.3 Install ROS 2 Jazzy Desktop
sudo apt update
sudo apt upgrade
sudo apt install ros-jazzy-desktop
The desktop install includes RViz2 (visualisation), rqt tools, and Gazebo bindings. It takes 5–10 minutes on a fast connection.
1.4 Source the Setup File (Every Terminal Session)
# Add to ~/.bashrc so it runs automatically
echo "source /opt/ros/jazzy/setup.bash" >> ~/.bashrc
source ~/.bashrc
# Verify installation
ros2 --help
✅ Quick Verification Test: Run
ros2 run demo_nodes_py talkerin one terminal andros2 run demo_nodes_py listenerin another. If you see “Hello World” messages flowing between them, your ROS 2 Jazzy installation is working perfectly.
Step 2: Core Concepts — The ROS 2 Architecture
Before writing any code, you need to understand four core concepts that underpin every ROS 2 application. These are the same concepts Dr. Limbu’s team used in Moovita’s autonomous bus fleet — at any scale.
2.1 Nodes
A node is a single executable process with a specific purpose. In a robot, you might have separate nodes for: reading the LiDAR sensor, processing the camera image, running the path planner, and commanding the wheel motors. Each node is independent and communicates with others through the ROS 2 graph.
2.2 Topics
Topics are named communication channels. A node publishes messages to a topic, and any number of other nodes can subscribe to that topic and receive those messages. Topics are asynchronous — the publisher does not wait for subscribers to receive the data.
2.3 Messages
Messages define the data structure sent over a topic. ROS 2 ships with hundreds of standard message types: sensor_msgs/LaserScan for LiDAR data, geometry_msgs/Twist for velocity commands, nav_msgs/OccupancyGrid for maps. You can also define custom message types.
2.4 Services
Services provide request-response communication — unlike topics which are fire-and-forget. You call a service, it processes your request, and returns a result. Use services for operations that need confirmation: asking the robot to navigate to a goal, saving a map, or resetting a sensor.
| Concept | Communication Type | Use Case | ROS 2 Tool |
|---|---|---|---|
| Topics | Publish / Subscribe (async) | Sensor streams, motor commands, camera frames | ros2 topic echo |
| Services | Request / Response (sync) | Navigation goals, map saving, sensor reset | ros2 service call |
| Actions | Goal / Feedback / Result | Long-running tasks: move arm, navigate room | ros2 action send_goal |
| Parameters | Key-value configuration | PID gains, speed limits, update rates | ros2 param set |
Step 3: Creating Your First ROS 2 Workspace and Package
3.1 Create the Workspace
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws
colcon build
source install/setup.bash
3.2 Create a Python Package
cd ~/ros2_ws/src
ros2 pkg create --build-type ament_python \
--license Apache-2.0 \
my_first_robot
cd my_first_robot
Your package structure will look like this: my_first_robot/my_first_robot/__init__.py, package.xml, setup.py, and setup.cfg. This is the standard ROS 2 Python package layout.
Step 4: Writing a Publisher Node
A publisher node sends data to a topic. In this example, we build a simple sensor simulator that publishes a temperature reading every second.
# udhy_first_robot/temperature_publisher.py
import rclpy
from rclpy.node import Node
from std_msgs.msg import Float32
import random
class TemperaturePublisher(Node):
def __init__(self):
super().__init__('temperature_publisher')
self.publisher_ = self.create_publisher(
Float32, # message type
'temperature', # topic name
10 # queue size
)
# Timer: publish every 1.0 second
self.timer = self.create_timer(1.0, self.publish_temperature)
self.get_logger().info('Temperature Publisher started.')
def publish_temperature(self):
msg = Float32()
# Simulate sensor reading: 20–35 degrees Celsius
msg.data = 20.0 + random.uniform(0, 15)
self.publisher_.publish(msg)
self.get_logger().info(f'Publishing temperature: {msg.data:.2f}°C')
def main(args=None):
rclpy.init(args=args)
node = TemperaturePublisher()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
Step 5: Writing a Subscriber Node
A subscriber node listens to a topic and reacts to incoming messages. Here we build a subscriber that receives temperature readings and triggers an alert if the temperature exceeds a threshold.
# udhy_first_robot/temperature_subscriber.py
import rclpy
from rclpy.node import Node
from std_msgs.msg import Float32
class TemperatureSubscriber(Node):
def __init__(self):
super().__init__('temperature_subscriber')
self.subscription = self.create_subscription(
Float32,
'temperature',
self.temperature_callback,
10
)
self.ALERT_THRESHOLD = 30.0
self.get_logger().info('Temperature Subscriber started.')
def temperature_callback(self, msg):
temp = msg.data
if temp > self.ALERT_THRESHOLD:
self.get_logger().warn(
f'HIGH TEMP ALERT: {temp:.2f}°C exceeds {self.ALERT_THRESHOLD}°C!'
)
else:
self.get_logger().info(f'Temperature received: {temp:.2f}°C — Normal.')
def main(args=None):
rclpy.init(args=args)
node = TemperatureSubscriber()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
Step 6: Building and Running Your Nodes
Register both nodes in setup.py, then build and run:
# In setup.py, inside entry_points, console_scripts add:
'temperature_publisher = my_first_robot.temperature_publisher:main',
'temperature_subscriber = my_first_robot.temperature_subscriber:main',
# Then build:
cd ~/ros2_ws
colcon build --packages-select my_first_robot
source install/setup.bash
# Terminal 1 — run publisher:
ros2 run my_first_robot temperature_publisher
# Terminal 2 — run subscriber:
ros2 run my_first_robot temperature_subscriber
# Terminal 3 — inspect live topic:
ros2 topic echo /temperature
ros2 topic hz /temperature # confirm 1 Hz publish rate
Step 7: Visualising the ROS 2 Graph
One of the most powerful features of ROS 2 is the ability to visualise the entire communication graph of your robot in real time. With your publisher and subscriber running, open a new terminal and run:
rqt_graph
This opens an interactive GUI showing every node in your system as a circle, every topic as a labelled arrow, and every publisher-subscriber relationship. This graph view is invaluable for debugging complex multi-robot systems — Dr. Limbu’s team used it daily during Moovita’s Singapore AV fleet integration, where over 40 nodes communicated simultaneously across a single ROS 2 graph.
Step 8: Running Gazebo Harmonic Simulation
Gazebo Harmonic is the simulation engine paired with ROS 2 Jazzy. You can simulate a complete TurtleBot3 — a standard differential-drive research robot — without any physical hardware:
# Install TurtleBot3 simulation packages
sudo apt install ros-jazzy-turtlebot3*
export TURTLEBOT3_MODEL=waffle
# Launch simulation world
ros2 launch turtlebot3_gazebo turtlebot3_world.launch.py
# In a new terminal — drive the robot manually:
ros2 run turtlebot3_teleop teleop_keyboard
Your TurtleBot3 will appear in a simulated environment with LiDAR data visible in RViz2. You can drive it with keyboard controls, observe how the LiDAR scan changes as it moves, and experiment with SLAM — building a map of the simulated world in real time. This is exactly the simulation pipeline Moovita used before deploying software onto its physical autonomous bus fleet. learn more about Robotics for Advanced Learners — SLAM, Nav2 and Path Planning and Robotics for Experts — Fleet Management and Multi-Agent Systems.
From UDHY’s Robotics Platform: Applying ROS 2 in Production
At UDHY, our robotic platform ran a ROS 2-based architecture connecting over 40 specialised nodes: a LiDAR processing node ingesting 300,000 points per second from a Velodyne HDL-32E, a multi-camera fusion node processing six synchronised video streams at 30 fps, a GPS/IMU sensor fusion node running Extended Kalman Filter localisation at 200 Hz, path planning nodes running hybrid A* on occupancy grids updated in real time, and safety arbitration nodes that could override any downstream command within 5 milliseconds.
Every single one of these nodes communicated through ROS 2 topics and services using the same publisher-subscriber pattern you have just learned in this tutorial. The architecture you practice here is not an educational simplification — it is the exact pattern used in commercial autonomous vehicle deployments globally.
Lessons Learned
- Source your setup file: The single most common beginner mistake is forgetting to run
source /opt/ros/jazzy/setup.bashin each new terminal. Add it to~/.bashrconce and never forget again. - One node, one job: Keep each node focused on a single responsibility. A node that does sensor reading, processing, and control simultaneously is hard to debug, test, and reuse.
- Simulate first, always: Before deploying any code change to a physical robot, test it thoroughly in Gazebo. Physical robots are expensive, breakable, and sometimes dangerous. Simulators are free, instant, and endlessly repeatable.
- Use rqt_graph to debug: When your nodes are not communicating as expected, open rqt_graph immediately. It will reveal topic name mismatches — the most common cause of silent communication failures — instantly.
- ROS 2 topics are not guaranteed delivery: Topics use UDP-based transport by default. For critical commands (emergency stop, safety overrides), use Services or configure your DDS QoS profile for reliable delivery.
UDHY Learning Path: From Beginner to Job‑Ready Robotics Engineer
Interested in becoming a robotics engineer and building humanoid robots? UDHY offers a structured learning path designed to help you transition from curious enthusiast to industry‑ready professional. Follow this progressive track to gain the skills, projects, and confidence needed to thrive in corporate robotics roles.
| 1. Foundation | Introduction to AI + ML Fundamentals | 3–5 hrs | Python + ML context |
| 2. Physical sandbox | Robotics for Beginners | 8–12 hrs | First physical project |
| 3. Core engineering | Robotics for Advanced | 25–35 hrs | ROS 2 + YOLO + kinematics |
| 4. Deep learning | Deep Learning for Robotics | 10–14 hrs | PyTorch + TensorRT deployment |
| 5. Navigation | Autonomous Navigation & SLAM | 12–16 hrs | Nav2 + SLAM + A* planning |
| 6. Frontier | Expert Robotics + Physical AI | 30–40 hrs | VLA models + production deployment |
FAQs on ROS 2 Jazzy
References & Authoritative Sources
- ROS 2 Official Documentation — Jazzy Jalisco.
- Open Robotics. ROS 2 Design Documentation.
- Macenski, S. et al. (2022). Robot Operating System 2: Design, Architecture, and Uses In The Wild. Science Robotics, 7(66).
- NVIDIA Isaac Platform Documentation.
- Automatic Addison. How to Create a ROS 2 Python Publisher — Jazzy.
- ROS Discourse Community Forum.
- Husarion ROS 2 Tutorials.
- Gazebo Harmonic Documentation.
- IEEE Xplore: Robotics and Automation Letters.
About the Author
Dr. Dilip Kumar Limbu Co-Founder, Moovita | Former Principal Scientist, A*STAR | PhD, Auckland University of Technology
Connect via LinkedIn Direct Inquiry.
Disclaimer
The views expressed here are personal and based on 30+ years in the industry, including my work at Moovita. They do not necessarily reflect the views of any organization.
Enjoying this post? Subscribe to get more AI insights.



