rerun-data-model
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseRerun data model
Rerun数据模型
The hard part of ingesting a dataset is the modeling decision, not the API call.
Get the model right and any mechanism works; get it wrong and queries, views, and training all break.
This skill is just the decisions.
For mechanism details see (pipeline mechanics) and the importer skills it routes to: ,,, , .
For exact signatures, the docs at .
rerun-chunk-processingrerun-mcaprerun-urdfrerun-parquetrerun-mp4rerun-lerobotrerun.io/docs/concepts/logging-and-ingestionBefore writing conversion code, fill in the mapping table below. It is the design, and a human can review it in seconds.
导入数据集的难点在于建模决策,而非API调用。模型正确,任何机制都能正常工作;模型错误,查询、视图和训练都会失效。本文仅阐述决策内容。有关机制细节,请参阅(流水线机制)及其指向的导入工具技能:、、、、。如需确切的签名信息,请查看文档。
rerun-chunk-processingrerun-mcaprerun-urdfrerun-parquetrerun-mp4rerun-lerobotrerun.io/docs/concepts/logging-and-ingestion在编写转换代码之前,请填写下方的映射表。这是设计方案,人工审核只需几秒。
Pick the mechanism before you model the bytes
先选择机制,再建模字节数据
Modeling decides what each datum becomes; this decides how it gets there — and the default is a reader + lenses, not hand-built chunks:
- Does a reader exist for this source? MCAP→, URDF→
McapReader, parquet→UrdfTree, RRD→ParquetReader, LeRobot dir→RrdReader. Yes →log_file_from_path+ lenses; the reader produces the chunks, you do not.reader.stream() - No, and it is genuine external metadata (JSON calibration, offsets) or a specific custom use case that can't be covered by a generic reader**→** .
Chunk.from_columns - Otherwise: consider if you are about to hand-build something a reader or lens should produce and ask for clarification.
For MCAP specifically: a Foxglove- or ROS-decodable file emits archetypes like , , and for certain supported message schemas ready-made — pass those through, never re-derive them; only custom protobuf signal topics need lenses. The full decision tree and the anti-pattern list are in .
Transform3DPinholeVideoStreamrerun-chunk-processing建模决定每个数据项的最终形态;而机制决定实现方式——默认方案是读取器+镜头,而非手动构建块:
- 该数据源是否已有对应的读取器? MCAP→,URDF→
McapReader,parquet→UrdfTree,RRD→ParquetReader,LeRobot目录→RrdReader。是 → 使用log_file_from_path+镜头;读取器会生成块,无需手动构建。reader.stream() - 否,且属于真实的外部元数据(JSON校准数据、偏移量)或无法通过通用读取器覆盖的特定自定义场景**→** 使用。
Chunk.from_columns - 其他情况:考虑是否要手动构建读取器或镜头本应生成的内容,并请求澄清。
针对MCAP的特殊说明:可被Foxglove或ROS解码的文件会为某些受支持的消息模式直接生成、、等原型——直接传递这些内容即可,切勿重新推导;仅自定义protobuf信号主题需要使用镜头。完整的决策树和反模式列表请参阅。
Transform3DPinholeVideoStreamrerun-chunk-processingThe model
数据模型
Dataset → Segment → Layer → Recording → Entity → Component → Chunk- Entity = a thing, named by a path (). Component = one typed field on it (positions, image, a scalar). Archetype = a standard bundle of components that log and render together (
/robot/arm/camera,Points3D,Image).Transform3D - Every value you log sits on two axes: where (entity path + component) and when (which timeline, or static = all time).
- Segment = one episode; on registration its becomes the
recording_id. Layer = an extrasegment_idon top of a segment. It attaches by matching the segment's.rrdand nothing else: that shared id is the whole layering mechanism.recording_id
Dataset → Segment → Layer → Recording → Entity → Component → Chunk- Entity(实体) = 一个事物,由路径命名(如)。 Component(组件) = 实体上的一个类型字段(位置、图像、标量)。 Archetype(原型) = 一组可协同记录和渲染的标准组件集合(如
/robot/arm/camera、Points3D、Image)。Transform3D - 你记录的每个值都位于两个维度上:位置(实体路径+组件)和时间(所属时间线,或_static_=全时段)。
- Segment(片段) = 一个片段;注册时其会成为
recording_id。Layer(层) = 附加在片段之上的额外.rrd文件。它通过匹配片段的segment_id进行关联:共享ID是唯一的分层机制。recording_id
The decisions
决策规则
Entity vs component on an existing entity
New entity if it has its own spatial frame (/), its own annotation context, or should be shown/cleared/shared independently (each robot link, each camera, each sensor). Same entity + extra component for auxiliary data at the same instances (per-point confidence).
Use for non-standard fields.
Transform3DPinholeAnyValuesProperty vs component vs layer (the most common confusion)
- Component: per-timestamp signal on the timeline (joint angle, image).
- Segment property: one-per-episode metadata for catalog filter/search (operator, robot, site, task, date). Not per timestamp.
- Layer: a whole derived over a base segment (FK transforms, point clouds, gripper state, labels, quality scores). Queryable as if part of base.
.rrd
Static vs temporal
Static belongs to all timelines and shadows any temporal value of the same component on the same entity. Use it for invariants (calibration, coordinate frames, robot meshes, annotation context, a video asset). Never make per-frame data static.
Which timeline
A timeline (ns since epoch) for cross-sensor clock alignment, a timeline for frame/ordinal alignment; stamp on both when useful.
Do not resample to a common rate. Latest-at reconciles multi-rate streams at query time by holding each component's last sample (no interpolation).
timestampsequenceBase vs layer
Base = faithful conversion of the raw streams, nothing computed.
Layer = anything derived (FK from URDF + joint states, clouds from depth + intrinsics).
Keep them separate s.
.rrd实体 vs 现有实体上的组件
如果新对象拥有自己的空间坐标系(/)、自己的标注上下文,或需要独立显示/清除/共享(每个机器人连杆、每个摄像头、每个传感器),则创建新实体。若为同一实例的辅助数据(如逐点置信度),则使用同一实体+额外组件。非标准字段使用。
Transform3DPinholeAnyValues属性 vs 组件 vs 层(最易混淆的点)
- 组件:时间线上的每时间戳信号(关节角度、图像)。
- 片段属性:每个片段的元数据,用于目录过滤/搜索(操作员、机器人、场地、任务、日期)。不属于每时间戳数据。
- 层:基于基础片段生成的完整衍生.rrd文件(FK变换、点云、夹具状态、标签、质量分数)。可像基础片段的一部分一样被查询。
静态 vs 时间相关
静态数据属于所有时间线,会覆盖同一实体上同一组件的任何时间相关值。用于不变数据(校准信息、坐标系、机器人网格、标注上下文、视频资产)。切勿将每帧数据设为静态。
选择哪个时间线
使用时间线(纪元以来的纳秒数)实现跨传感器时钟对齐,使用时间线实现帧/序号对齐;必要时可同时使用两个时间线。
不要重采样到统一速率。查询时,Latest-at机制会通过保留每个组件的最新样本(无插值)来协调多速率流。
timestampsequence基础 vs 层
基础 = 原始流的忠实转换,无任何计算内容。
层 = 任何衍生内容(URDF+关节状态的FK变换、深度图+内参生成的点云)。
将它们保存为独立的.rrd文件。
The mapping table (produce before coding)
映射表(编码前填写)
| Source (topic/column/key) | Entity path | Archetype | Component(s) | Timeline | Static/temporal | Base/layer | Property? |
|---|---|---|---|---|---|---|---|
mcap | | | | | temporal | base | no |
| | | codec+sample | | codec static, samples temporal | base | no |
| | | | — | static | base | no |
| URDF + joints (computed) | | | translation/rotation | | temporal | layer | no |
| segment | — | — | — | — | — | yes |
| 来源(主题/列/键) | 实体路径 | 原型 | 组件 | 时间线 | 静态/时间相关 | 基础/层 | 是否为属性 |
|---|---|---|---|---|---|---|---|
mcap | | | | | 时间相关 | 基础 | 否 |
| | | codec+sample | | codec为静态,样本为时间相关 | 基础 | 否 |
| | | | — | 静态 | 基础 | 否 |
| URDF + 关节(计算生成) | | | translation/rotation | | 时间相关 | 层 | 否 |
| segment | — | — | — | — | — | 是 |
Patterns worth knowing
值得了解的模式
- Transforms / FK trees: log a per link entity; it relates to the parent path and composes down the tree. (Named
Transform3D+CoordinateFrame/child_frameonly when topology must be a flexible graph.)parent_frame - Cameras: extrinsics () + intrinsics (
Transform3D) on the camera entity, image/depth as children so they inherit the projection.Pinhole - Video: for compressed samples — the default for an mp4 (
VideoStream) and what the Foxglove decoder already hands you.rerun-mp4+AssetVideois the fallback for a codecVideoFrameReferencecannot represent.VideoStream - Columnar ingest: for an existing file, use the matching reader (/
rerun-mcap/-parquet/-mp4), which produces chunks directly — do not hand-assemble-lerobotfrom a custom parser. When you do log columns directly (live logging),send_columnsadds no automatic timelines, so pass every timeline you want.send_columns
- 变换/FK树:为每个连杆实体记录一个;它与父路径关联,并沿树向下组合。(仅当拓扑必须为灵活图时,才使用
Transform3D+CoordinateFrame/child_frame。)parent_frame - 摄像头:在摄像头实体上记录外参()+内参(
Transform3D),图像/深度作为子实体,以便继承投影关系。Pinhole - 视频:使用处理压缩样本——这是mp4文件的默认方式(
VideoStream),也是Foxglove解码器直接输出的格式。若rerun-mp4无法表示对应编码格式,则使用VideoStream+AssetVideo作为备选方案。VideoFrameReference - 列式导入:对于现有文件,使用匹配的读取器(/
rerun-mcap/-parquet/-mp4),它会直接生成块——不要通过自定义解析器手动组装-lerobot。当直接记录列数据(实时记录)时,send_columns不会自动添加时间线,因此需要传入所有所需的时间线。send_columns
Gotchas that cause real failures
会导致实际故障的陷阱
- Component columns come back as in queries: index
ListArray/[0](0-based DataFrame, 1-based SQL). See[0][0].rerun-catalog-queries - A layer must share the segment's , or it won't attach.
recording_idis discarded on registration.application_id - /
send_columnsadd nosend_chunks/log_time; only the timelines you pass exist.log_tick - Static shadows all temporal data of that component for all time; static is overwritten in the viewer but every write stays on disk until .
rerun rrd optimize - One /
Transform3Drelation per frame pair; logging the same relation on a second entity is rejected.Pinhole - Entity paths are not file paths (is meaningless,
..is reserved).__ - A catalog layer written with a default injects a
RecordingStream(/__properties) chunk that can collide with the base segment's properties when the catalog merges layers byRecordingInfo; the dataset's default blueprint then stops applying on open. Construct the layer's stream withrecording_id.send_properties=False
- 查询中组件列会以形式返回:使用索引
ListArray/[0](DataFrame为0索引,SQL为1索引)。请参阅[0][0]。rerun-catalog-queries - 层必须与片段共享,否则无法关联。注册时
recording_id会被丢弃。application_id - /
send_columns不会添加send_chunks/log_time;仅存在你传入的时间线。log_tick - 静态数据会覆盖该组件所有时间的时间相关数据;静态数据在查看器中可被覆盖,但所有写入内容会保留在磁盘上,直到执行。
rerun rrd optimize - 每对帧仅能记录一个/
Transform3D关系;在第二个实体上记录同一关系会被拒绝。Pinhole - 实体路径不是文件路径(无意义,
..为保留字符)。__ - 使用默认编写的目录层会注入一个
RecordingStream(/__properties)块,当目录按RecordingInfo合并层时,该块可能与基础片段的属性冲突;此时数据集的默认蓝图在打开时将不再生效。请使用recording_id构建层的流。send_properties=False