Compare commits

..

7 Commits

Author SHA1 Message Date
CarolinePascal 34454748f4 fix(datasets) 2026-03-09 15:06:55 +01:00
CarolinePascal 8e5763c5ab fix(datasets) 2026-03-08 20:53:16 +01:00
CarolinePascal 388d4518ba fix(datasets) 2026-03-07 17:57:56 +01:00
CarolinePascal 232dbe4176 fix(datasets) 2026-03-07 17:46:09 +01:00
CarolinePascal 10c2e2fc87 fix(datasets) 2026-03-07 01:14:19 +01:00
CarolinePascal 5e74f06b20 fix(datasets) 2026-03-07 00:24:01 +01:00
CarolinePascal 07931b1101 fix(datasets) 2026-03-07 00:18:57 +01:00
47 changed files with 174 additions and 222 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ pytest -sx tests/test_stuff.py::test_something
``` ```
```bash ```bash
lerobot-train --some.option=true python -m lerobot.scripts.train --some.option=true
``` ```
## SECTION TO REMOVE BEFORE SUBMITTING YOUR PR ## SECTION TO REMOVE BEFORE SUBMITTING YOUR PR
+2 -2
View File
@@ -29,8 +29,8 @@ on:
env: env:
UV_VERSION: "0.8.0" UV_VERSION: "0.8.0"
PYTHON_VERSION: "3.10" PYTHON_VERSION: "3.10"
DOCKER_IMAGE_NAME_CPU: huggingface/lerobot-cpu:latest DOCKER_IMAGE_NAME_CPU: huggingface/lerobot-gpu:latest
DOCKER_IMAGE_NAME_GPU: huggingface/lerobot-gpu:latest DOCKER_IMAGE_NAME_GPU: huggingface/lerobot-cpu:latest
# Ensures that only the latest commit is built, canceling older runs. # Ensures that only the latest commit is built, canceling older runs.
concurrency: concurrency:
+5 -5
View File
@@ -86,11 +86,11 @@ repos:
# TODO(Steven): Uncomment when ready to use # TODO(Steven): Uncomment when ready to use
##### Static Analysis & Typing ##### ##### Static Analysis & Typing #####
- repo: https://github.com/pre-commit/mirrors-mypy # - repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.16.0 # rev: v1.16.0
hooks: # hooks:
- id: mypy # - id: mypy
args: [--python-version=3.10] # args: [--python-version=3.10]
##### Docstring Checks ##### ##### Docstring Checks #####
# - repo: https://github.com/akaihola/darglint2 # - repo: https://github.com/akaihola/darglint2
+9 -9
View File
@@ -44,7 +44,7 @@ test-end-to-end:
${MAKE} DEVICE=$(DEVICE) test-smolvla-ete-eval ${MAKE} DEVICE=$(DEVICE) test-smolvla-ete-eval
test-act-ete-train: test-act-ete-train:
lerobot-train \ python -m lerobot.scripts.train \
--policy.type=act \ --policy.type=act \
--policy.dim_model=64 \ --policy.dim_model=64 \
--policy.n_action_steps=20 \ --policy.n_action_steps=20 \
@@ -68,12 +68,12 @@ test-act-ete-train:
--output_dir=tests/outputs/act/ --output_dir=tests/outputs/act/
test-act-ete-train-resume: test-act-ete-train-resume:
lerobot-train \ python -m lerobot.scripts.train \
--config_path=tests/outputs/act/checkpoints/000002/pretrained_model/train_config.json \ --config_path=tests/outputs/act/checkpoints/000002/pretrained_model/train_config.json \
--resume=true --resume=true
test-act-ete-eval: test-act-ete-eval:
lerobot-eval \ python -m lerobot.scripts.eval \
--policy.path=tests/outputs/act/checkpoints/000004/pretrained_model \ --policy.path=tests/outputs/act/checkpoints/000004/pretrained_model \
--policy.device=$(DEVICE) \ --policy.device=$(DEVICE) \
--env.type=aloha \ --env.type=aloha \
@@ -82,7 +82,7 @@ test-act-ete-eval:
--eval.batch_size=1 --eval.batch_size=1
test-diffusion-ete-train: test-diffusion-ete-train:
lerobot-train \ python -m lerobot.scripts.train \
--policy.type=diffusion \ --policy.type=diffusion \
--policy.down_dims='[64,128,256]' \ --policy.down_dims='[64,128,256]' \
--policy.diffusion_step_embed_dim=32 \ --policy.diffusion_step_embed_dim=32 \
@@ -106,7 +106,7 @@ test-diffusion-ete-train:
--output_dir=tests/outputs/diffusion/ --output_dir=tests/outputs/diffusion/
test-diffusion-ete-eval: test-diffusion-ete-eval:
lerobot-eval \ python -m lerobot.scripts.eval \
--policy.path=tests/outputs/diffusion/checkpoints/000002/pretrained_model \ --policy.path=tests/outputs/diffusion/checkpoints/000002/pretrained_model \
--policy.device=$(DEVICE) \ --policy.device=$(DEVICE) \
--env.type=pusht \ --env.type=pusht \
@@ -115,7 +115,7 @@ test-diffusion-ete-eval:
--eval.batch_size=1 --eval.batch_size=1
test-tdmpc-ete-train: test-tdmpc-ete-train:
lerobot-train \ python -m lerobot.scripts.train \
--policy.type=tdmpc \ --policy.type=tdmpc \
--policy.device=$(DEVICE) \ --policy.device=$(DEVICE) \
--policy.push_to_hub=false \ --policy.push_to_hub=false \
@@ -137,7 +137,7 @@ test-tdmpc-ete-train:
--output_dir=tests/outputs/tdmpc/ --output_dir=tests/outputs/tdmpc/
test-tdmpc-ete-eval: test-tdmpc-ete-eval:
lerobot-eval \ python -m lerobot.scripts.eval \
--policy.path=tests/outputs/tdmpc/checkpoints/000002/pretrained_model \ --policy.path=tests/outputs/tdmpc/checkpoints/000002/pretrained_model \
--policy.device=$(DEVICE) \ --policy.device=$(DEVICE) \
--env.type=xarm \ --env.type=xarm \
@@ -148,7 +148,7 @@ test-tdmpc-ete-eval:
test-smolvla-ete-train: test-smolvla-ete-train:
lerobot-train \ python -m lerobot.scripts.train \
--policy.type=smolvla \ --policy.type=smolvla \
--policy.n_action_steps=20 \ --policy.n_action_steps=20 \
--policy.chunk_size=20 \ --policy.chunk_size=20 \
@@ -171,7 +171,7 @@ test-smolvla-ete-train:
--output_dir=tests/outputs/smolvla/ --output_dir=tests/outputs/smolvla/
test-smolvla-ete-eval: test-smolvla-ete-eval:
lerobot-eval \ python -m lerobot.scripts.eval \
--policy.path=tests/outputs/smolvla/checkpoints/000004/pretrained_model \ --policy.path=tests/outputs/smolvla/checkpoints/000004/pretrained_model \
--policy.device=$(DEVICE) \ --policy.device=$(DEVICE) \
--env.type=aloha \ --env.type=aloha \
+6 -6
View File
@@ -6,7 +6,7 @@
<div align="center"> <div align="center">
[![Tests](https://github.com/huggingface/lerobot/actions/workflows/nightly.yml/badge.svg?branch=main)](https://github.com/huggingface/lerobot/actions/workflows/nightly.yml?query=branch%3Amain) [![Tests](https://github.com/huggingface/lerobot/actions/workflows/nightly.yml/badge.svg?branch=main)](https://github.com/huggingface/lerobot/actions/workflows/nighty.yml?query=branch%3Amain)
[![Python versions](https://img.shields.io/pypi/pyversions/lerobot)](https://www.python.org/downloads/) [![Python versions](https://img.shields.io/pypi/pyversions/lerobot)](https://www.python.org/downloads/)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/huggingface/lerobot/blob/main/LICENSE) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/huggingface/lerobot/blob/main/LICENSE)
[![Status](https://img.shields.io/pypi/status/lerobot)](https://pypi.org/project/lerobot/) [![Status](https://img.shields.io/pypi/status/lerobot)](https://pypi.org/project/lerobot/)
@@ -276,7 +276,7 @@ Check out [example 2](https://github.com/huggingface/lerobot/blob/main/examples/
We also provide a more capable script to parallelize the evaluation over multiple environments during the same rollout. Here is an example with a pretrained model hosted on [lerobot/diffusion_pusht](https://huggingface.co/lerobot/diffusion_pusht): We also provide a more capable script to parallelize the evaluation over multiple environments during the same rollout. Here is an example with a pretrained model hosted on [lerobot/diffusion_pusht](https://huggingface.co/lerobot/diffusion_pusht):
```bash ```bash
lerobot-eval \ python -m lerobot.scripts.eval \
--policy.path=lerobot/diffusion_pusht \ --policy.path=lerobot/diffusion_pusht \
--env.type=pusht \ --env.type=pusht \
--eval.batch_size=10 \ --eval.batch_size=10 \
@@ -288,10 +288,10 @@ lerobot-eval \
Note: After training your own policy, you can re-evaluate the checkpoints with: Note: After training your own policy, you can re-evaluate the checkpoints with:
```bash ```bash
lerobot-eval --policy.path={OUTPUT_DIR}/checkpoints/last/pretrained_model python -m lerobot.scripts.eval --policy.path={OUTPUT_DIR}/checkpoints/last/pretrained_model
``` ```
See `lerobot-eval --help` for more instructions. See `python -m lerobot.scripts.eval --help` for more instructions.
### Train your own policy ### Train your own policy
@@ -303,7 +303,7 @@ A link to the wandb logs for the run will also show up in yellow in your termina
\<img src="https://raw.githubusercontent.com/huggingface/lerobot/main/media/wandb.png" alt="WandB logs example"\> \<img src="https://raw.githubusercontent.com/huggingface/lerobot/main/media/wandb.png" alt="WandB logs example"\>
Note: For efficiency, during training every checkpoint is evaluated on a low number of episodes. You may use `--eval.n_episodes=500` to evaluate on more episodes than the default. Or, after training, you may want to re-evaluate your best checkpoints on more episodes or change the evaluation settings. See `lerobot-eval --help` for more instructions. Note: For efficiency, during training every checkpoint is evaluated on a low number of episodes. You may use `--eval.n_episodes=500` to evaluate on more episodes than the default. Or, after training, you may want to re-evaluate your best checkpoints on more episodes or change the evaluation settings. See `python -m lerobot.scripts.eval --help` for more instructions.
#### Reproduce state-of-the-art (SOTA) #### Reproduce state-of-the-art (SOTA)
@@ -311,7 +311,7 @@ We provide some pretrained policies on our [hub page](https://huggingface.co/ler
You can reproduce their training by loading the config from their run. Simply running: You can reproduce their training by loading the config from their run. Simply running:
```bash ```bash
lerobot-train --config_path=lerobot/diffusion_pusht python -m lerobot.scripts.train --config_path=lerobot/diffusion_pusht
``` ```
reproduces SOTA results for Diffusion Policy on the PushT task. reproduces SOTA results for Diffusion Policy on the PushT task.
+1 -1
View File
@@ -29,7 +29,7 @@ ENV DEBIAN_FRONTEND=noninteractive \
# Install system dependencies and uv (as root) # Install system dependencies and uv (as root)
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential git curl libglib2.0-0 libegl1-mesa-dev ffmpeg \ build-essential git curl libglib2.0-0 libegl1-mesa ffmpeg \
libusb-1.0-0-dev speech-dispatcher libgeos-dev portaudio19-dev \ libusb-1.0-0-dev speech-dispatcher libgeos-dev portaudio19-dev \
&& curl -LsSf https://astral.sh/uv/install.sh | sh \ && curl -LsSf https://astral.sh/uv/install.sh | sh \
&& mv /root/.local/bin/uv /usr/local/bin/uv \ && mv /root/.local/bin/uv /usr/local/bin/uv \
-2
View File
@@ -39,8 +39,6 @@
- sections: - sections:
- local: notebooks - local: notebooks
title: Notebooks title: Notebooks
- local: feetech
title: Updating Feetech Firmware
title: "Resources" title: "Resources"
- sections: - sections:
- local: contributing - local: contributing
+1 -1
View File
@@ -9,7 +9,7 @@ To instantiate a camera, you need a camera identifier. This identifier might cha
To find the camera indices of the cameras plugged into your system, run the following script: To find the camera indices of the cameras plugged into your system, run the following script:
```bash ```bash
lerobot-find-cameras opencv # or realsense for Intel Realsense cameras python -m lerobot.find_cameras opencv # or realsense for Intel Realsense cameras
``` ```
The output will look something like this if you have two cameras connected: The output will look something like this if you have two cameras connected:
-71
View File
@@ -1,71 +0,0 @@
# Feetech Motor Firmware Update
This tutorial guides you through updating the firmware of Feetech motors using the official Feetech software.
## Prerequisites
- Windows computer (Feetech software is only available for Windows)
- Feetech motor control board
- USB cable to connect the control board to your computer
- Feetech motors connected to the control board
## Step 1: Download Feetech Software
1. Visit the official Feetech software download page: [https://www.feetechrc.com/software.html](https://www.feetechrc.com/software.html)
2. Download the latest version of the Feetech debugging software (FD)
3. Install the software on your Windows computer
## Step 2: Hardware Setup
1. Connect your Feetech motors to the motor control board
2. Connect the motor control board to your Windows computer via USB cable
3. Ensure power is supplied to the motors
## Step 3: Configure Connection
1. Launch the Feetech debugging software
2. Select the correct COM port from the port dropdown menu
- If unsure which port to use, check Windows Device Manager under "Ports (COM & LPT)"
3. Set the appropriate baud rate (typically 1000000 for most Feetech motors)
4. Click "Open" to establish communication with the control board
## Step 4: Scan for Motors
1. Once connected, click the "Search" button to detect all connected motors
2. The software will automatically discover and list all motors on the bus
3. Each motor will appear with its ID number
## Step 5: Update Firmware
For each motor you want to update:
1. **Select the motor** from the list by clicking on it
2. **Click on Upgrade tab**:
3. **Click on Online button**:
- If an potential firmware update is found, it will be displayed in the box
4. **Click on Upgrade button**:
- The update progress will be displayed
## Step 6: Verify Update
1. After the update completes, the software should automatically refresh the motor information
2. Verify that the firmware version has been updated to the expected version
## Important Notes
⚠️ **Warning**: Do not disconnect power or USB during firmware updates, it will potentially brick the motor.
## Bonus: Motor Debugging on Linux/macOS
For debugging purposes only, you can use the open-source Feetech Debug Tool:
- **Repository**: [FT_SCServo_Debug_Qt](https://github.com/CarolinePascal/FT_SCServo_Debug_Qt/tree/fix/port-search-timer)
### Installation Instructions
Follow the instructions in the repository to install the tool, for Ubuntu you can directly install it, for MacOS you need to build it from source.
**Limitations:**
- This tool is for debugging and parameter adjustment only
- Firmware updates must still be done on Windows with official Feetech software
+2 -2
View File
@@ -412,7 +412,7 @@ Example configuration for training the [reward classifier](https://huggingface.c
To train the classifier, use the `train.py` script with your configuration: To train the classifier, use the `train.py` script with your configuration:
```bash ```bash
lerobot-train --config_path path/to/reward_classifier_train_config.json python -m lerobot.scripts.train --config_path path/to/reward_classifier_train_config.json
``` ```
**Deploying and Testing the Model** **Deploying and Testing the Model**
@@ -458,7 +458,7 @@ The reward classifier will automatically provide rewards based on the visual inp
3. **Train the classifier**: 3. **Train the classifier**:
```bash ```bash
lerobot-train --config_path src/lerobot/configs/reward_classifier_train_config.json python -m lerobot.scripts.train --config_path src/lerobot/configs/reward_classifier_train_config.json
``` ```
4. **Test the classifier**: 4. **Test the classifier**:
+11 -11
View File
@@ -19,7 +19,7 @@ pip install -e ".[hopejr]"
Before starting calibration and operation, you need to identify the USB ports for each HopeJR component. Run this script to find the USB ports for the arm, hand, glove, and exoskeleton: Before starting calibration and operation, you need to identify the USB ports for each HopeJR component. Run this script to find the USB ports for the arm, hand, glove, and exoskeleton:
```bash ```bash
lerobot-find-port python -m lerobot.find_port
``` ```
This will display the available USB ports and their associated devices. Make note of the port paths (e.g., `/dev/tty.usbmodem58760433331`, `/dev/tty.usbmodem11301`) as you'll need to specify them in the `--robot.port` and `--teleop.port` parameters when recording data, replaying episodes, or running teleoperation scripts. This will display the available USB ports and their associated devices. Make note of the port paths (e.g., `/dev/tty.usbmodem58760433331`, `/dev/tty.usbmodem11301`) as you'll need to specify them in the `--robot.port` and `--teleop.port` parameters when recording data, replaying episodes, or running teleoperation scripts.
@@ -31,7 +31,7 @@ Before performing teleoperation, HopeJR's limbs need to be calibrated. Calibrati
### 1.1 Calibrate Robot Hand ### 1.1 Calibrate Robot Hand
```bash ```bash
lerobot-calibrate \ python -m lerobot.calibrate \
--robot.type=hope_jr_hand \ --robot.type=hope_jr_hand \
--robot.port=/dev/tty.usbmodem58760432281 \ --robot.port=/dev/tty.usbmodem58760432281 \
--robot.id=blue \ --robot.id=blue \
@@ -81,7 +81,7 @@ Once you have set the appropriate boundaries for all joints, click "Save" to sav
### 1.2 Calibrate Teleoperator Glove ### 1.2 Calibrate Teleoperator Glove
```bash ```bash
lerobot-calibrate \ python -m lerobot.calibrate \
--teleop.type=homunculus_glove \ --teleop.type=homunculus_glove \
--teleop.port=/dev/tty.usbmodem11201 \ --teleop.port=/dev/tty.usbmodem11201 \
--teleop.id=red \ --teleop.id=red \
@@ -120,7 +120,7 @@ Once calibration is complete, the system will save the calibration to `/Users/yo
### 1.3 Calibrate Robot Arm ### 1.3 Calibrate Robot Arm
```bash ```bash
lerobot-calibrate \ python -m lerobot.calibrate \
--robot.type=hope_jr_arm \ --robot.type=hope_jr_arm \
--robot.port=/dev/tty.usbserial-1110 \ --robot.port=/dev/tty.usbserial-1110 \
--robot.id=white --robot.id=white
@@ -146,7 +146,7 @@ Use the calibration interface to set the range boundaries for each joint. Move e
### 1.4 Calibrate Teleoperator Exoskeleton ### 1.4 Calibrate Teleoperator Exoskeleton
```bash ```bash
lerobot-calibrate \ python -m lerobot.calibrate \
--teleop.type=homunculus_arm \ --teleop.type=homunculus_arm \
--teleop.port=/dev/tty.usbmodem11201 \ --teleop.port=/dev/tty.usbmodem11201 \
--teleop.id=black --teleop.id=black
@@ -178,7 +178,7 @@ Due to global variable conflicts in the Feetech middleware, teleoperation for ar
### Hand ### Hand
```bash ```bash
lerobot-teleoperate \ python -m lerobot.teleoperate \
--robot.type=hope_jr_hand \ --robot.type=hope_jr_hand \
--robot.port=/dev/tty.usbmodem58760432281 \ --robot.port=/dev/tty.usbmodem58760432281 \
--robot.id=blue \ --robot.id=blue \
@@ -194,7 +194,7 @@ lerobot-teleoperate \
### Arm ### Arm
```bash ```bash
lerobot-teleoperate \ python -m lerobot.teleoperate \
--robot.type=hope_jr_arm \ --robot.type=hope_jr_arm \
--robot.port=/dev/tty.usbserial-1110 \ --robot.port=/dev/tty.usbserial-1110 \
--robot.id=white \ --robot.id=white \
@@ -214,7 +214,7 @@ Record, Replay and Train with Hope-JR is still experimental.
This step records the dataset, which can be seen as an example [here](https://huggingface.co/datasets/nepyope/hand_record_test_with_video_data/settings). This step records the dataset, which can be seen as an example [here](https://huggingface.co/datasets/nepyope/hand_record_test_with_video_data/settings).
```bash ```bash
lerobot-record \ python -m lerobot.record \
--robot.type=hope_jr_hand \ --robot.type=hope_jr_hand \
--robot.port=/dev/tty.usbmodem58760432281 \ --robot.port=/dev/tty.usbmodem58760432281 \
--robot.id=right \ --robot.id=right \
@@ -236,7 +236,7 @@ lerobot-record \
### Replay ### Replay
```bash ```bash
lerobot-replay \ python -m lerobot.replay \
--robot.type=hope_jr_hand \ --robot.type=hope_jr_hand \
--robot.port=/dev/tty.usbmodem58760432281 \ --robot.port=/dev/tty.usbmodem58760432281 \
--robot.id=right \ --robot.id=right \
@@ -248,7 +248,7 @@ lerobot-replay \
### Train ### Train
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--dataset.repo_id=nepyope/hand_record_test_with_video_data \ --dataset.repo_id=nepyope/hand_record_test_with_video_data \
--policy.type=act \ --policy.type=act \
--output_dir=outputs/train/hopejr_hand \ --output_dir=outputs/train/hopejr_hand \
@@ -263,7 +263,7 @@ lerobot-train \
This training run can be viewed as an example [here](https://wandb.ai/tino/lerobot/runs/rp0k8zvw?nw=nwusertino). This training run can be viewed as an example [here](https://wandb.ai/tino/lerobot/runs/rp0k8zvw?nw=nwusertino).
```bash ```bash
lerobot-record \ python -m lerobot.record \
--robot.type=hope_jr_hand \ --robot.type=hope_jr_hand \
--robot.port=/dev/tty.usbmodem58760432281 \ --robot.port=/dev/tty.usbmodem58760432281 \
--robot.id=right \ --robot.id=right \
+8 -8
View File
@@ -45,7 +45,7 @@ Note that the `id` associated with a robot is used to store the calibration file
<hfoptions id="teleoperate_so101"> <hfoptions id="teleoperate_so101">
<hfoption id="Command"> <hfoption id="Command">
```bash ```bash
lerobot-teleoperate \ python -m lerobot.teleoperate \
--robot.type=so101_follower \ --robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem58760431541 \ --robot.port=/dev/tty.usbmodem58760431541 \
--robot.id=my_awesome_follower_arm \ --robot.id=my_awesome_follower_arm \
@@ -101,7 +101,7 @@ With `rerun`, you can teleoperate again while simultaneously visualizing the cam
<hfoptions id="teleoperate_koch_camera"> <hfoptions id="teleoperate_koch_camera">
<hfoption id="Command"> <hfoption id="Command">
```bash ```bash
lerobot-teleoperate \ python -m lerobot.teleoperate \
--robot.type=koch_follower \ --robot.type=koch_follower \
--robot.port=/dev/tty.usbmodem58760431541 \ --robot.port=/dev/tty.usbmodem58760431541 \
--robot.id=my_awesome_follower_arm \ --robot.id=my_awesome_follower_arm \
@@ -174,7 +174,7 @@ Now you can record a dataset. To record 5 episodes and upload your dataset to th
<hfoptions id="record"> <hfoptions id="record">
<hfoption id="Command"> <hfoption id="Command">
```bash ```bash
lerobot-record \ python -m lerobot.record \
--robot.type=so101_follower \ --robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem585A0076841 \ --robot.port=/dev/tty.usbmodem585A0076841 \
--robot.id=my_awesome_follower_arm \ --robot.id=my_awesome_follower_arm \
@@ -376,7 +376,7 @@ You can replay the first episode on your robot with either the command below or
<hfoptions id="replay"> <hfoptions id="replay">
<hfoption id="Command"> <hfoption id="Command">
```bash ```bash
lerobot-replay \ python -m lerobot.replay \
--robot.type=so101_follower \ --robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem58760431541 \ --robot.port=/dev/tty.usbmodem58760431541 \
--robot.id=my_awesome_follower_arm \ --robot.id=my_awesome_follower_arm \
@@ -428,10 +428,10 @@ Your robot should replicate movements similar to those you recorded. For example
## Train a policy ## Train a policy
To train a policy to control your robot, use the [`lerobot-train`](https://github.com/huggingface/lerobot/blob/main/src/lerobot/scripts/train.py) script. A few arguments are required. Here is an example command: To train a policy to control your robot, use the [`python -m lerobot.scripts.train`](https://github.com/huggingface/lerobot/blob/main/src/lerobot/scripts/train.py) script. A few arguments are required. Here is an example command:
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--dataset.repo_id=${HF_USER}/so101_test \ --dataset.repo_id=${HF_USER}/so101_test \
--policy.type=act \ --policy.type=act \
--output_dir=outputs/train/act_so101_test \ --output_dir=outputs/train/act_so101_test \
@@ -453,7 +453,7 @@ Training should take several hours. You will find checkpoints in `outputs/train/
To resume training from a checkpoint, below is an example command to resume from `last` checkpoint of the `act_so101_test` policy: To resume training from a checkpoint, below is an example command to resume from `last` checkpoint of the `act_so101_test` policy:
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--config_path=outputs/train/act_so101_test/checkpoints/last/pretrained_model/train_config.json \ --config_path=outputs/train/act_so101_test/checkpoints/last/pretrained_model/train_config.json \
--resume=true --resume=true
``` ```
@@ -490,7 +490,7 @@ You can use the `record` script from [`lerobot/record.py`](https://github.com/hu
<hfoptions id="eval"> <hfoptions id="eval">
<hfoption id="Command"> <hfoption id="Command">
```bash ```bash
lerobot-record \ python -m lerobot.record \
--robot.type=so100_follower \ --robot.type=so100_follower \
--robot.port=/dev/ttyACM1 \ --robot.port=/dev/ttyACM1 \
--robot.cameras="{ up: {type: opencv, index_or_path: /dev/video10, width: 640, height: 480, fps: 30}, side: {type: intelrealsense, serial_number_or_name: 233522074606, width: 640, height: 480, fps: 30}}" \ --robot.cameras="{ up: {type: opencv, index_or_path: /dev/video10, width: 640, height: 480, fps: 30}, side: {type: intelrealsense, serial_number_or_name: 233522074606, width: 640, height: 480, fps: 30}}" \
+2 -2
View File
@@ -96,10 +96,10 @@ If you uploaded your dataset to the hub you can [visualize your dataset online](
## Train a policy ## Train a policy
To train a policy to control your robot, use the [`lerobot-train`](https://github.com/huggingface/lerobot/blob/main/src/lerobot/scripts/train.py) script. A few arguments are required. Here is an example command: To train a policy to control your robot, use the [`python -m lerobot.scripts.train`](https://github.com/huggingface/lerobot/blob/main/src/lerobot/scripts/train.py) script. A few arguments are required. Here is an example command:
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--dataset.repo_id=${HF_USER}/il_gym \ --dataset.repo_id=${HF_USER}/il_gym \
--policy.type=act \ --policy.type=act \
--output_dir=outputs/train/il_sim_test \ --output_dir=outputs/train/il_sim_test \
+5 -5
View File
@@ -31,7 +31,7 @@ pip install -e ".[dynamixel]"
To find the port for each bus servo adapter, run this script: To find the port for each bus servo adapter, run this script:
```bash ```bash
lerobot-find-port python -m lerobot.find_port
``` ```
<hfoptions id="example"> <hfoptions id="example">
@@ -98,7 +98,7 @@ For a visual reference on how to set the motor ids please refer to [this video](
<hfoption id="Command"> <hfoption id="Command">
```bash ```bash
lerobot-setup-motors \ python -m lerobot.setup_motors \
--robot.type=koch_follower \ --robot.type=koch_follower \
--robot.port=/dev/tty.usbmodem575E0031751 # <- paste here the port found at previous step --robot.port=/dev/tty.usbmodem575E0031751 # <- paste here the port found at previous step
``` ```
@@ -174,7 +174,7 @@ Do the same steps for the leader arm but modify the command or script accordingl
<hfoption id="Command"> <hfoption id="Command">
```bash ```bash
lerobot-setup-motors \ python -m lerobot.setup_motors \
--teleop.type=koch_leader \ --teleop.type=koch_leader \
--teleop.port=/dev/tty.usbmodem575E0031751 \ # <- paste here the port found at previous step --teleop.port=/dev/tty.usbmodem575E0031751 \ # <- paste here the port found at previous step
``` ```
@@ -211,7 +211,7 @@ Run the following command or API example to calibrate the follower arm:
<hfoption id="Command"> <hfoption id="Command">
```bash ```bash
lerobot-calibrate \ python -m lerobot.calibrate \
--robot.type=koch_follower \ --robot.type=koch_follower \
--robot.port=/dev/tty.usbmodem58760431551 \ # <- The port of your robot --robot.port=/dev/tty.usbmodem58760431551 \ # <- The port of your robot
--robot.id=my_awesome_follower_arm # <- Give the robot a unique name --robot.id=my_awesome_follower_arm # <- Give the robot a unique name
@@ -249,7 +249,7 @@ Do the same steps to calibrate the leader arm, run the following command or API
<hfoption id="Command"> <hfoption id="Command">
```bash ```bash
lerobot-calibrate \ python -m lerobot.calibrate \
--teleop.type=koch_leader \ --teleop.type=koch_leader \
--teleop.port=/dev/tty.usbmodem58760431551 \ # <- The port of your robot --teleop.port=/dev/tty.usbmodem58760431551 \ # <- The port of your robot
--teleop.id=my_awesome_leader_arm # <- Give the robot a unique name --teleop.id=my_awesome_leader_arm # <- Give the robot a unique name
+4 -4
View File
@@ -60,7 +60,7 @@ First, we will assemble the two SO100/SO101 arms. One to attach to the mobile ba
To find the port for each bus servo adapter, run this script: To find the port for each bus servo adapter, run this script:
```bash ```bash
lerobot-find-port python -m lerobot.find_port
``` ```
<hfoptions id="example"> <hfoptions id="example">
@@ -116,7 +116,7 @@ The instructions for configuring the motors can be found in the SO101 [docs](./s
You can run this command to setup motors for LeKiwi. It will first setup the motors for arm (id 6..1) and then setup motors for wheels (9,8,7) You can run this command to setup motors for LeKiwi. It will first setup the motors for arm (id 6..1) and then setup motors for wheels (9,8,7)
```bash ```bash
lerobot-setup-motors \ python -m lerobot.setup_motors \
--robot.type=lekiwi \ --robot.type=lekiwi \
--robot.port=/dev/tty.usbmodem58760431551 # <- paste here the port found at previous step --robot.port=/dev/tty.usbmodem58760431551 # <- paste here the port found at previous step
``` ```
@@ -174,7 +174,7 @@ The calibration process is very important because it allows a neural network tra
Make sure the arm is connected to the Raspberry Pi and run this script or API example (on the Raspberry Pi via SSH) to launch calibration of the follower arm: Make sure the arm is connected to the Raspberry Pi and run this script or API example (on the Raspberry Pi via SSH) to launch calibration of the follower arm:
```bash ```bash
lerobot-calibrate \ python -m lerobot.calibrate \
--robot.type=lekiwi \ --robot.type=lekiwi \
--robot.id=my_awesome_kiwi # <- Give the robot a unique name --robot.id=my_awesome_kiwi # <- Give the robot a unique name
``` ```
@@ -193,7 +193,7 @@ Then, to calibrate the leader arm (which is attached to the laptop/pc). Run the
<hfoption id="Command"> <hfoption id="Command">
```bash ```bash
lerobot-calibrate \ python -m lerobot.calibrate \
--teleop.type=so100_leader \ --teleop.type=so100_leader \
--teleop.port=/dev/tty.usbmodem58760431551 \ # <- The port of your robot --teleop.port=/dev/tty.usbmodem58760431551 \ # <- The port of your robot
--teleop.id=my_awesome_leader_arm # <- Give the robot a unique name --teleop.id=my_awesome_leader_arm # <- Give the robot a unique name
+3 -3
View File
@@ -54,7 +54,7 @@ If you don't have a gpu device, you can train using our notebook on [![Google Co
Pass your dataset to the training script using `--dataset.repo_id`. If you want to test your installation, run the following command where we use one of the datasets we collected for the [SmolVLA Paper](https://huggingface.co/papers/2506.01844). Pass your dataset to the training script using `--dataset.repo_id`. If you want to test your installation, run the following command where we use one of the datasets we collected for the [SmolVLA Paper](https://huggingface.co/papers/2506.01844).
```bash ```bash
cd lerobot && lerobot-train \ cd lerobot && python -m lerobot.scripts.train \
--policy.path=lerobot/smolvla_base \ --policy.path=lerobot/smolvla_base \
--dataset.repo_id=${HF_USER}/mydataset \ --dataset.repo_id=${HF_USER}/mydataset \
--batch_size=64 \ --batch_size=64 \
@@ -73,7 +73,7 @@ cd lerobot && lerobot-train \
Fine-tuning is an art. For a complete overview of the options for finetuning, run Fine-tuning is an art. For a complete overview of the options for finetuning, run
```bash ```bash
lerobot-train --help python -m lerobot.scripts.train --help
``` ```
<p align="center"> <p align="center">
@@ -97,7 +97,7 @@ Similarly for when recording an episode, it is recommended that you are logged i
Once you are logged in, you can run inference in your setup by doing: Once you are logged in, you can run inference in your setup by doing:
```bash ```bash
lerobot-record \ python -m lerobot.record \
--robot.type=so101_follower \ --robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \ # <- Use your port --robot.port=/dev/ttyACM0 \ # <- Use your port
--robot.id=my_blue_follower_arm \ # <- Use your robot id --robot.id=my_blue_follower_arm \ # <- Use your robot id
+5 -5
View File
@@ -26,7 +26,7 @@ Unlike the SO-101, the motor connectors are not easily accessible once the arm i
To find the port for each bus servo adapter, run this script: To find the port for each bus servo adapter, run this script:
```bash ```bash
lerobot-find-port python -m lerobot.find_port
``` ```
<hfoptions id="example"> <hfoptions id="example">
@@ -93,7 +93,7 @@ For a visual reference on how to set the motor ids please refer to [this video](
<hfoption id="Command"> <hfoption id="Command">
```bash ```bash
lerobot-setup-motors \ python -m lerobot.setup_motors \
--robot.type=so100_follower \ --robot.type=so100_follower \
--robot.port=/dev/tty.usbmodem585A0076841 # <- paste here the port found at previous step --robot.port=/dev/tty.usbmodem585A0076841 # <- paste here the port found at previous step
``` ```
@@ -168,7 +168,7 @@ Do the same steps for the leader arm.
<hfoptions id="setup_motors"> <hfoptions id="setup_motors">
<hfoption id="Command"> <hfoption id="Command">
```bash ```bash
lerobot-setup-motors \ python -m lerobot.setup_motors \
--teleop.type=so100_leader \ --teleop.type=so100_leader \
--teleop.port=/dev/tty.usbmodem575E0031751 # <- paste here the port found at previous step --teleop.port=/dev/tty.usbmodem575E0031751 # <- paste here the port found at previous step
``` ```
@@ -568,7 +568,7 @@ Run the following command or API example to calibrate the follower arm:
<hfoption id="Command"> <hfoption id="Command">
```bash ```bash
lerobot-calibrate \ python -m lerobot.calibrate \
--robot.type=so100_follower \ --robot.type=so100_follower \
--robot.port=/dev/tty.usbmodem58760431551 \ # <- The port of your robot --robot.port=/dev/tty.usbmodem58760431551 \ # <- The port of your robot
--robot.id=my_awesome_follower_arm # <- Give the robot a unique name --robot.id=my_awesome_follower_arm # <- Give the robot a unique name
@@ -606,7 +606,7 @@ Do the same steps to calibrate the leader arm, run the following command or API
<hfoption id="Command"> <hfoption id="Command">
```bash ```bash
lerobot-calibrate \ python -m lerobot.calibrate \
--teleop.type=so100_leader \ --teleop.type=so100_leader \
--teleop.port=/dev/tty.usbmodem58760431551 \ # <- The port of your robot --teleop.port=/dev/tty.usbmodem58760431551 \ # <- The port of your robot
--teleop.id=my_awesome_leader_arm # <- Give the robot a unique name --teleop.id=my_awesome_leader_arm # <- Give the robot a unique name
+5 -5
View File
@@ -162,7 +162,7 @@ It is advisable to install one 3-pin cable in the motor after placing them befor
To find the port for each bus servo adapter, connect MotorBus to your computer via USB and power. Run the following script and disconnect the MotorBus when prompted: To find the port for each bus servo adapter, connect MotorBus to your computer via USB and power. Run the following script and disconnect the MotorBus when prompted:
```bash ```bash
lerobot-find-port python -m lerobot.find_port
``` ```
<hfoptions id="example"> <hfoptions id="example">
@@ -240,7 +240,7 @@ Connect the usb cable from your computer and the power supply to the follower ar
<hfoption id="Command"> <hfoption id="Command">
```bash ```bash
lerobot-setup-motors \ python -m lerobot.setup_motors \
--robot.type=so101_follower \ --robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem585A0076841 # <- paste here the port found at previous step --robot.port=/dev/tty.usbmodem585A0076841 # <- paste here the port found at previous step
``` ```
@@ -316,7 +316,7 @@ Do the same steps for the leader arm.
<hfoption id="Command"> <hfoption id="Command">
```bash ```bash
lerobot-setup-motors \ python -m lerobot.setup_motors \
--teleop.type=so101_leader \ --teleop.type=so101_leader \
--teleop.port=/dev/tty.usbmodem575E0031751 # <- paste here the port found at previous step --teleop.port=/dev/tty.usbmodem575E0031751 # <- paste here the port found at previous step
``` ```
@@ -353,7 +353,7 @@ Run the following command or API example to calibrate the follower arm:
<hfoption id="Command"> <hfoption id="Command">
```bash ```bash
lerobot-calibrate \ python -m lerobot.calibrate \
--robot.type=so101_follower \ --robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem58760431551 \ # <- The port of your robot --robot.port=/dev/tty.usbmodem58760431551 \ # <- The port of your robot
--robot.id=my_awesome_follower_arm # <- Give the robot a unique name --robot.id=my_awesome_follower_arm # <- Give the robot a unique name
@@ -402,7 +402,7 @@ Do the same steps to calibrate the leader arm, run the following command or API
<hfoption id="Command"> <hfoption id="Command">
```bash ```bash
lerobot-calibrate \ python -m lerobot.calibrate \
--teleop.type=so101_leader \ --teleop.type=so101_leader \
--teleop.port=/dev/tty.usbmodem58760431551 \ # <- The port of your robot --teleop.port=/dev/tty.usbmodem58760431551 \ # <- The port of your robot
--teleop.id=my_awesome_leader_arm # <- Give the robot a unique name --teleop.id=my_awesome_leader_arm # <- Give the robot a unique name
+14 -14
View File
@@ -62,7 +62,7 @@ By default, every field takes its default value specified in the dataclass. If a
Let's say that we want to train [Diffusion Policy](../src/lerobot/policies/diffusion) on the [pusht](https://huggingface.co/datasets/lerobot/pusht) dataset, using the [gym_pusht](https://github.com/huggingface/gym-pusht) environment for evaluation. The command to do so would look like this: Let's say that we want to train [Diffusion Policy](../src/lerobot/policies/diffusion) on the [pusht](https://huggingface.co/datasets/lerobot/pusht) dataset, using the [gym_pusht](https://github.com/huggingface/gym-pusht) environment for evaluation. The command to do so would look like this:
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--dataset.repo_id=lerobot/pusht \ --dataset.repo_id=lerobot/pusht \
--policy.type=diffusion \ --policy.type=diffusion \
--env.type=pusht --env.type=pusht
@@ -77,7 +77,7 @@ Let's break this down:
Let's see another example. Let's say you've been training [ACT](../src/lerobot/policies/act) on [lerobot/aloha_sim_insertion_human](https://huggingface.co/datasets/lerobot/aloha_sim_insertion_human) using the [gym-aloha](https://github.com/huggingface/gym-aloha) environment for evaluation with: Let's see another example. Let's say you've been training [ACT](../src/lerobot/policies/act) on [lerobot/aloha_sim_insertion_human](https://huggingface.co/datasets/lerobot/aloha_sim_insertion_human) using the [gym-aloha](https://github.com/huggingface/gym-aloha) environment for evaluation with:
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--policy.type=act \ --policy.type=act \
--dataset.repo_id=lerobot/aloha_sim_insertion_human \ --dataset.repo_id=lerobot/aloha_sim_insertion_human \
--env.type=aloha \ --env.type=aloha \
@@ -90,7 +90,7 @@ We now want to train a different policy for aloha on another task. We'll change
Looking at the [`AlohaEnv`](../src/lerobot/envs/configs.py) config, the task is `"AlohaInsertion-v0"` by default, which corresponds to the task we trained on in the command above. The [gym-aloha](https://github.com/huggingface/gym-aloha?tab=readme-ov-file#description) environment also has the `AlohaTransferCube-v0` task which corresponds to this other task we want to train on. Putting this together, we can train this new policy on this different task using: Looking at the [`AlohaEnv`](../src/lerobot/envs/configs.py) config, the task is `"AlohaInsertion-v0"` by default, which corresponds to the task we trained on in the command above. The [gym-aloha](https://github.com/huggingface/gym-aloha?tab=readme-ov-file#description) environment also has the `AlohaTransferCube-v0` task which corresponds to this other task we want to train on. Putting this together, we can train this new policy on this different task using:
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--policy.type=act \ --policy.type=act \
--dataset.repo_id=lerobot/aloha_sim_transfer_cube_human \ --dataset.repo_id=lerobot/aloha_sim_transfer_cube_human \
--env.type=aloha \ --env.type=aloha \
@@ -127,7 +127,7 @@ Now, let's assume that we want to reproduce the run just above. That run has pro
We can then simply load the config values from this file using: We can then simply load the config values from this file using:
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--config_path=outputs/train/act_aloha_transfer/checkpoints/last/pretrained_model/ \ --config_path=outputs/train/act_aloha_transfer/checkpoints/last/pretrained_model/ \
--output_dir=outputs/train/act_aloha_transfer_2 --output_dir=outputs/train/act_aloha_transfer_2
``` ```
@@ -137,7 +137,7 @@ lerobot-train \
Similarly to Hydra, we can still override some parameters in the CLI if we want to, e.g.: Similarly to Hydra, we can still override some parameters in the CLI if we want to, e.g.:
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--config_path=outputs/train/act_aloha_transfer/checkpoints/last/pretrained_model/ \ --config_path=outputs/train/act_aloha_transfer/checkpoints/last/pretrained_model/ \
--output_dir=outputs/train/act_aloha_transfer_2 --output_dir=outputs/train/act_aloha_transfer_2
--policy.n_action_steps=80 --policy.n_action_steps=80
@@ -148,7 +148,7 @@ lerobot-train \
`--config_path` can also accept the repo_id of a repo on the hub that contains a `train_config.json` file, e.g. running: `--config_path` can also accept the repo_id of a repo on the hub that contains a `train_config.json` file, e.g. running:
```bash ```bash
lerobot-train --config_path=lerobot/diffusion_pusht python -m lerobot.scripts.train --config_path=lerobot/diffusion_pusht
``` ```
will start a training run with the same configuration used for training [lerobot/diffusion_pusht](https://huggingface.co/lerobot/diffusion_pusht) will start a training run with the same configuration used for training [lerobot/diffusion_pusht](https://huggingface.co/lerobot/diffusion_pusht)
@@ -160,7 +160,7 @@ Being able to resume a training run is important in case it crashed or aborted f
Let's reuse the command from the previous run and add a few more options: Let's reuse the command from the previous run and add a few more options:
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--policy.type=act \ --policy.type=act \
--dataset.repo_id=lerobot/aloha_sim_transfer_cube_human \ --dataset.repo_id=lerobot/aloha_sim_transfer_cube_human \
--env.type=aloha \ --env.type=aloha \
@@ -179,7 +179,7 @@ INFO 2025-01-24 16:10:56 ts/train.py:263 Checkpoint policy after step 100
Now let's simulate a crash by killing the process (hit `ctrl`+`c`). We can then simply resume this run from the last checkpoint available with: Now let's simulate a crash by killing the process (hit `ctrl`+`c`). We can then simply resume this run from the last checkpoint available with:
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--config_path=outputs/train/run_resumption/checkpoints/last/pretrained_model/ \ --config_path=outputs/train/run_resumption/checkpoints/last/pretrained_model/ \
--resume=true --resume=true
``` ```
@@ -190,7 +190,7 @@ Another reason for which you might want to resume a run is simply to extend trai
You could double the number of steps of the previous run with: You could double the number of steps of the previous run with:
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--config_path=outputs/train/run_resumption/checkpoints/last/pretrained_model/ \ --config_path=outputs/train/run_resumption/checkpoints/last/pretrained_model/ \
--resume=true \ --resume=true \
--steps=200000 --steps=200000
@@ -224,7 +224,7 @@ In addition to the features currently in Draccus, we've added a special `.path`
For example, we could fine-tune a [policy pre-trained on the aloha transfer task](https://huggingface.co/lerobot/act_aloha_sim_transfer_cube_human) on the aloha insertion task. We can achieve this with: For example, we could fine-tune a [policy pre-trained on the aloha transfer task](https://huggingface.co/lerobot/act_aloha_sim_transfer_cube_human) on the aloha insertion task. We can achieve this with:
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--policy.path=lerobot/act_aloha_sim_transfer_cube_human \ --policy.path=lerobot/act_aloha_sim_transfer_cube_human \
--dataset.repo_id=lerobot/aloha_sim_insertion_human \ --dataset.repo_id=lerobot/aloha_sim_insertion_human \
--env.type=aloha \ --env.type=aloha \
@@ -270,7 +270,7 @@ We'll summarize here the main use cases to remember from this tutorial.
#### Train a policy from scratch CLI #### Train a policy from scratch CLI
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--policy.type=act \ # <- select 'act' policy --policy.type=act \ # <- select 'act' policy
--env.type=pusht \ # <- select 'pusht' environment --env.type=pusht \ # <- select 'pusht' environment
--dataset.repo_id=lerobot/pusht # <- train on this dataset --dataset.repo_id=lerobot/pusht # <- train on this dataset
@@ -279,7 +279,7 @@ lerobot-train \
#### Train a policy from scratch - config file + CLI #### Train a policy from scratch - config file + CLI
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--config_path=path/to/pretrained_model \ # <- can also be a repo_id --config_path=path/to/pretrained_model \ # <- can also be a repo_id
--policy.n_action_steps=80 # <- you may still override values --policy.n_action_steps=80 # <- you may still override values
``` ```
@@ -287,7 +287,7 @@ lerobot-train \
#### Resume/continue a training run #### Resume/continue a training run
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--config_path=checkpoint/pretrained_model/ \ --config_path=checkpoint/pretrained_model/ \
--resume=true \ --resume=true \
--steps=200000 # <- you can change some training parameters --steps=200000 # <- you can change some training parameters
@@ -296,7 +296,7 @@ lerobot-train \
#### Fine-tuning #### Fine-tuning
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--policy.path=lerobot/act_aloha_sim_transfer_cube_human \ # <- can also be a local path to a checkpoint --policy.path=lerobot/act_aloha_sim_transfer_cube_human \ # <- can also be a local path to a checkpoint
--dataset.repo_id=lerobot/aloha_sim_insertion_human \ --dataset.repo_id=lerobot/aloha_sim_insertion_human \
--env.type=aloha \ --env.type=aloha \
+1 -1
View File
@@ -18,7 +18,7 @@ Replays the actions of an episode from a dataset on a robot.
Example: Example:
```shell ```shell
lerobot-replay \ python -m lerobot.replay \
--robot.type=so100_follower \ --robot.type=so100_follower \
--robot.port=/dev/tty.usbmodem58760431541 \ --robot.port=/dev/tty.usbmodem58760431541 \
--robot.id=black \ --robot.id=black \
+6 -6
View File
@@ -25,7 +25,7 @@ discord = "https://discord.gg/s3KuuzsPFb"
[project] [project]
name = "lerobot" name = "lerobot"
version = "0.3.4" version = "0.3.3"
description = "🤗 LeRobot: State-of-the-art Machine Learning for Real-World Robotics in Pytorch" description = "🤗 LeRobot: State-of-the-art Machine Learning for Real-World Robotics in Pytorch"
readme = "README.md" readme = "README.md"
license = { text = "Apache-2.0" } license = { text = "Apache-2.0" }
@@ -257,8 +257,8 @@ default.extend-ignore-identifiers-re = [
# color = true # color = true
# paths = ["src/lerobot"] # paths = ["src/lerobot"]
[tool.mypy] # [tool.mypy]
python_version = "3.10" # python_version = "3.10"
warn_return_any = true # warn_return_any = true
warn_unused_configs = true # warn_unused_configs = true
ignore_missing_imports = false # ignore_missing_imports = false
+1 -1
View File
@@ -18,7 +18,7 @@ Helper to recalibrate your device (robot or teleoperator).
Example: Example:
```shell ```shell
lerobot-calibrate \ python -m lerobot.calibrate \
--teleop.type=so100_leader \ --teleop.type=so100_leader \
--teleop.port=/dev/tty.usbmodem58760431551 \ --teleop.port=/dev/tty.usbmodem58760431551 \
--teleop.id=blue --teleop.id=blue
+3 -2
View File
@@ -60,7 +60,7 @@ class OpenCVCamera(Camera):
or port changes, especially on Linux. Use the provided utility script to find or port changes, especially on Linux. Use the provided utility script to find
available camera indices or paths: available camera indices or paths:
```bash ```bash
lerobot-find-cameras opencv python -m lerobot.find_cameras opencv
``` ```
The camera's default settings (FPS, resolution, color mode) are used unless The camera's default settings (FPS, resolution, color mode) are used unless
@@ -165,7 +165,8 @@ class OpenCVCamera(Camera):
self.videocapture.release() self.videocapture.release()
self.videocapture = None self.videocapture = None
raise ConnectionError( raise ConnectionError(
f"Failed to open {self}.Run `lerobot-find-cameras opencv` to find available cameras." f"Failed to open {self}."
f"Run `python -m lerobot.find_cameras opencv` to find available cameras."
) )
self._configure_capture_settings() self._configure_capture_settings()
@@ -51,7 +51,7 @@ class RealSenseCamera(Camera):
Use the provided utility script to find available camera indices and default profiles: Use the provided utility script to find available camera indices and default profiles:
```bash ```bash
lerobot-find-cameras realsense python -m lerobot.find_cameras realsense
``` ```
A `RealSenseCamera` instance requires a configuration object specifying the A `RealSenseCamera` instance requires a configuration object specifying the
@@ -176,7 +176,8 @@ class RealSenseCamera(Camera):
self.rs_profile = None self.rs_profile = None
self.rs_pipeline = None self.rs_pipeline = None
raise ConnectionError( raise ConnectionError(
f"Failed to open {self}.Run `lerobot-find-cameras realsense` to find available cameras." f"Failed to open {self}."
"Run `python -m lerobot.find_cameras realsense` to find available cameras."
) from e ) from e
self._configure_capture_settings() self._configure_capture_settings()
+4 -6
View File
@@ -486,8 +486,8 @@ class LeRobotDataset(torch.utils.data.Dataset):
self.episode_data_index = get_episode_data_index(self.meta.episodes, self.episodes) self.episode_data_index = get_episode_data_index(self.meta.episodes, self.episodes)
# Check timestamps # Check timestamps
timestamps = torch.stack(self.hf_dataset["timestamp"]).numpy() timestamps = torch.tensor(self.hf_dataset["timestamp"]).numpy()
episode_indices = torch.stack(self.hf_dataset["episode_index"]).numpy() episode_indices = torch.tensor(self.hf_dataset["episode_index"]).numpy()
ep_data_index_np = {k: t.numpy() for k, t in self.episode_data_index.items()} ep_data_index_np = {k: t.numpy() for k, t in self.episode_data_index.items()}
check_timestamps_sync(timestamps, episode_indices, ep_data_index_np, self.fps, self.tolerance_s) check_timestamps_sync(timestamps, episode_indices, ep_data_index_np, self.fps, self.tolerance_s)
@@ -667,7 +667,7 @@ class LeRobotDataset(torch.utils.data.Dataset):
for key in self.meta.video_keys: for key in self.meta.video_keys:
if query_indices is not None and key in query_indices: if query_indices is not None and key in query_indices:
timestamps = self.hf_dataset.select(query_indices[key])["timestamp"] timestamps = self.hf_dataset.select(query_indices[key])["timestamp"]
query_timestamps[key] = torch.stack(timestamps).tolist() query_timestamps[key] = torch.tensor(timestamps).tolist()
else: else:
query_timestamps[key] = [current_ts] query_timestamps[key] = [current_ts]
@@ -675,7 +675,7 @@ class LeRobotDataset(torch.utils.data.Dataset):
def _query_hf_dataset(self, query_indices: dict[str, list[int]]) -> dict: def _query_hf_dataset(self, query_indices: dict[str, list[int]]) -> dict:
return { return {
key: torch.stack(self.hf_dataset.select(q_idx)[key]) key: torch.tensor(self.hf_dataset.select(q_idx)[key])
for key, q_idx in query_indices.items() for key, q_idx in query_indices.items()
if key not in self.meta.video_keys if key not in self.meta.video_keys
} }
@@ -825,8 +825,6 @@ class LeRobotDataset(torch.utils.data.Dataset):
""" """
if not episode_data: if not episode_data:
episode_buffer = self.episode_buffer episode_buffer = self.episode_buffer
else:
episode_buffer = episode_data
validate_episode_buffer(episode_buffer, self.meta.total_episodes, self.features) validate_episode_buffer(episode_buffer, self.meta.total_episodes, self.features)
+2 -2
View File
@@ -632,7 +632,7 @@ def cycle(iterable):
iterator = iter(iterable) iterator = iter(iterable)
def create_branch(repo_id, *, branch: str, repo_type: str | None = None) -> None: def create_branch(repo_id, *, branch: str, repo_type: str | None = None, revision: str | None = None) -> None:
"""Create a branch on a existing Hugging Face repo. Delete the branch if it already """Create a branch on a existing Hugging Face repo. Delete the branch if it already
exists before creating it. exists before creating it.
""" """
@@ -644,7 +644,7 @@ def create_branch(repo_id, *, branch: str, repo_type: str | None = None) -> None
if ref in refs: if ref in refs:
api.delete_branch(repo_id, repo_type=repo_type, branch=branch) api.delete_branch(repo_id, repo_type=repo_type, branch=branch)
api.create_branch(repo_id, repo_type=repo_type, branch=branch) api.create_branch(repo_id, repo_type=repo_type, branch=branch, revision=revision)
def create_lerobot_dataset_card( def create_lerobot_dataset_card(
@@ -105,6 +105,7 @@ import filecmp
import json import json
import logging import logging
import math import math
import re
import shutil import shutil
import subprocess import subprocess
import tempfile import tempfile
@@ -119,6 +120,7 @@ from huggingface_hub import HfApi
from huggingface_hub.errors import EntryNotFoundError, HfHubHTTPError from huggingface_hub.errors import EntryNotFoundError, HfHubHTTPError
from safetensors.torch import load_file from safetensors.torch import load_file
from lerobot.datasets.backward_compatibility import CompatibilityError
from lerobot.datasets.utils import ( from lerobot.datasets.utils import (
DEFAULT_CHUNK_SIZE, DEFAULT_CHUNK_SIZE,
DEFAULT_PARQUET_PATH, DEFAULT_PARQUET_PATH,
@@ -130,6 +132,7 @@ from lerobot.datasets.utils import (
create_branch, create_branch,
create_lerobot_dataset_card, create_lerobot_dataset_card,
flatten_dict, flatten_dict,
get_repo_versions,
get_safe_version, get_safe_version,
load_json, load_json,
unflatten_dict, unflatten_dict,
@@ -205,7 +208,7 @@ def convert_stats_to_json(v1_dir: Path, v2_dir: Path) -> None:
def get_features_from_hf_dataset( def get_features_from_hf_dataset(
dataset: Dataset, robot_config: RobotConfig | None = None dataset: Dataset, robot_config: RobotConfig | None = None
) -> dict[str, list]: ) -> dict[str, list]:
robot_config = parse_robot_config(robot_config) robot_config = parse_robot_config(robot_config) if robot_config else None
features = {} features = {}
for key, ft in dataset.features.items(): for key, ft in dataset.features.items():
if isinstance(ft, datasets.Value): if isinstance(ft, datasets.Value):
@@ -325,7 +328,19 @@ def move_videos(
video_files = [str(f.relative_to(work_dir)) for f in work_dir.glob("videos*/*/*/*.mp4")] video_files = [str(f.relative_to(work_dir)) for f in work_dir.glob("videos*/*/*/*.mp4")]
videos_moved = True # Videos have already been moved videos_moved = True # Videos have already been moved
assert len(video_files) == total_episodes * len(video_keys) expected_count = total_episodes * len(video_keys)
if len(video_files) != expected_count:
print(
f"Warning: expected {expected_count} video files "
f"({total_episodes} episodes x {len(video_keys)} keys), "
f"found {len(video_files)}. Keeping only videos matching existing episodes."
)
episode_pattern = re.compile(r"episode_(\d+)")
valid_episodes = set(range(total_episodes))
video_files = [
f for f in video_files
if (m := episode_pattern.search(f)) and int(m.group(1)) in valid_episodes
]
lfs_untracked_videos = _get_lfs_untracked_videos(work_dir, video_files) lfs_untracked_videos = _get_lfs_untracked_videos(work_dir, video_files)
@@ -442,8 +457,16 @@ def convert_dataset(
test_branch: str | None = None, test_branch: str | None = None,
**card_kwargs, **card_kwargs,
): ):
v1 = get_safe_version(repo_id, V16) try:
v1x_dir = local_dir / V16 / repo_id v1 = get_safe_version(repo_id, V16)
except CompatibilityError:
hub_versions = get_repo_versions(repo_id)
v1x_versions = [v for v in hub_versions if v.major == 1]
if not v1x_versions:
raise
v1 = f"v{max(v1x_versions)}"
logging.warning(f"v1.6 not found for {repo_id}, falling back to {v1}")
v1x_dir = local_dir / v1 / repo_id
v20_dir = local_dir / V20 / repo_id v20_dir = local_dir / V20 / repo_id
v1x_dir.mkdir(parents=True, exist_ok=True) v1x_dir.mkdir(parents=True, exist_ok=True)
v20_dir.mkdir(parents=True, exist_ok=True) v20_dir.mkdir(parents=True, exist_ok=True)
@@ -455,7 +478,7 @@ def convert_dataset(
branch = "main" branch = "main"
if test_branch: if test_branch:
branch = test_branch branch = test_branch
create_branch(repo_id=repo_id, branch=test_branch, repo_type="dataset") create_branch(repo_id=repo_id, branch=test_branch, repo_type="dataset", revision=v1)
metadata_v1 = load_json(v1x_dir / V1_INFO_PATH) metadata_v1 = load_json(v1x_dir / V1_INFO_PATH)
dataset = datasets.load_dataset("parquet", data_dir=v1x_dir / "data", split="train") dataset = datasets.load_dataset("parquet", data_dir=v1x_dir / "data", split="train")
@@ -564,6 +587,12 @@ def convert_dataset(
"features": features, "features": features,
} }
write_json(metadata_v2_0, v20_dir / INFO_PATH) write_json(metadata_v2_0, v20_dir / INFO_PATH)
info = load_json(v20_dir / INFO_PATH)
if "language_instruction" in info.get("features", {}):
del info["features"]["language_instruction"]
write_json(info, v20_dir / INFO_PATH)
convert_stats_to_json(v1x_dir, v20_dir) convert_stats_to_json(v1x_dir, v20_dir)
card = create_lerobot_dataset_card(tags=repo_tags, dataset_info=metadata_v2_0, **card_kwargs) card = create_lerobot_dataset_card(tags=repo_tags, dataset_info=metadata_v2_0, **card_kwargs)
@@ -677,6 +706,8 @@ def main():
if args.robot is not None: if args.robot is not None:
robot_config = make_robot_config(args.robot) robot_config = make_robot_config(args.robot)
else:
robot_config = None
del args.robot del args.robot
@@ -85,7 +85,7 @@ def convert_dataset(
path_in_repo=STATS_PATH, repo_id=dataset.repo_id, revision=branch, repo_type="dataset" path_in_repo=STATS_PATH, repo_id=dataset.repo_id, revision=branch, repo_type="dataset"
) )
hub_api.create_tag(repo_id, tag=CODEBASE_VERSION, revision=branch, repo_type="dataset") #hub_api.create_tag(repo_id, tag=CODEBASE_VERSION, revision=branch, repo_type="dataset")
if __name__ == "__main__": if __name__ == "__main__":
@@ -45,6 +45,8 @@ def convert_episode_stats(dataset: LeRobotDataset, ep_idx: int):
axes_to_reduce = (0, 2, 3) if ft["dtype"] in ["image", "video"] else 0 axes_to_reduce = (0, 2, 3) if ft["dtype"] in ["image", "video"] else 0
keepdims = True if ft["dtype"] in ["image", "video"] else ep_ft_data.ndim == 1 keepdims = True if ft["dtype"] in ["image", "video"] else ep_ft_data.ndim == 1
if ft["dtype"] in ["image", "video"] and ep_ft_data.ndim == 3:
ep_ft_data = np.expand_dims(ep_ft_data, axis=0)
ep_stats[key] = get_feature_stats(ep_ft_data, axis=axes_to_reduce, keepdims=keepdims) ep_stats[key] = get_feature_stats(ep_ft_data, axis=axes_to_reduce, keepdims=keepdims)
if ft["dtype"] in ["image", "video"]: # remove batch dim if ft["dtype"] in ["image", "video"]: # remove batch dim
+1 -1
View File
@@ -20,7 +20,7 @@ Helper to find the camera devices available in your system.
Example: Example:
```shell ```shell
lerobot-find-cameras python -m lerobot.find_cameras
``` ```
""" """
+1 -1
View File
@@ -18,7 +18,7 @@ Helper to find the USB port associated with your MotorsBus.
Example: Example:
```shell ```shell
lerobot-find-port python -m lerobot.find_port
``` ```
""" """
-2
View File
@@ -107,8 +107,6 @@ X_SERIES_ENCODINGS_TABLE = {
"Goal_PWM": X_SERIES_CONTROL_TABLE["Goal_PWM"][1], "Goal_PWM": X_SERIES_CONTROL_TABLE["Goal_PWM"][1],
"Goal_Current": X_SERIES_CONTROL_TABLE["Goal_Current"][1], "Goal_Current": X_SERIES_CONTROL_TABLE["Goal_Current"][1],
"Goal_Velocity": X_SERIES_CONTROL_TABLE["Goal_Velocity"][1], "Goal_Velocity": X_SERIES_CONTROL_TABLE["Goal_Velocity"][1],
"Goal_Position": X_SERIES_CONTROL_TABLE["Goal_Position"][1],
"Present_Position": X_SERIES_CONTROL_TABLE["Present_Position"][1],
"Present_PWM": X_SERIES_CONTROL_TABLE["Present_PWM"][1], "Present_PWM": X_SERIES_CONTROL_TABLE["Present_PWM"][1],
"Present_Current": X_SERIES_CONTROL_TABLE["Present_Current"][1], "Present_Current": X_SERIES_CONTROL_TABLE["Present_Current"][1],
"Present_Velocity": X_SERIES_CONTROL_TABLE["Present_Velocity"][1], "Present_Velocity": X_SERIES_CONTROL_TABLE["Present_Velocity"][1],
+2 -2
View File
@@ -222,7 +222,7 @@ class MotorsBus(abc.ABC):
A MotorsBus subclass instance requires a port (e.g. `FeetechMotorsBus(port="/dev/tty.usbmodem575E0031751"`)). A MotorsBus subclass instance requires a port (e.g. `FeetechMotorsBus(port="/dev/tty.usbmodem575E0031751"`)).
To find the port, you can run our utility script: To find the port, you can run our utility script:
```bash ```bash
lerobot-find-port.py python -m lerobot.find_port.py
>>> Finding all available ports for the MotorsBus. >>> Finding all available ports for the MotorsBus.
>>> ["/dev/tty.usbmodem575E0032081", "/dev/tty.usbmodem575E0031751"] >>> ["/dev/tty.usbmodem575E0032081", "/dev/tty.usbmodem575E0031751"]
>>> Remove the usb cable from your MotorsBus and press Enter when done. >>> Remove the usb cable from your MotorsBus and press Enter when done.
@@ -446,7 +446,7 @@ class MotorsBus(abc.ABC):
except (FileNotFoundError, OSError, serial.SerialException) as e: except (FileNotFoundError, OSError, serial.SerialException) as e:
raise ConnectionError( raise ConnectionError(
f"\nCould not connect on port '{self.port}'. Make sure you are using the correct port." f"\nCould not connect on port '{self.port}'. Make sure you are using the correct port."
"\nTry running `lerobot-find-port`\n" "\nTry running `python -m lerobot.find_port`\n"
) from e ) from e
@abc.abstractmethod @abc.abstractmethod
+2 -2
View File
@@ -30,7 +30,7 @@ pip install -e ".[pi0]"
Example of finetuning the pi0 pretrained model (`pi0_base` in `openpi`): Example of finetuning the pi0 pretrained model (`pi0_base` in `openpi`):
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--policy.path=lerobot/pi0 \ --policy.path=lerobot/pi0 \
--dataset.repo_id=danaaubakirova/koch_test --dataset.repo_id=danaaubakirova/koch_test
``` ```
@@ -38,7 +38,7 @@ lerobot-train \
Example of finetuning the pi0 neural network with PaliGemma and expert Gemma Example of finetuning the pi0 neural network with PaliGemma and expert Gemma
pretrained with VLM default parameters before pi0 finetuning: pretrained with VLM default parameters before pi0 finetuning:
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--policy.type=pi0 \ --policy.type=pi0 \
--dataset.repo_id=danaaubakirova/koch_test --dataset.repo_id=danaaubakirova/koch_test
``` ```
@@ -25,14 +25,14 @@ Disclaimer: It is not expected to perform as well as the original implementation
Example of finetuning the pi0+FAST pretrained model (`pi0_fast_base` in `openpi`): Example of finetuning the pi0+FAST pretrained model (`pi0_fast_base` in `openpi`):
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--policy.path=lerobot/pi0fast_base \ --policy.path=lerobot/pi0fast_base \
--dataset.repo_id=danaaubakirova/koch_test --dataset.repo_id=danaaubakirova/koch_test
``` ```
Example of training the pi0+FAST neural network with from scratch: Example of training the pi0+FAST neural network with from scratch:
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--policy.type=pi0fast \ --policy.type=pi0fast \
--dataset.repo_id=danaaubakirova/koch_test --dataset.repo_id=danaaubakirova/koch_test
``` ```
@@ -28,7 +28,7 @@ pip install -e ".[smolvla]"
Example of finetuning the smolvla pretrained model (`smolvla_base`): Example of finetuning the smolvla pretrained model (`smolvla_base`):
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--policy.path=lerobot/smolvla_base \ --policy.path=lerobot/smolvla_base \
--dataset.repo_id=danaaubakirova/svla_so100_task1_v3 \ --dataset.repo_id=danaaubakirova/svla_so100_task1_v3 \
--batch_size=64 \ --batch_size=64 \
@@ -38,7 +38,7 @@ lerobot-train \
Example of finetuning a smolVLA. SmolVLA is composed of a pretrained VLM, Example of finetuning a smolVLA. SmolVLA is composed of a pretrained VLM,
and an action expert. and an action expert.
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--policy.type=smolvla \ --policy.type=smolvla \
--dataset.repo_id=danaaubakirova/svla_so100_task1_v3 \ --dataset.repo_id=danaaubakirova/svla_so100_task1_v3 \
--batch_size=64 \ --batch_size=64 \
+2 -2
View File
@@ -18,7 +18,7 @@ Records a dataset. Actions for the robot can be either generated by teleoperatio
Example: Example:
```shell ```shell
lerobot-record \ python -m lerobot.record \
--robot.type=so100_follower \ --robot.type=so100_follower \
--robot.port=/dev/tty.usbmodem58760431541 \ --robot.port=/dev/tty.usbmodem58760431541 \
--robot.cameras="{laptop: {type: opencv, camera_index: 0, width: 640, height: 480}}" \ --robot.cameras="{laptop: {type: opencv, camera_index: 0, width: 640, height: 480}}" \
@@ -36,7 +36,7 @@ lerobot-record \
Example recording with bimanual so100: Example recording with bimanual so100:
```shell ```shell
lerobot-record \ python -m lerobot.record \
--robot.type=bi_so100_follower \ --robot.type=bi_so100_follower \
--robot.left_arm_port=/dev/tty.usbmodem5A460851411 \ --robot.left_arm_port=/dev/tty.usbmodem5A460851411 \
--robot.right_arm_port=/dev/tty.usbmodem5A460812391 \ --robot.right_arm_port=/dev/tty.usbmodem5A460812391 \
+2 -2
View File
@@ -18,7 +18,7 @@ Replays the actions of an episode from a dataset on a robot.
Examples: Examples:
```shell ```shell
lerobot-replay \ python -m lerobot.replay \
--robot.type=so100_follower \ --robot.type=so100_follower \
--robot.port=/dev/tty.usbmodem58760431541 \ --robot.port=/dev/tty.usbmodem58760431541 \
--robot.id=black \ --robot.id=black \
@@ -28,7 +28,7 @@ lerobot-replay \
Example replay with bimanual so100: Example replay with bimanual so100:
```shell ```shell
lerobot-replay \ python -m lerobot.replay \
--robot.type=bi_so100_follower \ --robot.type=bi_so100_follower \
--robot.left_arm_port=/dev/tty.usbmodem5A460851411 \ --robot.left_arm_port=/dev/tty.usbmodem5A460851411 \
--robot.right_arm_port=/dev/tty.usbmodem5A460812391 \ --robot.right_arm_port=/dev/tty.usbmodem5A460812391 \
@@ -161,11 +161,6 @@ class SO100Follower(Robot):
self.bus.write("I_Coefficient", motor, 0) self.bus.write("I_Coefficient", motor, 0)
self.bus.write("D_Coefficient", motor, 32) self.bus.write("D_Coefficient", motor, 32)
if motor == "gripper":
self.bus.write("Max_Torque_Limit", motor, 500) # 50% of max torque to avoid burnout
self.bus.write("Protection_Current", motor, 250) # 50% of max current to avoid burnout
self.bus.write("Overload_Torque", motor, 25) # 25% torque when overloaded
def setup_motors(self) -> None: def setup_motors(self) -> None:
for motor in reversed(self.bus.motors): for motor in reversed(self.bus.motors):
input(f"Connect the controller board to the '{motor}' motor only and press enter.") input(f"Connect the controller board to the '{motor}' motor only and press enter.")
@@ -157,13 +157,6 @@ class SO101Follower(Robot):
self.bus.write("I_Coefficient", motor, 0) self.bus.write("I_Coefficient", motor, 0)
self.bus.write("D_Coefficient", motor, 32) self.bus.write("D_Coefficient", motor, 32)
if motor == "gripper":
self.bus.write(
"Max_Torque_Limit", motor, 500
) # 50% of the max torque limit to avoid burnout
self.bus.write("Protection_Current", motor, 250) # 50% of max current to avoid burnout
self.bus.write("Overload_Torque", motor, 25) # 25% torque when overloaded
def setup_motors(self) -> None: def setup_motors(self) -> None:
for motor in reversed(self.bus.motors): for motor in reversed(self.bus.motors):
input(f"Connect the controller board to the '{motor}' motor only and press enter.") input(f"Connect the controller board to the '{motor}' motor only and press enter.")
+2 -2
View File
@@ -141,10 +141,10 @@ python lerobot/scripts/control_robot.py \
## Train a policy ## Train a policy
To train a policy to control your robot, use the [`lerobot-train`](../src/lerobot/scripts/train.py) script. A few arguments are required. Here is an example command: To train a policy to control your robot, use the [`python -m lerobot.scripts.train`](../src/lerobot/scripts/train.py) script. A few arguments are required. Here is an example command:
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--dataset.repo_id=${HF_USER}/aloha_test \ --dataset.repo_id=${HF_USER}/aloha_test \
--policy.type=act \ --policy.type=act \
--output_dir=outputs/train/act_aloha_test \ --output_dir=outputs/train/act_aloha_test \
+2 -2
View File
@@ -21,7 +21,7 @@ You want to evaluate a model from the hub (eg: https://huggingface.co/lerobot/di
for 10 episodes. for 10 episodes.
``` ```
lerobot-eval \ python -m lerobot.scripts.eval \
--policy.path=lerobot/diffusion_pusht \ --policy.path=lerobot/diffusion_pusht \
--env.type=pusht \ --env.type=pusht \
--eval.batch_size=10 \ --eval.batch_size=10 \
@@ -32,7 +32,7 @@ lerobot-eval \
OR, you want to evaluate a model checkpoint from the LeRobot training script for 10 episodes. OR, you want to evaluate a model checkpoint from the LeRobot training script for 10 episodes.
``` ```
lerobot-eval \ python -m lerobot.scripts.eval \
--policy.path=outputs/train/diffusion_pusht/checkpoints/005000/pretrained_model \ --policy.path=outputs/train/diffusion_pusht/checkpoints/005000/pretrained_model \
--env.type=pusht \ --env.type=pusht \
--eval.batch_size=10 \ --eval.batch_size=10 \
@@ -302,6 +302,11 @@ class RobotClient:
self.logger.debug(f"Current latest action: {latest_action}") self.logger.debug(f"Current latest action: {latest_action}")
# Get queue state before changes
old_size, old_timesteps = self._inspect_action_queue()
if not old_timesteps:
old_timesteps = [latest_action] # queue was empty
# Get queue state before changes # Get queue state before changes
old_size, old_timesteps = self._inspect_action_queue() old_size, old_timesteps = self._inspect_action_queue()
if not old_timesteps: if not old_timesteps:
+1 -1
View File
@@ -18,7 +18,7 @@ Helper to set motor ids and baudrate.
Example: Example:
```shell ```shell
lerobot-setup-motors \ python -m lerobot.setup_motors \
--teleop.type=so100_leader \ --teleop.type=so100_leader \
--teleop.port=/dev/tty.usbmodem575E0031751 --teleop.port=/dev/tty.usbmodem575E0031751
``` ```
+2 -2
View File
@@ -18,7 +18,7 @@ Simple script to control a robot from teleoperation.
Example: Example:
```shell ```shell
lerobot-teleoperate \ python -m lerobot.teleoperate \
--robot.type=so101_follower \ --robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem58760431541 \ --robot.port=/dev/tty.usbmodem58760431541 \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 1920, height: 1080, fps: 30}}" \ --robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 1920, height: 1080, fps: 30}}" \
@@ -32,7 +32,7 @@ lerobot-teleoperate \
Example teleoperation with bimanual so100: Example teleoperation with bimanual so100:
```shell ```shell
lerobot-teleoperate \ python -m lerobot.teleoperate \
--robot.type=bi_so100_follower \ --robot.type=bi_so100_follower \
--robot.left_arm_port=/dev/tty.usbmodem5A460851411 \ --robot.left_arm_port=/dev/tty.usbmodem5A460851411 \
--robot.right_arm_port=/dev/tty.usbmodem5A460812391 \ --robot.right_arm_port=/dev/tty.usbmodem5A460812391 \
@@ -44,7 +44,7 @@ Below is the short version on how to train and run inference/eval:
### Train from scratch ### Train from scratch
```bash ```bash
lerobot-train \ python -m lerobot.scripts.train \
--dataset.repo_id=${HF_USER}/<dataset> \ --dataset.repo_id=${HF_USER}/<dataset> \
--policy.type=act \ --policy.type=act \
--output_dir=outputs/train/<desired_policy_repo_id> \ --output_dir=outputs/train/<desired_policy_repo_id> \
@@ -59,7 +59,7 @@ _Writes checkpoints to `outputs/train/<desired_policy_repo_id>/checkpoints/`._
### Evaluate the policy/run inference ### Evaluate the policy/run inference
```bash ```bash
lerobot-record \ python -m lerobot.record \
--robot.type=so100_follower \ --robot.type=so100_follower \
--dataset.repo_id=<hf_user>/eval_<dataset> \ --dataset.repo_id=<hf_user>/eval_<dataset> \
--policy.path=<hf_user>/<desired_policy_repo_id> \ --policy.path=<hf_user>/<desired_policy_repo_id> \
+3 -2
View File
@@ -17,9 +17,10 @@ import time
def busy_wait(seconds): def busy_wait(seconds):
if platform.system() == "Darwin" or platform.system() == "Windows": if platform.system() == "Darwin":
# On Mac and Windows, `time.sleep` is not accurate and we need to use this while loop trick, # On Mac, `time.sleep` is not accurate and we need to use this while loop trick,
# but it consumes CPU cycles. # but it consumes CPU cycles.
# TODO(rcadene): find an alternative: from python 11, time.sleep is precise
end_time = time.perf_counter() + seconds end_time = time.perf_counter() + seconds
while time.perf_counter() < end_time: while time.perf_counter() < end_time:
pass pass