LeRobot&SO101

此文档以 Windiws + WSL(Ubuntu) 为开发环境,如果你直接使用 Ubuntu系统可以跳过部分步骤。

一、安装 WSL

在管理员模式下打开 PowerShell 运行以下命令,然后重启电脑。

wsl --install

使用

wsl.exe --list --online

查看可用 Linux 发行版列表。

❯ wsl.exe --list --online
以下是可安装的有效分发的列表。
使用“wsl.exe --install <Distro>”安装。

NAME                            FRIENDLY NAME
AlmaLinux-8                     AlmaLinux OS 8
AlmaLinux-9                     AlmaLinux OS 9
AlmaLinux-Kitten-10             AlmaLinux OS Kitten 10
AlmaLinux-10                    AlmaLinux OS 10
Debian                          Debian GNU/Linux
FedoraLinux-44                  Fedora Linux 44
FedoraLinux-43                  Fedora Linux 43
SUSE-Linux-Enterprise-15-SP7    SUSE Linux Enterprise 15 SP7
SUSE-Linux-Enterprise-16.0      SUSE Linux Enterprise 16.0
Ubuntu                          Ubuntu
Ubuntu-26.04                    Ubuntu 26.04 LTS
Ubuntu-24.04                    Ubuntu 24.04 LTS
Ubuntu-22.04                    Ubuntu 22.04 LTS
archlinux                       Arch Linux
eLxr                            eLxr 12.12.0.0 GNU/Linux
kali-linux                      Kali Linux Rolling
openSUSE-Tumbleweed             openSUSE Tumbleweed
openSUSE-Leap-16.0              openSUSE Leap 16.0
OracleLinux_7_9                 Oracle Linux 7.9
OracleLinux_8_10                Oracle Linux 8.10
OracleLinux_9_5                 Oracle Linux 9.5
SUSE-Linux-Enterprise-15-SP6    SUSE Linux Enterprise 15 SP6

输入

wsl.exe --install -d Ubuntu-24.04

安装 Ubuntu-24.04,你也可以使用 Ubuntu 的其他版本。

在开始菜单搜索 Ubuntu,单击即可打开命令行终端。

二、安装 Miniconda

在上一步打开的控制台中输入

curl -O https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh

等待脚本下载

  % Total    % Received % Xferd  Average Speed  Time    Time    Time   Current
                                 Dload  Upload  Total   Spent   Left   Speed
 70 188.1M  70 132.3M   0      0  4.11M      0   00:45   00:32   00:13  3.80M

执行安装脚本

bash ~/Miniconda3-latest-Linux-x86_64.sh

设置全部默认,无脑 yes 下一步即可。

完成后输入 conda --version 可以查看到版本号就代表安装成功了,如果提示找不到 conda 命令,尝试重启 wsl 控制台。

(base) shawn@pc:~$ conda --version
conda 26.5.3

更多信息可以查看 微软官方文档

三、安装 LeRobot

更多信息可以查看 LeRobot中文文档

1.下载、安装 miniforge:

wget "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh"
bash Miniforge3-$(uname)-$(uname -m).sh

完成后重启 wsl 控制台。

创建一个名为 lerobot 的 Python 3.12 虚拟环境

conda create -y -n lerobot python=3.12

看见如下输出即为成功

Downloading and Extracting Packages:

Preparing transaction: done
Verifying transaction: done
Executing transaction: done
#
# To activate this environment, use
#
#     $ conda activate lerobot
#
# To deactivate an active environment, use
#
#     $ conda deactivate

使用 conda activate lerobot 命令进入刚刚创建的虚拟环境,使用 conda deactivate 退出虚拟环境。

(base) shawn@114514yyds:~$
(base) shawn@114514yyds:~$ conda activate lerobot
(lerobot) shawn@114514yyds:~$ conda deactivate
(base) shawn@114514yyds:~$

2.安装 evdev

conda activate lerobot
conda install evdev -c conda-forge

3.安装 ffmpeg

conda install ffmpeg -c conda-forge

4.安装 LeRobot

克隆并进入项目目录

git clone https://github.com/huggingface/lerobot.git
cd lerobot

以可编辑模式安装库,安装时确保网络通畅。

pip install -e .

安装电机控制组件

pip install -e ".[feetech]"

四、驱动机械臂

1.安装 usbipd

打开一个 Windows 终端

winget install usbipd

查看当前的 usb 设备

usbipd list
Connected:
BUSID  VID:PID    DEVICE                                                        STATE
1-6    0461:5b4a  USB 输入设备                                                  Not shared
1-11   048d:5702  USB 输入设备                                                  Not shared
1-13   17ef:6099  USB 输入设备                                                  Not shared
1-14   8087:0033  英特尔(R) 无线 Bluetooth(R)                                   Not shared
2-3    1bcf:2281  JYU2C-2083                                                    Shared
2-4    1bcf:2281  JYU2C-2083                                                    Shared

Persisted:
GUID                                  DEVICE
01e5c160-1ccb-406b-8fc1-0e7d7242cf4f  USB-Enhanced-SERIAL CH343 (COM8)
3a2ecc41-718f-4683-9678-54b1953fd5ac  icspring camera
6ae2504b-b1ee-4cee-842b-baea9d48d3f5  icspring camera
737fc7db-e7e2-4b51-b1c2-918f1aa4e3ef  icspring camera
7dd49518-1480-4653-bb07-0ab347fa75f2  icspring camera
b10ae574-cb8f-4154-9ae8-a62ad8ddb2f0  USB-Enhanced-SERIAL CH343 (COM10)
ed0cf675-f16f-4bf7-a612-e8509cff0509  USB-Enhanced-SERIAL CH343 (COM9)
f508f19f-a548-41e2-97ad-8b79a4236ad8  icspring camera

插上机械臂数据线后

Connected:
BUSID  VID:PID    DEVICE                                                        STATE
1-6    0461:5b4a  USB 输入设备                                                  Not shared
1-11   048d:5702  USB 输入设备                                                  Not shared
1-13   17ef:6099  USB 输入设备                                                  Not shared
1-14   8087:0033  英特尔(R) 无线 Bluetooth(R)                                   Not shared
2-3    1bcf:2281  JYU2C-2083                                                    Shared
2-4    1bcf:2281  JYU2C-2083                                                    Shared
4-1    1a86:55d3  USB-Enhanced-SERIAL CH343 (COM10)                             Shared
4-2    1a86:55d3  USB-Enhanced-SERIAL CH343 (COM9)                              Shared

Persisted:
GUID                                  DEVICE
01e5c160-1ccb-406b-8fc1-0e7d7242cf4f  USB-Enhanced-SERIAL CH343 (COM8)
3a2ecc41-718f-4683-9678-54b1953fd5ac  icspring camera
6ae2504b-b1ee-4cee-842b-baea9d48d3f5  icspring camera
737fc7db-e7e2-4b51-b1c2-918f1aa4e3ef  icspring camera
7dd49518-1480-4653-bb07-0ab347fa75f2  icspring camera
f508f19f-a548-41e2-97ad-8b79a4236ad8  icspring camera

对比发现

4-1    1a86:55d3  USB-Enhanced-SERIAL CH343 (COM10)                             Shared
4-2    1a86:55d3  USB-Enhanced-SERIAL CH343 (COM9)                              Shared

两个新增设备。

补充关于 usbipd 的说明
STATE 这一列表示每个 USB 设备当前在 usbipd-win 里的共享/连接状态。它反映设备是否已经被"绑定"以便通过 USB/IP 转发给远程主机(比如 WSL2 或另一台机器)。
常见的 STATE 取值

┌─────────────────┬──────────────────────────────────────────────────────────────────────────────────────┐
│      STATE      │                                         含义                                         │
├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
│ Not shared      │ 设备未绑定,不能被远程连接。这是默认状态。                                                │
├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
│ Shared          │ 设备已通过 usbipd bind 绑定,可以被远程客户端(如 WSL)attach 使用,但当前还没有被连接。      │
├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
│ Shared (forced) │ 用 --force 强制绑定,会替换掉原本的 Windows 驱动,连一些"顽固"设备也能共享。                │
├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
│ Attached        │ 设备已经被某个远程客户端连接并正在使用(比如已经 attach 到 WSL 里)。                       │
└─────────────────┴──────────────────────────────────────────────────────────────────────────────────────┘

对应你的输出

- 1-6、1-11、1-13、1-14 → Not shared:这些(键盘鼠标、蓝牙等本机输入设备)没有共享,仍由 Windows 本地使用。
- 2-3、2-4(JYU2C-2083)→ Shared:这两个设备已经绑定,处于"可被远程 attach"的待命状态,但目前还没有被 attach。

状态流转关系

Not shared  --(usbipd bind)-->  Shared  --(usbipd attach)-->  Attached
     ^                             |                              |
     +------(usbipd unbind)--------+------(usbipd detach)---------+

如果你想让 2-3 真正在 WSL 里用起来,下一步是在管理员权限下执行:

usbipd attach --wsl --busid 2-3

attach 成功后,那一行的 STATE 就会变成 Attached。

---
顺便说明:下面的 Persisted 区块是另一回事——那是曾经绑定过、即使设备当前没插着也会"记住"绑定信息的设备列表(按 GUID 记录),插上后会自动恢复共享状态。

在 Windows 中打开一个管理员权限的终端

usbipd bind --busid=4-1
usbipd attach --wsl --busid 4-1

2.使用 WSL Dashboard

前往下载安装 WSL Dashboard

完成后打开即可看到已经安装的虚拟机实例,同时也可以管理 USB 设备

3.确定机械臂的端口

将刚刚确定的 4-1 和 4-2 两个设备连接到虚拟机,例子中 4-1 是主臂 4-2 是从臂。

在虚拟机中执行 lerobot-find-port ,看到如下输出

Finding all available ports for the MotorsBus.
Ports before disconnecting: ['/dev/ttyACM1', '/dev/ttyACM0', '/dev/ttyS7', '/dev/ttyS6', '/dev/ttyS5', '/dev/ttyS4', '/dev/ttyS3', '/dev/ttyS2', '/dev/ttyS1', '/dev/ttyS0', '/dev/tty63', '/dev/tty62', '/dev/tty61', '/dev/tty60', '/dev/tty59', '/dev/tty58', '/dev/tty57', '/dev/tty56', '/dev/tty55', '/dev/tty54', '/dev/tty53', '/dev/tty52', '/dev/tty51', '/dev/tty50', '/dev/tty49', '/dev/tty48', '/dev/tty47', '/dev/tty46', '/dev/tty45', '/dev/tty44', '/dev/tty43', '/dev/tty42', '/dev/tty41', '/dev/tty40', '/dev/tty39', '/dev/tty38', '/dev/tty37', '/dev/tty36', '/dev/tty35', '/dev/tty34', '/dev/tty33', '/dev/tty32', '/dev/tty31', '/dev/tty30', '/dev/tty29', '/dev/tty28', '/dev/tty27', '/dev/tty26', '/dev/tty25', '/dev/tty24', '/dev/tty23', '/dev/tty22', '/dev/tty21', '/dev/tty20', '/dev/tty19', '/dev/tty18', '/dev/tty17', '/dev/tty16', '/dev/tty15', '/dev/tty14', '/dev/tty13', '/dev/tty12', '/dev/tty11', '/dev/tty10', '/dev/tty9', '/dev/tty8', '/dev/tty7', '/dev/tty6', '/dev/tty5', '/dev/tty4', '/dev/tty3', '/dev/tty2', '/dev/tty1', '/dev/tty0', '/dev/tty']
Remove the USB cable from your MotorsBus and press Enter when done.

断开主臂(4-1)

回到虚拟机中按下回车

Finding all available ports for the MotorsBus.
Ports before disconnecting: ['/dev/ttyACM1', '/dev/ttyACM0', '/dev/ttyS7', '/dev/ttyS6', '/dev/ttyS5', '/dev/ttyS4', '/dev/ttyS3', '/dev/ttyS2', '/dev/ttyS1', '/dev/ttyS0', '/dev/tty63', '/dev/tty62', '/dev/tty61', '/dev/tty60', '/dev/tty59', '/dev/tty58', '/dev/tty57', '/dev/tty56', '/dev/tty55', '/dev/tty54', '/dev/tty53', '/dev/tty52', '/dev/tty51', '/dev/tty50', '/dev/tty49', '/dev/tty48', '/dev/tty47', '/dev/tty46', '/dev/tty45', '/dev/tty44', '/dev/tty43', '/dev/tty42', '/dev/tty41', '/dev/tty40', '/dev/tty39', '/dev/tty38', '/dev/tty37', '/dev/tty36', '/dev/tty35', '/dev/tty34', '/dev/tty33', '/dev/tty32', '/dev/tty31', '/dev/tty30', '/dev/tty29', '/dev/tty28', '/dev/tty27', '/dev/tty26', '/dev/tty25', '/dev/tty24', '/dev/tty23', '/dev/tty22', '/dev/tty21', '/dev/tty20', '/dev/tty19', '/dev/tty18', '/dev/tty17', '/dev/tty16', '/dev/tty15', '/dev/tty14', '/dev/tty13', '/dev/tty12', '/dev/tty11', '/dev/tty10', '/dev/tty9', '/dev/tty8', '/dev/tty7', '/dev/tty6', '/dev/tty5', '/dev/tty4', '/dev/tty3', '/dev/tty2', '/dev/tty1', '/dev/tty0', '/dev/tty']
Remove the USB cable from your MotorsBus and press Enter when done.

The port of this MotorsBus is '/dev/ttyACM0'
Reconnect the USB cable.

可知主臂(4-1)对应 ttyACM0 ,同样的操作确认从臂(4-2)对应 ttyACM1

4.机械臂校准

主臂校准

lerobot-calibrate \
    --teleop.type=so101_leader \
    --teleop.port=/dev/ttyACM0 \
    --teleop.id=R07260541

从臂校准

lerobot-calibrate \
    --robot.type=so101_follower \
    --robot.port=/dev/ttyACM1 \
    --robot.id=R12260541

port 是端口由上一步获得,id 是名称可以任取但不要重复

校准视频

错误处理:

成功示例

INFO 2026-07-09 14:43:57 calibrate.py:89 {'robot': None,
 'teleop': {'calibration_dir': None,
            'id': 'R07260541',
            'port': '/dev/ttyACM0',
            'use_degrees': True}}
INFO 2026-07-09 14:43:57 so_leader.py:78 R07260541 SOLeader connected.
INFO 2026-07-09 14:43:57 so_leader.py:95
Running calibration of R07260541 SOLeader
Move R07260541 SOLeader to the middle of its range of motion and press ENTER....
Move all joints except 'wrist_roll' sequentially through their entire ranges of motion.
Recording positions. Press ENTER to stop...

-------------------------------------------
-------------------------------------------
NAME            |    MIN |    POS |    MAX
shoulder_pan    |    849 |   1925 |   3270
shoulder_lift   |    790 |    807 |   2089
elbow_flex      |   1024 |   3224 |   3228
wrist_flex      |    659 |   2201 |   2990
gripper         |   2037 |   2048 |   3272
Calibration saved to /home/shawn/.cache/huggingface/lerobot/calibration/teleoperators/so_leader/R07260541.json
INFO 2026-07-09 14:44:35 o_leader.py:163 R07260541 SOLeader disconnected.

查看校准文件

(lerobot) shawn@pc:~/lerobot$ cat /home/shawn/.cache/huggingface/lerobot/calibration/robots/so_follower/R12260541.json
{
    "shoulder_pan": {
        "id": 1,
        "drive_mode": 0,
        "homing_offset": -1305,
        "range_min": 908,
        "range_max": 3311
    },
    "shoulder_lift": {
        "id": 2,
        "drive_mode": 0,
        "homing_offset": 2033,
        "range_min": 835,
        "range_max": 3207
    },
    "elbow_flex": {
        "id": 3,
        "drive_mode": 0,
        "homing_offset": 1988,
        "range_min": 848,
        "range_max": 2993
    },
    "wrist_flex": {
        "id": 4,
        "drive_mode": 0,
        "homing_offset": -1949,
        "range_min": 961,
        "range_max": 3279
    },
    "wrist_roll": {
        "id": 5,
        "drive_mode": 0,
        "homing_offset": -338,
        "range_min": 0,
        "range_max": 4095
    },
    "gripper": {
        "id": 6,
        "drive_mode": 0,
        "homing_offset": 861,
        "range_min": 2047,
        "range_max": 3489
    }
}
(lerobot) shawn@114514yyds:~/lerobot$ cat /home/shawn/.cache/huggingface/lerobot/calibration/teleoperators/so_leader/R07260541.json
{
    "shoulder_pan": {
        "id": 1,
        "drive_mode": 0,
        "homing_offset": -1588,
        "range_min": 849,
        "range_max": 3270
    },
    "shoulder_lift": {
        "id": 2,
        "drive_mode": 0,
        "homing_offset": 1867,
        "range_min": 790,
        "range_max": 2089
    },
    "elbow_flex": {
        "id": 3,
        "drive_mode": 0,
        "homing_offset": -1205,
        "range_min": 1024,
        "range_max": 3228
    },
    "wrist_flex": {
        "id": 4,
        "drive_mode": 0,
        "homing_offset": 1495,
        "range_min": 659,
        "range_max": 2990
    },
    "wrist_roll": {
        "id": 5,
        "drive_mode": 0,
        "homing_offset": -350,
        "range_min": 0,
        "range_max": 4095
    },
    "gripper": {
        "id": 6,
        "drive_mode": 0,
        "homing_offset": 1874,
        "range_min": 2037,
        "range_max": 3272
    }
}

5.开始遥操

lerobot-teleoperate \
    --robot.type=so101_follower \
    --robot.port=/dev/ttyACM1 \
    --robot.id=R12260541 \
    --teleop.type=so101_leader \
    --teleop.port=/dev/ttyACM0 \
    --teleop.id=R07260541

五、连接摄像头