Rerun 内置 LeRobot 数据集导入器:零代码可视化多模态机器人数据
2026/9/17 17:57:22 网站建设 项目流程

Rerun 内置 LeRobot 数据集导入器:零代码可视化多模态机器人数据

【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun

导读

LeRobot 是 Hugging Face 推出的开源机器人数据格式,广泛用于具身智能与多模态机器人数据集(如 SmolVLA 所用的数据集)。Rerun 在re_importer中内置了 LeRobot 数据集导入器,用户只需把 Viewer 指向一个 LeRobot 数据集目录,即可像打开普通录制文件一样浏览其中的多路相机图像、深度图、视频流、标量状态与语言标注。本文以 examples/python/lerobot_loader/README.md 为主体,结合仓库内 re_lerobot 与 re_importer 的源码实现,带你从"下载一个数据集、一行命令打开"到"理解底层加载链路与格式支持边界",掌握在 Rerun 中使用 LeRobot 数据的完整方法。

快速上手:把 LeRobot 数据集目录当作一个录制文件

Rerun 对 LeRobot 数据集的加载体验与其他录制格式(.rrd.mcap)对齐:你不需要写任何 Python 或 Rust 代码,Viewer 会识别目录结构并自动切换导入器。

获取一个示例数据集

README 中给出的示例来自 SmolVLA 博客中使用的数据集satvikahuja/mixer_on_off_new_1(托管在 Hugging Face Hub 上)。由于数据集文件由 Git LFS 管理,需要先确保 LFS 可用:

git lfs install # If not already installed git clone https://huggingface.co/datasets/satvikahuja/mixer_on_off_new_1

说明:仓库源码 importer_lerobot.rs 的文档注释中还提到了另一个常用示例数据集lerobot/pusht_image,同样可以直接用于体验本功能。

两种打开方式

方式一:在 Rerun Viewer 中点击打开文件,选择刚才克隆下来的目录即可加载。

方式二:直接从终端把目录路径作为参数传给rerun命令:

rerun mixer_on_off_new_1

命令行参数的形式与加载其他录制文件完全一致,区别仅在于传入的是一个目录而不是文件。这正是 README 中强调的"像加载一个 rerun 文件一样"的体验。

SDK 能力对齐:目录即录制

README 的 "SDK support" 一节指出:由于该导入器是内置的,其他 SDK 功能(如播放、查询、导出、时间轴导航等)对 LeRobot 数据集同样生效,只是把"文件路径"换成了"目录路径"。从实现看,导入器会把每个 episode 包装为一个独立的 recording(store),因此你可以在 Viewer 的录制切换器中逐个回放 episode。

底层机制:导入器如何识别一个 LeRobot 数据集

目录级路由:DirectoryImporter 的委托逻辑

Rerun 的目录导入由 DirectoryImporter 负责。它先判断路径是否为目录,然后检查是否为 LeRobot 数据集:如果是,就返回Incompatible并交由专门的LeRobotDatasetImporter处理,从而避免把 LeRobot 目录当作普通文件目录逐个递归导入:

// LeRobot datasets are loaded by LeRobotDatasetImporter. #[cfg(feature = "lerobot")] if crate::is_lerobot_dataset(&dirpath) { return Err(crate::ImporterError::Incompatible(dirpath.clone())); }

从 lib.rs 可以看出,LeRobotDatasetImporterRrdImporterDirectoryImporterMcapImporterParquetImporter等并列注册在内置导入器列表中(BUILTIN_IMPORTERS),且仅在启用lerobotfeature 且非 wasm 目标时编译。

版本识别:v1 / v2 / v3

lib.rs 中的LeRobotDatasetVersion::find_version负责判定数据集格式版本,规则非常直观(基于目录结构,而非文件内容):

版本判定条件说明
v1存在非空的meta_data/data/子目录旧格式,元数据目录名为meta_data导入器已明确不支持
v2存在非空的meta/data/子目录元数据目录为meta
v3在 v2 基础上额外要求meta/episodes/目录存在每集元数据存放在meta/episodes/

is_lerobot_dataset只要命中上述任一版本即返回 true。当find_version识别到 v1 时,importer_lerobot.rs 会直接打印"LeRobot 'v1.x' dataset format is unsupported."并跳过加载;v2/v3 才真正进入load_dataset流程。

支持的目录结构与元数据格式

v2 数据集布局

datasetv2.rs 中给出了标准的 v2 目录结构:

. ├── README.md ├── data │ └── chunk-000 │ ├── episode_000000.parquet │ ├── episode_000001.parquet │ ├── … ├── meta │ ├── episodes.jsonl │ ├── info.json │ ├── stats.json │ └── tasks.jsonl └── videos └── chunk-000 └── observation.image ├── episode_000000.mp4 ├── episode_000001.mp4 ├── …

各目录/文件职责:

  • data/:以 Parquet 格式存储每集数据,按 chunk 分目录;
  • meta/info.json:数据集全局元数据(机器人类型、总集数、总帧数、总任务数、总视频数、每 chunk 集数、fps、feature 定义、data_path/video_path路径模板等);
  • meta/episodes.jsonl:逐行存储每集元数据(episode_index、关联任务列表、帧数);
  • meta/tasks.jsonl:任务定义;
  • meta/stats.json:feature 汇总统计;
  • videos/:可选目录,按与data/相同的 chunk 组织存放视频观察数据。

路径模板中的{episode_chunk:03d}{episode_index:06d}会被替换为实际数值,用于定位episode_000000.parquetepisode_000000.mp4这类文件。

v3 数据集布局

datasetv3.rs 描述了 v3 的结构差异——每集元数据改为 Parquet 文件、任务与子任务也以 Parquet 存储:

. ├── README.md ├── data/ │ └── chunk-000/ │ ├── episode_000000.parquet │ ├── episode_000001.parquet │ └── … ├── meta/ │ ├── episodes/ │ │ └── chunk-000/ │ │ ├── file-000.parquet │ │ ├── file-001.parquet │ │ └── … │ ├── tasks.parquet │ ├── stats.json │ └── info.json └── videos/ └── chunk-000/ └── observation.image/ ├── episode_000000.mp4 ├── episode_000001.mp4 └── …

v3 的关键差异:

  • meta/episodes/中的每集元数据文件同时记录了该集主数据文件的位置(data/chunk_indexdata/file_index)以及每个视频/图像 feature 各自独立的文件位置(列名形如videos/{feature_name}/chunk_indexvideos/{feature_name}/file_index,以及from_timestamp/to_timestamp),这意味着多个 episode 可以高效共享同一个视频文件;
  • 任务定义从 JSONL 换成tasks.parquet(任务名列兼容task与旧版__index_level_0__两种命名,见TASK_COLUMN_NAMES);
  • 可选的subtasks.parquet用于子任务(subtask)标注,存在时才加载。

数据模型:Feature、DType 与时间线

Feature 与 DType

meta/info.json中的features映射定义了每个数据通道的类型与形状。在 lib.rs 中,Feature由三部分组成:

  • dtype:数据类型,支持VideoImageBoolFloat32Float64Int16Int64StringLanguage
  • shape:数据维度,例如[3, 224, 224]表示 3 通道(RGB)、224×224 的图像;
  • names:可选的维度名元数据,支持多种 JSON 表示(见下)。

channel_dim()方法用于推断通道数:优先查找名为channels的维度,找不到则取 shape 的最后一维。加载时按通道数分流:1 通道 → 深度图(DepthImage),3 通道 → 普通图像(EncodedImage),其他通道数会被warn_once告警并跳过。

names的四种合法 JSON 形态(见 lib.rs 的NamesVisitor及其单元测试):

"img_state_delta" // 单字符串 ["x", "y", "z"] // 扁平字符串数组 [["kLeftShoulderPitch", "kLeftShoulderRoll"]] // 嵌套字符串数组 {"motors": ["motor_0", "motor_1"]} // 单键对象(值可为数组或 null)

如果names存在,导入器会为标量 feature 额外生成一个静态名称 chunk(SeriesLines名称),方便 Viewer 中的曲线图直接显示各关节/轴的名字。

时间线推导

common.rs 中的derive_timeline决定每个 episode 使用哪条时间线:

  • 若数据中存在frame_index列 → 使用序列时间线frame_index
  • 否则若存在timestamp列 → 使用持续时间时间线timestamp(秒,转换为纳秒);
  • 两者皆无则报错。

与此同时,LEROBOT_DATASET_IGNORED_COLUMNS定义了不会被可视化的元数据列:episode_indexindexframe_indextimestamp——它们只服务于分集与时间线,而不是实体数据。

各类 feature 的映射规则

结合build_plan(分别在 datasetv2.rs 与 datasetv3.rs 中),各 dtype 的落地方式如下:

dtype处理方式
Videov2:整段视频作为静态AssetVideo资产,并尝试读取帧时间戳生成VideoFrameReference;v3:按该集的from_timestamp~to_timestamp区间切出VideoStream(codec + samples),采样点均匀映射到帧时间线
Imagechannel_dim分流:1 通道 →DepthImage,3 通道 →EncodedImage,其他通道数告警跳过
Float32/Float64标量 feature,转为Scalars曲线数据(形状为列表/定长列表时,先抽取元素再转 f64)
Int64且键为task_index渲染为task文本实体(TextDocument),把tasks.jsonl/tasks.parquet中的任务描述按帧写入
Int64且键为subtask_index(仅 v3)渲染为subtask文本实体
Languagev3 支持:language_persistent(持久化、带时间戳、广播到匹配帧)与language_events(事件、仅落在发射帧),按style/role/camera分段生成实体路径,tool_calls渲染到…/tool_calls子实体;v2 不支持并直接报错(有对应回归测试test_v2_language_dtype_is_rejected
Int16/Int64/Bool/String(其余场景)尚未实现,warn_once告警并跳过

性能与缓存设计:v3 的流式加载优化

对于动辄数 GB 的机器人数据,导入器在 v3 上做了明显的性能优化(见 datasetv3.rs):

  • Episode 数据缓存(episode_data_cache:打开数据集时按"文件→episode"分组,把同一 Parquet 文件一次性读入并拼接(concat_batches),再通过build_episode_row_index单遍扫描episode_index列构建行区间索引,按需切片出每个 episode 的RecordBatch。多个 episode 共用文件时只读一次磁盘。
  • 视频引用计数缓存(VideoBlobCache:视频 blob 懒加载(fs::read一次后缓存为Arc<[u8]>),并用remaining_refs统计每个视频文件仍被多少个 episode 引用;某集加载完成(或失败)后调用release_episode_videos递减引用,计数归零即从缓存中淘汰,从而在流式加载多集时控制内存峰值。
  • 有序遍历:episode 元数据用有序 map 存储,iter_episode_indices保证按索引升序返回——导入器会为每个 episode 广播一个 recording,有序遍历保证 Viewer 中 episode 顺序稳定(对应测试episode_indices_iterate_in_ascending_order)。

加载流程本身是异步的:importer_lerobot.rs 会在专用 IO 线程上执行load_and_stream_versioned,逐集生成SetStoreInfo与数据 chunk 并通过 crossbeam channel 发回,避免阻塞 rayond 线程池。

使用约束与注意事项

  1. v1 数据集不支持:仅 v2(含 v2.1)与 v3 可加载,v1 会被明确拒绝。
  2. lerobotfeature 开关:LeRobot 导入器以 Cargo feature 形式编译(#[cfg(feature = "lerobot")]),且不适用于 wasm 目标;桌面版/服务端构建默认启用。
  3. 图像通道数限制:仅 1 通道(深度)与 3 通道(RGB)图像会被渲染,其余通道数告警跳过。
  4. 部分 dtype 尚未落地Int16/Int64/Bool/String(非task_index/subtask_index场景)与 v2 的Language目前不会可视化,加载时会有warn_once提示。
  5. SDK 语义对齐:由于每个 episode 映射为一个独立 recording,SDK 中针对录制文件的查询、导出与回放能力均可直接用于 LeRobot 目录,无需额外适配。

延伸阅读

  • 示例文档:examples/python/lerobot_loader/README.md
  • 核心 crate 说明:crates/data_flow/re_lerobot/README.md
  • 数据集解析与 chunk 生成:lib.rs、common.rs
  • 各版本格式实现:datasetv2.rs、datasetv3.rs
  • 导入器注册与目录路由:importer_lerobot.rs、importer_directory.rs、lib.rs

【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询