LeRobot v0.1.0 实战部署全攻略从环境搭建到双机械臂精准控制最近在折腾具身智能项目LeRobot 这个开源框架确实让人眼前一亮。它把机器人学习从实验室搬到了普通开发者的桌面上尤其是搭配像 SO-ARM101 这样的低成本机械臂套件让亲手搭建一个能学习的机器人不再是遥不可及的梦想。不过理想很丰满现实往往会在环境配置和硬件调试环节给你当头一棒。我花了整整一周时间踩遍了从 Python 依赖冲突到机械臂电机配置的各种坑才终于让主从两个机械臂型号 XL330 和 XL430成功联动起来。这篇文章就是这份血泪史的结晶我会把整个过程中最棘手的问题和解决方案掰开揉碎了讲清楚希望能帮你省下几十个小时的折腾时间。1. 环境搭建避开 PyAV 与 Python 3.10 的兼容性陷阱LeRobot 的官方安装指南看起来很简单但如果你直接照着pip install -e .执行十有八九会卡在 PyAV 这个多媒体处理库上。PyAV 是底层视频编解码库 FFmpeg 的 Python 绑定LeRobot 用它来处理数据采集时的视频流。问题在于PyAV 的版本与 Python 3.10 的兼容性非常微妙尤其是在某些 Linux 发行版上。1.1 核心依赖冲突与解决方案我第一次安装时遇到的报错信息大致如下Building wheels for collected packages: av Building wheel for av (pyproject.toml) ... error error: subprocess-exited-with-error × Building wheel for av (pyproject.toml) did not run successfully. ... av/backend/ffmpeg/libavformat.pxd:10:10: fatal error: libavformat/avformat.h: No such file or directory这个错误表明系统缺少 FFmpeg 的开发库。但即使你安装了libavformat-dev后续仍可能遇到更棘手的版本不匹配问题。经过反复尝试我发现最稳妥的路径不是从源码编译 PyAV而是直接安装 LeRobot 预编译好的特定版本。最关键的步骤放弃从源码安装整个项目转而使用官方发布的 PyPI 包。这能确保所有二进制依赖都是匹配的。# 1. 创建并激活 Conda 环境强烈推荐使用 Conda 管理 Python 环境 conda create -y -n lerobot python3.10 conda activate lerobot # 2. 优先安装 FFmpeg通过 Conda-forge 渠道版本兼容性最好 conda install -c conda-forge ffmpeg # 3. 安装 LeRobot 核心包及其特定功能扩展 # 直接安装 v0.1.0 版本避免从源码构建 PyAV pip install lerobot0.1.0 # 4. 安装额外的功能模块如支持特定机械臂型号 pip install lerobot[aloha, pusht, dynamixel]注意pip install lerobot[aloha, pusht, dynamixel]这条命令会安装用于数据采集Aloha、Pusht 策略和 Dynamixel 电机驱动的额外依赖。如果你不确定是否需要可以先只安装核心包后续按需添加。为什么这个方法有效因为lerobot0.1.0这个 PyPI 包包含了针对常见平台Linux x86_64, macOS ARM64 等预编译好的 PyAV wheel 文件。它绕过了从源码编译的过程直接使用了与 LeRobot 其他组件测试过的兼容版本。1.2 验证安装与常见问题排查安装完成后运行一个简单的导入测试来验证核心功能是否正常import lerobot print(fLeRobot version: {lerobot.__version__}) # 尝试导入关键模块 from lerobot.common.robot_devices.motors.dynamixel import DynamixelMotorsBus print(Dynamixel 电机驱动模块导入成功。)如果遇到类似ImportError: libavcodec.so.58: cannot open shared object file的错误说明动态链接库路径有问题。可以尝试以下命令修复# 查找 ffmpeg 库的实际位置 conda list ffmpeg # 通常库文件在类似这样的路径下~/miniconda3/envs/lerobot/lib/ # 将其添加到 LD_LIBRARY_PATHLinux/macOS export LD_LIBRARY_PATH$HOME/miniconda3/envs/lerobot/lib:$LD_LIBRARY_PATH # 对于 macOS变量名为 DYLD_LIBRARY_PATH export DYLD_LIBRARY_PATH$HOME/miniconda3/envs/lerobot/lib:$DYLD_LIBRARY_PATH为了永久生效可以将这行导出命令添加到你的~/.bashrc或~/.zshrc文件中。2. 硬件准备与机械臂组装要点LeRobot 官方支持的 SO-ARM101 套件包含主从两个机械臂、控制板和摄像头。在动手组装之前有几点必须特别注意否则轻则无法通信重则可能损坏电机。2.1 电源与电机型号核对这是最容易出错也最危险的一步。SO-ARM101 套件可能包含不同电压规格的电机机械臂类型典型电机型号额定电压电源要求主臂 (Leader)XL330-M077, XL330-M2887.4V - 12V必须使用 5V 电源适配器从臂 (Follower)XL430-W250, XL330-M28812V必须使用 12V 电源适配器重要警告切勿混用电源给 7.4V 电机接 12V 电源会瞬间烧毁电机。USB 仅用于通信不供电。必须同时连接 USB 数据线和对应的电源适配器机械臂才能工作。在组装前强烈建议用标签纸标记每个电机的 ID 和所属臂如 L1-L6 代表主臂 1-6 号关节F1-F6 代表从臂。这会在后续的软件配置中节省大量时间。2.2 组装流程中的关键检查点组装过程可以参考官方的3D动画教程但有几个细节官方可能没强调线缆管理舵机线3针杜邦线在穿过机械臂关节时要预留足够的活动余量避免关节运动时拉扯线缆。可以使用附带的扎带固定。螺丝紧固使用合适的螺丝刀通常是 PH1 或 PH0确保所有螺丝紧固到位但切忌过度用力以免滑丝或损坏塑料件。通电前检查在连接电源前再次确认所有电机的 3 针信号线已按顺序串联ID 1 - ID 2 - ... - ID 6。电源极性正确红线接黑线接-。主臂接 5V 电源从臂接 12V 电源。3. 电机配置与 USB 端口永久绑定硬件组装好后下一步是让电脑识别并稳定地控制两个机械臂。这里最大的挑战是每次重启或重新插拔 USB 线系统分配给两个机械臂的端口号如/dev/ttyACM0和/dev/ttyACM1可能会交换。这会导致代码中指定的主从臂端口错误控制完全混乱。3.1 动态查找端口临时测试在建立永久绑定前我们可以先用 LeRobot 提供的工具动态查找端口确保硬件连接正常# 查找当前连接的所有电机总线端口 python -m lerobot.find_port执行后你会看到类似输出Finding all available ports for the MotorBus. [/dev/ttyACM0, /dev/ttyACM1] Remove the USB cable from your MotorsBus and press Enter when done.此时拔掉主臂的 USB 线按回车。脚本会识别出消失的端口是哪一个并将其标记为“主臂”的端口。重新插上后再对从臂重复此操作。这个方法能帮你临时确定哪个端口对应哪个臂但下次开机可能又变了。3.2 创建 udev 规则实现永久绑定为了解决端口随机分配的问题我们需要在 Linux 系统如果你是 Windows/macOS 用户可能需要寻找等效方案如创建 COM 端口别名中创建 udev 规则。udev 是 Linux 的设备管理器可以根据设备的固有属性如供应商ID、产品ID、序列号为其创建固定的符号链接。第一步获取设备的唯一标识信息分别连接主臂和从臂使用udevadm命令获取其详细信息# 假设当前主臂在 /dev/ttyACM0从臂在 /dev/ttyACM1 # 获取主臂信息 udevadm info -a -n /dev/ttyACM0 | grep -E “(idVendor|idProduct|serial)” # 获取从臂信息 udevadm info -a -n /dev/ttyACM1 | grep -E “(idVendor|idProduct|serial)”你会得到类似这样的输出数值因人而异ATTRS{idVendor}1a86 ATTRS{idProduct}55d3 ATTRS{serial}5970073336 # 这是主臂的序列号记录下每个臂的idVendor,idProduct, 和serial。序列号是区分同型号两个臂的关键。第二步编写 udev 规则文件使用sudo权限创建规则文件sudo vim /etc/udev/rules.d/99-usb-serial.rules在文件中添加以下内容将idVendor,idProduct,serial替换为你刚才查到的值# 规则解释 # SUBSYSTEMtty: 仅匹配串口设备。 # ATTRS{...}: 通过供应商ID、产品ID和序列号精确匹配特定设备。 # SYMLINKttyACM10: 为该设备创建一个固定的符号链接 /dev/ttyACM10。 # 主臂 (Leader) 绑定到 ttyACM10 SUBSYSTEMtty, ATTRS{idVendor}1a86, ATTRS{idProduct}55d3, ATTRS{serial}5970073336, SYMLINKttyACM10, MODE0666 # 从臂 (Follower) 绑定到 ttyACM11 SUBSYSTEMtty, ATTRS{idVendor}1a86, ATTRS{idProduct}55d3, ATTRS{serial}58FA101430, SYMLINKttyACM11, MODE0666MODE0666是为了让普通用户也有读写权限避免每次都要sudo。第三步应用规则并验证保存文件后重新加载 udev 规则并触发设备重新识别sudo udevadm control --reload-rules sudo udevadm trigger然后重新插拔两个机械臂的 USB 线。现在无论系统原始分配是什么你都可以通过固定的/dev/ttyACM10和/dev/ttyACM11来访问它们。ls -l /dev/ttyACM10 /dev/ttyACM11你应该能看到它们链接到了类似/dev/ttyACM0的实际设备节点。4. 电机初始化、校准与双臂联动测试端口固定后就可以开始配置电机了。LeRobot 提供了便捷的 CLI 工具来完成电机 ID 设置和运动范围校准。4.1 电机初始化与 ID 设置全新电机的默认 ID 通常都是 1。我们需要为每个关节的电机设置唯一的 ID。务必一个臂一个臂地操作并且每次只连接一个电机到控制板。# 配置从臂 (Follower) 电机 lerobot-setup-motors \ --robot.typeso101_follower \ --robot.port/dev/ttyACM11 # 使用我们绑定的从臂端口 # 配置主臂 (Leader) 电机 lerobot-setup-motors \ --teleop.typeso101_leader \ --teleop.port/dev/ttyACM10 # 使用我们绑定的主臂端口运行命令后脚本会一步步提示你连接哪个关节的电机如 “Connect the controller board to the gripper motor only and press enter”。严格按提示操作确保当前只有指定关节的电机连接到控制板然后按回车。脚本会自动为其设置 ID 和波特率。完成后将所有电机按顺序ID 1 到 6串联最后将 ID 为 1 的电机连接到控制板。4.2 机械臂关节校准校准的目的是建立每个关节电机的物理位置角度与软件读取的数值之间的映射关系并确定其安全运动范围。这对于主从臂的精确映射至关重要。# 校准从臂 lerobot-calibrate \ --robot.typeso101_follower \ --robot.port/dev/ttyACM11 \ --robot.idmy_follower_arm # 给从臂起个名字 # 校准主臂 lerobot-calibrate \ --teleop.typeso101_leader \ --teleop.port/dev/ttyACM10 \ --teleop.idmy_leader_arm # 给主臂起个名字校准过程是交互式的脚本会提示你将机械臂所有关节移动到运动范围的中间位置然后按回车。接着你需要依次缓慢移动每个关节从其机械限位的一端运动到另一端。软件会自动记录最大值和最小值。完成后校准数据会保存在~/.cache/huggingface/lerobot/calibration/目录下以你设置的id命名。提示校准数据是 JSON 文件。如果后续觉得校准不准可以直接删除对应的文件重新运行校准命令。4.3 双机械臂遥操作测试这是最激动人心的时刻——测试主臂是否能控制从臂。lerobot-teleoperate \ --robot.typeso101_follower \ --robot.port/dev/ttyACM11 \ --robot.idmy_follower_arm \ --teleop.typeso101_leader \ --teleop.port/dev/ttyACM10 \ --teleop.idmy_leader_arm如果一切顺利你现在手动移动主臂从臂应该会跟随做出相同的动作。首次运行可能会自动加载刚才的校准文件。如果跟随动作不准确或相反可能是校准步骤没做好或者主从臂的关节映射shoulder_pan, shoulder_lift 等在代码定义中不一致需要回头检查电机 ID 设置和机械臂型号配置。4.4 通过 Python API 进行底层控制与状态读取除了 CLI你还可以直接使用 LeRobot 的 Python API 进行更灵活的控制。下面是一个简单的脚本用于连接双机械臂并读取它们的实时位置from lerobot.common.robot_devices.motors.dynamixel import DynamixelMotorsBus import time # 配置主臂Leader电机参数 leader_config { port: /dev/ttyACM10, motors: { shoulder_pan: (1, xl330-m077), shoulder_lift: (2, xl330-m077), elbow_flex: (3, xl330-m077), wrist_flex: (4, xl330-m077), wrist_roll: (5, xl330-m077), gripper: (6, xl330-m077), }, } # 配置从臂Follower电机参数 follower_config { port: /dev/ttyACM11, motors: { shoulder_pan: (1, xl430-w250), shoulder_lift: (2, xl430-w250), elbow_flex: (3, xl330-m288), wrist_flex: (4, xl330-m288), wrist_roll: (5, xl330-m288), gripper: (6, xl330-m288), }, } # 创建电机总线对象并连接 leader_arm DynamixelMotorsBus(**leader_config) follower_arm DynamixelMotorsBus(**follower_config) leader_arm.connect() follower_arm.connect() print(双机械臂连接成功。尝试读取当前位置...) try: while True: # 读取主臂和从臂所有电机的当前位置 leader_pos leader_arm.read(“Present_Position”) follower_pos follower_arm.read(“Present_Position”) print(f主臂位置: {leader_pos}) print(f从臂位置: {follower_pos}) print(- * 30) time.sleep(0.5) # 每0.5秒读取一次 except KeyboardInterrupt: print(\n程序被用户中断。) finally: # 断开连接 leader_arm.disconnect() follower_arm.disconnect() print(已断开机械臂连接。)这段代码会持续打印出两个机械臂六个关节的编码器位置值。你可以手动移动它们观察数值的变化。这是后续进行数据采集和模型训练的基础。5. 摄像头集成与数据采集入门让机械臂“看”到世界是具身智能的关键。LeRobot 支持多种摄像头最常见的是普通的 USB 摄像头。5.1 摄像头检测与配置首先检测系统连接的摄像头python -m lerobot.find_cameras opencv输出会列出所有检测到的摄像头及其索引如 0, 1, 2。记下你打算使用的摄像头索引。然后你可以在遥操作命令中加入摄像头参数实时查看画面lerobot-teleoperate \ --robot.typeso101_follower \ --robot.port/dev/ttyACM11 \ --robot.idmy_follower_arm \ --robot.cameras{“front”: {“type”: “opencv”, “index_or_path”: 0, “width”: 640, “height”: 480, “fps”: 30}} \ --teleop.typeso101_leader \ --teleop.port/dev/ttyACM10 \ --teleop.idmy_leader_arm \ --display_datatrue参数--display_datatrue会打开一个实时视频窗口。这对于调整摄像头角度、确保工作区在画面内非常有用。5.2 开始你的第一次数据采集数据是训练机器人模型的“粮食”。LeRobot 的数据采集命令lerobot-record将控制信号来自主臂和观察数据摄像头画面、从臂状态同步记录下来。lerobot-record \ --robot.typeso101_follower \ --robot.port/dev/ttyACM11 \ --robot.idmy_follower_arm \ --robot.cameras{“front”: {“type”: “opencv”, “index_or_path”: 0, “width”: 640, “height”: 480, “fps”: 30}} \ --teleop.typeso101_leader \ --teleop.port/dev/ttyACM10 \ --teleop.idmy_leader_arm \ --display_datatrue \ --dataset.repo_id”my_first_dataset” \ --dataset.num_episodes5 \ --dataset.single_task”pick up the red block” \ --dataset.push_to_hubfalse \ --dataset.episode_time_s20 \ --dataset.reset_time_s5关键参数解释--dataset.num_episodes5: 采集5条数据。--dataset.single_task”pick up the red block”: 为这组数据添加一个语言指令标签。--dataset.push_to_hubfalse: 数据保存在本地~/.cache/huggingface/lerobot/my_first_dataset/不上传到 Hugging Face Hub。--dataset.episode_time_s20: 每条数据录制20秒。--dataset.reset_time_s5: 每条数据录制结束后有5秒的复位/准备时间。采集时的操作提示按下右箭头键→ 可以提前结束当前回合并开始下一回合。按下左箭头键← 可以取消当前回合并重新录制。按下ESC 键可以立即停止整个采集会话。第一次采集建议任务简单些比如将一个积木从一个固定位置移动到另一个固定位置。保持摄像头和场景不变重复几次让模型先学会最基本的动作映射。6. 模型训练与部署展望环境搭好硬件调通数据也有了下一步就是训练一个属于你自己的机器人策略模型。LeRobot 支持多种先进的算法如 ACT、Diffusion Policy 等。一个最简单的本地训练命令如下假设你已将数据上传到 Hugging Face Hub或使用本地路径lerobot-train \ --dataset.repo_id”your_hf_username/my_first_dataset” \ # 或本地路径 --policy.typeact \ --output_dir./training_output \ --job_namemy_first_training \ --policy.devicecuda \ # 有 GPU 的话 --wandb.enablefalse \ # 不启用权重与偏置可视化 --steps50000训练完成后你可以使用训练好的模型来让机械臂“回放”或尝试执行新任务lerobot-replay \ --robot.typeso101_follower \ --robot.port/dev/ttyACM11 \ --robot.idmy_follower_arm \ --dataset.repo_id”your_hf_username/my_first_dataset” \ --policy.path./training_output/checkpoints/last/pretrained_model \ --dataset.episode0这条路从环境搭建到模型部署每一步都有不少细节。我最初在 PyAV 上卡了两天又因为电源接错差点烧掉一个电机USB 端口乱序更是让早期测试充满随机性。但当你看到自己校准好的机械臂随着你的手部动作而精准跟随时那种成就感是无可替代的。具身智能的门槛正在被 LeRobot 这样的项目迅速拉低剩下的就是我们的动手能力和耐心了。希望这份避坑指南能成为你探索路上的可靠地图。