Rosbag
ros2 bag records and replays ROS 2 data. This page covers recording, inspecting, and playing back bags, selecting topics deliberately, simulated time via /clock and use_sim_time, playback rate, storage considerations, and the safe way to replay recorded TF data.
Overview
A rosbag is a stored, timestamped sequence of messages from one or more topics. Recording lets you capture a real run once and replay it repeatedly for development, debugging, or demonstration — including the recorded demos used in Manipulation, which replay /joint_states and /tf instead of requiring physical hardware.
Why It Matters
Recorded data lets you iterate on perception, planning, or visualization work without a live sensor or robot attached, and lets you share a reproducible scenario with someone else. It also has real failure modes — recording too much data fills disks quickly, and replaying TF incorrectly produces a broken or duplicated frame tree (see TF2).
Core Concepts
The Default Storage Format
ros2 bag record writes a bag directory rather than a single file.
The directory contains metadata and one or more data files managed by a rosbag2 storage plugin, such as SQLite3 or MCAP.
The default storage backend depends on the ROS 2 distribution and the installed rosbag2 packages. Use the rosbag2 CLI tools available in your distribution to inspect the configured or installed storage plugins instead of assuming a specific backend.
/clock and use_sim_time
By default, nodes use the system (wall-clock) time. When simulated time is required — for example, replaying a bag and wanting every node to agree on "recorded time" instead of "wall time" — two things must both be true:
- Something publishes
/clock(aros2 bag play --clockflag, or a simulator). - Every node that should follow simulated time has its
use_sim_timeparameter set totrue.
If /clock is published but a node has use_sim_time set to false, that node continues to use system time. If use_sim_time is true but no /clock source is available, ROS time does not advance normally, which can prevent timers or time-dependent processing from behaving as expected.
Playback Rate
ros2 bag play supports a rate multiplier so you can slow down a fast recording for careful inspection, or speed up a long one:
ros2 bag play my_bag --rate 0.5 # half speed
ros2 bag play my_bag --rate 2.0 # double speed
Rate changes affect wall-clock playback speed; if other nodes rely on /clock, their behavior scales with it as well.
Hands-on Steps
1. Record Specific Topics
Recording everything is rarely a good idea — prefer an explicit topic list so bags stay a manageable size and stay easy to reason about:
ros2 bag record -o my_bag /tutorial_chatter /tf /tf_static
-o my_bagnames the output directory (omit it andros2 bagpicks a timestamped name).- List only the topics you actually need; add more later if something is missing.
To record everything currently available (useful for a one-off exploratory capture, less suitable for routine use):
ros2 bag record -o my_bag_all -a
2. Inspect a Bag Without Playing It
ros2 bag info my_bag
This reports the duration, message count and type per topic, storage format, and start/end time — always run this before replaying an unfamiliar bag.
3. Play It Back
ros2 bag play my_bag
Watch it alongside a subscriber, for example the simple_subscriber node from Publisher/Subscriber, or ros2 topic echo /tutorial_chatter.
4. Play Back with Simulated Time
ros2 bag play my_bag --clock
Any node that should follow simulated time must have its use_sim_time parameter set to true. A launch file may configure this parameter at startup, or it can be changed on a running node with:
ros2 param set <node_name> use_sim_time true
Expected Result
ros2 bag info my_bag lists each recorded topic with its message type and count. During playback, ros2 topic echo /tutorial_chatter (or the equivalent topic you recorded) shows the same sequence of messages as during recording, at the rate you selected.
Useful Commands
ros2 bag record -o <name> <topic1> <topic2> ... # record specific topics
ros2 bag record -o <name> -a # record everything (use sparingly)
ros2 bag info <bag_path> # inspect without playing
ros2 bag play <bag_path> # play back
ros2 bag play <bag_path> --rate 0.5 # half-speed playback
ros2 bag play <bag_path> --clock # publish /clock for simulated time
ros2 bag play <bag_path> --topics /a /b # replay only a subset of recorded topics
ros2 bag play <bag_path> --loop # loop playback
Storage Considerations
- High-rate topics (raw camera images, point clouds) dominate bag size quickly; record compressed or downsampled versions when only approximate data is needed.
- Prefer an explicit topic list over
-afor anything you intend to keep or share — it documents intent and avoids accidentally capturing unrelated, large topics. - Bag directories can be large; store them outside of source control and clean up exploratory recordings you no longer need.
- If disk space is constrained, check available compression options for your installed storage plugin (
ros2 bag record --help) rather than recording uncompressed by default.
TF During Playback
Never publish the same transform from multiple authorities If recorded TF overlaps with transforms generated by live nodes such as robot_state_publisher, ensure that each child frame has only one active TF authority during playback.
For a bag that already contains the robot's complete link TF tree, choose one of these approaches:
-
Replay recorded TF directly — replay the recorded
/tfand/tf_static, and do not simultaneously generate the same robot-link transforms withrobot_state_publisher. -
Regenerate robot-link TF from joint states — replay
/joint_statesand runrobot_state_publisherwith the matching URDF, while avoiding playback of recorded transforms that overlap with those generated links.
To replay only /joint_states and exclude the recorded TF topics:
ros2 bag play my_bag --topics /joint_states
Common Problems
- Playback runs but nothing subscribes — confirm the topic names in the bag (
ros2 bag info) match what your subscriber expects, and thatROS_DOMAIN_IDmatches between the playback terminal and the subscriber's terminal (see ROS 2 Domain ID). - Nodes ignore
/clockduring playback —--clockwas not passed toros2 bag play, or the consuming nodes do not haveuse_sim_timeset totrue. Both sides are required. - RViz shows a frozen or jumping robot model — likely a duplicate-TF-authority problem; check whether both a bag and
robot_state_publisherare publishing/tffor the same robot, per the warning above. - Bag directory is unexpectedly huge — an
-arecording captured high-rate image or point cloud topics unintentionally; re-record with an explicit topic list. ros2 bag playreports an unknown storage format — the storage plugin used to record the bag is not installed in the environment doing playback; checkros2 bag infoand the plugins listed byros2 bag play --help.
Key Takeaways
- Record an explicit topic list rather than everything, unless you specifically need an exploratory full capture.
ros2 bag infobeforeros2 bag play— always know what is in a bag before replaying it.--clockon the rosbag player anduse_sim_time=trueon every node that should use simulated time are both required.- Never replay recorded
/tf//tf_staticat the same time as a liverobot_state_publisherfor the same robot.
Next
Continue to Troubleshooting for a systematic checklist when recording, playback, or any other part of the ROS 2 path does not behave as expected.