1. 项目缘起与整体思路拆解
1.1 为什么选择 SO-ARM100 这套低成本机械臂方案
搞机器人最怕两件事:一是硬件贵得离谱,二是软件生态稀碎。SO-ARM100 这套东西恰好把这两个痛点都按住了。它是一套开源的低成本舵机机械臂,整机物料成本控制得相当克制,结构件可以自己打印,关节用的是常见的串行总线舵机,配合 LeRobot 这个开源框架,能把数据采集、模型训练、真机部署串成一条完整的链路。
我最初盯上它,是因为想验证一个想法:用模仿学习(Imitation Learning)的方式,让机械臂学会一些简单的抓取和放置动作,到底需要多少数据、多强的算力、多长的调试周期。市面上动辄几万块的协作臂对个人开发者不友好,而 SO-ARM100 这种几百块到一千出头就能凑齐的方案,试错成本低,坏了也不心疼,特别适合拿来跑通全流程。
LeRobot 是这套方案里的软件核心。它把机器人数据的采集格式、数据集管理、策略训练、真机推理都做了封装,底层还是 PyTorch 那一套。你可以理解成:SO-ARM100 是身体,LeRobot 是大脑和神经系统,ACT 模型则是具体要训练的那个"技能包"。
1.2 ACT 模型在整个链路里扮演什么角色
ACT,全称 Action Chunking with Transformers,是模仿学习里一个很实用的策略网络。它的核心思想不复杂:传统方法是一帧观测对应一个动作,ACT 则是一次性预测未来一小段动作序列(也就是 action chunk),这样能缓解单步预测的抖动问题,让机械臂动作更连贯。
为什么选 ACT 而不是别的?我的考量有三点。第一,它对数据量的要求相对温和,几十条演示轨迹就能看到初步效果,不像某些方法动辄要几百上千条。第二,它对观测的利用比较充分,图像加关节状态一起喂进去,能学到视觉和动作之间的关联。第三,LeRobot 官方对 ACT 的支持比较完善,配置文件和训练脚本都是现成的,改起来方便。
当然,ACT 也不是万能的。它对任务的时间跨度比较敏感,动作 chunk 的长度设小了学不到长程依赖,设大了又容易过拟合。这个参数后面会重点讲。
1.3 整体实施路线的规划逻辑
我把整个项目拆成了四个阶段,每个阶段都有明确的验收标准,避免一锅粥地往前冲。
第一阶段是环境搭建,目标是让 LeRobot 能在本机跑起来,能读到机械臂的串口,能采集到第一帧图像和关节数据。第二阶段是数据采集,目标是攒够一批质量过关的演示数据,并且能可视化回放确认没问题。第三阶段是模型训练,目标是让 ACT 在训练集上 loss 收敛,在验证集上动作预测合理。第四阶段是真机部署和调参,目标是机械臂能稳定复现演示动作,并且针对失败案例做针对性优化。
这个顺序不能乱。我见过太多人环境还没跑通就急着训模型,结果数据格式不对、串口读不到,白白浪费几天时间。先把地基打牢,后面才顺。
提示:整个链路里最容易出问题的不是模型本身,而是数据采集环节。数据质量差,再好的模型也救不回来。这一点后面会反复强调。
2. 环境搭建的核心细节与实操要点
2.1 系统与 Python 环境的选择考量
LeRobot 对系统环境有一定要求,我实测下来 Ubuntu 22.04 是最省心的选择。为什么不用 Windows?因为串口权限管理、USB 设备识别、以及部分依赖库在 Linux 下更顺滑,尤其是涉及到实时读取舵机数据的时候,Linux 的稳定性明显更好。如果你只有 Windows,用 WSL2 也能跑,但串口透传会多一层折腾,我建议直接上原生 Ubuntu 或者双系统。
Python 版本我锁定在 3.10。3.8 太老,部分新库不支持;3.11 和 3.12 有些依赖还没跟上,容易在编译阶段报错。3.10 是当前生态兼容性最好的甜点版本。
虚拟环境必须用。我习惯用 conda 建一个独立环境,避免和系统 Python 打架。命令很简单:
conda create -n lerobot python=3.10 conda activate lerobot建完环境先别急着装 LeRobot,先把 PyTorch 装好。这里有个坑:PyTorch 版本要和你的 CUDA 驱动匹配。如果你有 NVIDIA 显卡,先跑nvidia-smi看驱动支持的 CUDA 版本,然后去 PyTorch 官网找对应的安装命令。没有显卡也能跑,用 CPU 训练,就是慢,ACT 这种模型用 CPU 训可能要等到天荒地老,所以强烈建议至少有一张 8G 显存的卡。
2.2 LeRobot 安装过程中的依赖处理
LeRobot 的安装方式有几种,我推荐从源码装,因为后面要改配置、看源码,源码装最灵活。
git clone https://github.com/huggingface/lerobot.git cd lerobot pip install -e .这个-e是 editable 模式,改了代码不用重装。装的过程中最容易卡在几个地方:一是ffmpeg相关的依赖,视频编解码要用;二是pybullet之类的仿真依赖,如果你不需要仿真可以跳过;三是串口库pyserial,这个必须装好,不然读不到机械臂。
我遇到过一次pip install -e .卡在编译某个包上,最后发现是系统缺libffi-dev和build-essential。所以装之前先把系统依赖补齐:
sudo apt update sudo apt install -y build-essential libffi-dev ffmpeg装完之后验证一下,跑python -c "import lerobot",不报错就说明基础环境 OK。
2.3 机械臂串口识别与权限配置
SO-ARM100 通过 USB 转串口和电脑通信,插上之后系统会识别成一个/dev/ttyUSB*或者/dev/ttyACM*设备。先用ls /dev/tty*看一眼,插拔前后对比,多出来的那个就是。
默认情况下普通用户没有串口读写权限,直接跑程序会报 Permission denied。解决办法有两个:一是每次用sudo,但这样会把环境变量搞乱,不推荐;二是把用户加到dialout组:
sudo usermod -aG dialout $USER加完要重新登录才生效。这一步很多人会忘,然后纳闷为什么权限还是不对。
还有一个坑:如果同时插了多个串口设备,ttyUSB0和ttyUSB1可能会变。我建议用 udev 规则给机械臂绑定一个固定的设备名,或者每次插拔后用dmesg | grep tty确认当前是哪个口,再填到配置文件里。
2.4 舵机 ID 与波特率的核对
SO-ARM100 用的是串行总线舵机,每个舵机有一个 ID,出厂默认可能都是 1,需要你逐个改成不同的 ID。这一步如果没做,机械臂会完全不响应或者乱动。
核对方法是用厂商提供的调试工具,或者用 LeRobot 自带的脚本扫描总线。波特率也要对上,常见的是 1000000,但不同批次可能不一样,以实际为准。我踩过的坑是:波特率设错,程序不报错,但读回来的数据全是乱的,排查了半天才发现是波特率问题。
注意:改舵机 ID 的时候,一次只接一个舵机,改完再接下一个。同时接多个同 ID 的舵机会导致总线冲突,严重时可能损坏舵机。
3. 数据采集与数据集构建的实操过程
3.1 采集前的机械臂标定与零点设置
数据采集之前,必须做一次标定。标定的目的是告诉系统:机械臂的每个关节在什么位置是"零位",运动范围是多少。如果标定不准,采集的数据里关节角度就是错的,训出来的模型自然也是歪的。
LeRobot 提供了标定脚本,大致流程是:把机械臂摆到一个已知的参考姿态,记录当前各关节的原始读数,作为零点偏移。然后手动把每个关节推到极限位置,记录最小值和最大值,作为运动范围。
标定过程中手要稳,别抖。我建议标定两到三次,取一致的结果。如果每次标定出来的数值差异很大,说明机械臂的机械结构有松动,或者舵机有回程差,需要先解决硬件问题。
3.2 演示数据的采集节奏与质量控制
采集数据就是人手动拖着机械臂(或者用遥控器)完成一遍任务,系统同步记录图像和关节状态。听起来简单,但采集节奏很讲究。
第一,动作要平滑。不要忽快忽慢,不要中途停顿太久。ACT 学的是动作序列的分布,你的演示越接近真实执行时的节奏,模型学出来越自然。
第二,每个任务至少采集 30 到 50 条轨迹。太少了模型学不到泛化性,太多了采集成本高。我一般先采 30 条跑一版,看效果再决定要不要补。
第三,要覆盖不同的初始条件。比如抓取任务,物体的位置要有些变化,不能每次都放在同一个点。否则模型只会记住那一个位置,换个地方就抓瞎。
第四,采集环境的光照要稳定。图像是模型的重要输入,光照突变会让模型困惑。我吃过这个亏:白天采的数据,晚上训完部署,识别率直接掉一半,就是因为光照变了。
3.3 数据集格式与可视化回放验证
LeRobot 的数据集有自己的格式,底层是视频加 parquet 或者类似的列式存储。采集完之后,一定要做可视化回放,确认三件事:图像和关节数据是否对齐、时间戳是否连续、有没有丢帧。
回放的时候重点看关节曲线,正常的曲线应该是平滑的,如果出现锯齿状或者跳变,说明采集时有丢包或者干扰。这种数据要剔掉,不然会污染训练集。
我一般会把数据集按 8:2 分成训练集和验证集。验证集不参与训练,只用来评估模型泛化能力。如果训练 loss 一直降但验证 loss 不降,说明过拟合了,要么加数据,要么减模型复杂度。
提示:数据集命名和版本管理要规范。我习惯用"任务名_日期_版本号"的格式,比如
pick_cube_20240510_v2。不然过几天你自己都分不清哪个是哪个。
4. ACT 模型训练与调参的核心环节
4.1 训练配置文件的参数解读
LeRobot 里 ACT 的训练配置是一个 YAML 或者 Python 字典,里面有几个关键参数必须搞懂。
chunk_size是 action chunk 的长度,也就是模型一次预测多少个未来动作。这个参数直接决定了模型的时间视野。设太小,比如 10,模型只能看到很短的一段,动作会碎;设太大,比如 100,模型要预测很长的序列,训练难度陡增,而且容易过拟合。我的经验是从 30 到 50 开始试,根据任务的时间跨度调整。
hidden_dim是 Transformer 的隐藏层维度,决定了模型的容量。太小欠拟合,太大过拟合还费显存。一般 256 到 512 之间比较合适。
n_heads是注意力头数,要和hidden_dim配合,通常hidden_dim能被n_heads整除。
learning_rate学习率,ACT 对学习率比较敏感,我一般从 1e-5 开始,配合 warmup 和 cosine 衰减。
batch_size看显存,8G 显存大概能跑 8 到 16,不够就开梯度累积。
4.2 训练过程的监控与收敛判断
训练启动之后,要盯着几个指标:训练 loss、验证 loss、以及动作预测的可视化。
训练 loss 正常应该是先快速下降,然后缓慢收敛。如果一开始就不降,检查学习率是不是太大或者太小,检查数据有没有问题。如果降到一半开始震荡,可能是 batch size 太小,或者学习率没有衰减。
验证 loss 是判断过拟合的关键。理想情况是训练 loss 和验证 loss 同步下降,最后都趋于平稳。如果训练 loss 继续降而验证 loss 开始上升,就是过拟合了,这时候要么早停,要么加数据增强,要么减小模型。
我还会在训练过程中定期跑一次推理,把模型预测的动作和真实动作画在一起对比。如果预测曲线和真实曲线形状接近,只是有相位差,说明模型学到了动作模式;如果预测曲线是一条直线或者乱跳,说明模型没学到东西。
4.3 学习率与 chunk_size 的联合调参经验
这两个参数是相互影响的,不能单独调。
我的一般流程是:先固定chunk_size为 50,调学习率,找到 loss 下降最稳的那个值。然后固定学习率,试chunk_size为 20、30、50、80,看哪个在验证集上表现最好。
实测下来,对于抓取放置这类任务,chunk_size在 30 到 50 之间效果最好。太小了动作不连贯,太大了模型会"想太多",反而预测出一些莫名其妙的动作。
学习率方面,1e-5 配合 500 步 warmup 是个比较稳的起点。如果 loss 下降太慢,可以试 3e-5,但要注意别太大,太大了会直接发散。
注意:调参的时候一次只改一个变量,改完记录结果。同时改多个参数,你根本不知道是哪个起了作用。我习惯用一个表格记录每次实验的配置和结果,后面回看非常有用。
5. 真机部署与常见问题排查实录
5.1 模型推理的延迟与实时性优化
训练好的模型要部署到真机上,最大的挑战是推理延迟。ACT 模型不算小,如果推理一次要几百毫秒,机械臂动作就会一顿一顿的。
优化手段有几个:一是用半精度(fp16)推理,速度能快不少,精度损失很小;二是把模型导出成 ONNX 或者 TensorRT,进一步加速;三是减少输入图像的分辨率,但要注意别降太多,否则模型看不清。
我实测下来,在 RTX 3060 上,fp16 推理一次大概 30 到 50 毫秒,配合 action chunk 的机制,机械臂动作基本流畅。如果用 CPU 推理,可能要 200 毫秒以上,那就很卡了。
5.2 动作抖动与执行失败的典型原因
部署之后最常见的问题是动作抖动。原因可能有好几个:一是模型预测的动作本身就不平滑,这通常是训练数据质量或者 chunk_size 设置的问题;二是推理频率和执行频率不匹配,导致动作被重复执行或者跳过;三是舵机的控制精度不够,指令和实际位置有偏差。
排查的时候,先把模型预测的动作序列单独打出来看,如果预测本身就抖,那是模型问题;如果预测平滑但执行抖,那是控制链路问题。
执行失败还有可能是初始位置不对。模型是在特定初始条件下训练的,如果部署时机械臂的起始姿态和训练时差太多,模型会懵。解决办法是在每次执行前把机械臂复位到一个固定的初始姿态。
5.3 常见问题速查表
| 问题现象 | 可能原因 | 排查方向 | 解决办法 |
|---|---|---|---|
| 串口读不到数据 | 权限不足或设备名错误 | 检查/dev/tty*和用户组 | 加入 dialout 组,确认设备名 |
| 舵机不响应 | ID 冲突或波特率错误 | 扫描总线,核对波特率 | 逐个改 ID,统一波特率 |
| 训练 loss 不降 | 学习率不当或数据有问题 | 检查数据可视化和学习率 | 调整学习率,清洗数据 |
| 验证 loss 上升 | 过拟合 | 对比训练和验证曲线 | 加数据,减模型,早停 |
| 真机动作抖动 | 推理延迟或预测不平滑 | 单独看预测序列 | 优化推理,调 chunk_size |
| 换环境后失效 | 光照或背景变化 | 对比采集和部署环境 | 固定光照,增加数据多样性 |
5.4 独家避坑经验分享
第一个坑:数据采集时忘了开摄像头或者摄像头被占用。LeRobot 采集时会同时读摄像头和串口,如果摄像头被其他程序占用,采集会静默失败,数据里只有关节没有图像。所以采集前先确认摄像头可用。
第二个坑:训练时显存不够,程序直接崩。ACT 的显存占用和 batch_size、图像分辨率、chunk_size 都有关。显存不够就减 batch_size,开梯度累积,或者降图像分辨率。
第三个坑:部署时忘了切换模型到 eval 模式。PyTorch 模型在 train 和 eval 模式下行为不同,如果忘了切,dropout 和 batchnorm 会捣乱,导致推理结果不稳定。
第四个坑:机械臂电源功率不够。多个舵机同时运动时电流很大,如果电源功率不足,舵机会掉电复位,表现为机械臂突然软掉。换一个功率足够的电源能解决。
第五个坑:数据集路径写错。LeRobot 读数据集是按配置里的路径找的,路径错了会报找不到文件。建议用绝对路径,别用相对路径,省得因为工作目录不同而出错。
6. 项目复盘与后续扩展方向
整套流程跑下来,我最大的感受是:模仿学习的门槛不在模型,而在数据和工程细节。ACT 本身并不复杂,LeRobot 也把很多脏活累活封装好了,但数据采集的质量、环境搭建的稳定性、部署时的实时性,这些才是决定项目成败的关键。
如果让我重新做一遍,我会在数据采集阶段投入更多时间,把演示轨迹的质量再提高一档,而不是急着训模型。因为数据质量的上限,决定了模型效果的上限。
后续可以扩展的方向有几个:一是增加任务复杂度,从单物体抓取扩展到多物体、多步骤的任务;二是尝试其他策略网络,比如 Diffusion Policy,对比一下和 ACT 的优劣;三是加入语言条件,让机械臂能听懂指令,这就涉及到视觉语言动作模型(VLA)的范畴了。
最后分享一个小技巧:每次实验都做好记录,配置、数据、结果、问题,全部记下来。机器人项目周期长,细节多,不记录的话,过两周你自己都忘了当时为什么那么调。我用一个简单的 Markdown 表格记录每次实验,回看的时候一目了然,省了很多重复踩坑的时间。