LeRobot SO-101 机械臂从零组装与调试完全指南:电机配置、逐步装配与标定
【免费下载链接】lerobot🤗 LeRobot: Making AI for Robotics more accessible with end-to-end learning项目地址: https://gitcode.com/GitHub_Trending/le/lerobot
本指南以 LeRobot 的旗舰机械臂 SO-101 为核心,完整讲解从零件采购、环境依赖安装、总线电机 ID 与波特率配置,到六关节逐级装配和 leader/follower 双臂校准的完整实战流程。读完本文,你将掌握使用lerobot-find-port、lerobot-setup-motors、lerobot-calibrate三条 CLI 命令(及其等价 Python API)完成 SO-101 双臂从硬件到软件的全链路就绪,并为后续的遥操作、数据采集与模仿学习训练铺平道路。
SO-101 是什么
SO-101 是 LeRobot 项目的旗舰开源机器人:一套由 3D 打印结构件、6 个 Feetech STS3215 总线舵机与 MotorBus 控制器板组成的 6 自由度机械臂(5 个关节 + 1 个夹爪)。它通常以「leader 臂 + follower 臂」成对出现——leader 臂由人手直接操作,follower 臂复现动作,从而完成遥操作数据采集,为端到端模仿学习提供训练数据。
在仓库中,SO-101 的底层实现集中在两个模块:
- follower 臂:src/lerobot/robots/so_follower/so_follower.py 中的
SOFollower类(SO101Follower即其别名,见 so_follower.py 第 241-242 行); - leader 臂:src/lerobot/teleoperators/so_leader/so_leader.py 中的
SOLeader类(SO101Leader同理)。
二者共享同一套 6 电机总线定义与标定流程,仅在扭矩控制与数据流方向上有所分工。
1. 采购零件
SO-101 的物料清单(BOM)、零件采购渠道以及 3D 打印文件说明,来自 SO-ARM100 项目 的 README。它同时提供了 3D 打印指南。如果你是第一打印或者手头没有 3D 打印机,建议先阅读该 README 中的建议(例如委托打印服务),避免在打印环节走弯路。
2. 安装 LeRobot 与 Feetech 依赖
在开始之前,需要先完成 LeRobot 的安装,安装步骤见 docs/source/installation.mdx(安装指南)。除基础安装外,SO-101 依赖 Feetech 总线舵机的 SDK,必须追加安装对应 extra:
pip install -e ".[feetech]"feetechextra 会引入 FeetechMotorsBus 所需的底层通信库,这是后续一切电机读写操作的前提。
3. 理解 SO-101 的电机布局与齿轮比
SO-101 的 follower 臂使用6 个 STS3215 电机,统一采用 1/345 减速比。而 leader 臂为了保证「既能自持重量、又不需要很大力气就能推动」,在 6 个关节上混用了三种不同减速比的电机,具体分配如下表:
| Leader-Arm Axis | Motor | Gear Ratio |
|---|---|---|
| Base / Shoulder Pan | 1 | 1 / 191 |
| Shoulder Lift | 2 | 1 / 345 |
| Elbow Flex | 3 | 1 / 191 |
| Wrist Flex | 4 | 1 / 147 |
| Wrist Roll | 5 | 1 / 147 |
| Gripper | 6 | 1 / 147 |
对应到软件侧,so_follower.py 第 51-62 行 定义了 follower 臂的总线电机映射:shoulder_pan(id=1)、shoulder_lift(id=2)、elbow_flex(id=3)、wrist_flex(id=4)、wrist_roll(id=5)、gripper(id=6),全部为sts3215型号。body 关节使用统一归一化模式,而gripper单独使用RANGE_0_100归一化模式(因为夹爪的物理输出范围与旋转关节不同)。leader 臂的定义见 so_leader.py 第 43-54 行,电机布局完全相同。
4. 配置电机(总线 ID 与波特率)
4.1 为什么需要配置
每台电机在总线上通过唯一的id被识别。全新电机的出厂默认 id 通常是1,若 6 个电机都保持 id=1,控制器将无法区分它们;此外,总线上的数据传输速率由波特率(baudrate)决定,控制器与所有电机必须使用相同波特率才能互相通信。因此,组装前必须为每台电机写入唯一 id 并统一波特率。
这些参数被写入电机内部存储器的非易失区(EEPROM),因此只需配置一次。如果你是从其他机器人上拆下来的旧电机,也建议重做本步骤,因为旧电机的 id 和波特率很可能不匹配。
SO-100 与 SO-101 的一个重要差异:SO-101 的电机连接器在整机装配后仍然可插拔,因此可以在组装之后再配置;而 SO-100 装配完成后电机连接器不可触及,必须在组装前完成配置。
4.2 第一步:查找每个臂对应的 USB 端口
把 MotorBus 控制器板通过 USB 接到电脑并通电,然后运行:
lerobot-find-port脚本会列出所有可用串口,并提示你在识别当前总线后拔下 USB 以区分对应的臂。以下是典型输出:
macOS:
Finding all available ports for the MotorBus. ['/dev/tty.usbmodem575E0032081', '/dev/tty.usbmodem575E0031751'] Remove the USB cable from your MotorsBus and press Enter when done. [...Disconnect corresponding leader or follower arm and press Enter...] The port of this MotorsBus is /dev/tty.usbmodem575E0032081 Reconnect the USB cable.该例中/dev/tty.usbmodem575E0032081即对应某一条臂(leader 或 follower)。
Linux:
Linux 下可能需要先给 USB 串口授权:
sudo chmod 666 /dev/ttyACM0 sudo chmod 666 /dev/ttyACM1典型输出:
Finding all available ports for the MotorBus. ['/dev/ttyACM0', '/dev/ttyACM1'] Remove the usb cable from your MotorsBus and press Enter when done. [...Disconnect corresponding leader or follower arm and press Enter...] The port of this MotorsBus is /dev/ttyACM1 Reconnect the USB cable.该例中/dev/ttyACM1即对应你的某条臂。请记下两条臂各自的端口,后续所有命令都需要用到。
4.3 第二步:设置电机 id 与波特率
配置的核心思想是:一次只把一个电机接到控制器板上,逐台写入 id 与波特率,全部完成后再按菊花链(daisy-chain)方式串联起来。
Follower 臂
将 USB 线和电源接到 follower 臂的控制器板上,用上一步得到的端口运行命令,并通过id参数给 follower 臂起一个名字(这个名字将作为标定文件的关联标识,后续遥操作、录制、评估必须保持一致):
命令行方式:
lerobot-setup-motors \ --robot.type=so101_follower \ --robot.port=/dev/tty.usbmodem585A0076841 # <- 粘贴上一步找到的端口API 方式:
from lerobot.robots.so_follower import SO101Follower, SO101FollowerConfig config = SO101FollowerConfig( port="/dev/tty.usbmodem585A0076841", id="my_awesome_follower_arm", ) follower = SO101Follower(config) follower.setup_motors()脚本启动后会提示:
Connect the controller board to the 'gripper' motor only and press enter.此时只把gripper 电机(id=6)接到控制器板上:确保它是板上唯一电机,且尚未与任何其他电机菊花链串联。按下[Enter]后,脚本自动为该电机写入 id 与波特率,随后输出:
'gripper' motor id set to 6接着提示连接下一个电机:
Connect the controller board to the 'wrist_roll' motor only and press enter.可以把 3-pin 线从控制器板上拔下,但另一端保持接在 gripper 电机上(它最终就在那个位置);再取一根新的 3-pin 线接上 wrist roll 电机并连到控制器板,同样确保它孤零零地只连着板子。按此流程逐台完成所有 6 个电机。
故障排查(Troubleshooting):
- 若在此处报错,逐项检查:电源是否正常、电脑与控制器板之间的 USB 线、控制器板到电机的 3-pin 线;
- 如果使用 Waveshare 控制器板,确认两个跳线帽位于B 通道(USB)。
经验提示:每次按下 Enter 前先检查一遍线缆——例如插拔过程中电源线可能意外松脱。
全部完成后脚本自动结束,此时电机已就绪。接下来就可以把每个电机的 3-pin 线首尾串联(菊花链),并把第一台电机(id=1 的shoulder_pan)的线接到控制器板上;控制器板随后可固定到机械臂底座。
Leader 臂
leader 臂重复同样流程,仅参数命名空间不同(leader 在配置体系中被归类为teleop):
命令行方式:
lerobot-setup-motors \ --teleop.type=so101_leader \ --teleop.port=/dev/tty.usbmodem575E0031751 # <- 粘贴上一步找到的端口API 方式:
from lerobot.teleoperators.so_leader import SO101Leader, SO101LeaderConfig config = SO101LeaderConfig( port="/dev/tty.usbmodem585A0076841", id="my_awesome_leader_arm", ) leader = SO101Leader(config) leader.setup_motors()4.4 源码视角:setup_motors 是如何工作的
从源码看,lerobot-setup-motors脚本(src/lerobot/scripts/lerobot_setup_motors.py)通过 draccus 解析配置后,依据--robot还是--teleop构造对应设备并调用其setup_motors()方法。而 so_follower.py 第 173-177 行 与 so_leader.py 第 139-143 行 的实现是按reversed()逆序遍历电机(从 gripper 到 shoulder_pan),每轮用input()阻塞等待你接线确认,然后调用self.bus.setup_motor(motor)完成单台电机的 id/波特率写入,并打印'<motor>' motor id set to <id>。这正是前面交互流程的底层实现。
5. 逐步装配 SO-101
5.1 清理打印件
先移除所有 3D 打印件上的支撑材料。最省事的方式是用小螺丝刀从支撑材料下方撬起。建议在放置电机后、继续装配之前,为每台电机预先插好一根 3-pin 线(后期布线会困难得多)。
5.2 Joint 1(肩部底盘)
- 安装两个电机 horn(舵盘)。顶部 horn 用 1 颗 M3x6mm 螺丝固定;底部 horn 无需螺丝。
- 将第一个电机放入底座。
- 用 4 颗 M2x6mm 螺丝(最小号)固定电机:顶部 2 颗、底部 2 颗。
- 套上第一个电机固定座,用 2 颗 M2x6mm 螺丝(每侧 1 颗)固定。
- 装上肩部零件。
- 用顶部 4 颗 + 底部 4 颗 M3x6mm 螺丝拧紧肩部零件。
- 加上肩部电机固定座。
5.3 Joint 2(肩部抬升)
- 安装两个电机 horn,顶部 horn 用 M3x6mm 螺丝固定。
- 从上方滑入第二个电机。
- 用 4 颗 M2x6mm 螺丝固定第二电机。
- 用每侧 4 颗 M3x6mm 螺丝装上大臂。
5.4 Joint 3(肘部弯曲)
- 安装两个电机 horn,顶部 horn 用 M3x6mm 螺丝固定。
- 插入电机 3,用 4 颗 M2x6mm 螺丝固定。
- 用每侧 4 颗 M3x6mm 螺丝将前臂连接到电机 3。
5.5 Joint 4(腕部弯曲)
- 安装两个电机 horn,顶部 horn 用 M3x6mm 螺丝固定。
- 套上电机 4 的固定座。
- 滑入电机 4。
- 用 4 颗 M2x6mm 螺丝固定电机 4。
5.6 Joint 5(腕部旋转)
- 将电机 5 插入腕部固定座,用 2 颗 M2x6mm 前部螺丝固定。
- 腕部电机只安装一个电机 horn,用 1 颗 M3x6mm horn 螺丝固定。
- 用两侧各 4 颗 M3x6mm 螺丝将腕部固定到电机 4 上。
5.7 夹爪 / 把手(Gripper / Handle)
Follower 臂:
- 将夹爪连接到电机 5(腕部电机 horn 上),用 4 颗 M3x6mm 螺丝固定。
- 插入夹爪电机,每侧用 2 颗 M2x6mm 螺丝固定。
- 在夹爪电机上安装两个电机 horn:顶部 horn 用 M3x6mm 螺丝,底部 horn 无需螺丝。
- 安装夹爪爪齿,两侧各用 4 颗 M3x6mm 螺丝固定。
Leader 臂:
- 将 leader 固定座安装到腕部,用 4 颗 M3x6mm 螺丝固定。
- 用 1 颗 M2x6mm 螺丝将把手固定到 leader 固定座。
- 插入夹爪电机,每侧用 2 颗 M2x6mm 螺丝固定,再用 M3x6mm horn 螺丝安装一个电机 horn。
- 用 4 颗 M3x6mm 螺丝固定 follower 扳机(trigger,即遥操作时手指扣动夹爪的部件)。
6. 标定双臂(Calibrate)
6.1 为什么必须标定
标定的目标是确保leader 臂与 follower 臂在相同物理位姿下输出相同的关节位置值。这一点至关重要:标定让「在一台机器人上训练的神经网络能够迁移到另一台机器人上工作」成为可能(例如用 leader 采集数据、用 follower 执行)。
从源码看(so_follower.py 第 115-157 行),标定流程为:
- 若已存在与
id关联的标定文件,脚本会询问是直接使用现有文件还是输入c重新标定; - 禁用扭矩,将所有电机切换到 POSITION 运行模式;
- 提示你将机械臂移动到所有关节量程中间位置并回车——此时通过
set_half_turn_homings()记录每个电机的半圈归零偏移(homing offset); - 提示你依次把除
wrist_roll外的所有关节完整走一遍量程,脚本实时记录每个关节的range_min/range_max;而wrist_roll是 360° 连续旋转关节,其量程被直接固定为0到4095(对应 12-bit 编码器全量程); - 将
homing_offset、range_min、range_max等构成MotorCalibration写入电机 EEPROM,并保存到本地标定文件(路径与id关联)。
leader 臂的标定实现见 so_leader.py 第 84-125 行,流程一致。标定文件随后会保存在~/.cache/huggingface/lerobot/下按 robot id 命名的目录中。
6.2 Follower 臂标定
命令行方式:
lerobot-calibrate \ --robot.type=so101_follower \ --robot.port=/dev/tty.usbmodem58760431551 \ # <- 你的机械臂端口 --robot.id=my_awesome_follower_arm # <- 给机械臂起个唯一名字API 方式:
from lerobot.robots.so_follower import SO101FollowerConfig, SO101Follower config = SO101FollowerConfig( port="/dev/tty.usbmodem585A0076891", id="my_awesome_follower_arm", ) follower = SO101Follower(config) follower.connect(calibrate=False) follower.calibrate() follower.disconnect()6.3 Leader 臂标定
命令行方式:
lerobot-calibrate \ --teleop.type=so101_leader \ --teleop.port=/dev/tty.usbmodem58760431551 \ # <- 你的机械臂端口 --teleop.id=my_awesome_leader_arm # <- 给机械臂起个唯一名字API 方式:
from lerobot.teleoperators.so_leader import SO101LeaderConfig, SO101Leader config = SO101LeaderConfig( port="/dev/tty.usbmodem58760431551", id="my_awesome_leader_arm", ) leader = SO101Leader(config) leader.connect(calibrate=False) leader.calibrate() leader.disconnect()标定过程的操作要点:先把机械臂移到所有关节都在量程中间的位姿,回车后逐个关节完整走满量程。另外注意,lerobot-calibrate脚本(src/lerobot/scripts/lerobot_calibrate.py)同样通过--robot.*/--teleop.*前缀区分两条臂。
标定完成后,机械臂便已全部就绪,可以开始学习任务了。
7. 标定之后的完整闭环
SO-101 就绪后,接下来的标准流程是:遥操作 → 录制数据集 → 训练策略 → 部署评估,完整教程见 docs/source/il_robots.mdx(真实世界机器人入门)。以下是与 SO-101 直接相关的关键命令:
遥操作(leader 驱动 follower):
lerobot-teleoperate \ --robot.type=so101_follower \ --robot.port=/dev/tty.usbmodem58760431541 \ --robot.id=my_awesome_follower_arm \ --teleop.type=so101_leader \ --teleop.port=/dev/tty.usbmodem58760431551 \ --teleop.id=my_awesome_leader_arm录制数据集(以 5 个 episode 为例):
lerobot-record \ --robot.type=so101_follower \ --robot.port=/dev/tty.usbmodem585A0076841 \ --robot.id=my_awesome_follower_arm \ --robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 1920, height: 1080, fps: 30}}" \ --teleop.type=so101_leader \ --teleop.port=/dev/tty.usbmodem58760431551 \ --teleop.id=my_awesome_leader_arm \ --display_data=true \ --dataset.repo_id=${HF_USER}/record-test \ --dataset.num_episodes=5 \ --dataset.single_task="Grab the black cube" \ --dataset.streaming_encoding=true \ --dataset.encoder_threads=2训练策略(以 ACT 为例):
lerobot-train \ --dataset.repo_id=${HF_USER}/so101_test \ --policy.type=act \ --output_dir=outputs/train/act_so101_test \ --job_name=act_so101_test \ --policy.device=cuda \ --wandb.enable=true \ --policy.repo_id=${HF_USER}/my_policy部署评估(base 模式):
lerobot-rollout \ --strategy.type=base \ --policy.path=${HF_USER}/my_policy \ --robot.type=so101_follower \ --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}}" \ --task="Put lego brick into the transparent box" \ --duration=608. 进阶配置参数速查
围绕 SO-101,源码中的可调配置集中在 src/lerobot/robots/so_follower/config_so_follower.py 与 src/lerobot/teleoperators/so_leader/config_so_leader.py,常用参数如下:
| 参数 | 默认值 | 说明 |
|---|---|---|
port | 必填 | 总线串口路径(如/dev/ttyACM1) |
id | 必填 | 设备唯一名称,用于关联标定文件 |
use_degrees | True | 关节角度归一化是否使用度数;设为False以兼容新策略/数据集 |
max_relative_target | None | 限制每次动作的关节相对目标幅值上限,可传单个标量或按电机名的字典,用于安全保护(见 so_follower.py 第 219-230 行 的ensure_safe_goal_position裁剪逻辑) |
position_p_coefficient | 16 | POSITION 模式 PID 的 P 系数,连接时写入电机 |
position_i_coefficient | 0 | PID 的 I 系数 |
position_d_coefficient | 32 | PID 的 D 系数 |
num_read_retries | 2 | 电机sync_read失败时的重试次数;Feetech 总线在多个关节同时运动时偶尔返回损坏状态包,重试可避免控制循环中断 |
disable_torque_on_disconnect | True | 断开连接时是否禁用扭矩 |
cameras | {} | 相机配置字典(如{"front": OpenCVCameraConfig(...)}) |
其中,PID 系数与夹爪保护参数在configure()阶段(so_follower.py 第 159-171 行)写入电机:夹爪电机还会被写入Max_Torque_Limit=500(最大扭矩的 50%,防止烧毁)、Protection_Current=250(最大电流的 50%)与Overload_Torque=25(过载时扭矩 25%)三个保护参数。
总结
SO-101 的从零就绪可以归纳为五步:采购打印 → 安装依赖 → 配置电机 → 逐步装配 → 双臂标定。整个过程既有清晰的 CLI 工具支撑(lerobot-find-port、lerobot-setup-motors、lerobot-calibrate),也有完整的 Python API 等价实现(SO101Follower/SO101Leader),且标定文件与设备id强绑定,保证了「leader 采集、follower 执行」的跨机迁移能力。完成上述步骤后,即可进入 docs/source/il_robots.mdx 教程,开始遥操作、录制数据集并训练你自己的端到端策略。
【免费下载链接】lerobot🤗 LeRobot: Making AI for Robotics more accessible with end-to-end learning项目地址: https://gitcode.com/GitHub_Trending/le/lerobot
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考