Rerun MCAP 解码器架构全解析:从原始字节到语义可视化的多级解读管线
【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun
MCAP(Message Container And Payloads)是机器人领域通用的容器格式,Rerun 通过一套解码器(decoder)架构从同一份 MCAP 文件中提取不同层次的信息:文件级元数据、消息级语义可视化、Protobuf 反射结构以及原始字节。本文以 decoders-explained.md 为核心骨架,结合re_mcapcrate 的源码实现与 CLI 实战,系统讲解每种解码器的工作原理、选择策略与数据访问方式,帮助你按需组合解码器,最大化挖掘 MCAP 数据价值。
解码器架构总览:两种作用域、一套注册与执行机制
Rerun 的 MCAP 处理管线把"解读 MCAP"抽象为若干解码器(decoder),每个解码器代表一种从同一 MCAP 源中解释和提取数据的方式。打开文件时,Rerun 会分析 MCAP 内容并自动确定激活哪些解码器,在"尽可能全面呈现数据"与"避免重复"之间取得平衡;转换(convert)时则允许你显式指定解码器集合,只提取分析所需的信息。
从源码结构看(crates/data_flow/re_mcap/src/decoders/mod.rs),解码器被划分为两大类,分别实现两个 trait:
| 作用域 | Trait | 特征 | 代表解码器 |
|---|---|---|---|
| 文件级(file-scoped) | Decoder | 对整份文件的mcap::Summary执行一次处理,输出静态 chunk | schema、stats、recording_info、metadata、attachments |
| 消息级(message-scoped) | MessageDecoder | 逐通道(channel)声明支持能力,逐消息解析 | ros2msg、ros2_reflection、protobuf、raw |
消息级解码器的核心接口是supports_channel()与message_parser():前者决定"哪个解码器负责哪个通道",后者为被认领的通道实例化一个解析器(parser)。通道与解码器的分配遵循显式优先级顺序——DecoderRegistry::all_builtin()注册顺序为ros2msg→ros2_reflection→protobuf,然后可选地把raw注册为全局兜底(global fallback),即没有任何解码器能处理的通道自动交给raw(对应all_with_raw_fallback();若使用all_without_raw_fallback()则raw仍需显式选择)。分配结果记录在DecoderAssignment中,最终由ExecutionPlan统一执行:先运行所有文件级解码器,再按通道把消息分发到对应的MessageDecoderRunner。
实体路径的生成规则很直接:消息级解码器输出的实体路径直接取自 MCAP 通道的 topic(见McapChunkDecoder中EntityPath::from(channel.topic.as_str())),因此同一 topic 上的不同解码结果会共存于同一实体路径之下。
理解多解码器共存:以 ROS2 相机图像为例
当多个解码器同时启用时,它们各自独立处理相同的消息,在相同的实体路径上创建不同类型的组件,由此可能产生数据重复——例如同时启用raw与protobuf,同一条消息会被同时保存为结构化字段数据与原始二进制 blob。
原文档给出的例子非常直观:假设 MCAP 来自一台 ROS2 机器人,topic 为/robot/camera/image_raw,承载sensor_msgs/msg/Image消息:
- 仅启用
ros2msg解码器:创建 Image archetype,可直接在 Rerun viewer 中可视化; - 仅启用
raw解码器:创建 McapMessage,内含原始 CDR 编码的消息字节; - 两者同时启用:所有表示形式在同一实体路径
/robot/camera/image_raw上共存。
这种"一源多解"的设计意味着:你可以根据下游用途选择信息层次——要可视化就选语义解码器,要做底层调试就选raw,要两者兼得就组合启用。
Schema 与 Stats:理解文件结构的两个入口
schema解码器:通道与消息类型的静态目录
schema解码器提取 MCAP 文件的结构化组织信息,为每个通道创建描述性元数据实体:通道 topic、消息类型名、schema 定义等。对不熟悉的 MCAP 文件,它是快速建立全局认知的首选——无需深入消息体即可知道"这个文件里有哪些 topic、各自什么类型"。
从实现看(crates/data_flow/re_mcap/src/decoders/schema.rs),该解码器遍历DecoderContext::relevant_channels()(已剔除空通道并应用 topic 过滤),为每个通道构建McapChannelarchetype(channel id、topic、message encoding、key-value 元数据),若通道携带 schema 则再追加McapSchema字段(name、id、encoding、原始 schema data),最终以TimePoint::STATIC静态 chunk 形式输出到以 topic 命名的实体路径上。
stats解码器:文件级规模与质量评估
stats解码器计算文件级指标,输出到专用静态实体__mcap_properties(源码中的常量MCAP_PROPERTIES_ENTITY_PATH),内容包括:消息总数、schema 数量、通道数量、附件与元数据数量、chunk 数量、消息起始/结束时间,以及按通道的消息数(channel_message_counts)。
实现上(crates/data_flow/re_mcap/src/decoders/stats.rs),它直接读取mcap::records::Statistics并映射为McapStatisticsarchetype。这些数据可用于数据集规模评估、质量检查与存储规划;其单元测试test_stats_entity_path验证了输出确在__mcap_properties且为静态 chunk。
消息解读解码器:语义与结构两条路线
语义解读:ros2msg与foxglove
ros2msg和foxglove解码器对标准 ROS 2 与 Foxglove 消息类型提供语义解读与可视化:它理解消息语义并创建有意义的 Rerun 可视化 archetype——图像变成 Image,点云变成 Points3D,IMU 消息变成 SeriesLines 并随时间绘制数据,依此类推。这与protobuf解码器形成鲜明对比:后者只给数据结构,不给视觉解释。
支持的完整消息类型清单见 Supported Message Formats,映射关系覆盖面很广,例如:
| 模态 | ROS 2 | Rerun Archetypes |
|---|---|---|
| 原始图像 | sensor_msgs/Image | Image、DepthImage |
| 点云 | sensor_msgs/PointCloud2 | Points3D |
| 变换 | tf2_msgs/TFMessage | Transform3D |
| 位姿 | geometry_msgs/PoseStamped | InstancePoses3D |
| 标量传感器 | sensor_msgs/Imu等 | Scalars |
ros2msg解码器的实现(crates/data_flow/re_mcap/src/decoders/ros2.rs)维护了一个按schema 名索引的解析器注册表,目前内置sensor_msgs/msg/BatteryState、Imu、Joy、JointState、PointCloud2、Range与std_msgs/msg/Float64Array、Float64MultiArray等解析器(源码位于 crates/data_flow/re_mcap/src/parsers/ros2msg/)。它认领通道有两个硬性条件:schema 的 encoding 必须是ros2msg,且消息编码必须是CDR(supports_ros2_cdr_channel)。若 schema 名是 ROS2 类型但编码不是 CDR,会触发一次性警告"ROS 2 deserialization is only supported for CDR-encoded messages"。注意:ROS 1 数据不支持任何语义解读,raw/schema解码器可保留其字节与结构,但不会转换为可视化 archetype(见 message-formats.md 中关于 ROS1 的说明)。
TF 变换消息会被转为Transform3D,parent_frame/child_frame取自每条geometry_msgs/TransformStamped的frame_id/child_frame_id,时间戳放入对应 timeline,viewer 可像 ROS 的 TF buffer 一样随时间解析帧间空间关系。此外,解码器还会基于std_msgs/Header的frame_id创建 CoordinateFrame,让 3D 视图中的数据相对坐标系正确渲染。
Protobuf 反射解码:结构化的通用路径
protobuf解码器使用反射自动解码 protobuf 编码的消息(源码 crates/data_flow/re_mcap/src/decoders/protobuf.rs),它基于prost-reflect在运行时构建MessageDescriptor,把消息字段映射为可查询的 Rerun 组件,并忠实保留 protobuf 语义:
- oneof字段包装为嵌套结构;
- map / repeated字段按 Arrow 约束编码(list 项非空、map 条目非空);
google.protobuf.Struct/Value/ListValue等自引用动态消息以 JSON 文本存储;- 无法用 Arrow 表达的递归消息字段以原始字节存储(快照测试
recursive_message_fields_are_stored_as_bytes.snap等可佐证)。
该解码器提供的是结构化访问而非语义可视化:数据可查询,但不会自动变成图像、点云这类有意义的可视化——它给你数据结构,而不是视觉解读。对自定义 Protobuf schema,反射解码的字段会成为可查询组件(每个实体带.message组件),你可以在蓝图中手动为字段添加可视化器,例如为标量字段建时间序列视图,或用 Lenses 为反射数据附加 Rerun 语义(详见 message-formats.md 的 Schema reflection 一节)。
值得补充的是:任何 ROS 2 消息也有一条反射路径。ros2_reflection解码器(crates/data_flow/re_mcap/src/decoders/ros2_reflection.rs)在运行时动态解析 ROS 2 消息,直接生成与 protobuf 解码器类似的字段级 Arrow 表示。它认领所有能被反射成功解析的ros2msg通道;但注册优先级低于ros2msg,因此已注册语义解析器的 schema 会优先走语义路线(源码注释明确说明DecoderRegistry::plan会为支持语义解析的 schema 选择McapRos2Decoder)。若 schema 包含wstring(线上为 UTF-16,反射无法解码且会破坏消息其余部分)或依赖缺失无法解析,对应通道会降级交给raw解码器处理而不是让整个文件失败。
raw解码器:零解释的字节保鲜库
raw解码器不做任何解读,原样保留消息字节,创建包含未处理消息数据的 blob 实体——每条消息成为一个二进制 blob,可供自定义分析工具以编程方式访问。
实现极简(crates/data_flow/re_mcap/src/decoders/raw.rs):supports_channel对所有通道返回true(所以能作为全局兜底),解析器把msg.data逐条追加进 Arrow 二进制列表,最终封装为McapMessagearchetype。注释点明其定位:"verbatim copies of the original messages without decoding or imposing any semantic meaning"。
recording_info:录制会话的元数据快照
recording_info解码器提取录制会话与采集上下文相关的元数据,创建包含录制时间戳、源系统信息、采集软件版本等信息的元数据实体。
实现上(crates/data_flow/re_mcap/src/decoders/recording_info.rs),它从mcap::Summary的 statistics 中取出message_start_time,构造成RecordingInfoarchetype,同样写入__mcap_properties静态实体;单元测试test_recording_info_entity_path对此有明确验证。
URDF 选项:把机器人本体装进 3D 场景
urdf选项使用 Rerun 内置的 URDF 加载器:当 MCAP 中存在名为/robot_description的 ROS 2 string topic 时,将机器人模型作为静态 3D 几何记录。需要特别强调的是:在本 MCAP 工作流中,关节变换不会从 URDF 本身加载,而是期望来自 MCAP 中的 TF topic(如/tf、/tf_static)。
该逻辑实际在 importer 层实现(crates/data_flow/re_importer/src/importer_mcap/robot_description.rs):扫描 topic 包含robot_description、schema 为std_msgs/msg/String且 encoding 为ros2msg的通道,用 CDR 反序列化消息体取出 URDF XML,再交给build_urdf_chunks_from_xml生成静态几何 chunk。文件头注释同样注明"transforms are not extracted from the URDF in this context",与文档表述一致。关于在已有 recording 中加载 URDF 的通用方法,见 URDF 加载指南。
解码器选择与性能
用-d标志精确选择解码器
默认情况下,Rerun 处理 MCAP 时激活全部解码器(等价于把raw、attachments、schema、stats、metadata、protobuf、recording_info、urdf、ros2msg、foxglove全部列出,见 CLI Reference for MCAP)。通过rerun mcap convert的-d标志可以精确控制转换时使用的解码器:
# 只使用特定解码器 rerun mcap convert input.mcap -d protobuf -d stats -o output.rrd # 用多个解码器获取不同视角 rerun mcap convert input.mcap -d ros2msg -d raw -d recording_info -o output.rrd # 从 ROS robot_description topic 添加机器人几何 rerun mcap convert input.mcap -d ros2msg -d urdf -o output.rrd # 仅 ROS2 语义解读 rerun mcap convert input.mcap -d ros2msg -o output.rrd可用选项汇总(含 CLI 文档中补充的metadata、attachments):
| 选项 | 类别 | 作用 |
|---|---|---|
raw | 解码 | 保留原始消息字节 |
schema | 解码 | 提取通道与 schema 元数据 |
stats | 解码 | 计算文件与通道统计到 RRD__mcap_properties |
metadata | 解码 | 提取 metadata 记录到 RRD__mcap_metadata(如存在) |
attachments | 解码 | 提取 MCAP 附件记录为__mcap_attachments下的静态数据 |
protobuf | 解码 | 将 protobuf 消息解码为通用 Arrow 数据(无可视化组件) |
recording_info | 解码 | 提取录制会话元数据到 RRD__mcap_properties |
urdf | 解码 | 存在 ROS 2/robot_descriptiontopic 时用内置 URDF 加载器 |
foxglove | 语义 | Foxglove Protobuf 消息的语义解读 |
ros2msg | 语义 | ROS2 消息的语义解读 |
性能设计:主题过滤与并行解码
从源码可看到两个影响性能的机制。其一是topic 过滤:TopicFilter支持 include/exclude 正则(RE2 语法),命中规则为"include 为空或任一匹配,且不被任何 exclude 匹配"。DecoderRegistry::plan在分配通道时即应用过滤,被排除的通道连解析器都不会实例化;ExecutionPlan还支持可选的时间范围[start, end)(纳秒),范围外的 chunk 在解压前就被跳过,既省 CPU 也约束峰值内存。
其二是并行解码:MessageDecoderRunner::process在非 wasm32 平台使用rayon多线程按 chunk 并行解码,通过有界 channel 限制在途批次(max_in_flight = workers * 2),并由单线程消费端重新分配单调递增的RowId,保证输出顺序确定、可复现;wasm32 上则退化为单线程串行路径。
访问解码器数据:组件映射表
每个解码器都会在实体路径(派生自 MCAP 通道 topic)上创建不同类型的组件,可通过 Rerun SDK 访问:
ros2msg解码器及受支持的 Foxglove 消息数据以原生 Rerun 可视化 archetype呈现(概览见 message-formats.md 的 Overview 表);protobuf或ros2_reflection解码器的数据呈现为结构化组件,可按字段名查询,或手动添加到某些视图中(示例见 自定义消息标量的时间序列图);raw解码器的数据呈现为包含原始消息字节的blob 组件;urdf选项的数据呈现为从 ROS 2/robot_descriptiontopic 加载的静态 3D 机器人几何;schema、stats、recording_info解码器的元数据呈现为专用元数据实体。
关于查询数据与使用 archetype 的更多信息,参见 Data Queries 文档。
每个解码器都向 Rerun 原生数据贡献自己的 chunks。下面是 MCAP 数据到 Rerun 组件的官方映射表:
| MCAP Data | Rerun component | Description |
|---|---|---|
| Schema name | mcap.Schema:name | 来自 schema 定义的消息类型名 |
| Schema data | mcap.Schema:data | 原始 schema 定义(protobuf、ROS2 msg 等) |
| Schema encoding | mcap.Schema:encoding | schema 格式类型 |
| Channel topic | mcap.Channel:topic | 来自 MCAP 通道的 topic 名 |
| Channel ID | mcap.Channel:id | 数值通道标识符 |
| Message encoding | mcap.Channel:message_encoding | 编码格式(如protobuf、cdr) |
| Statistics | mcap.Statistics | 文件级指标,如消息数与时间范围 |
| Raw message data | mcap.Message:data | 未处理的消息字节,以二进制 blob 存储,由raw解码器处理 |
这套组件命名遵循mcap.*前缀,与实体路径(topic)共同构成完整的可寻址数据空间:既能在 viewer 中直接浏览语义 archetype,也能通过 SDK 按组件描述符精确查询反射结构与原始字节。理解解码器之间的分工与优先级,是高效使用 Rerun 处理 MCAP 机器人数据的关键一步。
【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考