Reconstruct ROS bag
Takes sequences previously ingested into Mosaico and writes them back out as native ROS 2 .mcap bag files. It is the inverse operation of the ROS Ingestion example. Connection handling, topic filtering, ROS type resolution, and bag writing are all handled automatically.
- Python
- C++
- Rust
The C++ SDK is currently in development.
The Rust SDK is currently in development.
mosaicolabs.examples reconstruct_rosbags
Run the command with --help to see all available options.
The daemon must be running, and it must already contain the sequences ingested by the ROS Ingestion example. This script only reads back data already on the server, it does not download or ingest anything itself.
The full source is on GitHub.
Custom Ontology Definition
The R2B dataset includes isaac_ros_nova_interfaces/msg/EncoderTicks, the same custom, hand-modeled type introduced in the Custom Ontology example to make wheel-encoder ticks ingestible (reused here without modification).
No Adapter Needed to Reconstruct
Reuse, not required. The ROS Ingestion example writes EncoderTicksAdapter by hand (imported here via ros_injection.custom_ontology, see ROS Ingestion) to get a fully-typed, queryable EncoderTicks model, but that step is a choice, not a requirement.
Automatic fallback. Writing a reverse adapter is optional too: for any topic that reaches the extractor with no adapter registered for its ROS message type, the bridge falls back to the same automatic Unmodeled Adapter used at ingestion time. Since the original .msg definition was already captured as topic metadata when the sequence was ingested, the extractor can recover it, re-register it with the local ROS typestore, and reconstruct the native ROS message from it. See Advanced: Ingesting Unmodeled Ontologies for the full mechanics of this round-trip.
Reconstruction Pipeline
ROSSequenceExtractor.run() mirrors the injector's pipeline in reverse:
Connect. Opens a connection to Mosaico using the credentials and TLS settings in ROSExtractorConfig.
Stream. Reads back every message of the requested sequence, resolving the adapter for each topic (falling back to the automatic Unmodeled Adapter as described above).
Write. Translates each message back into its native ROS type and writes it into a fresh bag under rosbag_path/sequence_name.
BAG_FILE_PATH = Path(ASSET_DIR) / "reconstructed"
SEQUENCE_NAMES = [
"r2b_galileo2_0",
"r2b_galileo_0",
"r2b_whitetunnel_0",
"r2b_robotarm_0",
]
ROS_DISTRO = Stores.ROS2_JAZZY
for sequence in SEQUENCE_NAMES:
configs = ROSExtractorConfig(
rosbag_path=BAG_FILE_PATH,
sequence_name=sequence,
host=MOSAICO_HOST,
port=MOSAICO_PORT,
ros_distro=ROS_DISTRO,
storage_plugin=StoragePlugin.MCAP,
log_level=LOG_LEVEL,
mosaico_api_key=API_KEY,
enable_tls=ENABLE_TLS,
overwrite=True,
)
extractor = ROSSequenceExtractor(configs)
extractor.run()
Each sequence is written to its own .mcap bag under /tmp/mosaico_assets/reconstructed/<sequence_name>/, ready to be replayed with any standard ROS 2 tooling (ros2 bag play, ros2 bag info, ...).