ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Aubo i5与RealSense D435i视觉抓取实战:从手眼标定到MoveIt完整闭环

Aubo i5与RealSense D435i视觉抓取实战:从手眼标定到MoveIt完整闭环 简介面向机器人视觉抓取开发者这份可运行源码包将aubo i5机械臂与Realsense D435i深度相机结合演示了从物体识别到机械臂抓取的完整流程利用相机获取工件位姿建立临时工件坐标系推算关键点坐标并通过坐标变换映射到机械臂基坐标系最后由moveit控制执行。资源共3个文件包含inscode在线运行配置、html说明页面与gitignore工程文件压缩包仅6KB轻量易读便于快速部署与二次开发。目前已有107人学习下载。代码涵盖结构体定义、工件位置信息获取、临时坐标系发布、关键点位姿计算、机械臂初始化与动作执行等关键环节关键部分附有示例与说明可直接作为抓取流程实现模板同时文中建议在实际场景中用server或action机制触发检测与抓取帮助开发者进一步优化工程结构、提升响应速度。整体内容聚焦ROS环境下视觉与机械臂协同的常见痛点兼具教学参考与工程实用价值。 调试这套Aubo i5配合Intel RealSense D435i做视觉抓取前后花了三周踩了不少坑也积累了一些文档里不会写的经验。项目核心其实很直接用D435i深度相机把目标物体在空间中的位置算出来再让Aubo i5机械臂完成识别—定位—规划—抓取的完整闭环最终开源出来的源码是真正能直接跑的版本不是那种缺几个依赖、缺几个launch文件的半成品。做完回头看这套组合确实很适合做机器人入门和毕设选题。Aubo i5是负载5kg、重复定位精度±0.02mm的六轴协作机械臂官方基于ROS维护了完整的aubo_robot驱动和MoveIt配置D435i作为集成RGB、深度和IMU的相机刚好覆盖了看得见、测得准、价格不贵三个关键点。对正在做视觉抓取预研、或者被导师丢了个机械臂自主抓取课题的朋友来说这套方案几乎是当前最稳妥的落地组合。1. 项目背景与整体方案1.1 为什么选Aubo i5 D435i这个组合视觉引导抓取的核心痛点就两个字标定。机械臂选Aubo i5主要看三点。第一它基于ROS生态官方驱动包里MoveIt配置是现成的省去了从零建模的麻烦第二协作臂本身有碰撞检测调试阶段就算轨迹算错了机械臂也会停下来不会硬撞桌面或相机第三5kg负载、886.5mm臂展装一个D435i再加一套夹爪绰绰有余。相机选D435i不是因为它性能最强而是它最省心。D435i的深度模块基于主动红外立体视觉在0.3到1.5米这个抓取常用距离内深度误差能控制在1%左右对抓取来说完全够用。更关键的是realsense-ros驱动在ROS1和ROS2下都有官方维护启动之后RGB图像、深度图像、相机内参直接发布到话题上不需要自己写相机驱动。这套组合也有短板。D435i在强光环境下深度会有空洞透明物体基本测不出深度黑色吸光物体在近距离也会出现深度缺失。所以抓取场景尽量选漫反射、不透明的物体后面我会专门讲怎么规避。1.2 整体系统框架与工作流程整套系统说白了就是一句话用D435i当眼睛用MoveIt当规划大脑指挥Aubo i5的手完成抓取。具体拆成六个环节相机内参标定确定像素位置和光线方向的映射关系。手眼标定确定相机坐标系和机械臂末端坐标系之间的固定变换这是整个项目最关键的步骤。目标检测从RGB图像里找到目标物体分割出它的像素区域。深度采样在深度图上取物体区域的深度值算出物体在相机坐标系下的三维坐标。坐标变换通过TF树把相机坐标系下的点逐步转换到机械臂基座坐标系。运动规划与执行MoveIt规划一条无碰撞轨迹机械臂走到抓取点上方下探闭合夹爪抬升。整个流程跑通之后你会发现难点不在于某个单独模块有多复杂而在于模块之间的接缝非常容易出错。比如深度图和彩色图忘了对齐TF树里某个link名字写错标定拍了几十张但角点检测失败的图片没剔除。后面每个环节我都会把实际踩过的坑说出来。2. 搭建准备软硬件环境与通信2.1 硬件清单与接线先列一份完整的硬件清单我调试用的配置是这样的硬件型号/规格说明机械臂Aubo i5协作机械臂6轴负载5kg臂展886.5mm控制器Aubo i系列标准控制柜机械臂标配深度相机Intel RealSense D435iRGB Depth IMU夹爪二指平行夹爪电动建议可调行程方便适配不同物体相机安装板定制铝合金连接板末端安装相机用上位机工控机或高性能笔记本建议CPU i5以上内存16G起步相机的安装方式很关键。桌面固定抓取场景下我强烈建议把D435i装在机械臂末端也就是eye-in-hand模式。相机跟着机械臂移动视野不会被桌面或者支架遮挡抓取前还能主动移动到物体斜上方找角度。也有人用eye-to-hand模式把相机架在天花板上表面看省去了末端负载但实际标定和视野范围调试反而更麻烦后期机械臂一移动就挡视线。2.2 软件环境配置我的环境是Ubuntu 18.04 ROS Melodic这也是目前教程最多、坑最少的组合。Ubuntu 20.04配ROS Noetic的流程几乎一样但注意仓库分支要选对。# 安装realsense-ros sudo apt-get install ros-melodic-realsense2-camera # 安装realsense SDK sudo apt-get install librealsense2-dev # 克隆aubo_robot官方驱动 cd ~/catkin_ws/src git clone https://github.com/AuboRobot/aubo_robot_melodic.git # 编译 cd ~/catkin_ws catkin_make编译Aubo驱动时有个高频坑部分旧版本包里的MoveIt配置与当前ROS发行版不兼容会报Could not find the required component moveit_ros_perception之类的错误。解决办法是把MoveIt相关依赖一次性装齐sudo apt-get install ros-melodic-moveit ros-melodic-moveit-ros-perception ros-melodic-moveit-ros-planning装完再重新编译基本就通过了。2.3 验证机械臂与相机通信这一步千万不能跳过。先把机械臂控制柜上电等控制器状态灯变绿在上位机里执行roslaunch aubo_i5_moveit_config moveit_planning_execution.launch一切正常的话rviz里会显示Aubo i5的三维模型拖动模型末端实体机械臂会跟着动。这个环节最容易忽略的一点是用MoveIt之前机械臂必须处于手动低速模式或者使能状态否则控制器会拒收轨迹。我第一次调试时MoveIt界面完全正常但机械臂死活不动查了一个多小时才发现是控制柜面板上的使能按钮没按下去。相机验证更简单rostopic hz /camera/color/image_raw话题频率稳定在30Hz左右说明相机SDK工作正常。我建议顺手用realsense-viewer跑一遍健康检查确认深度图的精度和传感器温度正常再进行长时间标定否则标定做到一半相机过热漂移数据全废。3. 相机标定与手眼标定3.1 相机内参标定要点D435i出厂时彩色图和深度图并不是完全对齐的这一步不处理后面所有坐标计算都会偏。在realsense2_camera的launch文件中加上对齐参数arg namealign_depth valuetrue/ arg namefilters valuespatial,temporal/align_depthtrue会把深度图对齐到彩色图坐标系这样在彩色图上分割出的像素坐标可以直接拿到深度图上取深度值省去手动对齐的麻烦。内参标定用经典的张正友标定法OpenCV的cv2.calibrateCamera就能做。打印一张棋盘格推荐9x6或者7x6别买太小的从不同角度拍20张左右。我的经验是标定板不要只在一个角度范围内转要涵盖俯仰、平移、旋转多种姿态不然内参拟合会退化标出来的fx、fy偏差很大。标定完会得到一个相机内参矩阵fx 0 cx 0 fy cy 0 0 1D435i自带的/camera/color/camera_info话题里其实已经有一个比较准确的内参。如果只是演示抓取直接用话题里的内参就能跑但追求精度特别是复现别人误差10mm以内的效果时还是自己标一次把结果写进配置文件更稳。3.2 手眼标定的AXXB问题这是整个项目最绕、最容易出错的地方我尽量用大白话讲清楚。手眼标定要解决的是相机坐标系和机械臂末端坐标系之间差了一个固定的旋转平移关系这个关系怎么求。eye-in-hand模式下相机装在末端上标定出的就是相机相对末端的矩阵。数学上这个问题被归纳为AXXB。A是机械臂末端在基座坐标系下的位姿可以从MoveIt或者驱动里拿到B是标定板在相机坐标系下的位姿通过角点检测加solvePnP可以算出来X就是我们需要的手眼变换矩阵。多动几次机械臂让相机从不同角度观察固定不动的标定板采集足够多的样本后就能解出X。实操上我推荐直接用easy_handeye这个ROS包它封装了标定板检测和数据求解的全过程。运行流程# 先启动相机注意对齐参数 roslaunch realsense2_camera rs_camera.launch align_depth:true # 再启动easy_handeye的eye-in-hand模式 roslaunch easy_handeye easy_handeye.launch namespace:aubo_i5 eye_on_hand:true启动后rviz里会出现标定界面。手动控制机械臂末端移动到9个以上的不同位姿每次移动后点击采集样本。采集的核心要领是相邻两次样本之间机械臂末端姿态要有明显的旋转变化不能只是平动。如果全都是平动AXXB方程里的旋转分量解不出来求解结果会非常差这是新手最容易犯的错误。标定结束会生成一个yaml文件里面保存的就是相机到末端的变换矩阵。这个文件一定要备份好它就是你整套系统的眼手连接线丢了就得从头标。3.3 标定精度提升技巧我实测下来标定精度直接决定最终抓取误差。这几个技巧是实打实有用的标定板尽量大打印成A4纸大小起步。棋盘格太小远距离角点检测精度下降手眼标定的整体误差会在最后抓取时放大好几倍。每次移动后等机械臂完全静止再采集。机械臂停止前的残余抖动会让相机位姿产生几毫米偏差这几毫米到最后就是几厘米的抓取偏差。采样点位要均匀分布不要集中在一小片区域。建议定义6个高度乘3个旋转角凑够18个采样点覆盖末端的不同高度和朝向。标定完一定要验证。拿标定板上的某个角点通过手眼矩阵把它从相机坐标变换到机械臂基座坐标对比真实位置误差在5mm以内才算合格。超过10mm的结果直接重做不要将就。4. 视觉识别与坐标转换核心代码4.1 目标检测与深度采样识别物体这块越是追求通用方案越容易在抓取环节翻车。我的建议是先跑通简单场景再考虑上深度学习。简单场景我用的是HSV颜色空间阈值分割。为什么不用RGB因为RGB对光照变化极其敏感同一块红色积木在亮处和暗处RGB值能差出一大截。HSV把色调(H)、饱和度(S)、亮度(V)分开只靠H通道就能锁定颜色对光照鲁棒性好很多。核心代码就几行import cv2 import numpy as np class ObjectDetector: def __init__(self): # 以红色物体为例HSV下界/上界 self.color_lower np.array([0, 100, 100]) self.color_upper np.array([10, 255, 255]) def detect(self, cv_img): hsv cv2.cvtColor(cv_img, cv2.COLOR_BGR2HSV) mask cv2.inRange(hsv, self.color_lower, self.color_upper) # 开闭运算去掉噪点 mask cv2.morphologyEx(mask, cv2.MORPH_OPEN, np.ones((5, 5), np.uint8)) mask cv2.morphologyEx(mask, cv2.MORPH_CLOSE, np.ones((5, 5), np.uint8)) contours, _ cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if not contours: return None max_contour max(contours, keycv2.contourArea) if cv2.contourArea(max_contour) 500: return None M cv2.moments(max_contour) if M[m00] 0: return None cx int(M[m10] / M[m00]) cy int(M[m01] / M[m00]) return cx, cy拿到物体中心像素坐标后去对齐之后的深度图上取深度值。这里有个关键细节不要只取单个像素的深度要取中心点周围一个小邻域的中值。深度图边缘和物体表面存在噪声取单点很容易踩到深度值为0的空洞上取中值能显著提升稳定性def get_depth_at_pixel(depth_img, cx, cy, radius5): region depth_img[cy-radius:cyradius, cx-radius:cxradius] valid region[region 0] if len(valid) 5: return None return np.median(valid) / 1000.0 # D435i默认深度单位是毫米转成米4.2 像素坐标到机器人基座坐标的变换链完成深度采样后就进入坐标变换环节这是整个项目的灵魂代码。捋一下逻辑。物体中心对应像素坐标(u, v)和深度值d先还原相机坐标系下的三维点。相机内参为fx、fy、cx、cy那么X_cam (u - cx) * d / fx Y_cam (v - cy) * d / fy Z_cam d再用相机到末端的手眼矩阵T_cam_to_tool把点转到末端坐标系最后用机械臂正运动学得到的T_tool_to_base转到基座坐标系P_base T_tool_to_base * T_cam_to_tool * P_cam实际工程里我不会在代码里手动做矩阵连乘而是把相机安装到机械臂末端后将手眼矩阵作为一个静态变换直接写进URDF模型这样TF树里就有一条从camera_link到tool0的固定链接。在代码里直接用TF查询import rospy import tf2_ros class CoordinateTransformer: def __init__(self): self.tf_buffer tf2_ros.Buffer() self.listener tf2_ros.TransformListener(self.tf_buffer) def lookup_transform(self): try: trans self.tf_buffer.lookup_transform( base_link, camera_link, rospy.Time(0), rospy.Duration(1.0)) return trans except Exception as e: rospy.logerr(TF查询失败: %s, e) return None只要TF树搭对了一次lookup_transform就能拿到整个坐标变换链省掉手写矩阵连乘的麻烦也不容易出错。4.3 抓取点姿态计算知道物体在基座坐标系下的位置还不够机械臂抓取需要的不只是位置还有姿态。比如抓一个细长圆柱体末端不能直直地从正上方下去夹爪开口方向要对着圆柱的轴向。我用的是轮廓方向计算法在目标检测阶段用cv2.minAreaRect求最小外接矩形得到物体的长宽和旋转角度。抓取时让末端夹爪的闭合方向对齐矩形短边方向对规则盒子和圆柱体都很适用。抓取姿态里的常见坑是欧拉角顺序问题。MoveIt里设置的rpy是固定轴欧拉角顺序是roll、pitch、yaw。如果从物体外形算出一个旋转角放进MoveIt里末端方向却完全不对那八成是没搞清楚这个角度是在图像坐标系里算的还是在世界坐标系里算的。图像里的角度和世界坐标系的yaw角之间通常需要用相机外参做一步转换这一步我在源码里封装成了函数直接调用就行。5. 抓取执行MoveIt规划与实现5.1 运动规划流程我推荐的抓取流程分三步先快速走到预抓取点再直线下探到抓取点抓取抬升后返回安全位置。为什么分三步如果直接从初始位置一步规划到抓取点MoveIt很可能规划出从侧面绕路或者姿态奇怪的轨迹笛卡尔路径越长越容易出现避障抖动。预抓取点放在抓取点正上方15cm左右姿态保持一致最后下探用笛卡尔直线插补保证末端走竖直直线避免夹爪碰倒物体旁边的障碍物。核心代码import moveit_commander import rospy moveit_commander.roscpp_initialize([]) rospy.init_node(pick_node, anonymousTrue) robot moveit_commander.RobotCommander() group moveit_commander.MoveGroupCommander(aubo_i5_arm) # 规划参数设置 group.set_planning_time(10.0) group.set_goal_position_tolerance(0.001) # 1mm位置误差 group.set_goal_orientation_tolerance(0.01) # 0.01rad方向误差 # 预抓取点 pre_grasp_pose [x, y, z 0.15, roll, pitch, yaw] group.set_pose_target(pre_grasp_pose) plan1, _ group.plan() group.execute(plan1, waitTrue) # 笛卡尔直线下探 grasp_pose [x, y, z, roll, pitch, yaw] plan2, fraction group.compute_cartesian_path([grasp_pose], 0.01, 0.0, avoid_collisionsTrue) group.execute(plan2, waitTrue) # 闭合夹爪 gripper.close() # 抬升到安全高度 lift_pose [x, y, z 0.15, roll, pitch, yaw] group.set_pose_target(lift_pose) plan3, _ group.plan() group.execute(plan3, waitTrue)这里提醒一下不同版本的moveit_commander接口有差异。老版本group.plan()返回plan对象新版本返回(plan, fraction)元组跑源码遇到报错先检查接口版本别上来就怀疑代码逻辑。5.2 抓取位姿调整与手爪控制抓取成功率影响最大的细节是不要把夹爪开度设成刚好比物体宽度大一点点。实际抓取时识别误差、机械臂定位误差、手眼标定误差会叠加开度太紧的话夹爪边缘会撞到物体把它推倒。建议开度设置为物体宽度的1.2到1.3倍让夹爪先套住物体再闭合力抓取。下探速度一定要慢。协作臂下探太快接触物体瞬间的动量会把物体弹飞。我实测下来最后10cm的下探线速度控制在5cm/s以下成功率会明显提升。MoveIt的set_max_velocity_scaling_factor(0.1)可以把速度限制到10%这个参数对抓取稳定性的影响非常直接。手爪控制一般走Modbus或者数字IO。如果用的是电动夹爪记得在夹爪闭合后加0.5到1秒延时再抬升给夹爪留出建立摩擦力的时间否则物体在上升瞬间很容易滑脱。5.3 可运行源码核心结构我开源的这套源码把以上内容组织成了清晰的包结构拿到手后可以直接编译运行aubo_d435i_grasp/ ├── launch/ │ ├── demo.launch # 一键启动机械臂、相机和抓取节点 │ ├── rs_camera.launch # D435i相机启动参数 │ └── aubo_moveit.launch # MoveIt规划节点 ├── config/ │ ├── hand_eye.yaml # 手眼标定结果替换成你的 │ ├── camera_intrinsics.yaml # 相机内参 │ └── grasp_config.yaml # 抓取参数物体颜色、尺寸、速度 ├── scripts/ │ ├── detect_object.py # 目标检测 │ ├── transform_point.py # 坐标变换 │ ├── pick_place.py # 抓取主流程 │ └── test_tf.py # TF变换验证脚本 └── README.md # 环境安装和运行步骤demo.launch做了很多自动化处理包括等待TF树建立、检测目标是否在视野内、不在视野内会打印提示并等待。这种开箱即用的体验很重要调试阶段可以少敲非常多命令。6. 常见问题与排错经验6.1 三个高频报错整理了一份问题速查表都是实际调试中反复遇到的问题现象原因解决方案启动MoveIt后机械臂不动控制器使能未开启或处于手动模式按下控制柜面板使能按钮切换到自动模式深度图全是黑的光照太强或距离太远调整相机曝光物体距离控制在0.3到1.5m抓取位置整体偏向一侧手眼标定旋转矩阵偏差按3.3节验证方法重新采样标定TF树缺少camera_linklaunch文件未加载URDF扩展把相机模型和固定变换写进URDF目标检测框抖动严重深度噪声或颜色阈值太窄加大形态学核尽量放宽HSV范围规划失败或轨迹报错工作空间限制或碰撞检测误判增大规划时间放宽终点容忍度6.2 抓取失败的排查思路抓取失败时不要盲改参数按这个顺序排查第一步先看定位准不准。把检测到的物体中心点用rviz的Marker直接显示出来如果Marker落在物体中心附近但有偏移那是识别或坐标转换问题如果Marker完全不在物体附近是手眼标定或TF树问题。第二步检查机械臂实际到位位姿和规划位姿是否一致。让机械臂执行到抓取点后暂停手动测一下末端位置和物体位置之间的偏差。如果不一致检查MoveIt的基座坐标系和驱动、URDF模型是否匹配。第三步确认夹爪动作触发时机。有人把夹爪控制放在轨迹执行完成之前导致夹爪提前闭合撞飞物体。这属于逻辑时序问题代码里加延时或者状态机判断就能解决。推荐在抓取主循环里加一个dry-run模式不实际闭合夹爪只让机械臂走完整套轨迹并在抓取点悬停。运行的时候在物体旁边放尺子量误差通常能定位到90%的问题。6.3 一些独门的避坑技巧最后分享几个源码和文档里不会写的细节。第一D435i要定期关注温度。长时间工作后相机发烫深度误差会明显变大。realsense-viewer里能查看传感器温度超过40摄氏度建议加装散热风扇或者间歇性让相机休眠。第二手眼标定时机械臂要避开奇异点附近的姿态。奇异点附近即使末端位置没动关节角度也可能剧烈变化会导致采样数据数值不稳定。每条轴的角度尽量控制在关节极限的20%到80%区间。第三抓白色或黑色物体时HSV阈值方案基本失效因为这类颜色在HSV空间里紧贴着去饱和度区域。这种情况我建议换YOLO或者轻量深度学习检测网络。第一版调试时可以先给物体贴彩色贴纸或者选用彩色积木成功率会高很多。第四夹爪的通信协议一定要提前确认。有些开源源码里演示的是串口夹爪换CAN协议的夹爪后串口部分得整体改掉。我一开始就在这个上面浪费了半天时间。这套Aubo i5加D435i抓取实践跑完之后我最深的感受是视觉抓取项目真正难的从来不是单个算法而是把所有模块的坐标系、时间戳、通信机制粘合在一起。只要把标定和TF树这两座大山翻过去后面的路就顺畅了。如果你也是刚接到这类项目一定要给标定环节留足时间我第一次摸索加踩坑用了一周第二次重标只花了一个晚上。源码里的配置和launch文件都是可以直接改参数运行的祝你一次成功。本文还有配套的精品资源点击获取
返回列表