第一次把SmolVLA接到SO101机械臂上,比我预想的要曲折得多。模型本身部署不难,难的是让模型的“想法”真正传到那六个舵机上,还能稳定跑完一个抓取流程。我身边好几个朋友都是卡在“模型加载成功、机械臂纹丝不动”这个阶段,然后就开始怀疑是模型问题、硬件问题、还是自己写错了代码。其实都不是,问题大多出在对整条链路缺少一个清晰的认知。
这篇文章我会按自己实际跑通的顺序来写:从SO101机械臂的硬件通信讲起,再讲SmolVLA这个视觉语言动作模型该怎么选、怎么部署,然后是数据采集、训练、推理联调,最后是常见错误排查。适合手里有SO101或者SO-ARM100这类六自由度桌面机械臂、想从传统脚本控制切换到VLA控制的人参考;如果你用的是其他总线舵机机械臂,思路也一样能套用。
1. 动手前先理清一条链:SO101的关节、总线舵机与上位机通信
1.1 SO101的硬件结构到底是怎么回事
SO101本质上是一台六自由度桌面机械臂,和SO-ARM100属于同一个思路的产物。六个关节全部由串行总线舵机驱动,结构件大多是通过3D打印或铝合金加工做出来的。你在网上搜SO101的时候,会看到大量“3D打印机械臂毕业设计”的帖子,说明这东西非常依赖DIY装配质量,硬件本身的一致性并不高。
这是第一件要记住的事:SO101并不是一个“插上电就绝对精确”的设备。每个关节的舵机都有独立ID、有零位偏移、有角度限位。如果你在部署SmolVLA之前没有把这些项确认好,后面模型输出动作再准,机械臂也会表现出“偏到姥姥家”的效果。
很多人第一次拿到SO101,习惯性先跑通了串口发送舵机角度的脚本,就以为硬件准备好了。实际上至少还差两件事:一是把所有关节归零后确认机械臂姿态是正确的,二是确认每个舵机在运动中不会撞限位。这两件事不做,后面训练数据都会是脏数据。
1.2 上位机与舵机之间的通信链路
SO101的控制链路是这样一个顺序:
上位机(Linux)→ USB转TTL → 串行总线舵机(关节1~6)上位机通过串口发送舵机角度指令,总线舵机串联在一根总线上,每个关节用ID区分。SO101在LeRobot生态里对应的控制脚本通常通过/dev/ttyUSB0这样的串口设备访问舵机。第一次接入时,建议先检查一下系统是否识别到了串口设备:
ls /dev/ttyUSB*如果识别不到,先看看是不是USB转TTL的驱动没装好,或者线材本身有问题。这个非常基础,但非常多人卡在这。识别到之后,还需要确认当前用户是否有串口权限。Linux下如果启动控制脚本提示permission denied,大概率是没把用户加进dialout组:
sudo usermod -a -G dialout $USER # 注销重新登录后生效还有一点很容易忽略:接线时TX和RX要交叉,就是上位机的发送端对舵机总线的接收端。很多舵机没反应、收发数据不正常,其实只是杜邦线插反了。
电源问题也要提前说。串行总线舵机在启动瞬间和急停反转时电流会冲得很高,如果电源余量不足,最常见的表现是机械臂运行到一半突然全体断电复位,或者是单片机重启。我自己的经验是,桌面型的SO101用官方推荐的电压范围,电流余量留足50%以上比较稳。
1.3 零位校准:以后所有偏差的根源
零位校准听起来简单,但确实值得单独讲。SO101每个舵机在装配时很难保证“舵机默认零位”就是“机械臂竖直姿态”,如果不校准,机械臂的坐标系就是歪的。
LeRobot的SO101端到端控制脚本里一般有校准入口,你手动让所有关节归零,然后松开舵机臂的固定螺丝,把机械臂摆正到目标零位姿态,再锁紧。这个过程要慢一点,因为直接给舵机上电后它会锁定位置,强行掰可能会打齿。
零位校准的精度会直接反映在训练数据里。动作值在舵机空间里可能只是角度,但如果零位偏了2度,视觉上机械臂末端可能偏出好几厘米,模型再聪明也没办法靠预测补偿这种系统性误差。
2. SmolVLA是什么、为什么适合桌面机械臂:模型选型与运行环境
2.1 SmolVLA不是“一个模型”,是两个方向
SmolVLA是Hugging Face团队开源的轻量级视觉语言动作模型。它分为两种形态:Instruct模型和Policy模型。
Instruct模型偏“多模态理解”,你给它一张图像和一句自然语言指令,它输出一段文字或动作描述。Policy模型则是真正用于机器人控制的,输入图像和当前关节状态,直接输出关节动作序列。控制SO101走完整个抓取流程,用的是Policy模型。很多人不看文档,把Instruct模型当成控制模型来用,自然跑不出机械臂动作。
SmolVLA的模型尺寸分为0.4B、2.5B、8B等几个档位。对于SO101这种六自由度桌面机械臂,2.5B的Policy模型在推理速度、精度、显存占用之间比较均衡。0.4B推理更快,但策略的精细程度会低一些,比较适合在无GPU或低算力设备上快速验证链路;8B在桌面任务上会更聪明,但一台普通游戏本跑起来就吃力了。
2.2 为什么选它而不是从零写PID或传统规划
每当你提到“机械臂控制”,网上大量内容是PID、FOC、级联PID这一类底层电机控制。SO101的舵机内部本身就集成了底层控制,你不太需要再从零调舵机PID。你真正缺的是“上层决策”:看到桌上的红色方块,决定怎么伸过去、怎么抓、怎么放到杯子里。
传统做法是手写运动规划和抓取逻辑:先标定相机,再做物体识别,再算逆运动学,再规划轨迹。这套流程在固定场景下能用,但换一个物体、换一个摆放位置就要重新调,且对没学过机器人学的同学来讲门槛偏高。
SmolVLA走的是“模仿学习”路线:你采集几组机械臂操作的示范数据,模型直接学习“看到什么状态,输出什么动作”。不用手写逆解,不用做物体检测模型。这正是它适合SO101这种桌面机械臂的核心原因——硬件便宜,场景相对固定,但需要快速迭代不同抓取任务。
2.3 部署环境的配置细节
SmolVLA在LeRobot框架中运行。LeRobot是Hugging Face开源的机器人学习框架,SO101正好也是LeRobot支持的环境之一。部署时我建议直接用LeRobot源码或官方镜像,因为SmolVLA的策略代码更新比较频繁,直接用pip装一个固定版本很可能会碰到策略类型不识别的问题。
强烈建议使用Python 3.10以上版本,并且确认CUDA、PyTorch版本匹配。LeRobot自带一些环境检查命令,跑模型前先跑一遍环境检查,会省掉很多莫名其妙的问题。
模型权重可以提前下载到本地目录,避免运行时反复拉取网络资源。加载时使用本地路径比直接填HuggingFace仓库名更可控,尤其是你身处的网络环境对国外模型仓库访问不稳定时,提前下载离线权重是更稳妥的做法。下载时注意一下模型卡里的说明,Policy模型和Instruct模型的权重不要搞混。
显存方面我做了一个简单对照,方便你判断自己手里的机器适合跑哪一档:
| 模型尺寸 | 最低显存参考 | 适合场景 |
|---|---|---|
| 0.4B | 约4~6GB | 验证链路、低算力设备、CPU兜底 |
| 2.5B | 约8~10GB | 桌面抓取、常规训练与推理 |
| 8B | 约16GB以上 | 复杂任务、追求更高成功率 |
3. 让模型听你的话:数据采集、训练与监控的关键细节
3.1 别跳过采集,也別只采十几条数据就开训
SmolVLA-Policy虽然带着预训练权重,但它不是一个“装上去就什么都会”的通用大脑。预训练模型更多是帮你少训练一些基础视觉特征,要在你自己的SO101上完成某个具体任务,比如“把红色方块放进白色杯子”,还是得采集自己的示范数据微调。
有些人想偷懒,采集十几个episode就去训练,出来的模型可能在训练数据上表现得很好,但稍微换个摆放位置就失败了。这就是典型的过拟合。我的建议是最少采集50个episode,如果要追求一个稳定的成功率,最好做到80到100个episode。每个episode不需要长,5到15秒足够,把机械臂从初始位置开始、完成操作、回到初始位置这个过程录完整。
数据采集时使用LeRobot的机器人控制脚本,它会同时记录多个相机图像、关节状态和动作。SO101环境中通常支持手柄或键盘遥控,建议用手柄,因为键盘控制容易出现动作不连贯,影响数据质量。
3.2 图像视角和光照:最容易被低估的两个变量
数据采集时相机的位置必须设计成和推理时一致。你训练时相机装在A位置,推理时随手放到B位置,模型输出的动作大概率会乱。这个不是模型不聪明,而是采集和推理的观察分布变了。最稳的做法是固定相机支架,训练和推理全程不动。
光照也是个大坑。同一个工作台,白天自然光和晚上台灯下的图像差异非常大。模型会把阴影、反光当成特征的一部分。如果你不想后期反复补数据,一开始就把光照固定下来。
SO101的视觉输入可以是一个或多个相机。我的经验是至少两个视角:一个俯视全局,一个正视工作区域。单个视角在处理前后遮挡时明显不够用。
3.3 训练参数怎么看:别盯着一个Loss死磕
训练命令本质上就是调用LeRobot的训练脚本,核心参数包括策略类型、数据集路径、训练步数、批次大小、动作预测的时间戳范围。以SmolVLA为例,动作预测往往不是只预测下一步动作,而是预测未来一段时间内的多个动作,这就是动作分块(action chunking)。delta_timestamps.action这个参数决定了模型一次预测多长一段时间内的动作,对执行平滑性影响很大。
用我当时训练一个“抓取并放到杯子里”任务的命令作为参考:
python lerobot/scripts/train.py \ --policy.type=smolvla \ --dataset.repo_id=my-robot/so101_pick_place \ --steps=20000 \ --batch_size=8 \ --use_amp \ --save_freq=2000 \ --policy.delta_timestamps.action="[0.0, 0.2, 0.4, 0.6, 0.8, 1.0]"注意,不同版本的LeRobot参数名可能有变化,跑之前先看一下官方示例。
训练时不要只看总loss。SmolVLA训练过程里更值得关注的是动作预测部分在验证集上的表现。如果训练loss降得很好,但推理时机械臂动作还是很生硬,通常不是训练不够,而是数据多样性不够或者图像视角不对。
4. 模型到舵机:推理联调里的几个决定性因素
4.1 推理命令跑起来,只代表完成了三分之一
训练完模型后,就可以用LeRobot的评测脚本加载训练好的权重,让模型在SO101上实际操作。保存下来的权重目录里包含模型结构和配置,评测脚本会自动加载并运行。
python lerobot/scripts/eval.py \ --policy.path=my-robot/so101_pick_place \ --env.type=so101 \ --use_amp如果你只是想先看模型有没有反应,可以用0.4B的预训练权重做一次快速通断测试,没必要一上来就训练。
推理跑起来之后,观察几个点:模型推理一帧需要多长时间、机械臂执行动作是否平滑、相机图像是否和训练时一致。推理速度非常关键,如果模型单帧推理耗时超过控制周期太多,机械臂动作就会顿挫。SmolVLA相对其他VLA模型优势就在这里,2.5B在有GPU的机器上推理延迟能做到百毫秒级别,基本满足桌面抓取的实时性要求。
4.2 动作范围与安全限位检查
模型输出的动作值有可能超出机械臂实际关节的安全范围,尤其是模型在训练中没有见过的状态。你需要在评测脚本里加入动作裁减或限位保护,不要让舵机硬怼到物理限位。舵机长期撞限位会发热、扫齿、甚至烧毁。
这个看起来是小事,但我见过太多人忽略了。模型第一次跑挺好,第二次在某个奇怪姿态下输出了一个极限角度,机械臂直接“咔”一声卡死,接着就是舵机过热保护。加一层限位裁剪,等于给这套系统上了个保险。
4.3 成功率多少算“能用”
评测时建议每次重置机械臂到相同初始位置,然后跑20次任务,统计成功率。桌面级任务的评判标准不用定得太高,像视觉变化大、物体摆放随机这类条件下,60%到70%的成功率已经算能用。如果你需要更稳定,再回头检查数据多样性和数量,而不是盲目加大训练步数。
一个我实测有效的技巧:训练完成后先跑几次推理,录制视频回看,重点观察失败是发生在接近物体阶段还是抓取阶段。接近阶段失败,通常是图像角度或相机位置问题;抓取阶段失败,则可能是动作块长度不够、数据里缺少微调动作。
5. 常见错误排查:从完全没反应到疯狂乱抖的完整链路
5.1 机械臂完全没反应:按这个顺序排查
这是遇到最多的现象。模型加载正常、程序也没有报错,但机械臂就是不动。不要先去翻模型代码,先按顺序查链路:
| 检查项 | 方法 | 可能的原因 |
|---|---|---|
| 串口设备 | ls /dev/ttyUSB* | 线材损坏、驱动未装 |
| 串口权限 | 启动脚本是否提示permission denied | 用户未加入dialout组 |
| 供电 | 测量舵机电源电压和电流 | 电源余量不足 |
| 接线 | 查看TX/RX是否交叉 | 收发接反 |
| 舵机总线 | 单个舵机是否单独能响应 | 总线某个节点短路 |
如果在Windows下接串口舵机时,遇到了驱动安装包被“智能应用控制”这类系统安全策略拦截,导致USB转TTL的驱动一直装不上,可以在Windows安全中心里临时关闭智能应用控制、完成驱动安装后再恢复,或者直接用Linux系统跑控制脚本。这个情形不算少见,尤其是教室里那些受企业或学校统一安全策略锁定的电脑。
5.2 舵机剧烈抖动或异响
舵机抖动大多不是模型问题,而是物理层面。首查电源,总线舵机在负载变化时电流波动很大,劣质电源或USB供电会造成舵机反复重启,表现为抖动和异响。其次查舵机安装螺丝是否过紧或过松,传动机构卡顿会让舵机不断挣扎。如果电源和结构都没问题,再回头看模型输出的动作序列是否跳变剧烈,这时可以在控制脚本里加一个平滑滤波,或者增加模型预测的动作块长度。
5.3 模型加载报Unknown policy type之类的错误
这基本是LeRobot版本太旧导致的。SmolVLA策略是在LeRobot较新版本里加入的,旧版本不认识这个策略类型。解决方式很简单,更新LeRobot到最新版本,或者直接拉源码安装。不要死磕报错信息。
还有一类报错是显存不足。推理时如果加载2.5B模型爆显存,可以先开启AMP混合精度,把图像分辨率调低,看是否解决。这些参数LeRobot脚本里都有开关。
5.4 模型能跑,但动作明显偏离目标
动作偏离要从多个方向排查:训练和推理的相机位置是否一致、光照是否一致、机械臂零位是否在训练过程中被动过、训练数据的动作标注是否准确。别急着重新训练,先录制一段评测视频和训练数据对比,看模型是不是在“寻找”某个不存在的视觉特征。
5.5 训练中断或数据丢失
训练到一半断掉是家常便饭。最重要的经验是:训练脚本里会自动保存断点,重启训练时用断点路径继续,而不是从头开始。数据丢失大多是因为本地缓存目录被清理,或者数据集版本管理混乱。建议每个任务建一个独立数据集根目录,训练前备份metadata文件。
最后再分享两个我实际踩出来的经验。第一个是数据处理:训练前把坏的episode删掉,比如机械臂中途掉线、物体初始位置不合理的样本。脏数据对VLA策略的负面影响比你想的大得多。第二个是日志记录:每个版本的训练数据和模型权重,命名里加上日期和任务名,别用final、final2这种名字,过两周你绝对分不清哪个才是真正能用的模型。
我自己的体会是,SmolVLA控制SO101这套组合,真正决定成败的环节从来不在“模型多聪明”,而在数据质量、硬件链路稳定性和视角一致性这三件事上。把这三点伺候好了,桌面抓取任务的成功率会肉眼可见地往上走。希望这篇经验能帮你少走一段弯路。