A rosbag is the black box recorder of a ROS 2 robot. When a navigation run fails at 2 a.m., the bag is the only way to see what the robot actually thought.
This guide covers recording the right topics, keeping bags small, replaying them with simulated time, and the file formats and gotchas that decide whether the bag is usable a week later.
Record the topics that matter, not everything
ros2 bag record -o nav_test_01 /scan /odom /tf /tf_static /cmd_velRecording everything with -a is convenient on a bench and expensive on a robot. Camera and point cloud topics can fill a disk in minutes. Add them only when the investigation needs them.
| Topic | Record | Why |
|---|---|---|
| /scan | Yes | Lidar input for SLAM and Nav2 |
| /odom | Yes | Wheel odometry and velocity |
| /tf, /tf_static | Yes | Without transforms the bag is unreadable |
| /cmd_vel | Yes | What the controller actually commanded |
| /map | Optional | Large, and usually reproducible |
| Camera images | Only when needed | Very large at full rate |
| Point clouds | Only when needed | Largest topics on most robots |
Storage format and compression
| Format | Notes |
|---|---|
| sqlite3 | Long-standing default, easy to query |
| mcap | Faster writes, better tooling, widely adopted in newer distributions |
| zstd compression | Shrinks bags substantially, small CPU cost |
ros2 bag record -o run_01 --compression-mode file \
--compression-format zstd /scan /odom /tf /tf_static /cmd_velCompress when the bag leaves the robot. Leave compression off during live debugging, when you may want to read the file immediately.
Inspect before you trust a bag
ros2 bag info run_01Check duration, message counts and topic list. A bag with zero /tf messages looks fine in the file listing and is useless for replay. Check it at the robot, not later.
Replay with simulated time
ros2 bag play run_01 --clock
# in another terminal
ros2 param set /use_sim_time trueEvery node that consumes the bag must use simulated time. If one node reads wall time while the rest read bag time, TF lookups fail with extrapolation errors and you will chase a bug that does not exist on the robot.
- Set
use_sim_timeon the launch file, not individually. - Start the replay, then start the consumers, or restart them after the clock is live.
- Use
--rate 0.5when a heavy pipeline cannot keep up. - Use
--start-offsetto skip the boring first minute. - Do not run a live lidar at the same time as the bag on the same topic.
QoS mismatches
If a topic is recorded but stays empty, or replay produces no data for one topic, it is usually QoS. A sensor publisher using best-effort will not deliver to a subscriber asking for reliable. Record with a QoS override file when you need to force compatibility.
ros2 bag record -o run_02 --qos-profile-overrides-path qos.yaml /scanA recording routine for field tests
- Check free disk space before starting.
- Use a bag name with date, robot ID and test purpose.
- Record the core topics plus anything specific to the test.
- Note the parameter file and map version used, in a text file beside the bag.
- Run
ros2 bag infoimmediately after stopping. - Copy the bag off the robot the same day.
The parameter file matters as much as the bag. A recording of a failure you cannot reproduce because the gains changed is a recording of a different robot.
Storage and retention
Bags are big. A lidar-only recording at 10 Hz is manageable; adding a camera turns hours into gigabytes. Keep a rotation policy: recent bags on the robot, everything else archived off-device, and a retention window measured in days, not months.
Mistakes to avoid
- Recording without
/tf, then discovering the bag cannot be visualised. - Mixing live and simulated time during replay.
- Filling the robot’s disk mid-test.
- Assuming a bag is valid because the command exited cleanly.
- Recording a 4K camera stream to debug a wheel slip issue.
- Losing the parameter file that made the run meaningful.
Related: ROS 2 topics, services and actions, TF2 tutorial, Nav2 tutorial, SLAM Toolbox tutorial, ROS 2 for beginners.
What is rosbag2 used for?
Recording and replaying ROS 2 topic data so you can debug a robot run later, share a failure with a colleague, or test a pipeline without the hardware.
Which topics should I record?
At minimum /scan, /odom, /tf, /tf_static and /cmd_vel. Add camera, map or point cloud topics only when the investigation needs them, because they fill storage quickly.
How do I replay a bag in ROS 2?
Run ros2 bag play with the –clock flag and set use_sim_time true on every consuming node, preferably in the launch file so nothing reads wall time mid-replay.
Why is my rosbag empty?
Common causes are a QoS mismatch between publisher and recorder, the topic not actually publishing, or the recorder started before the driver came up. Check with ros2 bag info and ros2 topic hz.
Is mcap better than sqlite3 for rosbags?
mcap writes faster and integrates well with modern tooling, while sqlite3 remains common and easy to query. Either works; check what your ROS 2 distribution supports best.
Record odometry and IMU together when you want to tune sensor fusion offline.
Recording a bag that contains custom types requires the same interface package to be installed, as covered in the custom messages guide.
Recording sessions is easier once your desktop toolchain is stable, and setting up ROS 2 on Windows is the usual starting point.
Sources and further reading
- ROS 2 documentation — rosbag2 command reference and storage plugins.
- MCAP — the container format specification and tooling.
- Nav2 documentation — replay-based debugging workflows.
- rosbag2 repository — source and issue tracker.


