1. 背景与目标
我使用的 SO-101 follower 机械臂,最开始跑的是一个社区 LeRobot 分支(盒子桥大佬的 lerobot-joycon / lerobot-kinematics / joycon-robotics)。这套方案之前帮我把手柄控制和 follower 跑了起来,对前期上手很有帮助。
不过最近官方 LeRobot 框架更新比较快,我回头看了下新版本,整体目录结构、环境管理和扩展方式都清晰了不少。再加上我现在也想把后续实验尽量往官方生态上靠,方便后面继续折腾,最近正好闲下来有空了,于是就准备把手上的 SO-101 follower 迁移到新版官方框架下面试一试。

本次迁移的目标是:在保留原有第三方环境的前提下,建立一个独立的官方 LeRobot 环境,验证 SO-101 follower 在官方框架下的基础功能,包括串口识别、电机配置、校准与最小控制测试。
迁移的第一阶段仅关注机械臂本体。
2. 迁移计划
第一阶段的目标:在官方环境中完成 follower 的端口识别、电机配置(setup-motors)与校准(calibrate)。
看了下官方的文档,现在可以用uv了,而且看了环境也简化不少,于是果断UV。具体要点如下:
- 环境管理:使用
uv创建独立的 Python 3.12 虚拟环境,避免与现有的conda环境冲突。 - 安装来源:从官方仓库(
https://github.com/huggingface/lerobot)源码安装,启用feetech扩展以支持 follower 舵机。 - 系统依赖:确保系统已安装
ffmpeg
3. 环境搭建
工作区根目录为 /home/ruali/aistudy/lerobot_ws,将官方仓库克隆至 /home/ruali/aistudy/lerobot_ws/official-lerobot
执行以下命令创建环境并安装官方 LeRobot:
cd /home/ruali/aistudy/lerobot_ws/official-lerobot
/home/ruali/.local/bin/uv venv --python 3.12 .venv
VIRTUAL_ENV=/home/ruali/aistudy/lerobot_ws/official-lerobot/.venv \
PATH=/home/ruali/aistudy/lerobot_ws/official-lerobot/.venv/bin:$PATH \
/home/ruali/.local/bin/uv pip install -e '.[feetech]'
为方便激活,创建脚本 activate_uv_env.sh,内容为 source .venv/bin/activate。
验证环境:
- Python 版本:
3.12.x ffmpeg版本:4.4.2lerobotCLI 可正常调用
4. 硬件连接与串口识别
将 SO-101 follower 通过 USB 连接到主机,并接通电机电源。系统识别到串口设备 /dev/ttyACM0。使用 lerobot-find-port 确认该端口为 follower 所用。
踩坑记录:首次执行 lerobot-calibrate 时,忘插舵机电源了,错误信息显示未检测到任何电机({})校准的时候还得插舵机电源。

(示意图,仅用于说明连接逻辑与供电状态,具体接线以实际硬件为准)
5. 舵机配置与机械臂校准
舵机编号按文档来说理论上来说是要配置的,但是我不觉得上层外部框架重构会把底层驱动板的固件一块更了,显然不合常理。事实也是如此,老版本到新版本的底层驱动板固件是没变的,舵机这里不用动。
因此跳过 lerobot-setup-motors 步骤,直接执行校准:
lerobot-calibrate \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=so101_follower_main
6. 测试
虽然校准好了,还是再试试这个环境能不能和机械臂正常通信,写个py脚本做个冒烟测试。
以下为精简后的核心逻辑示例(去掉了参数解析和异常处理):
from lerobot.robots.so_follower import SO101Follower, SO101FollowerConfig
config = SO101FollowerConfig(port="/dev/ttyACM0", id="my_so101")
follower = SO101Follower(config)
follower.connect(calibrate=True)
try:
observation = follower.get_observation()
joint_obs = {k: v for k, v in observation.items() if k.endswith(".pos")}
print("Current joint positions:", joint_obs)
follower.send_action(joint_obs)
print("Hold-position action sent.")
finally:
follower.disconnect()
该脚本执行以下操作:
- 使用现有校准连接 follower
- 读取一帧关节状态观测值
- 将当前关节位置作为保持位置命令发送回 follower
- 断开连接
测试命令如下:
# 仅读取观测
python ./local_smoke_test_so101_follower.py \
--port /dev/ttyACM0 \
--id so101_follower_main \
--skip-hold
# 完整读写测试
python ./local_smoke_test_so101_follower.py \
--port /dev/ttyACM0 \
--id so101_follower_main

测试结果:连接、读取关节位置、发送保持位置命令均成功。输出显示关节位置数据,并确认校准文件路径。
7. 总结
迁移后的结果如下
| 项目 | 值 |
|---|---|
| 官方仓库路径 | /home/ruali/aistudy/lerobot_ws/official-lerobot |
| 环境管理 | uv(虚拟环境 .venv) |
| Python 版本 | 3.12 |
ffmpeg 版本 |
4.4.2 |
| follower 串口 | /dev/ttyACM0 |
| 机器人 ID | so101_follower_main |
| 校准文件路径 | ~/.cache/huggingface/lerobot/calibration/robots/so_follower/so101_follower_main.json |
| 验证命令序列 | lerobot-find-port → lerobot-calibrate → 冒烟测试 |
| 测试结果 | 连接、读取、保持位置命令全部通过 |
本来以为这次迁移会比较折腾,不过实际做下来,没有一开始想的那么夸张。比较省心的一点是,这块驱动板的固件不需要改,省掉了不少底层排查工作。
另外,新版本在校准流程上的体验也更顺一些。相比我之前接触的旧版流程,这一版更简单,整体上更适合后续继续做实验和迭代。