关于 rerun-mcap
介绍如何使用 Rerun 的 `McapReader` 导入 MCAP 文件,面向处理机器人记录数据的开发者。内容包括惰性数据块流、按模式解码、主题筛选及空数据排查。
主要功能
- 01将 MCAP 读取为惰性数据块流
- 02按模式解码主题
- 03使用 RE2 模式筛选主题
- 04为自定义消息附加语义
- 05调整时间戳解释方式
适用场景
- 01检查 MCAP 传感器记录
- 02筛选记录中的指定主题
- 03为 Rerun 解码自定义 protobuf 消息
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ rerun-io/ rerun --skill rerun-mcap安装后在 Claude Code 中输入/rerun-mcap确认已加载。
详细介绍
重新运行 MCAP 摄取
McapReader 会将 MCAP 文件转换为惰性分块流:每个主题对应一个实体,实体位于主题路径上,消息负载由可插拔解码器解码。本技能介绍读取器的选项、每个主题会转换成什么,以及哪些故障模式会导致生成空流且不报错。流处理机制(筛选、丢弃、透镜、合并、写入)请参阅 rerun-chunk-processing。
API
from rerun.chunk import McapReader
reader = McapReader(mcap_path) # see help(McapReader) for the full option set
stream = reader.stream()
MCAP 中嵌入的 URDF 也可以一并摄取(然后参阅 rerun-urdf)。
主题会转换成什么
使用默认解码器(decoders=None)时,消息的架构名称决定主题会转换成什么——让原型直接通过,只对原始 :message 主题应用透镜:
| MCAP 架构名称 | 解码为 | 处理方式 |
|---|---|---|
foxglove.FrameTransforms | Transform3D | 直接通过;不要手动构建 |
foxglove.CameraCalibration | Pinhole | 直接通过 |
foxglove.CompressedVideo | VideoStream(真实样本字节)+ CoordinateFrame | 直接通过 |
其他 foxglove.* 已知类型 | 对应的原型 | 直接通过 |
ros2 已知类型(ros2msg / ros2_reflection) | 原型 | 直接通过 |
自定义 schemas.proto.* / 自定义 protobuf | 一个 <schema.name>:message 结构体 | 使用 DeriveLens + Selector 附加语义 |
因此,相机主题会直接作为 Pinhole 到达,视频会作为 VideoStream 到达,frame_transforms 主题会作为 Transform3D 到达——只有自定义消息(例如自定义关节状态架构、自定义夹爪状态枚举)会通过反射或仅以原始形式传入,需要使用透镜。
foxglove 解码器负责将架构映射到原型;由于 foxglove 消息采用 protobuf 编码,它依赖 protobuf 解码器,因此应保留 decoders=None(已验证:单独使用 decoders=["protobuf"] 会让 foxglove.CameraCalibration 保持为原始 :message;添加 foxglove 后才会变为 Pinhole)。请在自己的文件上确认:运行 McapReader(path).stream(),然后读取 McapSchema:name 和几个 Chunk.format(),再判断是否缺少内容或需要重建。
- 实体路径 = 主题名称(
/sensors/joint_states会保持为/sensors/joint_states)。 尽早筛选:McapReader(path).stream().filter(content="/sensors/**")。 - 通过反射解码的消息会落入一个结构体组件,名称为
<fully.qualified.MessageName>:message。 在透镜中使用Selector导航(Selector(".joint_positions"));这就是为自定义消息附加 Rerun 语义的方式(请参阅rerun-chunk-processing中的 DeriveLens 模式)。 - 主题正则表达式使用 RE2 语法,且不会自动锚定:
cam会匹配/external/cam_low和/camera_info。 需要时请显式锚定(^/external/cam)。条件允许时,优先使用读取器级主题筛选,而不是.filter(...), 这样就完全不会解码被排除的主题。
何时改用低级 mcap 包
McapReader 会将负载保留在列式分块流中,这几乎总是你需要的方式。仅当你需要不含负载的原始记录元数据,或需要重写容器本身(重新注册架构、通道和消息)时,才改用 mcap.reader.make_reader。
注意事项
- 流为空,且没有错误:主题正则表达式未匹配到任何内容,或某个通道的解码器未生成任何行。使用一个小型测试文件,检查
reader.stream().to_chunks()中几个块的Chunk.format(),或先将主题名称与mcapCLI / 包进行比较。 - 主题正则表达式使用未锚定的 RE2;排除项在包含项之后运行。
timeline_type="timestamp"会将 MCAP 日志时间解释为自纪元起的墙上时钟纳秒数。如果录制时钟有误,请通过timestamp_offset_ns在读取器处修正,而不要在下游修改时间戳。- 解码器子集会静默跳过没有解码器认领的主题;如果缺少某个主题,请尝试使用
decoders=None,以排除解码器选择导致的问题。 - 示例中的修复 lens 针对特定数据集。在复制类似
robot_data_preprocessing示例中的Pinhole:resolution交换操作的MutateLens之前,请从McapReader(path).stream()读取原始组件,并确认你的数据中确实存在该问题——盲目应用会破坏正确的标定(将正确的 648×480 翻转为 480×648)。 foxglove会根据每条消息的.frame_id(加上图像平面后缀)同时推导相机的Pinhole:child_frame和视频的CoordinateFrame:frame,因此当标定和视频主题共享同一个frame_id时,两者匹配。只有当这些主题携带不同的frame_id时,视频帧才会不一致,导致视频脱离其图像平面——此时使用针对每台相机的MutateLens,对CoordinateFrame:frame重新指定归属。
参考资料
- 端到端 MCAP 流水线:
https://github.com/rerun-io/rerun/tree/main/examples/python/robot_data_preprocessing rerun-chunk-processing(流 / lens 机制)、rerun-urdf(根据关节状态主题进行 FK)、rerun-data-model(建模决策)