基于Lerobot SO-101与OpenCV的智能捡袜子机器人系统实践
1. 项目缘起一个“懒人”的自动化执念我老婆有个习惯或者说是很多人的通病——脱下来的袜子总是不太愿意立刻放进脏衣篓。它们会出现在沙发扶手上、床脚边、甚至是通往浴室的半路上。每天下班回家看到这些散落的“地雷”弯腰去捡日复一日成了我一个小小的、但确实存在的家务痛点。作为一个搞技术出身的我的第一反应不是抱怨而是琢磨这事儿能不能自动化于是“造一个能自动捡袜子的机器人手臂”这个念头就冒出来了。它听起来有点小题大做甚至有点“杀鸡用牛刀”的荒诞感但对我而言这恰恰是技术宅的浪漫用看似复杂的工程解决一个极其具体、微小的生活问题。我最终选定的平台是Lerobot SO-101一款在创客圈和机器人教育领域口碑不错的桌面级六轴机械臂。它精度够用开发生态友好价格也在可接受的范围内是家庭自动化改造的理想试验品。这个项目的核心远不止是让一个机械臂动起来。它涉及到从环境感知找到袜子、目标识别确认那是袜子而不是其他东西、路径规划安全、高效地移动过去、抓取策略如何稳定抓起柔软的织物到系统集成让所有环节无缝衔接的一整套流程。这实际上是一个微缩版的“感知-决策-执行”机器人系统麻雀虽小五脏俱全。如果你也对机器人、计算机视觉或者智能家居自动化感兴趣这个项目会是一个绝佳的切入点它能让你把书本上的理论变成一个看得见摸得着、还能真正干点“家务活”的实体。2. 整体方案设计与核心思路拆解2.1 为什么是Lerobot SO-101市面上机械臂选择不少从玩具级的舵机臂到工业级的协作机器人价格和复杂度天差地别。选择SO-101我主要基于以下几点考量首先性能与价格的平衡。SO-101采用步进电机闭环控制重复定位精度宣称在±0.1mm左右对于抓取袜子这种对精度要求不算极端相比精密装配的场景完全够用。它的负载有1kg抓起一只袜子绰绰有余甚至未来升级夹爪抓个手机、遥控器也不成问题。价格在几千元级别作为个人项目投资可以接受。其次开放的生态与友好的开发接口。这是最关键的一点。SO-101支持多种控制方式可以通过厂家提供的上位机软件进行示教编程适合新手更支持通过ROS机器人操作系统、Python API甚至直接发送G代码进行控制。这意味着我可以完全自主地编写程序将视觉识别模块和运动控制模块深度集成实现真正的自动化而不是简单的重复动作回放。最后安全性与尺寸。作为家庭环境使用的设备安全第一。SO-101是桌面级尺寸工作半径约300mm力量有限即使发生意外碰撞破坏力也较小。它的电机在非使能状态下有自锁功能不会因断电而“瘫软”砸下来。这些特性让我能放心地把它放在客厅一角进行测试。2.2 系统架构总览眼睛、大脑与手的协作整个系统可以清晰地划分为三个层次感知层、决策层和执行层。感知层眼睛负责“看”到袜子在哪里。我选择了一款普通的USB网络摄像头通过OpenCV库进行图像处理。为什么不选更高级的深度相机如Intel RealSense主要基于成本和应用场景考虑。捡袜子通常发生在已知的、光照条件相对固定的地面如木地板、地毯袜子的颜色和纹理与背景有较大反差。通过传统的颜色阈值分割针对深色袜子或背景减除算法配合轮廓查找已经能以很高的成功率定位袜子。深度信息对于判断距离固然有用但在这个项目中我可以通过机械臂末端的固定高度贴近地面扫描来间接解决简化了系统复杂度。决策层大脑这是项目的核心逻辑所在。它接收感知层传来的袜子在图像中的像素坐标x, y以及通过一些先验知识如已知的地面平面方程或简单标定得到的粗略深度信息z。然后决策层需要完成两件事坐标转换将图像像素坐标2D转换到机械臂基座坐标系下的三维空间坐标3D。这里涉及相机标定获取内参和畸变系数和手眼标定确定相机与机械臂基座的相对位置关系。这是机器人视觉中最经典也最关键的一步。路径规划根据目标点坐标和当前机械臂末端位置规划出一条无碰撞、平滑的运动轨迹。我需要考虑机械臂自身的运动学限制关节角度限制、奇异点以及避开环境中的固定障碍物比如桌腿。SO-101的ROS驱动包通常集成了MoveIt!这样的运动规划框架可以大大简化这部分工作。执行层手即Lerobot SO-101机械臂本体及其末端执行器夹爪。我为其配备了一个两指的自适应夹爪这种夹爪在夹持不规则、柔软的物体如袜子时比平行夹爪有更好的包容性和稳定性。夹爪的开合通过机械臂的一个额外IO口或通过PWM信号控制。整个工作流程可以概括为摄像头周期性地拍摄地面图像 - OpenCV算法识别并定位袜子 - 计算其在机械臂坐标系下的位置 - MoveIt!规划抓取路径 - 机械臂移动至目标点上方 - 夹爪下降并闭合抓取 - 机械臂将袜子运送至指定回收点如脏衣篓上方 - 夹爪张开释放。注意这个架构是典型的“感知-规划-执行”开环。在实际部署中我强烈建议加入简单的反馈机制。例如在夹爪闭合后可以通过夹爪上的压力传感器或电机电流反馈来判断是否成功抓取物体。如果没有检测到力则可能抓空需要重新尝试或报警。这能极大提升系统的鲁棒性。3. 核心模块实现与关键技术细节3.1 视觉识别让机器人“看见”袜子视觉识别是整个自动化流程的触发器它的稳定性和准确性直接决定了项目的成败。我的方法没有追求最前沿的深度学习模型而是采用了更轻量、更可控的传统图像处理方案这对于在树莓派或普通笔记本电脑上实时运行非常友好。第一步图像预处理摄像头采集的原始图像通常包含噪声且受光照影响。我会先进行以下处理高斯模糊轻微模糊图像消除高频噪声和袜子纹理细节的干扰让轮廓更平滑。转换色彩空间将图像从BGR转换到HSV色彩空间。HSV色相、饱和度、明度比RGB更能抵抗光照变化的影响更容易通过颜色范围来分割目标。比如我老婆的袜子多是深色黑、灰、深蓝我就可以设定一个较低的明度V阈值来提取暗色区域。import cv2 import numpy as np # 读取图像 frame cv2.imread(scene.jpg) # 转换到HSV空间 hsv cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # 定义深色区域的HSV范围 (示例需根据实际环境调整) lower_dark np.array([0, 0, 0]) upper_dark np.array([180, 255, 50]) # 创建掩膜 mask cv2.inRange(hsv, lower_dark, upper_dark)第二步目标提取与筛选得到二值化掩膜后下一步是找到其中可能是袜子的连通区域。查找轮廓使用cv2.findContours函数找出掩膜中的所有轮廓。轮廓筛选不是所有深色区域都是袜子。可能是阴影、电源线或地板上的深色纹理。我通过一系列启发式规则进行筛选面积轮廓面积应在合理范围内比如500到5000像素之间过滤掉太小的噪点和过大的阴影块。宽高比一只卷起或摊开的袜子其轮廓的边界矩形通常有一个特定的宽高比范围例如0.3到3之间这可以过滤掉过于细长可能是线或过于方正可能是书本的物体。轮廓近似使用cv2.approxPolyDP对轮廓进行多边形近似。袜子的轮廓通常不会太复杂近似后的顶点数量在一个合理区间。确定中心点对最终筛选出的轮廓计算其最小外接矩形或直接计算轮廓矩得到质心坐标(cx, cy)。这个像素坐标就是袜子当前在图像中的位置。实操心得光照是传统视觉算法的天敌。我强烈建议在摄像头附近增加一个柔光补光灯创造稳定、均匀的光照环境。这比在算法上绞尽脑汁去适应各种光照变化要有效得多。另外准备几双不同颜色、纹理的袜子进行算法调参确保通用性。对于浅色或花纹复杂的袜子可以尝试背景减除算法如MOG2或KNN先学习一段时间的空场景背景然后检测前景运动物体。3.2 手眼标定建立“眼睛”与“手”的桥梁这是将图像中的像素点映射到真实三维空间中最关键、也最容易出错的一步。手眼标定的目的是求解出相机坐标系与机械臂基座坐标系之间的变换矩阵。我采用经典的“棋盘格标定法”。准备工作打印一张标准的棋盘格标定板例如9x6的内角点。将标定板固定在机械臂的末端夹爪上。确保固定牢固且棋盘格平面与夹爪的某个运动平面平行或垂直便于计算。编写一个控制程序让机械臂末端带着标定板在相机视野内以多种不同的姿态移动平移、旋转并确保在每个姿态下整个棋盘格都在相机视野内且清晰。标定过程采集数据在每个机械臂姿态下同时做两件事通过相机拍摄一张包含标定板的图片。通过机械臂控制器读取当前机械臂末端工具中心点TCP在基座坐标系下的位姿X, Y, Z, Rx, Ry, Rz。SO-101的API可以很方便地获取这些数据。图像处理对每张拍摄的图片使用OpenCV的cv2.findChessboardCorners函数精确检测出棋盘格所有内角点的像素坐标。求解变换现在我们有两组对应的数据一组是相机看到的棋盘格角点的像素坐标2D。另一组是机械臂末端即棋盘格在基座坐标系下的真实位姿3D。 通过求解一个AXXB的方程其中A是相机两次观察间的运动B是机械臂两次运动间的变换X就是我们要求解的手眼变换矩阵即可得到相机相对于机械臂基座的固定位置和姿态。简化方案对于要求不高的场景 如果觉得上述过程太复杂可以采用一种更工程化的近似方法让机械臂末端移动到一个非常容易测量的精确位置例如指向地面上的一个标记点。在图像中点击这个标记点记录其像素坐标(u, v)。同时从机械臂控制器读取此时末端的真实三维坐标(X, Y, Z)。通过多个至少4个越多越好这样的对应点对利用cv2.solvePnP函数可以直接求解出相机参数和位姿。这种方法精度稍低但对于捡袜子这种对绝对精度要求厘米级即可的场景往往足够用且实施起来快得多。注意事项手眼标定的精度直接决定抓取成功率。务必保证标定板固定牢固机械臂位姿读数准确以及角点检测精确。标定完成后一定要用几个未参与标定的点进行验证测试观察计算出的3D位置与实际位置偏差是否在可接受范围内例如1cm。3.3 运动规划与抓取策略得到袜子的3D坐标后就需要指挥机械臂去抓取了。这里我使用了ROS中的MoveIt!框架它封装了逆运动学求解、碰撞检测和路径规划等复杂功能。运动规划配置URDF模型首先需要有一个准确的SO-101机械臂的URDF模型文件描述其连杆尺寸、关节类型和限制。厂家通常会提供也可能需要根据实物微调。设置规划组在MoveIt!配置中定义机械臂的规划组如“arm”组控制所有关节“gripper”组控制夹爪。添加碰撞物体在规划场景中添加已知的固定障碍物比如工作台面、脏衣篓的简化模型。这能确保MoveIt!在规划路径时主动避开它们。抓取路径设计 一个可靠的抓取动作不是直接冲向目标点而应分为几个阶段预抓取点规划机械臂末端移动到目标点正上方一定高度例如10cm的位置。这个点应远离任何可能碰撞的物体作为安全的接近点。直线下降从预抓取点规划一条笔直向下的直线轨迹直到夹爪接触袜子。直线运动易于控制且能减少夹爪在下降过程中挂到其他物体的风险。抓取执行到达目标点后发送指令控制夹爪闭合。这里我设置了一个适中的夹持力并在闭合后保持一段时间如0.5秒确保袜子被牢牢抓住。提升与转运抓取成功后先垂直向上提升一段距离离开地面再规划路径将袜子运送到脏衣篓上方。释放到达释放点后控制夹爪完全张开袜子依靠重力落入篓中。夹爪选型与控制 我选择了两指自适应夹爪。它的优点是被动适应两指在闭合时能自适应物体的形状对袜子这种非刚性物体包裹性好。力控制可以通过控制电机电流或PWM占空比来间接控制夹持力避免夹坏物品虽然袜子不怕夹坏但这个习惯对未来抓取其他物品很重要。 控制命令很简单通过ROS话题或服务发送一个目标位置或目标力指令即可。# 示例通过ROS服务控制夹爪 from robot_arm_control.srv import GripperControl, GripperControlRequest ... gripper_control rospy.ServiceProxy(/so101_gripper/control, GripperControl) req GripperControlRequest() req.position 0.0 # 0.0表示完全闭合1.0表示完全张开具体值需标定 req.effort 30.0 # 夹持力大小 resp gripper_control(req)4. 系统集成与软件框架搭建4.1 ROS机器人系统的“粘合剂”我选择ROS作为整个项目的软件框架核心。ROS不是一个真正的操作系统而是一个分布式计算的通信框架和工具集。它完美解决了机器人系统中多个独立进程节点之间的通信、调度和管理问题。节点设计 我的系统主要包含以下几个ROS节点摄像头驱动节点负责发布/camera/image_raw话题提供原始的图像数据流。视觉处理节点订阅图像话题运行OpenCV识别算法识别到袜子后发布一个包含袜子像素坐标的自定义消息如/sock_position_pixel。坐标转换节点订阅像素坐标话题利用之前标定好的手眼变换参数将像素坐标转换为机械臂基座坐标系下的3D坐标发布新话题如/sock_position_3d。主控节点这是系统的大脑。它订阅3D坐标话题当收到新坐标时触发一系列动作调用MoveIt!的路径规划服务规划从当前位置到预抓取点的路径并执行。规划并执行下降、抓取、提升、转运、释放的完整序列。在关键步骤如抓取后可以加入状态判断如通过夹爪传感器反馈。MoveIt!节点提供运动规划、逆运动学求解等服务供主控节点调用。通信与消息 节点间通过话题和服务进行通信。话题用于异步、流式的数据发布/订阅如图像流、坐标信息。服务用于同步的请求/响应交互如调用路径规划、控制夹爪。这种松耦合的设计使得我能够单独调试和升级每个模块比如改进视觉算法时完全不用改动运动控制部分的代码。4.2 状态机与错误处理一个健壮的系统不能只是线性的“识别-抓取”循环。我设计了一个简单的有限状态机来管理整个流程IDLE空闲系统启动后的初始状态等待启动命令或定时触发。SCANNING扫描控制摄像头拍照运行视觉识别。如果未发现袜子等待一段时间后返回IDLE或继续SCANNING。如果发现袜子进入PLANNING状态。PLANNING规划根据袜子坐标计算预抓取点并请求MoveIt!进行路径规划。如果规划失败如无解或碰撞记录错误可能尝试一个备选抓取角度或进入ERROR状态。APPROACHING接近执行移动到预抓取点的动作。GRASPING抓取执行下降、闭合夹爪的动作。这里可以加入一个超时和力反馈检查。如果夹爪闭合后未检测到预期阻力可能抓空则进入RECOVERY恢复状态。TRANSPORTING运送执行提升和转运到脏衣篓的动作。RELEASING释放在脏衣篓上方张开夹爪。RECOVERY恢复处理抓取失败等异常。例如轻微调整位置重试或者放弃当前目标返回SCANNING状态。ERROR错误处理严重错误如机械臂通信中断、规划连续失败。可能需要人工干预复位。通过状态机系统的逻辑变得清晰可控也便于加入各种异常处理逻辑大大提升了鲁棒性。5. 实际部署、调试与性能优化5.1 物理部署与环境准备将代码从仿真或测试台迁移到真实的客厅环境会遇到一系列新问题。机械臂安装我将SO-101通过其底座螺栓固定在一块厚重的木板上再将木板放置在客厅一个靠墙的边柜上。这个位置视野相对开阔能覆盖袜子经常出现的区域。确保安装绝对稳固防止机械臂在高速运动时晃动或倾倒。摄像头安装为了获得俯瞰地面的最佳视角我将USB摄像头安装在天花板角落通过一根长的USB延长线连接到主机。安装角度需要仔细调整确保目标区域如沙发前的地毯完全在视野中心且图像畸变较小。广角镜头可以覆盖更大范围但边缘畸变会增加视觉处理难度需要权衡。安全区域设定在MoveIt!的规划场景中我不仅添加了脏衣篓、茶几等大型障碍物的简化模型还设定了一个“工作空间”的立方体边界。强制要求所有规划路径的路径点都必须在这个立方体内这样可以绝对防止机械臂运动到危险的区域比如撞到电视或伸到过道。5.2 调试过程与“踩坑”实录坑一光照变化导致识别失败最初算法在下午阳光斜射时工作良好但到了晚上开暖光灯后袜子识别率骤降。原因是HSV阈值是针对白天光照设置的。解决我改用了更鲁棒的背景减除算法cv2.createBackgroundSubtractorMOG2。系统启动后先让摄像头学习30秒的空场景背景模型。之后任何进入场景的移动物体比如扔下来的袜子都会被检测为前景。这种方法对光照渐变和局部阴影变化有很好的适应性。坑二抓取时袜子被推走机械臂末端夹爪下降时有时会碰到袜子的边缘将其推远而不是抓起来。解决优化末端速度在接近和抓取阶段大幅降低机械臂的运动速度。改进夹爪设计在夹爪内侧粘贴了一层薄薄的硅胶或绒布增加了摩擦力同时也起到缓冲作用。调整抓取点视觉识别给出的质心不一定是最佳抓取点。对于长条状的袜子我改为计算轮廓的主轴方向并选择沿主轴方向、距离质心一定偏移的点作为抓取点模拟人手捏起袜子的动作。坑三奇异点导致规划失败机械臂在某些特殊构型下如完全伸直会失去某个方向的运动能力称为奇异点。MoveIt!在规划路径时如果经过或过于接近奇异点可能会规划失败或产生不稳定的运动。解决在MoveIt!的规划请求中可以设置路径约束或偏好某些关节空间区域来避开奇异点。更简单有效的方法是在机械臂的“零位”即各关节在中间位置附近进行抓取动作的起始和结束规划这通常能避开大多数奇异点。5.3 性能评估与优化经过数周的调试和优化系统达到了一个比较实用的状态识别成功率在稳定光照下对颜色、纹理差异明显的袜子识别成功率95%。单次抓取成功率从识别到成功放入脏衣篓成功率约85%。失败主要发生在袜子形状特别诡异如紧紧卷成一团或被部分遮挡时。单次作业耗时平均约20-30秒包括扫描、规划、移动和抓取释放全过程。优化点多目标处理当视野内出现多只袜子时视觉算法会识别出多个轮廓。主控节点会按距离机械臂基座的远近进行排序优先抓取最近的然后依次处理实现“清场”效果。定期自检我编写了一个简单的自检程序每天第一次启动时机械臂会执行一套固定的动作如回零位、各关节慢速运动一遍确保系统正常。日志与监控所有关键步骤、识别坐标、规划结果、错误信息都记录到ROS的日志文件和单独的文本日志中方便后期排查问题。6. 项目总结与扩展思考这个“捡袜子机器人”项目从萌生想法到最终能磕磕绊绊地运行前后花了将近两个月的时间。它带给我的成就感远不止是解决了捡袜子这个小问题。它是一次完整的、从软件到硬件的机器人系统集成实践涵盖了机械、电子、计算机视觉、运动控制、软件工程等多个领域。最大的体会是机器人技术的落地难点往往不在算法本身有多高深而在于如何让各个模块稳定、可靠地协同工作并处理现实世界中无穷无尽的意外情况。一个在实验室灯光下、背景干净时表现完美的视觉算法到了客厅可能就失灵了一个在仿真里流畅无比的运动规划可能因为一根小小的电源线而失败。工程鲁棒性是这类项目最需要打磨的地方。这个项目还有巨大的扩展空间感知升级引入一个廉价的RGB-D深度相机如Intel RealSense D415可以更精确地获得袜子的3D点云不仅能得到位置还能估计其姿态比如是平铺还是卷曲从而实现更智能的抓取策略。移动底盘给机械臂加上一个移动底盘如差速轮式机器人就可以让它主动巡逻覆盖整个房间而不仅仅是固定摄像头下的那一小块区域。任务扩展同样的硬件平台只需更换视觉识别模型和末端执行器就能执行其他任务。比如识别并捡起散落的玩具、将遥控器归位、甚至给绿植浇水。它本质上是一个通用的“桌面物品整理机器人”。最后关于成本与实用性。必须承认这台机器人的制造成本和所花费的时间远远超过了它所能替代的劳动力价值。它更像是一个极客玩具或一个技术演示原型。但它最大的价值在于探索和学习的乐趣以及证明了在消费级硬件上实现一个有一定复杂度的家庭服务机器人是可行的。也许未来当机械臂和传感器成本进一步降低这样的“管家机器人”会真的走入寻常百姓家。而到那时你我已经是玩过它“爷爷辈”原型的人了。