Skip to main content

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:

  1. Something publishes /clock (a ros2 bag play --clock flag, or a simulator).
  2. Every node that should follow simulated time has its use_sim_time parameter set to true.

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_bag names the output directory (omit it and ros2 bag picks 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 -a for 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​

tip

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 /tf and /tf_static, and do not simultaneously generate the same robot-link transforms with robot_state_publisher.

  • Regenerate robot-link TF from joint states — replay /joint_states and run robot_state_publisher with 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 that ROS_DOMAIN_ID matches between the playback terminal and the subscriber's terminal (see ROS 2 Domain ID).
  • Nodes ignore /clock during playback — --clock was not passed to ros2 bag play, or the consuming nodes do not have use_sim_time set to true. 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_publisher are publishing /tf for the same robot, per the warning above.
  • Bag directory is unexpectedly huge — an -a recording captured high-rate image or point cloud topics unintentionally; re-record with an explicit topic list.
  • ros2 bag play reports an unknown storage format — the storage plugin used to record the bag is not installed in the environment doing playback; check ros2 bag info and the plugins listed by ros2 bag play --help.

Key Takeaways​

  • Record an explicit topic list rather than everything, unless you specifically need an exploratory full capture.
  • ros2 bag info before ros2 bag play — always know what is in a bag before replaying it.
  • --clock on the rosbag player and use_sim_time=true on every node that should use simulated time are both required.
  • Never replay recorded /tf//tf_static at the same time as a live robot_state_publisher for 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.