ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

基于机器视觉的SCARA机械臂分拣仿真:VREP与MATLAB联合实现

基于机器视觉的SCARA机械臂分拣仿真:VREP与MATLAB联合实现

"基于机器视觉技术的流水线自动分拣机器人仿真:VREP与MATLAB联合实现SCARA机械臂按色..."——这个标题完整展开其实是一类特别典型的项目:给流水线加一套“长了眼睛的机器人”,让它根据颜色把不同物料分到不同工位。很多搞自动化、机器人、机器视觉相关方向的朋友迟早都会撞上这类课题。我在某自动化实验室参与过一个类似的仿真模拟项目X,被安排从头搭建这套环境,中间踩了不少坑,也积累了一整套可复用的流程。这篇就把整个项目的设计、实现、联调过程完整复盘一遍,重点是那些文档里不会写、只有实际动手才会踩到的细节。

先说清楚这个项目到底是什么。我们用VREP(也就是现在的CoppeliaSim)搭建了一条仿真流水线,包括传送带、物料、视觉传感器和一台SCARA机械臂;MATLAB这边负责机器视觉处理,识别传送带上的物料颜色,计算抓取位置,然后通过远程API控制VREP里的SCARA机械臂完成分拣动作。整套系统打通后,给定不同颜色的物料,机械臂能自动识别并按预设规则放到对应区域,全程不用人干预。

这套东西适合谁参考?如果你正好在搞机器人仿真、机器视觉课程设计,或者公司要评估一套视觉分拣方案要不要上、节拍能跑到多少、识别率稳不稳,又不想一开始就动物理产线,那这篇就是按你这个需求写的。

1. 项目初衷与方案选型逻辑

1.1 为什么选择仿真先行

做任何产线级改动,我的原则都是:能先在仿真里验证的,绝不动物理设备。尤其是视觉分拣这套组合,牵涉到相机选型、光源布置、机械臂可达范围、节拍匹配好几个环节,直接在物理产线上试错,每一次改动都要停线,成本非常高。

仿真平台的好处在于:视觉算法可以直接用真实图像验证逻辑,机械臂的运动学计算可以验证是否撞限位、是否干涉,整条流水线的时序逻辑可以跑虚拟节拍。逻辑上,仿真通过了,物理实现的风险就已经压到了最低。这套虚拟联调方案,本质上和硬件在环测试的思路一致,只是把被控对象也虚拟化了。

1.2 为什么选SCARA而不是六轴机械臂

这个决定是有数据支撑的。六轴机械臂灵活度高,但造价、控制复杂度、编程难度全都上一个台阶。流水线上下料、分拣这种活儿,动作模式高度重复,需要的就是“从上往下拿,平移到边上放下”这种平面运动。

SCARA结构正好是刚性立柱加两轴平面运动,末端再带一个上下轴和旋转轴,天生适合平面搬运。Z轴行程不用太长,旋转角度范围大,在传送带上方作业时占地面积小,节拍还快。

从成本和性能匹配度看,在传送带分拣场景里,SCARA是绝对的主流选择。很多真实产线,尤其是3C、小工件装配线,满地都是SCARA。所以做仿真选SCARA,不仅技术上合适,也更贴近行业真实工况。

1.3 为什么是VREP加MATLAB这个组合

VREP的定位是通用机器人仿真器,物理引擎、传感器插件、脚本控制都覆盖了,而且远程API支持得很完整。MATLAB则强在算法快速验证——图像处理工具箱、计算机视觉工具箱都是现成的,写颜色识别、形态学处理、质心计算,十分钟就能出一版原型。

这个组合的合理性在于,把“强仿真”和“强算法”分开用。VREP把机械臂运动学、碰撞检测、传感器噪声这些底层物理问题管好,MATLAB专心干视觉识别和控制决策,各干各擅长的部分,联调时通过API对接,两个部分都能独立维护。

还有一点很关键:VREP的API支持MATLAB远程调用,数据交换方式简单可靠,场景状态、传感器数据、关节角度都能实时双向同步。这一点让联合仿真落地成了很顺滑的事。

2. 仿真环境搭建与配置

2.1 VREP场景建模思路

打开VREP第一件事,不是急着拖模型,而是先建场景结构。我习惯把整个场景按物理区域分图层:

  • 传送带区域:物料生成、运动、视觉检测区
  • 抓取区:SCARA机械臂工作半径覆盖范围
  • 分拣区:按颜色划分的落料区,每个颜色一个圆形或方形区域

VREP自带的模型库里有现成的传送带(Conveyor)、SCARA机械臂本体模型,可以直接拖进来用。传送带的速度参数在模型属性里调,建议初始值设在0.05到0.15米/秒之间,太快会让机械臂来不及响应,太慢又体现不出分拣效率。

2.2 视觉传感器配置要点

视觉信息用VREP里的Vision Sensor做。选好型号后,有四个参数必须先定:

  • 分辨率:建议不低于512x512,否则远处小物料的颜色特征不稳定。分辨率太高则仿真速度下降,512是性价比很高的起点。
  • 视角(View Angle):要覆盖整条检测区,我这里是60度到80度之间。
  • 近远裁剪面:把范围限制在传送带检测区,防止背景干扰。
  • 像素响应类型:选RGB彩色,这是颜色识别的基础。

视觉传感器不要正对传送带垂直往下装,稍微倾斜20度左右,这样能减少高光反射面带来的干扰,更接近真实相机的安装姿态。识别算法里我们也会做对应处理,确保即使视角倾斜也能准确找到物料位置。

2.3 MATLAB连接VREP的通讯配置

联合仿真的核心桥梁就是远程API。VREP里有几种通讯方式,我用的是传统Remote API方式,通过Socket交互,简单而且足够稳定。

MATLAB端做三件事:调用VREP远程API库、建立连接、拿到场景对象的句柄。代码如下:

% 加载VREP远程API库 addpath('C:\Program Files\CoppeliaRobotics\CoppeliaSimEdu\programming\remoteApiBindings\matlab\native'); loadLibrary; % 建立通讯连接 vrep = remApi('remoteApi','extApi.h'); sim = vrep.simxStart('127.0.0.1', 19999, true, false, 5000, 5); if sim > -1 disp('连接成功'); % 拿到各个关键对象句柄 [returnCode, camHandle] = vrep.simxGetObjectHandle(sim, 'Vision_sensor', vrep.simx_opmode_blocking); [returnCode, armHandle] = vrep.simxGetObjectHandle(sim, 'SCARA_joint1', vrep.simx_opmode_blocking); end

这里有一个很隐蔽的坑:VREP端口默认是19997,很多资料里写的是这个。但我用的VREP版本,传统Remote API默认监听端口其实是19999,需要在服务器端启动时确认。连不上时先检查这个,别一上来就怀疑代码写错。

3. 机器视觉识别的核心实现

3.1 从图像到目标坐标的完整链路

整个视觉模块的逻辑链路是:采集图像 → 颜色空间转换 → 阈值分割 → 形态学去噪 → 连通域提取 → 计算质心 → 坐标映射到机械臂坐标系。

MATLAB这边用vision.VideoFileReader读取VREP传回的图像,或者直接用snapshot获取当前帧。拿到RGB图后,第一步永远是转颜色空间。

3.2 颜色空间选择:为什么用HSV

RGB空间最大的问题是受光照影响太明显。传送带上物料要是经过一段光线变化区域,同一个红色在不同位置会相差很大。HSV空间把色调、饱和度、明度分开,抗干扰能力强得多。

红色、绿色、蓝色各自的HSV阈值范围是我反复测试出来的:

目标色H范围S范围V范围
红色0~10, 156~18080~25550~255
绿色35~7760~25550~255
蓝色100~12460~25550~255

注意红色的H范围是个环,因为色调的圆形特性,0度和180度相接,红色跨在两个端点上。这个细节最容易在写阈值时漏掉,漏了就会出现红色目标时有时无。

核心识别代码:

function [cx, cy, color] = detectObject(rgbImage) hsv = rgb2hsv(rgbImage); % 定义三种颜色的阈值 redMask = ((hsv(:,:,1) >= 0) & (hsv(:,:,1) <= 0.05)) | ... ((hsv(:,:,1) >= 0.95) & (hsv(:,:,1) <= 1)); greenMask = (hsv(:,:,1) > 0.15) & (hsv(:,:,1) < 0.35); blueMask = (hsv(:,:,1) > 0.50) & (hsv(:,:,1) < 0.65); % 形态学去噪 masks = {redMask, greenMask, blueMask}; colorNames = {'Red', 'Green', 'Blue'}; cx = 0; cy = 0; color = 'None'; for i = 1:3 mask = masks{i}; mask = imopen(mask, strel('disk', 3)); mask = imclose(mask, strel('disk', 5)); cc = bwconncomp(mask); if cc.NumObjects > 0 stats = regionprops(cc, 'Centroid', 'Area'); [~, idx] = max([stats.Area]); % 取最大连通域 centroid = stats(idx).Centroid; cx = centroid(1); cy = centroid(2); color = colorNames{i}; break; end end end

3.3 坐标映射与手眼标定

像素坐标不能直接给机械臂用,必须转换到机械臂基座坐标系。直角坐标转换的公式是:

[X_w, Y_w] = [X_c, Y_c] * R + T

R是相机外参旋转矩阵,T是平移向量。仿真环境里,R和T可以从VREP里的相机安装位置直接导出,相当于省掉了真实标定那一步。但我不推荐直接拿默认值用,因为相机有倾斜角,误差会累积,最稳妥的做法是:在传送带上放几个已知位置的特征点,记录像素坐标和真实坐标,用estimateGeometricTransform2D拟合单应性矩阵。

% 用四个特征点拟合坐标映射矩阵 [ tform, inlierIdx ] = estimateGeometricTransform2D( pixelPoints, worldPoints, 'projective');

拟合完成后,每次识别出像素坐标,都用transformPointsForward转成世界坐标。这个做法比直接手算R和T省心得多,而且抗角度误差能力更强。

4. SCARA机械臂的运动规划与抓取控制

4.1 SCARA逆运动学推导

SCARA只有三个主要自由度:两个旋转关节加一个上下关节(末端旋转先不管),逆运动学推导比六轴简化太多。已知末端目标坐标(X, Y, Z),两个关节角度的解是:

L1 = 0.3; % 大臂长度 L2 = 0.2; % 小臂长度 cos_theta2 = (X^2 + Y^2 - L1^2 - L2^2) / (2 * L1 * L2); sin_theta2 = sqrt(1 - cos_theta2^2); theta2 = atan2(sin_theta2, cos_theta2); theta1 = atan2(Y, X) - atan2(L2 * sin_theta2, L1 + L2 * cos_theta2);

注意这个公式有两个解,对应臂的“肘内”和“肘外”姿态。实际控制时要根据工作空间边界选择合适的一组,避免机械臂穿过传送带。这个在数学仿真里常被忽略,但物理设备上会直接撞机。

4.2 轨迹规划:点到点还是连续路径

传送带分拣场景下,经典的方案是PTP(点到点)加梯形速度规划。即每个动作分为四段:从当前位置上升到安全高度、平移到目标上方、下降到抓取高度、夹爪闭合抓取后抬升再平移放置。

每段都要做速度限制,防止加速度过大导致仿真关节抖动。

VREP自带的轨迹生成模块能帮我们做完整路径规划,前提是给每个关节设置最大速度、最大加速度,并指定运动模式。我用的是simxPauseCommunication批量下发目标角度,再调用VREP的非阻塞运动命令让机械臂平滑执行。

4.3 与传送带运动的配合逻辑

这里是最关键的工程问题:传送带一直在动,机械臂如果等物料到了固定点再抓,节拍浪费大。仿真里可以做成动态目标跟踪——机械臂预判物料到达抓取点的时间,提前运动到位置上方,等物料进入抓取区后直接下降抓取。

% 预判物料位置 conveyorSpeed = 0.1; % 传送带速度 distanceToPick = abs(worldPointX - pickPointX); arrivalTime = distanceToPick / conveyorSpeed; % 提前规划机械臂运动 targetPos = pickPoint; vrep.simxPauseCommunication(vrep.clientID, true); vrep.simxSetJointTargetPosition(vrep.clientID, joint1, theta1_target, vrep.simx_opmode_streaming); vrep.simxSetJointTargetPosition(vrep.clientID, joint2, theta2_target, vrep.simx_opmode_streaming); vrep.simxPauseCommunication(vrep.clientID, false);

这个做法可以在不减速传送带的情况下显著提升分拣节拍。实测下来比“先停带再抓”的方案,节拍提升约40%。

5. 联合调试复盘与问题排查

5.1 启动顺序与时间同步

联合仿真的启动顺序非常讲究。我建议按这个顺序来:

  1. 先启动VREP并加载场景,确认场景能正常运行
  2. 启动MATLAB,先只做连接测试,不要急着跑视觉
  3. 建立通讯后,再把视觉、识别、控制模块逐层启用

时间同步方面,VREP的仿真时钟默认不是实时时钟,可以设置同步模式,防止MATLAB视觉处理耗时导致时序错乱。在VREP的仿真设置里把步长调成50毫秒一帧,MATLAB端每步循环也按50毫秒节拍控制,两侧节奏基本就稳定了。

另外一个容易踩的坑是,如果MATLAB里直接用for循环连续读图像,而没加任何延时,会导致MATLAB端的数据请求频率远超VREP的处理速度,CPU占用飙升,最终通讯超时。

% 每个循环结束后,主动维持帧率 pause(0.05); % 与VREP步长时间保持一致

5.2 常见问题速查表

问题现象排查方向解决办法
MATLAB连接不上VREP端口号配置错误检查端口,确认VREP服务端已启动并启用外部脚本
图像全黑或全白光照强度不够或过曝调整VREP中的光源强度,或视角传感器曝光参数
识别不稳定、颜色跳变HSV阈值范围过窄适当扩大H范围,增加形态学开闭运算
机械臂抖动、过冲加速度限制不合理减小最大加速度,改用梯形速度规划
抓取位置偏差大坐标映射矩阵不准增加标定点数量,重新拟合单应性矩阵
节拍上不去抓取策略等待太多改成预判式动态跟踪抓取

5.3 几个必须分享的实践心得

第一,仿真里VREP的物理引擎模拟本身就带微小噪声,如果你在仿真里都出现机械臂末端抖动,真实设备上一定会更严重。建议把加速度限制设置得保守一点,先以稳定性为主,再逐步调快节奏。

第二,物料在传送带上运动时,视觉识别会产生运动模糊,尤其在传送带速度超过0.15米/秒以后。模拟运动模糊最直接的办法是降低快门时间,或者在图像采集前加一帧短曝光模拟。识别算法里的形态学操作能一定程度抵消模糊带来的边缘毛刺。

第三,分类逻辑不要写死。我一开始直接把“红色放1号区、绿色放2号区、蓝色放3号区”写死在代码里,后来业务方要调整分区,改代码相当痛苦。最好在启动时读取一个配置文件或参数数组,把颜色到目标区域的映射做成动态可配的。

6. 从仿真到物理实现的扩展思路

仿真验证完这套逻辑之后,往物理产线迁移时,有几个点是可以提前预留接口的。

视觉模块的代码迁移:MATLAB的计算机视觉算法可以直接连工业相机。关键区别在于去掉VREP的数据源,换成相机驱动采集的图像,通道接口走UDP或GigE协议。我在仿真里用的所有图像预处理步骤,物理产线上依然适用。

控制模块的替换:VREP里的机械臂控制逻辑,换成真实SCARA控制器时,需要把API调用换成控制器的指令协议。这个没什么黑魔法,就是多一层协议转换。这时候仿真时的价值就体现出来了——控制逻辑本身已经验证过,剩下的只是通信层替换。

这套仿真平台的另一个价值是做方案预研和节拍估算。在没动产线的情况下,我可以告诉生产部门:视觉识别单帧耗时约80毫秒,机械臂单次抓取动作约1.5秒,在0.1米/秒的传送带速度下,系统单小时分拣能力大概在800件上下。这个数据就是靠仿真跑出来的,而且实测验证过,置信度很高。

如果后续要加复杂度,可以考虑在识别端引入深度学习目标检测网络,替换掉传统HSV分割。HSV方法速度快、实现简单,但遇到物料形状接近、光照变化剧烈时仍有局限。深度学习模型更强,但推理时延会上升。好在仿真平台的架构是模块化的,视觉算法替换不会影响其他部分。

最后说一个我踩过多次坑才学到的经验:仿真项目里,美观的模型和真实感不是第一位的,模块解耦和可复现性才是。项目交付时,别人最关心的是环境能不能一键启动、代码是否清晰可维护、参数调整是否方便。把场景文件、MATLAB脚本、配置文件放在统一目录下,写一个一键启动脚本,整个流程跑通只需要点击一次。这套项目能被顺利复用,靠的就是这个习惯。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进