MCAP ROS2 Support
mcap-ros2-support provides utilities to seamlessly integrate ROS2 messages with the MCAP data logging format. It allows for efficient recording and playback of ROS2 data within MCAP files, handling schema definition and message serialization/deserialization. The current version is 0.5.7, and the project (including core mcap, CLI, and other support libraries) has a frequent release cadence.
Common errors
-
ModuleNotFoundError: No module named 'mcap_ros2'
cause Incorrect import path or `mcap-ros2-support` not installed.fixEnsure `mcap-ros2-support` is installed via `pip install mcap-ros2-support` and use the correct import path: `from mcap_ros2.<reader|writer> import ...`. -
AttributeError: 'bytes' object has no attribute '_TYPE'
cause Attempting to pass raw bytes (or an object without ROS2 message metadata) to `Ros2RawWriter.write_message` where a ROS2 message object is expected.fixEnsure you are passing a properly instantiated ROS2 message object (e.g., `String(data='...')`) or an object that mimics the ROS2 message interface expected by `mcap_ros2` (with attributes like `_TYPE`, `_HAS_HEADER`, `get_fields_and_field_types`, etc.). -
mcap.exceptions.McapError: Message type not found for schema id ...
cause Attempting to read a ROS2 message from an MCAP file where the corresponding ROS2 message type definition is not available in the current Python environment.fixVerify that all ROS2 packages containing the message types used in the MCAP file are installed and accessible in your Python environment. This often means having a ROS2 workspace sourced or relevant `rosidl_runtime_py` dependencies installed.
Warnings
- gotcha Deserializing ROS2 messages requires the corresponding `rosidl_runtime_py` and `rosidl_typesupport_fastrtps_cpp` (or other type support) packages for the message types to be installed and available in the Python environment where the MCAP file is being read. Missing these will result in deserialization errors.
- breaking Prior to v0.5.7, specifying topics might have had stricter type requirements. As of v0.5.7, topics can be specified as strings, providing more flexibility, indicated by 'allow topics specified as string' in the changelog.
- gotcha The `mcap_ros2` package (where `Ros2RawWriter` and `Ros2Reader` reside) is a sub-package within the `mcap-ros2-support` distribution. The import paths use `mcap_ros2` directly, which can be confusing for users expecting `mcap_ros2_support`.
Install
-
pip install mcap-ros2-support
Imports
- Ros2RawWriter
from mcap_ros2_support.writer import Ros2RawWriter
from mcap_ros2.writer import Ros2RawWriter
- Ros2Reader
from mcap_ros2_support.reader import Ros2Reader
from mcap_ros2.reader import Ros2Reader
- McapWriter
from mcap.mcap_writer import McapWriter
Quickstart
import os
from pathlib import Path
from mcap.mcap_writer import McapWriter
from mcap_ros2.writer import Ros2RawWriter
from mcap_ros2.reader import Ros2Reader
# Assuming a ROS2 message type is available, e.g., from an installed ROS2 package
# For demonstration, we'll mock a simple message structure for 'std_msgs/msg/String'
# In a real scenario, you would import the actual message type and populate it.
class MockStringMsg:
_TYPE = 'std_msgs/msg/String'
_HAS_HEADER = False
_LAYOUT = [
('data', 'string'),
]
_REGISTERED_TYPES = {}
_CDR_TYPES = {}
def __init__(self, data=''):
self.data = data
def __repr__(self):
return f"MockStringMsg(data='{self.data}')"
@staticmethod
def get_fields_and_field_types():
return [('data', 'string')]
def get_type_description_interfaces(self):
# Simplified mock for the purpose of the quickstart
return {'type_description': 'string data'}
# Write a simple MCAP file with a ROS2 message
output_file = Path('ros2_messages.mcap')
with open(output_file, 'wb') as f,
McapWriter(f) as mcap_writer,
Ros2RawWriter(mcap_writer) as ros2_writer:
# In a real ROS2 environment, you'd create actual ROS2 messages
# from std_msgs.msg import String
# msg = String(data='Hello ROS2 from MCAP!')
mock_msg = MockStringMsg(data='Hello ROS2 from MCAP!')
topic = '/chatter'
log_time_ns = 123456789
# The Ros2RawWriter can infer the schema from a ROS2 message object.
# For this mock, we ensure the mock_msg has the necessary _TYPE and field info.
ros2_writer.write_message(
topic=topic,
message=mock_msg,
log_time_ns=log_time_ns,
publish_time_ns=log_time_ns
)
print(f"Wrote ROS2 message to {output_file}")
# Read the MCAP file and verify
with open(output_file, 'rb') as f:
reader = Ros2Reader(f)
for msg, schema, channel in reader.iter_decoded_messages():
print(f"Read message from topic '{channel.topic}': {msg}")
assert msg.data == 'Hello ROS2 from MCAP!'
break # Only read one message for this example
# Clean up the created file
os.remove(output_file)
print(f"Cleaned up {output_file}")