mcpField
R
rerun-lerobot

rerun-lerobot

github.com/rerun-io数据与数据库11.7k120 次安装今天更新
代码仓库

关于 rerun-lerobot

rerun-lerobot 是处理 LeRobot 数据集的 Rerun 技能,面向查看数据或将其转换为按 episode 划分的 RRD。它介绍内置导入器与惰性 LeRobotReader 的不同用途,并涵盖数据下载、拆分和机器人模型接入。

主要功能

  1. 01使用内置导入器查看数据集
  2. 02惰性读取并逐 episode 写入 RRD
  3. 03下载并校验指定 episode
  4. 04将 URDF 关节映射到状态数据

适用场景

  1. 01在 Viewer 中浏览 LeRobot 数据集
  2. 02将 episode 分别导出为 RRD
  3. 03为 episode 数据添加机器人运动学模型

MCP 相关

说明可通过 MCP 的 open_url 打开数据集目录供查看;未描述 MCP 服务端功能。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/rerun-io/rerun --skill rerun-lerobot

安装后在 Claude Code 中输入/rerun-lerobot确认已加载。

附带文件scripts/fetch_lerobot_episodes.pyscripts/find_lerobot_dataset.py

详细介绍

Rerun LeRobot 数据导入

有两种方式,具体选择取决于你是要查看还是转换。

  • 只是查看? Rerun 内置了 LeRobot 导入器:将 log_file_from_path(或查看器,或命令行中的 rerun <dir>)指向数据集 目录,即可导入各个 episode、摄像头视频以及状态/动作表,无需编写转换代码。
  • 要转换? rr.experimental.LeRobotReader 会一次读取一个 episode,并以惰性分块流的形式提供数据,适用于按 episode 生成 RRD 和使用 lenses。

下载步骤需要 huggingface_hub。

步骤 0:选择数据集并检查 HF 令牌

下面两个脚本都位于此文件旁边的 scripts/ 目录中,可通过 uv 独立运行——它们在内联声明了 huggingface_hub,因此无需设置环境。

有两个因素决定获取数据集的成本,而 Hub 搜索结果不会显示这两项。 对每个候选数据集,通过一次调用获取这两项:

uv run scripts/find_lerobot_dataset.py <query> --robot-type <robot> --want 5

codebase_version 决定能否进行部分下载。

  • v2.1 及更早版本会为每个 episode 存储一个 parquet 和一个 mp4(video_path 以 episode_{episode_index:06d}.mp4 结尾),因此“只下载前 N 个 episode”只会下载这些 episode。
  • v3.0会将所有 episode 合并到少数几个大文件中(video_path 以 file-{file_index:03d}.mp4 结尾),因此下载任何子集都需要下载全部内容。 如果用户只需要几个 episode,下载时优先选择 v2.1 数据集。 文件下载到本地后,LeRobotReader 可以从任一版本中读取单个 episode。

摄像头帧的存储方式决定数据集大小,两者可能相差两个数量级。 frames 和 MB/ep 列会显示大小:

  • mp4:video 类型特征,每个 episode 的 parquet 旁边都有一个文件。
  • inline:image 类型特征,原始帧存储在 episode parquet 中,相同视频素材会占用大得多的空间。

两个脚本都会报告当前数据集的实际大小,因此请以该数值为准,而不要猜测。 开始下载前告知用户数据集大小;除非用户要求的内容只有另一种格式才有,否则优先选择 mp4。

公开数据集不需要 HF_TOKEN,但未设置该令牌时,Hub 会限制请求速率并对下载进行限流。 如果未设置,请告知用户,并引导他们前往 https://huggingface.co/settings/tokens 创建读取令牌,然后运行 export HF_TOKEN=hf_…(或 hf auth login)。 不要因此阻塞流程——继续以未认证状态操作,由用户决定是否设置令牌。

[ -n "$HF_TOKEN" ] || echo "HF_TOKEN unset — downloads will be throttled"

步骤 1:数据集 -> 一个合并的 RRD

仅当你希望将所有 episode 放在一个文件中时才需要此步骤——例如将单个 RRD 交给他人,或重新处理无法从数据集目录重新读取的数据。 如需按 episode 分段,请跳至步骤 2,让 LeRobotReader 直接读取数据集。

from huggingface_hub import snapshot_download
import rerun as rr

dataset_dir = snapshot_download(repo_id=repo_id, repo_type="dataset", local_dir=dest)

with rr.RecordingStream("rerun_example_lerobot") as rec:
    rec.save(str(combined_rrd))
    rec.log_file_from_path(str(dataset_dir))  # the built-in importer

导入器会为每个 episode 输出一条 recording(recording id 类似 episode_1),并输出一条仅含元数据的根 recording,全部写入同一个 RRD。

这里的 rr.RecordingStream + log_file_from_path 是导入器引导流程——在摄取管线中,只有这里适合使用 RecordingStream(它用于驱动内置导入器,而非逐消息记录)。不要将其泛化为逐消息调用 rr.log 的循环;导入之后的所有处理,都应使用 reader + lenses 重新处理(参见 rerun-chunk-processing:Chunk API 与 logging API)。

仅下载前几个 episode
uv run scripts/fetch_lerobot_episodes.py <repo_id> --episodes 5   # prints the dataset directory

脚本会在开始前报告下载大小,下载 meta/* 和所需的 episode_%06d 文件,将 meta/ 精简到与之匹配,验证恰好下载了请求的 episode,并打印下载结果。 最后一行是数据集目录;后面不要再接 find 或 du。 手动执行同样的操作时,以下三件事容易出问题:

  • 导入器会遍历 meta/ 中的 episode 列表,因此未精简的 meta/ 会针对每个缺失的 episode 发出一次警告。
  • snapshot_download 会写入现有目录,因此先前以不同 N 运行时留下的 episode 会继续保留,导致结果变大。
  • 只有在查看器中统计录制数量时才会发现这两种问题,这就是脚本会进行断言,而不是让你自己查看的原因。
只是想在查看器中查看?

完全跳过 RRD——查看器会直接导入数据集目录。 传入普通路径(rerun /path/to/dataset,或通过 MCP 调用 open_url)。 每个 episode 都会作为单独的录制加载,recording_id 分别为 episode_0、episode_1、……。

第 2 步:每个 episode 一个 RRD

目录分段采用每个文件一个录制的方式,注册时 recording_id 会成为分段 ID。

LeRobotReader 会直接读取这些文件,无需先构建第 1 步中的合并 RRD:

reader = rr.experimental.LeRobotReader(dataset_dir)  # v2 or v3
for episode in reader.episodes():
    episode_id = f"episode_{episode:05d}"  # zero-padded; see below
    reader.stream(episode).write_rrd(
        rrd_dir / f"{episode_id}.rrd",
        application_id="my_dataset",
        recording_id=episode_id,
    )

整个流程采用惰性流式处理,因此内存占用取决于分块大小,而不是 episode 或数据集的大小;视频也会裁剪到 episode 的时间窗口。 不含 B 帧的视频(AV1,即 LeRobot 的默认编解码器)会直接流式处理;必须重新编码的流——带 B 帧的 H.264,或从 GOP 中间开始的窗口——需要将 ffmpeg 放在 PATH 中。 stream() 还支持 entity_path_prefix、timeline 和 video_mode="skip",可完全丢弃视频。

如需添加镜头、丢弃主题或修正数据,请在流与写入之间加入相应处理——参见 rerun-chunk-processing。

拆分已有的 RRD

如果第 1 步生成的合并 RRD 已经存在——或者数据来自数据集目录以外的地方——可以改用 RrdReader 拆分:

reader = rr.chunk.RrdReader(str(combined_rrd))
for entry in reader.recordings():
    store = reader.store(store=entry)
    if not store.schema().entity_paths():  # skip the metadata-only root recording
        continue
    episode_id = zero_pad(entry.recording_id)  # episode_1 -> episode_00001
    with rr.RecordingStream("rerun_example_lerobot", recording_id=episode_id, send_properties=False) as rec:
        rec.save(str(rrd_dir / f"{episode_id}.rrd"))
        rec.send_chunks(store)

有两点不太显而易见:

  • 为 episode ID 补零。 按字典序,episode_10 会排在 episode_2 前面;分段表和查看器也按字典序排序。重新分配 recording_id 时,请补零到固定宽度。
  • 在新流上设置 send_properties=False,避免副本在复制的分块上注入新的录制属性。

send_chunks 不会保留源存储的身份;新流的 recording_id 优先生效,这正是重命名能够奏效的原因。

如果需要清理 episode(丢弃主题、修正数据、添加派生组件),请在读取与写入之间使用镜头处理存储:reader.stream(store=entry).drop(...).lenses(...),然后调用 collect().write_rrd(..., recording_id=episode_id)(参见 rerun-chunk-processing)。

之后,计算层和每个 episode 的属性都遵循 rerun-data-model 中的标准模式(层的 recording_id 必须与 episode 分段 ID 相同)。

步骤 3:添加机器人模型(URDF)

LeRobot 数据集提供的是关节值,而不是机器人。 没有 URDF,你只能看到摄像头画面和关节曲线,却看不到 3D 机械臂;这通常不是用户提出查看数据时所期望的效果。 添加 URDF 相当于增加一层正向运动学——这由 rerun-urdf 负责;本节只介绍 LeRobot 特定的接线方式。

  • URDF。 meta/info.json 中的 robot_type 指定了它(so100、so101、aloha 等);rerun-urdf 中有对应的源表。
  • 关节名称。 meta/info.json 中的 features.observation.state.names 按列顺序列出了这些名称。 将每个源名称明确映射到对应的 URDF 关节名称;不要假设去掉前缀后就能得到有效的 URDF 名称。
  • 数值。 observation.state 是测得的姿态,应在其上运行 FK;action 是命令姿态,应显示在曲线上,而不是机器人模型上。
  • 单位和校准。 对照数据集和机器人文档确认单位、正负方向和偏移量。 在信任姿态之前,先用 rerun-urdf 的 check_joint_mapping.py 检查各 episode 的 parquet 文件。

FK 数据源是每个 episode 的 parquet 文件,直接读取,而不是从导入后的 RRD 中读取:

ParquetReader(str(episode_parquet)).stream(
    column_grouping="individual",
    index_columns=[IndexColumn.sequence("frame_index")],
).drop(content="/__properties/**")

frame_index 也是导入器使用的索引,因此 FK 变换会与视频和曲线对齐。 将 URDF 模型流和 FK 流合并到每个 episode 的 RRD 中,并保留该 episode 的 recording_id(参见 rerun-urdf 的“Minimal shape”)。 对于整个数据集,应将模型放在共享资源中,而不是每个片段都放一份——另请参阅 rerun-urdf。

注意事项

  1. log_file_from_path 的目标必须是数据集根目录,而不是其中的某个文件。LeRobotReader 也是如此。
  2. 未补零的 episode ID 在后续排序时会出错;注册前应先补零。
  3. 合并后的 RRD 包含一个仅含元数据的根 recording;跳过没有实体路径的存储,否则会注册一个空片段。
  4. 部分下载的数据集可以正常导入,但对于 meta/ 中列出、磁盘上却缺失的每个 episode,都会发出一次警告。
  5. 将子集下载到之前运行已经写入内容的目录中,会保留旧 episode;请从空目录开始。
  6. 每个 episode 的 image 类型(内嵌)数据集可能比 mp4 数据集大约 100 倍;应在下载前检查,而不是下载后检查。
  7. 检查正负方向和单位——例如,以度为单位的 observation.state 输入到要求弧度的机器人模型中,可能会导致 FK 错误。

参考资料

  • rerun-chunk-processing(LazyChunkStream、lenses、RrdReader)
  • rerun-urdf(添加机器人模型和关节值映射)
  • https://github.com/rerun-io/rerun/tree/main/examples/python/dataloader 中的 prepare_dataset.py(下载 → 导入 → 拆分 → 注册,完整且可运行)和 train.py(通过 rerun.experimental.dataloader 在训练侧读取数据)

评论

支持 Markdown