关于 rerun-lerobot
rerun-lerobot 是处理 LeRobot 数据集的 Rerun 技能,面向查看数据或将其转换为按 episode 划分的 RRD。它介绍内置导入器与惰性 LeRobotReader 的不同用途,并涵盖数据下载、拆分和机器人模型接入。
主要功能
- 01使用内置导入器查看数据集
- 02惰性读取并逐 episode 写入 RRD
- 03下载并校验指定 episode
- 04将 URDF 关节映射到状态数据
适用场景
- 01在 Viewer 中浏览 LeRobot 数据集
- 02将 episode 分别导出为 RRD
- 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。
注意事项
log_file_from_path的目标必须是数据集根目录,而不是其中的某个文件。LeRobotReader也是如此。- 未补零的 episode ID 在后续排序时会出错;注册前应先补零。
- 合并后的 RRD 包含一个仅含元数据的根 recording;跳过没有实体路径的存储,否则会注册一个空片段。
- 部分下载的数据集可以正常导入,但对于
meta/中列出、磁盘上却缺失的每个 episode,都会发出一次警告。 - 将子集下载到之前运行已经写入内容的目录中,会保留旧 episode;请从空目录开始。
- 每个 episode 的
image类型(内嵌)数据集可能比mp4数据集大约 100 倍;应在下载前检查,而不是下载后检查。 - 检查正负方向和单位——例如,以度为单位的
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在训练侧读取数据)