LeRobot - Robot Episode Annotation
Annotate teleoperated robot demonstrations: synchronized camera streams and per-frame arm signals on one timeline, with phase segmentation, outcome and failure cause, and a dense progress-reward curve.
About this dataset
LeRobot is an open-source library for end-to-end robot learning from Hugging Face, presented by Remi Cadene and colleagues in "LeRobot: An Open-Source Library for End-to-End Robot Learning". It spans the robot learning stack, from low-level middleware for motor control to large-scale dataset collection, storage and streaming, with a focus on real-world robotics and accessible hardware.
A LeRobot episode is a recorded demonstration: one or more camera streams alongside the robot's own signals, sampled per frame. What the library does not provide is the human judgement about those episodes, which is what a policy trained on them ultimately depends on: where one sub-goal ends and the next begins, whether the demonstration actually succeeded, and how close to done the robot was at each moment.
Potato puts N synchronized video streams and M time-series lanes on a single timeline and collects three layers over them. Phase segmentation marks where the robot's sub-goal changes. Outcome records success, partial or failure, with a failure-cause taxonomy. Dense progress reward is drawn as a curve across the episode. The layers cost very different amounts of annotator time, so most projects enable a subset.
Three outcomes rather than two is a deliberate choice. "Partial" is the modal result in real robot data, and collapsing it into success or failure destroys the signal that makes the dataset worth annotating in the first place. The config also collects a relabelled instruction, so an episode that failed at the task it was recorded for can be reused as a successful demonstration of the task it actually performed.
The time-series lanes are downsampled with a min/max-preserving reduction, so a one-frame force spike survives being drawn into a 300-pixel-wide lane rather than being averaged away. This matters in practice: a missed grasp is usually visible in the gripper and wrist-force traces several frames before it becomes obvious in the video, which is why the lanes sit beside the video rather than behind a tab.
Potato reads LeRobot v2 through pyarrow, RoboMimic and ALOHA HDF5 through h5py, and RLDS/TFDS through tensorflow_datasets, all via the same source field, and exports a per-frame JSONL sidecar so a read-only public dataset does not have to be rewritten. Each episode is reviewed twice. Phase-boundary agreement is reported as temporal IoU, outcome agreement as Krippendorff's alpha, and reward-curve agreement as ICC plus Pearson, each with coverage stated alongside, because a correlation computed over 5% of a timeline says nothing about the other 95%.
- Episode layers
- Phases, outcome, dense reward
- Outcomes
- success / partial / failure
- Import formats
- LeRobot v2, RLDS/TFDS, HDF5 (RoboMimic, ALOHA)
- Agreement
- Temporal IoU, alpha, ICC + Pearson
- Library
- Hugging Face LeRobot
Configuration Fileconfig.yaml
This Potato config reproduces the annotation task. Save it as config.yaml and run potato start config.yaml to try it.
# yaml-language-server: $schema=https://potatoannotator.readthedocs.io/en/latest/schemas/potato-config.schema.json
#
# LeRobot — Robot Episode Annotation
#
# Paper: Cadene et al., "LeRobot: An Open-Source Library for End-to-End
# Robot Learning", 2026 — https://arxiv.org/abs/2602.22818
# Library: https://github.com/huggingface/lerobot
#
# A LeRobot episode is a teleoperated demonstration: one or more camera streams
# recorded alongside the arm's own signals, sampled per frame. This config puts
# the streams and the signals on one timeline and asks a human what the robot
# was doing, when, and whether it worked.
#
# Reproduction notes
# ------------------
# `source_field` names the item field holding the episode. Potato reads
# LeRobot v2 (pyarrow), RoboMimic and ALOHA HDF5 (h5py), and RLDS/TFDS
# (tensorflow_datasets) through the same field, plus its own manifest format
# which needs no extra dependency.
#
# Three layers are collected here. They cost very different amounts of
# annotator time -- phases are seconds per episode, a dense reward curve is
# minutes -- so most projects want a subset rather than all of them.
#
# The phase taxonomy below is for manipulation. Navigation or locomotion needs
# an entirely different set, which is why it is a config value and not a fixed
# list.
#
# Three outcomes, not two. "Partial" is the modal result in real robot data and
# collapsing it into success or failure destroys the signal that makes the
# dataset worth annotating.
#
# The series lanes are downsampled with a min/max-preserving reduction, so a
# one-frame force spike survives the trip to a 300-pixel-wide lane instead of
# being averaged away. That matters: a failed grasp is usually visible in the
# gripper and force lanes well before it is obvious in the video.
#
# Two annotators per episode. Potato reports phase-boundary agreement as
# temporal IoU, outcome agreement as alpha, and reward-curve agreement as ICC
# plus Pearson -- each with coverage stated alongside, because a correlation
# computed over 5% of a timeline says nothing about the other 95%.
port: 8000
annotation_task_name: "LeRobot - Robot Episode Annotation"
task_dir: "."
media_directory: media
output_annotation_dir: "annotation_output/"
output_annotation_format: "json"
data_files:
- sample-data.json
item_properties:
id_key: "id"
text_key: "instruction"
user_config:
allow_all_users: true
users: []
num_annotators_per_item:
default: 2
annotation_schemes:
- annotation_type: episode_annotation
name: episode_review
description: "Mark the phases, judge the outcome, and draw the progress."
source_field: episode
layers:
- phases
- outcome
- reward
phases:
- name: reach
color: "#4ECDC4"
key_value: "1"
- name: grasp
color: "#FFD93D"
key_value: "2"
- name: transport
color: "#6C8AE4"
key_value: "3"
- name: place
color: "#95E1A3"
key_value: "4"
- name: retract
color: "#C9A0DC"
key_value: "5"
outcomes:
- success
- partial
- failure
failure_causes:
- missed grasp
- object slipped
- collision
- wrong object
- wrong placement
- timeout / stalled
reward_range: [0.0, 1.0]
series_shown:
- gripper
- wrist_force
- shoulder_lift
- elbow
- annotation_type: text
name: relabelled_instruction
description: "Write the instruction this episode actually demonstrates, if it differs from the one given."
placeholder: "e.g. put the red block in the left bin"
- annotation_type: text
name: notes
description: "Anything the phases and the outcome do not capture? (optional)"
annotation_instructions: |
Each item is one robot demonstration: the camera views above, the arm's own
signals as lanes below, and one timeline running through all of them.
1. Segment the episode into phases. Drag a boundary where the robot's
sub-goal changes, not where the video happens to cut. Number keys 1-5
select phases directly.
2. Judge the outcome. Use "partial" when the task was advanced but not
completed; it is a real category, not a hedge.
3. If it failed or only partly succeeded, pick the cause.
4. Draw the dense progress reward: how close to done was the robot at each
point? This is the slowest layer, so it may be disabled for your project.
Watch the lanes, not only the video. A missed grasp is usually visible in the
gripper and wrist force traces several frames before it becomes obvious on
camera.
If the episode demonstrates something other than the instruction it was
recorded for, write what it actually shows. Hindsight relabelling turns a
failed demonstration into a usable one for a different instruction.
Sample Datasample-data.json
[
{
"id": "lerobot_001",
"episode": "episodes/pick_place_block_001.parquet",
"instruction": "Put the red block in the left bin.",
"task": "pick_place_block",
"recorded_outcome": "success",
"context": ""
},
{
"id": "lerobot_002",
"episode": "episodes/pick_place_block_002.parquet",
"instruction": "Put the red block in the left bin.",
"task": "pick_place_block",
"recorded_outcome": "failure",
"context": "gripper closes on nothing; visible in the force lane first"
}
]
// ... and 8 more itemsGet This Design
Clone or download from the repository
Quick start:
git clone https://github.com/davidjurgens/potato-showcase.git cd potato-showcase/multimodal/lerobot-episode-annotation potato start config.yaml
Dataset & paper
Cadene et al., 2026
Citation (BibTeX)
@article{cadene2026lerobot,
title = {LeRobot: An Open-Source Library for End-to-End Robot Learning},
author = {Cadene, Remi and Aliberts, Simon and Capuano, Francesco and Aractingi, Michel and Zouitine, Adil and Kooijmans, Pepijn and Choghari, Jade and Russi, Martino and Pascal, Caroline and Palma, Steven and Shukor, Mustafa and Moss, Jess and Soare, Alexander and Aubakirova, Dana and Lhoest, Quentin and Gallouédec, Quentin and Wolf, Thomas},
journal = {arXiv:2602.22818},
year = {2026}
}Details
Annotation Types
Domain
Use Cases
Tags
Found an issue or want to improve this design?
Open an IssueRelated Designs
RT-2 - Robotic Action Annotation
Robotic manipulation task evaluation and action segmentation based on RT-2 (Brohan et al., CoRL 2023). Annotators evaluate task success, describe actions, rate execution quality, and segment video into action phases.
SayCan: Grounding Language in Robotic Affordances
SayCan grounds a large language model in learned robot skills so a robot can carry out long-horizon natural-language instructions. This Potato config reproduces the human evaluation of its generated action plans.
MVBench Video Understanding
Comprehensive video understanding benchmark with multiple-choice questions, video segment annotation, and reasoning, based on MVBench (Li et al., CVPR 2024). Tests temporal perception, action recognition, and state change detection in videos.