☰
基于LeRobot的多臂协同控制:标定、训练与部署全流程解析
2026/10/23 3:57:38 网站建设 项目流程

干了几年机器人控制,最头疼的其实不是让一条臂精准走轨迹,而是让两条臂待在同一张桌子上还能“心往一处想”。你单独测左臂,走位漂亮得很;单独测右臂,重复精度也没话说。可一旦让它俩配合,拧个瓶盖都能互相怼上,或者一个往前一个往后直接打架。这就是我今天想聊的:基于 LeRobot 的多臂协同控制,怎么把两条机械臂从“各自为政”变成“一个整体”。

LeRobot 是目前开源社区里比较完整的机器人学习框架,核心思路是用模仿学习让机器人从示教数据里学动作,而不是靠手写一大堆规则。多臂协同控制这件事,恰恰是模仿学习最能发挥优势的领域——因为两条臂配合的动作,比如双手端盘子、协同插线缆、装配零件,用传统运动规划去写约束条件会写到怀疑人生,但如果你让机器人“照着人怎么操作去学”,问题就简单了一大截。

这篇文章我会从硬件选型、坐标系标定、数据采集、模型训练、部署调试一路讲到常见坑位,目标是让有基本机器人控制经验、但第一次碰双臂平台的开发者,能照着这套流程把两条臂真正跑起来。适合的人包括做具身智能研究的同学、实验室里搭双臂平台做验证的工程师,以及想从单臂控制往多臂协同进阶的机器人爱好者。

1. 双臂协同比单臂难在哪:先想清楚再动手

1.1 三个绕不开的技术坎

第一个坎是坐标系对齐。单臂的时候,所有轨迹、位姿都以机械臂自己的基座坐标系为基准,你不需要关心别的东西。但双臂一上桌,问题立刻出现:两条臂各自有各自的基座坐标系,你让左臂末端走到坐标 (0.4, 0.1, 0.3),右臂末端也走到同样的坐标,这个坐标的意义是完全不同的——因为两个基座可能差了0.5米、转了15度。所以第一步必须把两条臂的坐标系统一到一个公共坐标系下,这个动作在机器人领域叫外参标定,也就是求两条臂基座之间的变换关系。

第二个坎是空间干涉。两条臂的工作空间天然重叠,做协同动作的时候,如果两边各跑各的轨迹,很容易在中途发生碰撞。单臂控制里基本不用考虑自碰撞问题,但双臂必须把“另一条臂在哪”实时纳入规划或决策里。实现方式有很多种,传统路线是加碰撞检测算法,在模仿学习路线里,更实用的做法是在数据采集阶段就让人的操作天然避开干涉区,让模型学到“双臂该在什么时候让开”的习惯。

第三个坎是时间同步。协同动作对双边的时序一致性要求很高。比如双手捧着一个盒子往右平移,如果左臂比右臂慢了0.2秒,盒子就会被拧歪甚至掉落。单臂控制不需要和谁同步,双臂协同则需要让左右臂的控制指令在同一个时间基准上发出,这既涉及硬件通信层面的时钟同步,也涉及算法层面输出的双路动作是否保持一致。

1.2 模仿学习范式下,双臂协同的数据更“重”

单臂的模仿学习,一条数据样本通常是这样:一个状态(比如当前关节角、末端位姿、相机图像),对应一个动作(比如下一时刻的关节角目标)。这条链路在双臂上直接翻倍:状态变成了双臂的联合状态,动作变成了双臂的联合动作。假设每条臂6个关节、夹爪1个自由度,那么单臂动作维度是7,双臂就是14。数据维度翻倍带来两个直接影响:一是需要更多数据量才能覆盖足够多的状态空间,二是训练时模型要同时拟合两条臂的动作分布,难度指数级上升。

我在实际项目里体会最深的是数据采集阶段。单臂数据采集你可以慢慢来,动着一条臂,随时暂停、修正都行。双臂就完全不同了,它需要左右手同步操作,采集过程几乎不允许“一只手动一只手动”的录制方式——那样学出来的模型只会把两臂当成两个独立任务来处理,学不到协同关系。LeRobot 在数据采集环节提供了一套标准的 episode(回合)机制,每一条 episode 都是一个完整任务的左右臂同步记录,这种按回合组织数据的方式,天然适合双臂协同的学习。

1.3 为什么直接选 LeRobot 而不自己造轮子

我自己也写过控制程序,深知从零搭一条模仿学习链路有多痛苦:要写数据采集程序、要接相机同步、要设计模型结构、要写训练循环、要做评估……每个环节都有大量细节,一个没接好整条链路就断掉。LeRobot 把这些封装成了标准模块,你只需要把注意力放在硬件适配和任务设计上。

更关键的是,LeRobot 里默认支持了几类主流模仿学习算法,比如基于 ACT(Action Chunking with Transformers)和扩散策略(Diffusion Policy)的实现。这类算法特别适合多关节高维度输出的场景,正好匹配双臂14维动作的拟合需求。框架本身并不限定必须用哪类机械臂,只要你把机器人的关节控制接口和相机数据接进来,就能复用后面的采集、训练、评估流程。对多数团队来说,这是目前把双臂协同最快跑通的一条路。

2. 动手前的技术底牌:硬件和环境的正确姿势

2.1 硬件选型:别在起点给自己挖坑

先列出我建议的双臂协同最小硬件清单,每一件后面都注明为什么不能省:

硬件数量建议与理由
六轴协作机械臂(带关节角度反馈)2同型号最优,关节控制接口统一,标定和建模都省事
夹爪2优先选带开合度反馈的电动夹爪,数据里必须有“夹爪张合程度”这一维
RGB-D 深度相机1-2放在能同时覆盖两条臂工作空间的位置,别只盯着单臂
控制主机1消费级带独显的机器即可,LeRobot 训练对显存有一定要求
工作台1固定安装位,两条臂的基座一旦安装好就不许挪动

关于机械臂型号,我强烈建议两条臂用同一型号。如果条件所限必须用不同型号,那么至少保证关节控制频率一致、控制接口统一,否则后面数据采集时左右臂的响应延迟会有明显差异,学出来的模型动作会非常别扭。某次我在一个模拟项目里用过两条不同品牌的臂,结果训练出来的模型在回放时,一条臂已经到位了,另一条还在慢悠悠走,整个协同动作完全对不上。

2.2 软件环境搭建:版本踩坑记录

LeRobot 的安装流程不复杂,但有几个版本坑一定要提前避:

conda create -n lerobot python=3.10 -y conda activate lerobot pip install lerobot

注意 Python 版本,3.10 是我实测最稳的。装完以后验证一下依赖是否齐全:

import lerobot print(lerobot.__version__)

如果没有报错,基本框架就通了。接下来还需要安装 PyTorch,推荐在安装 LeRobot 之前先把 PyTorch 装好,避免依赖解析和你本机的 CUDA 版本错配。

pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118

这里的 cu118 对应 CUDA 11.8,具体版本根据你显卡驱动来选。我在一台只有低端显卡的机器上试过纯 CPU 训练,不是不能跑,但效率低到让人失去耐心,所以有 GPU 还是尽量用 GPU。

2.3 机械臂的通信与控制接口

LeRobot 本身不做底层运动控制,它需要你提供一个“拿关节角度换动作执行”的接口。常见做法是走 ROS,也可以直接走厂商提供的 SDK。我在实际项目里更推荐直接通过厂商 SDK 来控制,省去 ROS 环境配置这一层复杂度。

你需要在代码里实现的核心接口,可以封装成一个机器人类,里面至少包含读取关节状态和发送关节目标这两个方法:

class DualArmRobot: def __init__(self, left_sdk, right_sdk): self.left = left_sdk self.right = right_sdk def read_joint_states(self): # 返回 left_7d + right_7d,维度14 pass def send_joint_targets(self, target_14d): # 将14维目标拆成左右各7维,分别下发 pass

这里有个细节:夹爪的开合度最好也作为独立维度,和6个关节角一起拼成7维动作向量。LeRobot 内部对动作维度的理解很直接,你给它多少维,它就拟合多少维,夹爪不参与协同配合的任务也可以加,但那样模型就学不到“什么时候该抓什么时候该放”。

2.4 数据量级预期:几百回合起步

很多人问我,双臂协同到底要采多少数据才能训出一个能看的模型。我的经验是:简单任务(比如双手把一个立方体从A点搬到B点)起步300到500回合;中等复杂度任务(比如双手协同插线缆)要700到1000回合;更复杂的精细化任务,建议先别急着上真机,去仿真环境里预训练,再迁移到真机。

不要觉得这个数据量吓人,一个回合的任务时长通常只有5到15秒,按50Hz采样频率也就是250到750帧数据。整个采集过程半天到一天是正常的。真正要花时间的是保证每回合的数据质量,而不是盲目堆数量。

3. 先让两条臂“说同一种语言”:标定与协同环境搭建

3.1 标定到底在标什么

标定解决的是坐标统一问题。简单理解:每台设备都有自己的“世界观”,标定就是让两台设备对“什么是桌面上这一点”达成共识。双臂系统里通常要标定两件事:一是两条臂基座坐标系之间的变换矩阵,二是相机坐标系到某条臂基座坐标系的变换矩阵。

变换矩阵这个东西,本质是一个4x4的齐次矩阵,里面包含旋转分量和平移分量。我一般用这样的方式表述:假设你在左臂基座坐标系下有一个点,坐标为 p_left,那么它在右臂基座坐标系下的坐标 p_right 就等于:

p_right = T_left_to_right * p_left

T_left_to_right 就是我们要求的标定矩阵。采集数据时,每帧我们同时记录左右臂的关节角,当模型输出动作时,它学到的是“在这种联合状态下该输出什么联合动作”,这里面的隐式前提就是双臂在同一空间框架下。标定错一点,模型学到的协同映射就是错的,后面再调参都补不回来。

3.2 实操:用 ArUco 标定板做双臂基座外参标定

我用的标定方法算是经典里的经典:把标定板固定在工作台上,保证两条臂的相机都能看见它。先让左臂末端的相机读标定板,求出左臂末端坐标系与标定板坐标系的变换 T_end_left_to_board;再让右臂做同样的操作,得到 T_end_right_to_board。因为标定板是同一个,所以可以通过矩阵串联算出左臂基座到右臂基座的变换。

实现时我直接借助 OpenCV 的 ArUco 模块:

import cv2 import numpy as np # 假设已经通过相机拍到标定板,得到四个角点在图像上的坐标 # corners: (4, 2),实际板坐标按0.05m间距生成 board_points = np.array([ [0, 0, 0], [0.05, 0, 0], [0, 0.05, 0], [0.05, 0.05, 0] ], dtype=np.float32) # 通过solvePnP求相机到标定板的位姿 _, rvec, tvec = cv2.solvePnP(board_points, corners, camera_matrix, dist_coeffs) R, _ = cv2.Rodrigues(rvec) T_cam_to_board = np.eye(4) T_cam_to_board[:3, :3] = R T_cam_to_board[:3, 3] = tvec.flatten()

拿到相机到标定板的变换后,再通过机械臂的关节角正运动学求出末端到基座的变换 T_base_to_end,一串联就成了:

T_cam_to_board = T_cam_to_end * T_end_to_base * T_base_to_board

实际工程里,我会做至少5次不同视角的采样,把每次算出来的矩阵做平均,用来压低随机误差。标定做完之后必须验证:让右臂末端去碰左臂末端附近的某个固定点,把右臂坐标系下读到的位置,换算到左臂坐标系,再从左臂控制末端去同一个点,看看实际误差能不能控制在几毫米内。能,说明坐标系对齐了。

3.3 安全空间与碰撞避让

双臂协同跑起来之后,最怕的是训练阶段还没什么问题,一到模型的泛化场景,两条臂在特定状态下忽然撞上。传统解法是实时做碰撞检测,在每步控制前检查两臂的关键连杆距离是否小于安全阈值,如果小于就停止运动或进入避让逻辑。

我提供一个轻量级近似方案里很常用的做法:把每节连杆简化成圆柱体或球体,碰撞检测就退化成计算球心距:

def check_collision(spheres_left, spheres_right, threshold=0.05): for sl in spheres_left: for sr in spheres_right: dist = np.linalg.norm(sl.center - sr.center) if dist < sl.radius + sr.radius + threshold: return True return False

每根连杆包成1到2个球,两条臂各6到12个球,双循环的计算量也就上百次距离运算,完全够实时跑。这个检测结果可以作为数据采集阶段的“安全刹车”,也可以作为部署阶段的保护机制。注意,这个方案只能拦截碰撞,不能规划避让轨迹,所以别指望它解决动态避障问题,它是兜底,不是主力。

3.4 标定验证的小技巧

标定完成后别急着采集数据,花10分钟做个一致性检查。我的做法是让两条臂分别运动到工作空间内的5个不同位置,每到一个位置,同时记录左臂末端位姿和右臂末端位姿。然后利用标定矩阵把右臂末端位姿换算到左臂坐标系下,和左臂直接测得的位姿做差。如果三个位置的平移误差都在5毫米以内、旋转误差在1度以内,标定就算合格。

这一步看着不起眼,却是决定整个项目成败的关键。我曾经跳过验证直接开始采数据,训出来的模型表现很奇怪:左臂动作基本正常,右臂动作完全乱套。后来排查才发现标定矩阵里的平移向量差了2厘米,就是因为没做验证直接信任了单次标定结果。

4. 数据采集与训练:模型是怎么学会“配合”的

4.1 采集方案:主从遥操作是主流

采集双臂示范数据的方式,我试过三种:示教器逐步编程、视觉动捕跟随、主从遥操作。示教器太慢,一个5秒的动作可能要编20分钟;动捕方案精度高但设备贵、环境要求苛刻。最适合实验室环境的还是主从遥操作——你用两只手分别控制两条“主臂”,从臂实时跟随主臂的动作,或者用一个双摇杆手柄控制两条从臂末端速度。

LeRobot 社区里常见的方案是双臂同构遥操作,两条主臂和两条从臂型号一致,主臂的关节角度实时映射到从臂。映射时通常要加一个缩放系数,因为人的手臂长度和机械臂的工作空间不一定一致:

joint_target_from = joint_current_master * scale + offset

scale 一般取 0.5 到 1.0 之间,视工作空间匹配度而定。遥操作的手感和“人机匹配度”直接影响数据质量,这一块建议多花时间调,直到操作者能流畅、稳定地完成任务,再正式开始采数据。

4.2 数据集格式与采集节奏

LeRobot 采集的数据集按回合组织,在本地会生成一个目录,里面包含观测数据、动作数据和状态元数据。我通常会以 50Hz 的频率采样,也就是说每秒记录50帧。一帧数据里包括:

  • 左臂7维关节状态(6个关节角 + 夹爪开合度)
  • 右臂7维关节状态(同上)
  • 相机图像(可选,用于视觉输入)
  • 时间戳

采集过程中最容易犯的错是“想一次录完”。我用过一段时间后总结出比较稳妥的节奏:每采集20到30回合,停下来回放其中5回合,确认没有异常动作、没有目标物位置偏移过大,再继续采。如果连续出现“右手总是没抓到盒子中心”这种问题,多半是操作习惯的问题,趁早纠正,别等数据采完了才发现。

目录结构大致是:

data/ task_name/ episodes/ episode_000001.parquet episode_000002.parquet meta/ info.json

LeRobot 对这种结构可以直接读取,不需要你额外写复杂的解析代码。

4.3 训练配置:从默认参数开始,别乱动

LeRobot 内置了多个算法实现,我建议先从 ACT 默认配置跑起。ACT 在双臂协同这类高维连续动作控制任务上很稳,训练收敛速度也相对快。

一个典型的训练启动命令:

python lerobot/scripts/train.py \ --policy.type=act \ --dataset.repo_id=local/custom_dataset \ --output_dir=outputs/dual_arm_test \ --batch_size=8 \ --num_epochs=100 \ --lr=1e-4

这里几个参数值得解释一下:

  • batch_size 取 8 是因为双臂联合动作维度较高,显存占用大,小batch更容易稳定训练。强行上大batch容易OOM,收益也有限。
  • 学习率 1e-4 是这类模型常见的起点,别一上来就调大,ACT 结构对这种学习率已经足够。
  • num_epochs 建议先跑 100,看 loss 曲线再决定是否继续。有时候 100 轮已经够用,不需要盲目堆轮次。

训练过程中盯着 loss 曲线。正常情况是前20轮快速下降,后面进入缓慢下降平台期。如果 loss 从一开始就不降,或者跌到某个值再也不动,多半是数据问题,不是超参问题,先去检查数据回放。

4.4 看一眼 loss 曲线和成功率

训练结束后,LeRobot 会产出 checkpoint。不要只看训练损失,训练损失低只说明模型拟合了训练数据,不代表泛化好。我把验证拆成两步:先在仿真或回放环境里做一次 rollout,看模型在“见过的状态附近”表现;再上真机做50次评估,记录成功率。

一个比较可行的验收标准:同一个任务,模型在真机上连续执行50次,成功率做到80%以上,才算这个协同动作“学稳了”。如果成功率低,先看是左臂的问题还是右臂的问题,再具体分析。

5. 部署运行与问题排查:从“会配合”到“干得好”

5.1 模型推理到控制指令的实时链路

训练完的模型部署到真机,链路是这样的:读取相机图像和双臂关节状态 → 输入模型 → 输出一个动作块(比如未来50步的双臂联合动作)→ 控制器逐帧下发关节指令。LeRobot 的推理逻辑里有一个关键概念叫 action chunking,模型一次预测多步动作,而不是每帧都重新推理一次。这样做的好处是动作平滑、减少推理抖动。

实际部署时要注意:模型输出的动作块是关节角目标,不是直接发给伺服电机的原始指令。如果你的机械臂SDK提供的是位置控制模式,直接下发即可;如果是速度控制模式,还要先做差分换算。位置控制模式下,需要注意下发频率必须和训练时保持一致。训练时用50Hz采集,部署时如果只按10Hz下发,动作会变得卡顿且生硬。

5.2 高频踩坑实录

双臂协同部署时我踩过不少坑,挑几个最有代表性的说:

第一,两条臂动作明显“一快一慢”。排查后往往不是模型问题,而是通信延迟不一致。某型号机械臂的SDK走网络通信,天线位置稍有遮挡,命令下发的延迟就增大。解决办法很简单:把两条臂都用有线连接,或者改用同一个实时控制进程统一下发。

第二,夹爪开合动作错位。模型学得挺好,但夹爪张合总是比预期慢半拍。原因通常是采集时,夹爪开合度的数值变化是离散的(开/闭两档),而模型输出是连续的,导致夹爪在中间位置卡顿。解法是在夹爪控制里加一个映射阈值,把连续输出量化回开关量,但如果任务需要精细夹持,还是建议换带连续位置反馈的夹爪。

第三,模型表现的协同动作是对的,但总是差一点点就碰到目标物。这个通常是图像输入和关节状态不同步导致的。LeRobot 采集时相机和关节数据会打时间戳,同步时如果差值超过两帧,模型学到的“视觉-动作”映射就是糊的。所以采集前一定要确认相机的时间戳对齐,不要用默认值。

5.3 排查速查表

问题现象可能原因排查方向
双臂动作不协调,左右臂节奏不一致通信延迟差异或控制频率不统一检查SDK响应时间,统一频率,优先有线连接
模型输出动作抖动、发飘动作块被逐帧累加,误差积累使用LeRobot的chunk机制,按块执行,做滤波平滑
夹爪总是夹偏图像与关节数据时间戳未对齐校准相机时间戳,重新同步数据
训练loss不下降数据回放有问题或动作维度不匹配先做episode回放,确认数据正确性
一到某个特定位置两条臂就撞碰撞检测阈值过松调整安全距离,重建两臂连杆球体模型
模型泛化差,换目标位置就失败数据中目标物位置变化太少采集时人为改变目标物位置,增加数据多样性

5.4 数据质量是第一生产力

训练之前先做数据回放检查,也就是把采集的 episode 以动画形式播放出来,肉眼确认“人的操作痕迹”是否自然、连续。这一步能过滤掉绝大多数的数据问题。

我第一次做双臂协同项目时,采集了400回合数据,觉得肯定够用了,结果模型一上真机就暴露问题:左臂很稳,右臂总是绕远路。回放数据才发现,我采集时右手的操作习惯是“先抬高再平移”,这个动作模式被模型原封不动学了过去。单看每回合都成功,但绕远路这个习惯对效率影响很大。后面重新采集,刻意让右手走“直接平移”的路线,模型动作立刻变利索了。

6. 我的几点经验心得与进阶方向

6.1 三条能让项目少走弯路的经验

第一条经验:先分别把两条臂的单臂控制练到极致,再上双臂协同。这里说的“练”不一定是算法层面,而是底层接口的稳定性。左右臂各自的关节读取、目标下发、急停逻辑都验证过没问题之后,再开始折腾协同和高层学习。很多双臂项目死在底层通信不稳定上,这锅不该模型背。

第二条经验:数据一致性比数据量重要。500回合高质量、目标物位置分散、左右手动作模式一致的数据,远胜1500回合随便采的杂乱数据。我在实际测试中,把数据量砍掉一半但把每回合的动作质量提上来,成功率反而涨了十几个百分点。

第三条经验:标定不能省,也不能只做一次。整个项目过程中,机械臂基座一旦被碰歪,哪怕只偏了2毫米,协同精度就全毁了。每次开机先跑一遍快速标定验证,是一个值得养成的好习惯。

6.2 后续可以怎么进阶

跑通了双臂协同基础闭环之后,有很多方向可以继续深入。我目前比较看好的是任务分层:上层用一个独立模型负责把任务分解成“左臂负责夹持,右臂负责插入”这类子任务,下层再用模仿学习模型执行每一个子动作。LeRobot 现在的结构做这个分层改造很方便,你只需要在推理链路里插入一个任务规划模块。

另一个方向是引入语言指令。给双臂系统加一个语言接口,让人说出“把盒子端到左边”,模型就自动生成双臂协同动作。LeRobot 后续版本也在往多模态的方向走,语言、视觉、动作的统一建模,会让双臂协同的实用性再上一个台阶。

最后再分享一个小技巧:如果你有条件,先在仿真环境里把任务跑通,再迁移到真机。仿真里采集数据便宜、迭代快,用仿真预训练一个基础模型,再在真机上用小批量数据做微调,能把整个项目周期从两三周压缩到三四天。LeRobot 对仿真环境有现成的支持,这也是我为什么一直建议新项目从这套框架起步的原因——少造轮子,多验证想法,这才是做机器人学习该有的节奏。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询