news 2026/9/11 8:10:24

LeRobot SO-101 机械臂从零组装与调试完全指南:电机配置、逐步装配与标定

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LeRobot SO-101 机械臂从零组装与调试完全指南:电机配置、逐步装配与标定

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-portlerobot-setup-motorslerobot-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 AxisMotorGear Ratio
Base / Shoulder Pan11 / 191
Shoulder Lift21 / 345
Elbow Flex31 / 191
Wrist Flex41 / 147
Wrist Roll51 / 147
Gripper61 / 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 行),标定流程为:

  1. 若已存在与id关联的标定文件,脚本会询问是直接使用现有文件还是输入c重新标定;
  2. 禁用扭矩,将所有电机切换到 POSITION 运行模式;
  3. 提示你将机械臂移动到所有关节量程中间位置并回车——此时通过set_half_turn_homings()记录每个电机的半圈归零偏移(homing offset);
  4. 提示你依次把除wrist_roll外的所有关节完整走一遍量程,脚本实时记录每个关节的range_min/range_max;而wrist_roll是 360° 连续旋转关节,其量程被直接固定为04095(对应 12-bit 编码器全量程);
  5. homing_offsetrange_minrange_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=60

8. 进阶配置参数速查

围绕 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_degreesTrue关节角度归一化是否使用度数;设为False以兼容新策略/数据集
max_relative_targetNone限制每次动作的关节相对目标幅值上限,可传单个标量或按电机名的字典,用于安全保护(见 so_follower.py 第 219-230 行 的ensure_safe_goal_position裁剪逻辑)
position_p_coefficient16POSITION 模式 PID 的 P 系数,连接时写入电机
position_i_coefficient0PID 的 I 系数
position_d_coefficient32PID 的 D 系数
num_read_retries2电机sync_read失败时的重试次数;Feetech 总线在多个关节同时运动时偶尔返回损坏状态包,重试可避免控制循环中断
disable_torque_on_disconnectTrue断开连接时是否禁用扭矩
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-portlerobot-setup-motorslerobot-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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 8:10:16

G1垃圾回收器原理与实践:Java性能优化指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 8:07:17

AI Coding 进阶:如何编排 200 个 Agent 并行高效写代码

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 8:04:52

Zigbee2MQTT 容器部署完整指南:4 步跑通你的智能家居网关

Zigbee2MQTT 容器部署完整指南&#xff1a;4 步跑通你的智能家居网关 【免费下载链接】zigbee2mqtt Zigbee &#x1f41d; to MQTT bridge &#x1f309;, get rid of your proprietary Zigbee bridges &#x1f528; 项目地址: https://gitcode.com/GitHub_Trending/zi/zigb…

作者头像 李华
网站建设 2026/9/11 8:04:22

学习记录提交接口设计全解析:从字段定义到幂等性落地的产品实战

做在线学习类产品的时候&#xff0c;很多产品经理会把注意力放在页面交互、进度条样式、按钮触发逻辑上&#xff0c;但真正决定用户学习记录准不准、开发联调顺不顺的&#xff0c;往往是那个不起眼的学习记录提交接口。我是在拆解原型设计的第三个模块时&#xff0c;才彻底意识…

作者头像 李华
网站建设 2026/9/11 8:03:29

高性能数学库优化:从原理到工程实践

1. 为什么我们需要高性能数学库&#xff1f;在开始讨论如何实现高性能数学库之前&#xff0c;我们需要先理解为什么这个问题如此重要。现代计算领域对数学运算的需求无处不在——从游戏开发中的物理引擎&#xff0c;到金融领域的风险评估模型&#xff0c;再到机器学习算法的训练…

作者头像 李华