rosbag in Field Testing: What to Record, What It Costs and How to Replay It
Tom Cosgrove,

TL;DR: Use ros2 bag record during field testing to capture the data you need to reproduce failures in the lab. Record sensor inputs, control outputs, TF, and diagnostics. Budget roughly 5-40 GB per hour depending on cameras and LiDAR. Use MCAP with zstd compression, topic allow-lists, and image throttling to keep bags manageable. Replay with ros2 bag play plus --clock to drive your stack as if the robot were live. This guide shows what to record, what it costs on disk, and how to reproduce a mission from a single bag.
Why rosbag Record for Field Testing Matters
Field testing is expensive. Every trip to a test site consumes engineer-hours, transport, battery cycles, and weather luck. When a Leo Rover freezes in front of a puddle or a Raph Rover misclassifies a slope, you rarely get a second chance that day. The rosbag record field testing workflow exists so you can preserve the evidence needed to investigate it later. If you captured the right topics, you can rebuild the scenario at your desk, tweak parameters, and validate a fix before the next deployment.
A rosbag is a container that stores serialized ROS 2 messages with their recorded timestamps. In ROS 2, the default storage backend is SQLite3 and produces .db3 files; the MCAP plugin produces .mcap files when selected. You can later replay messages through ros2 bag play on the recorded topics and according to their recorded timing. With compatible message definitions, QoS settings, and simulated time configured correctly, this lets you exercise much of the stack as though the robot were live.
What to Record So You Can Actually Reproduce a Mission
Recording everything is tempting and wasteful. Recording too little means you cannot reconstruct the failure. The practical rule: record every input to your autonomy stack, every output it produces, and every piece of metadata you need to interpret the timestamps.
For a typical Leo Rover mission with a depth camera, IMU, and ROS 2 Nav2, the following topics are the minimum useful set:
- Sensor inputs:
/camera/color/image_raw/compressed,/camera/depth/image_rect_raw,/camera/color/camera_info,/imu/data,/scan(if LiDAR). - Odometry and localization:
/odom,/wheel_odom,/amcl_poseor/tfand/tf_static. - Commands and state:
/cmd_vel,/joy,/battery_state,/robot_description. - Diagnostics:
/diagnostics,/rosout, any custom/behavior_tree_logor planner status topics. - Ground truth (if available): RTK GPS fix, motion capture pose, or manually annotated events.
Skip large derived topics that you can recompute from inputs. There is no point recording /local_costmap if you have the source scans and TF. Skip visualization-only topics like markers and paths unless you specifically debug the planner.
Include TF and robot_description or Regret It Later
The single most common mistake in field bags is forgetting /tf_static and /robot_description. Without them, RViz may show disconnected point clouds and Nav2 may be unable to plan. Record /tf_static explicitly and ensure the recorder subscribes with QoS compatible with its transient-local publisher. Confirm it appears in ros2 bag info before you drive off.
How Much Disk Does an Hour of Recording Cost
The disk budget depends almost entirely on cameras and LiDAR. In testing on a Leo Rover configuration with a RealSense D435i and wheel odometry, approximate uncompressed rates are:
- IMU at 200 Hz: typically tens to a few hundred KB/s, depending on message contents and overhead.
- Wheel odometry, cmd_vel, TF, diagnostics: typically tens to a few hundred KB/s combined.
- Compressed color image at 30 Hz, 640×480: ~1-2 MB/s, roughly 4-7 GB/hour.
- Raw depth image at 15 Hz, 640×480, 16-bit: ~9 MB/s, roughly 32 GB/hour.
- 2D LiDAR at 10 Hz: ~0.05 MB/s, roughly 180 MB/hour.
- 3D LiDAR (e.g., 16-channel at 10 Hz): ~5-8 MB/s, roughly 20-30 GB/hour.
A realistic Leo Rover research mission with compressed color, throttled depth, IMU, odometry, TF, and diagnostics can land around 5-20 GB per hour, depending especially on the depth encoding, frame rate, scene content, and compression settings. Add a 3D LiDAR and total throughput can exceed 30 GB/hour. Plan storage accordingly: a 256 GB SSD may hold roughly a day of recording at the lower end of those rates, but substantially less at high camera or LiDAR rates. Use a quality USB 3 SSD with verified sustained write performance; many USB flash drives throttle during long writes.
Cut the Bill with MCAP and zstd Compression
ROS 2 distributions with the MCAP storage plugin support MCAP, which provides chunking and indexes for efficient seeking. MCAP supports zstd chunk compression through its storage configuration. Compression effectiveness varies substantially: raw depth often compresses well, while JPEG-compressed color images may shrink very little. Benchmark CPU use and resulting bag size on the actual onboard computer before a mission.
A recording command that balances fidelity and disk use looks like this:
ros2 bag record -s mcap --storage-config-file mcap_zstd.yaml -o field_run_2024_11_15 /tf /tf_static /robot_description /odom /imu/data /cmd_vel /camera/color/image_raw/compressed /camera/color/camera_info /camera/depth/image_rect_raw /scan /diagnostics /battery_state
The mcap_zstd.yaml storage configuration should enable zstd compression for the MCAP writer. If depth is still too large, throttle it before recording using topic_tools throttle:
ros2 run topic_tools throttle messages /camera/depth/image_rect_raw 5.0
Then record the throttled output topic, typically /camera/depth/image_rect_raw_throttle, instead. Five hertz can be enough for post-hoc obstacle analysis, but validate that rate against the failure modes you need to investigate.
How to Replay a Field Failure in the Lab
Reproducing a failure means feeding the recorded messages back into your stack while your nodes use simulated time. The key flag is --clock, which publishes /clock based on the bag’s timestamps. Every node in your stack must run with use_sim_time: true for this to work.
The minimal replay workflow is:
- Start your autonomy stack with
use_sim_time:=true, for exampleros2 launch leo_navigation navigation.launch.py use_sim_time:=true. - Play the bag with clock publishing:
ros2 bag play field_run_2024_11_15 --clock 100. - Open RViz2, also with
use_sim_timeenabled, to visualize.
To jump straight to the moment of failure, use --start-offset:
ros2 bag play field_run_2024_11_15 --clock 100 --start-offset 245.0 --rate 0.5
This starts 245 seconds in and plays at half speed, giving you time to watch the planner’s decisions frame by frame. If you want to exclude the recorded /cmd_vel so your live controller can react instead, use the player’s topic exclusion option where available, or play an explicit allow-list of the sensor and state topics you need.
ros2 bag play field_run_2024_11_15 --clock 100 --exclude "/cmd_vel"
Now your planner sees the same sensor stream but produces fresh commands, which is exactly what you want when validating a parameter change.
Filter, Slice, and Reindex Bags Before Replay
Large field bags become easier to work with once trimmed. ros2 bag supports several helpful subcommands:
ros2 bag info field_run_2024_11_15shows duration, topic list, message counts, and size.ros2 bag convertlets you convert bags to a new storage format and, through its conversion options, create filtered output bags with different compression settings.ros2 bag reindexcan rebuild metadata for supported bag storage formats after an interrupted recording.
Keep the raw bag archived and work from filtered copies. That way you can always go back if you decide you need a topic you originally excluded.
A Reproducible Example Recording Setup for Leo Rover
The Leo Rover supports ROS 2 workflows, so the recording workflow above can run on a compatible onboard computer. A practical field command that starts recording on a button press, splits bags at 2 GB, and stops cleanly on shutdown looks like:
ros2 bag record -s mcap --storage-config-file mcap_zstd.yaml -b 2000000000 -o /media/usb/leo_$(date +%Y%m%d_%H%M%S) --include-hidden-topics /tf /tf_static /robot_description /odom /imu/data /cmd_vel /joy /camera/color/image_raw/compressed /camera/color/camera_info /scan /diagnostics /battery_state /rosout
The -b flag sets the maximum size of each bag file before rosbag2 starts a new file. Splitting limits the amount of data affected by a write interruption, but it does not replace clean shutdowns or filesystem reliability. Bags land on a USB SSD mounted at /media/usb to avoid wearing out the internal SD card.
For teams building custom perception or control stacks on top of the platform, Fictionlab’s team documents deployment patterns and integration examples on the research applications page. For non-standard sensor payloads or bespoke recording setups, the custom robotics service covers hardware and firmware integration.
Frequently Asked Questions
What is the difference between .db3 and .mcap bag files?
SQLite3 (.db3) is the default ROS 2 storage format. MCAP is a newer format designed for robotics logging, with efficient indexed seeking and broad cross-tool support, including tools such as Foxglove and PlotJuggler where compatible. For new projects, MCAP is often a practical choice. Use -s mcap in your record command when the MCAP storage plugin is installed.
Can you record and replay on different ROS 2 distributions?
Usually yes, as long as message definitions and serialization support are compatible. Problems arise when a message definition changes between distributions or required custom message packages are unavailable on the replay system. Pin your message packages and retain the source or released packages needed to build custom interfaces.
How do you record only when something interesting happens?
Use snapshot mode. Start the recorder with --snapshot-mode and it keeps a rolling cache of messages in memory. Trigger a save with the /rosbag2_recorder/snapshot service. This is useful for long autonomous missions where you only care about the seconds around an anomaly.
Does replaying a bag drive the real robot?
Only if you play /cmd_vel onto a topic the motor driver subscribes to. In the lab, either exclude command topics with --exclude where supported, remap them to a dead topic, or simply do not run the motor driver. Never replay commands to a physical Leo Rover or Raph Rover without safety supervision.
How do you synchronize bags with external ground truth like RTK GPS?
Record the GPS as a ROS 2 topic on the same computer if possible, so timestamps share a clock. If the ground truth comes from an external logger, record a shared trigger event (e.g., a button press published to a topic and logged externally) and align offline.
What is the CPU cost of recording during a mission?
CPU cost depends on message rate, serialization, storage media, and compression settings. On a Raspberry Pi 4, high-rate image recording with zstd compression can consume a significant fraction of a core or more, so measure it under realistic load. If CPU is tight, file-level compression can reduce recording-time CPU use, but requires enough free disk space for the uncompressed data until a bag file is closed and compressed.
Where can you find an example rosbag to practice with?
Public ROS 2 bag datasets are available from Foxglove’s sample data repository and the Open Robotics community. For Leo Rover specific examples, sample recordings and integration notes are linked from Fictionlab’s documentation and application pages.
Bring Field Data Back to the Lab
A disciplined rosbag record field testing workflow turns every field trip into reusable engineering data. You stop guessing about what went wrong and start replaying it. To see how research teams use Leo Rover as a data-collection and algorithm-validation platform, explore Fictionlab’s research applications.