Context
In ros2/rosbag2#663, it was recommended that a "snapshot" feature be added to rosbag2.
Motivation
The goal of this feature is to provide the user with a mechanism to maintain a transient cache of the recent messages sent on specified topics that is only written to permanent storage upon a user-invoked trigger.
For example, if a rare, anomalous behavior occurs, this feature will allow the user to record the most recent ROS topic messages when the behavior is observed, instead of having to record the entire execution.
Example Usage
Starting rosbag2 in snapshot mode with a specified cache size:
$ ros2 bag record --max-cache-size 100000 --snapshot-mode [topics [topics ...]]
Triggering a snapshot via CLI:
$ ros2 service call /rosbag2_recorder/snapshot rosbag2_interfaces/Snapshot
Triggering a snapshot with a keyboard shortcut:
* For example, pressing the s key in the open recording process might be used to trigger a snapshot.
Implementation Proposal
-
Add a
--snapshot-modeflag to therecordverb inros2bagthat will be passed viaStorageOptions. -
Create a new class
CircularMessageCachewhich maintains two circular buffers, individally implemented in a classMessageCacheCircularBufferand sized according to the existing—max-cache-sizeparameter. During snapshot mode,CircularMessageCachewill keep adding messages to the same circular buffer until triggered to switch to the secondary buffer by theRecorderclass. -
Create a service
~/snapshotin therosbag2_recordernode that will listen for snapshot requests. Upon receiving a service call, it will trigger a buffer flip inCircularMessageCacheand call the newtake_snapeshotfunction inSequentialWriter(detailed below) to write the snapshot messages to storage. -
Modify
SequentialWriterto useCircularMessageCachewhen snapshot mode is enabled instead ofMessageCacheandCacheConsumer. -
Add a new
take_snapshotfunction toSequentialWriterthat will be invoked by therosbag2_recordernode's snapshot service to write the snapshot data to the rosbag. -
Modify
BaseWriterInterfaceto include a pure virutal functiontake_snapshotto ensure that all future writers are compatible with snapshot mode. -
Implement the
~/snapshotservice interface asSnapshot.srvinrosbag2_interfaces. It won’t require any arguments (similar toResume.srv).
Implementation Breakdown
The snapshot feature implementation could be broken down into the following PRs:
- Implement
CircularMessageCacheandMessageCacheCircularBuffer. Then add corresponding tests. - Integrate
CircularMessageCacheintoSequentialWriterand update its tests. - Create the
~/snapshotservice in theRecorderclass, add corresponding tests, and create theSnapshot.srvservice interface. - Add
--snapshot-modeto therecordverb and updateStorageOptions - Add keyboard shortcut for triggering a snapshot in snapshot mode