simulationros2tutorialamrgazeborosbag2debugsimulation

ROS 2 A to Z (P7): Simulation, rosbag2 and Debug

Simulate robots in Gazebo Harmonic, record/replay data with rosbag2 (MCAP), and master the ROS 2 debugging toolkit — the series finale for beginners (Jazzy, June 2026).

Nguyen Anh TuanApril 3, 20266 min readUpdated: Jun 14, 2026
ROS 2 A to Z (P7): Simulation, rosbag2 and Debug

You've made the full journey: setup (P1), communication (P2), configuration (P3), describing the robot (P4), driving hardware (P5), and autonomy (P6). This final part covers three skills that make you productive every day: Simulation (test without a real robot), rosbag2 (record/replay data), and Debug (find bugs fast).

Version (June 2026): ROS 2 Jazzy (Ubuntu 24.04). Important: Gazebo Classic is EOL — use the new Gazebo (Harmonic) with the gz sim command. On Jazzy, rosbag2 defaults to the MCAP format.

Simulating and debugging a robot in ROS 2
Simulating and debugging a robot in ROS 2

1. Simulation — test a robot without hardware

Real robots are expensive and easy to damage while your code still has bugs. Simulation gives you a virtual robot with real physics (gravity, friction, collisions) to test algorithms safely. ROS 2's default simulator is Gazebo (the new version is Harmonic, command gz sim).

Install Gazebo Harmonic + bridge

# New Gazebo + the ROS 2 ↔ Gazebo bridge
sudo apt install -y ros-jazzy-ros-gz

# Verify
gz sim --version

Important note: gazebo_ros_pkgs (Gazebo Classic) is gone on Jazzy. Every old tutorial using gazebo or roslaunch gazebo_ros is outdated. The new version is Gazebo Sim (formerly Ignition), installed via ros_gz.

ros_gz bridge — connect ROS 2 with Gazebo

Gazebo and ROS 2 are separate systems. ros_gz_bridge translates messages between them — e.g. feeding /cmd_vel (ROS) into Gazebo, and exposing /scan (a virtual LiDAR in Gazebo) to ROS:

# Bridge the cmd_vel topic: ROS Twist ↔ Gazebo Twist
ros2 run ros_gz_bridge parameter_bridge \
  /cmd_vel@geometry_msgs/msg/[email protected]

In a launch file (the practical way), spawn a robot from URDF into Gazebo:

# launch/sim.launch.py (simplified)
from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription([
        # Open Gazebo with an empty world
        # (gz sim -r empty.sdf — run in the background via ros_gz_sim launch)

        # Spawn the robot from /robot_description into Gazebo
        Node(
            package='ros_gz_sim', executable='create',
            arguments=['-topic', 'robot_description', '-name', 'my_robot'],
        ),
        # Bridge the required topics
        Node(
            package='ros_gz_bridge', executable='parameter_bridge',
            arguments=[
                '/cmd_vel@geometry_msgs/msg/[email protected]',
                '/scan@sensor_msgs/msg/[email protected]',
            ],
        ),
    ])

The quickest way to see Nav2 run in sim without building a world yourself: use the pre-packaged demo from Part 6 (nav2-minimal-tb3-sim).

Other sim options (June 2026): Besides Gazebo there's Webots (free, beginner-friendly), NVIDIA Isaac Sim (beautiful graphics, heavily used for AI/RL, needs a strong GPU), and MuJoCo (accurate physics for RL). Beginners should start with Gazebo or Webots for their built-in ROS 2 integration.

2. rosbag2 — the robot's "black box"

rosbag2 records every message on selected topics, then replays them identically later. It's an invaluable tool: run a real robot once, record the data, then replay at home to debug your algorithm hundreds of times without a robot.

# Record ALL topics
ros2 bag record -a -o my_session

# Record only the topics you need
ros2 bag record /scan /odom /cmd_vel -o nav_test

# Inspect the bag
ros2 bag info my_session

# Replay — other nodes receive data as if the robot were live
ros2 bag play my_session

# Replay at 0.5x to observe carefully
ros2 bag play my_session --rate 0.5

New (Jazzy, June 2026): rosbag2 defaults to the MCAP format (replacing the old SQLite) — faster, smaller, readable by many external tools (Foxglove, PlotJuggler). A .mcap file opens directly in Foxglove for visual inspection.

Real-world uses of rosbag2:

  • Debug rare bugs: the robot occasionally hits a wall — record continuously, and when it happens you have the data to dissect.
  • Regression testing: replay the same bag through old and new algorithms to compare.
  • Collect AI training data: record sensors + actions as a dataset for imitation learning.

Read a bag in code (Python) for analysis:

# Read a bag with rosbag2_py
import rosbag2_py
from rclpy.serialization import deserialize_message
from sensor_msgs.msg import LaserScan

reader = rosbag2_py.SequentialReader()
reader.open(
    rosbag2_py.StorageOptions(uri='nav_test', storage_id='mcap'),
    rosbag2_py.ConverterOptions('', ''))

while reader.has_next():
    topic, data, t = reader.read_next()
    if topic == '/scan':
        msg = deserialize_message(data, LaserScan)
        print(f'{t}: {len(msg.ranges)} LiDAR rays')

3. Debug — the ROS 2 bug-hunting toolkit

When the robot "just won't run," here's the inspection flow from simple to deep.

CLI — quick checks

# Check the health of the whole ROS 2 system
ros2 doctor

# List running nodes / topics
ros2 node list
ros2 topic list

# Is anyone publishing this topic? At what rate?
ros2 topic hz /scan          # frequency (Hz)
ros2 topic bw /scan          # bandwidth
ros2 topic echo /cmd_vel     # print message contents

# What is this node connected to?
ros2 node info /controller_manager

rqt — graphical tools

# See the node ↔ topic graph (who talks to whom)
rqt_graph

# View colored logs, filter by node/level
ros2 run rqt_console rqt_console

# Plot data over time (e.g. velocity)
ros2 run rqt_plot rqt_plot

rqt_graph is the number-one debug tool for beginners: if a topic isn't connected between two nodes, you see it immediately — usually a wrong topic name or a forgotten remap (covered in Part 3).

Logging in code

Set the log level to print more/less information:

# Python — log levels
self.get_logger().debug('Details only shown when DEBUG is on')
self.get_logger().info('Normal info')
self.get_logger().warn('Warning')
self.get_logger().error('Error')
# Run a node with the DEBUG log level
ros2 run my_pkg my_node --ros-args --log-level debug

A 5-step debug flow for beginners

  1. ros2 node list — is my node running? Not there → build/launch error.
  2. ros2 topic list — does the topic exist? No → wrong topic name.
  3. ros2 topic hz /topic — is anyone publishing? 0 Hz → dead publisher.
  4. ros2 topic echo /topic — are the message contents correct? Wrong → logic bug.
  5. rqt_graph — are connections correct? Broken → forgotten remap.

The most common "silent" bug: two nodes publish/subscribe to different topic names (e.g. /scan vs /laser/scan) → no error, just no data. rqt_graph exposes it instantly.

ROS 2 A to Z series wrap-up

Across 7 parts, you went from zero to a battle-ready ROS 2 skill set:

Part What you learned
P1 Install Jazzy, first publisher/subscriber node
P2 Topics, Services, Actions
P3 Parameters, Launch, Lifecycle
P4 TF2, URDF, RViz2
P5 ros2_control, C++ hardware interface
P6 Nav2 — autonomous navigation
P7 Simulation, rosbag2, Debug

Your next step? Pick a small project — say a diff-drive AMR in Gazebo running Nav2 — and put it all together. When you get stuck, return to the matching part. Learning ROS 2 isn't about reading it all, it's about building something that runs. Happy building!


NT

Nguyễn Anh Tuấn

Robotics & AI Engineer. Building VnRobo — sharing knowledge about robot learning, VLA models, and automation.

Khám phá VnRobo

Related Posts

Digital Twins và ROS 2: Simulation trong sản xuất
simulation

Digital Twins và ROS 2: Simulation trong sản xuất

4/3/202611 min read
NT
Sim-to-Real Pipeline: Từ training đến robot thật
simulation

Sim-to-Real Pipeline: Từ training đến robot thật

4/2/202615 min read
NT
Bắt đầu với MuJoCo: Cài đặt đến mô phỏng robot đầu tiên
simulation

Bắt đầu với MuJoCo: Cài đặt đến mô phỏng robot đầu tiên

3/30/202611 min read
NT