数据采集
EVA将遥操作采集与推理运行写为LeRobot v2.1数据集。
两种录制方式,一种格式
两条路径产出同一种数据集,均可通过dataset传输层回放。两者只在每帧记录的内容上不同。
- 遥操作采集——主端设备驱动机器人,EVA同时记录机器人位姿和下达的动作。在COLLECT中运行,由配置中的采集schema开启。
- 推理运行——训练好的策略驱动机器人,EVA记录机器人位姿并与策略实际下发的动作配对。这正是SFT所读取的内容。
hardware 层,内核只负责记录数据。若采集时需要实时 IK/FK,可在 hardware 层直接调用内核的 IK/FK 求解。待方案整理成熟后,后续版本会把采集的实时 IK/FK 逐步收入核心代码。录制前的准备
- 已安装EVA——终端可解析
eva命令。 - 机器人在线连接——已上电,可通过
ros1、ros2或zmq连通。纯数据集配置无法采集。 - 遥操作设备——主端已连接并在发布数据。
- 一份采集配置——定义了采集schema。示例位于
configs/02_collection/。
填写采集配置
一旦配置列出要保存的数据列(collection.schema.columns),它就成为采集配置。EVA启动时校验schema,若缺少任何必填项就拒绝启动。
| 区块 | 用途 |
|---|---|
storage | 输出文件夹(log_dir)、目标fps,以及后台保存队列深度(save_queue_max)。 |
schema | 每帧内容:机器人类型、最短episode长度、各手臂、各相机、输出列名。 |
transport | 要读取的在线数据流。每只手臂指明携带其位姿与下达动作的流。 |
tasks | 录制时可选的指令。每个任务独立成一份数据集文件夹。 |
schema内部:
- arms把每只手臂映射到一个简短前缀(如
left),用于left.j0、left.gripper等逐关节列名。 - cameras把每个相机映射到其在数据集中的视频名。
- columns为四个字段命名:
qpos、eef、action_qpos、action_eef。 - min_episode_frames设定不被标记的最短episode长度;更短的录制会被标记供复核。
eef每只手臂八个数:位置(x y z)、旋转四元数(qw qx qy qz)、夹爪开合。请从configs/02_collection/下对应示例开始,修改标注的值。除非训练流程要求不同列名,否则保留示例列名——它们是数据集的约定:
_base_ = ['../01_deploy/<你的机器人>/_base.py'] # ← 复用你机器人的部署配置 collection = dict( storage=dict( log_dir='<输出文件夹>', # ← 数据集写到哪里;留空则为 work_dirs/<配置文件名> fps=30, # 目标帧率(合理默认;慢任务可调低) save_queue_max=15, # 最多允许几个录完的 episode 排队保存 ), schema=dict( robot_type='<你的机器人类型>', # ← 例如 agilex_AGILEX min_episode_frames=10, # 更短的录制会被打上 'episode_too_short' 标记 arms=dict(left_arm='left', right_arm='right'), # ← 你的手臂 → 名称前缀 cameras=dict( cam_high='observation.images.cam_high', # ← 你的相机 → 其数据集名 ), columns=dict( # 除非训练另有要求,保留这些列名 qpos='observations.state.qpos', eef='observations.state.eef', action_qpos='action.qpos', action_eef='action.eef', ), ), transport=dict( # ← 指明携带位姿与下达动作的在线数据流 ros1=dict(groups=dict( left_arm=dict( qpos_topic='<机器人关节数据流>', # ← 手臂上报关节的来源 action_qpos_topic='<主臂关节数据流>', # ← 你下达动作的来源 ), )), ), tasks=['<你的任务指令>'], # ← 例如 '拿起苹果' )
若log_dir留空,EVA写入work_dirs/<配置文件名>/。
运行一次采集
用采集配置启动EVA;COLLECT在浏览器中打开:
eva --config configs/02_collection/<你的配置>.py
逐按钮完整流程见COLLECT页。每次录制都在后台流水线上记录,实时采集不卡顿:
- 开始——开始录制,帧缓冲区重置。
- 采集——每帧即时抓取并交后台处理。持续过采时占用内存上升并记一条告警,不会丢数据。
- 就绪前跳过——遥操作链路完成标定前还没有下达动作,这些起始帧被跳过,而不是存成空动作。
- 停止——结束录制,校验每一帧,该episode交后台保存器。零帧录制什么也不写。
- 取消——彻底丢弃当前录制;不写入任何内容。
控制台显示实时状态:采集/保存/空闲、已采帧数、保存队列深度、预计完成保存时间。每次保留的录制都追加到该任务的数据集中;录制绝不会覆盖之前的episode。
_,斜杠转-)。数据落在<log_dir>/<任务名>/。确认采集成功
按STOP后等状态回到空闲。一次成功的录制会新增:
data/chunk-000/下一个新的episode_NNNNNN.parquet;videos/chunk-000/下每个相机一个episode_NNNNNN.mp4;meta/episodes.jsonl中新增一行,带该episode的质量标记。
每行记录该episode的质量:所有帧通过为green,任一失败为red。红色episode仍会保存(坏值已修复,见下文),但应在COLLECT或REPLAY中回放后再决定是否重录。
数据集长什么样
每个任务一个文件夹。episode以六位数字编号(episode_000000……)归入chunk-000。一个chunk上限1000个;EVA只填满第一个。
<log_dir>/<任务名>/ ├── data/ │ └── chunk-000/ │ └── episode_000000.parquet # 主表,每帧一行 ├── videos/ │ └── chunk-000/ │ └── <相机>/ │ └── episode_000000.mp4 # 每个相机一个 mp4 └── meta/ ├── info.json # 数据集元信息:格式版本、fps、各列 ├── episodes.jsonl # 每个 episode 一行:编号、任务、长度、质量 ├── episodes_stats.jsonl # 每个 episode 的统计(仅采集路径) ├── tasks.jsonl # 每个 episode 的任务文本 └── stats.json # 全数据集统计
仓库在examples/agilex_dataset/附带完整示例(双臂AGILEX,三个相机)。
逐帧质量检查
每帧在保存时都会被检查。任一失败将该episode标为red,原因记入episodes.jsonl;否则为green。
| 标记 | 触发条件 |
|---|---|
episode_too_short | 帧数少于min_episode_frames。 |
non_monotonic_timestamp | 采集时间未超过前一帧。 |
missing_camera·invalid_image_shape | 已配置相机没有出帧,或形状不对。 |
missing_configured_column·invalid_vector_dim | 已配置字段缺失,或长度不符。 |
non_finite_value | 字段含无效数值(保存前置零)。 |
frame_count_mismatch | 某相机视频帧数与数据表行数不一致。 |
缺失或长度错误的字段会被替换为正确长度的零值,使表格保持规整;问题被标记。红色episode仍可使用,但值得检查。
时间戳如何记录
LeRobot要求各帧时间完全等间隔。EVA按配置的fps合成正式时间戳,真实采集时间另存入capture_time列以供诊断。
- 数据集中保存的
fps正是配置的目标值,而非测得平均值。 - 测得的平均帧率(抖动)按episode记录,仅供诊断。
- 每个相机视频以同一目标
fps播放,且每行数据严格对应一帧视频。
数据集元信息与统计
数据集定稿时,EVA写入info.json与stats.json:
- 各列描述——每个视频记录尺寸与编码;每个数据字段记录类型与逐元素标签(关节为
<arm>.j0…/<arm>.gripper,末端为<arm>.{x,y,z,qw,qx,qy,qz,gripper})。 - 统计——逐特征的min/max/mean/std,先按episode计算再汇总。训练工具用其归一化。
- 任务——每个episode的指令文本。
把推理运行作为数据集
推理运行录制同样的格式,有两点不同:
- 每行将机器人状态与策略实际下发的动作配对——每个执行步一行。若部署也跟踪末端位姿,则作为第二列状态保存;纯关节运行则省略。
- 评测运行在按STOP时立即保存,使试验可马上评分。分数存于数据集元信息中,绝不作为数据列。对同一「提示词+试验序号」组合的重跑会就地覆盖那一个episode——遥操作采集始终追加。
关于评测的设置与评分,参见配置页与EVAL流程。