Aubo i5与D435i视觉引导机械臂抓取实战:从手眼标定到MoveIt规划
发布时间:2026/9/1 6:18:03 作者:尧图编辑部 阅读量:1,286

简介面向机器人视觉抓取开发者的可运行源码包整合aubo i5机械臂与RealSense D435i深度相机解决物体识别定位到机械臂抓取的完整链路问题。压缩包共3个文件体积仅6KB以HTML页面和代码配置文件为主内容浓缩了从相机位姿识别、临时工件坐标系建立、关键点位姿计算到moveit控制执行的核心代码示例。已有107人浏览学习适合初涉视觉抓取或需要快速搭建原型的工程师参考。资料亮点在于提供了结构体定义、工件位置信息获取、坐标系发布、机械臂初始化与执行等关键步骤的可运行片段并给出实际应用中改用server或action机制触发检测抓取的优化建议便于读者在此基础上扩展为完整工程。代码示例围绕“视觉引导抓取”主线清晰展示如何将相机坐标系下的物体位姿转换到机械臂基坐标系最终驱动aubo i5完成抓取动作。1. 项目到底在做什么从深度图到机械臂末端的一整套抓取链路想用视觉引导机械臂做自主抓取很多人卡住的地方往往不是某一个算法而是“所有环节恰好能连起来跑通”这件事。Aubo i5 配合 Intel RealSense D435i 的抓取实践正好是把这条链路完整走通的一个典型参考。这套方案解决的核心问题很明确让机械臂能看到工作台上的物体、算出物体在机械臂坐标系下的位姿然后规划出一条无碰撞的轨迹控制末端移动到抓取点完成抓取。为什么选这两个硬件组合Aubo i5 是六自由度协作机械臂负载 5kg工作半径 886.5mm自带 ROS 驱动和 MoveIt 配置对于实验室和轻量工业场景很合适。D435i 则是主动立体视觉深度相机带 IMU 模块深度分辨率最高 1280x720RGB 分辨率 1920x1080工作距离在 0.3m 到 3m 区间内精度表现比较稳定且 USB 供电、体积小架在支架上或用连接件固定到机械臂末端都方便。两者组合起来成本可控、资料多、SDK 完善非常适合作为视觉抓取入门到实战的参考平台。这篇内容面向的读者是已经具备基本的 ROS、Python/C 基础手边恰好有类似硬件条件不一定是同一型号UR 或者其他六轴臂也适用同一套思路想要拿到一份能直接改、直接跑的源码参考而不是只停留在看论文和概念层面的工程师或研究生。我会从环境搭建、相机数据处理、手眼标定、目标位姿估计到机械臂执行把整套流程的关键环节和我在实际调试中踩过的坑都梳理一遍。2. 环境搭建驱动和依赖是第一个坑2.1 Aubo i5 驱动部署与网络配置先处理机械臂本体。Aubo i5 的官方 ROS 驱动是aubo_robot在 GitHub 上有维护包含aubo_driver、aubo_moveit_config、aubo_description等核心包。安装前需要确认本机 ROS 版本一般用的是 Ubuntu 16.04 Kinetic或者 Ubuntu 18.04 Melodic建议优先选用社区测试较多的版本组合能省去不少编译兼容性问题。机械臂出厂默认 IP 一般是 192.168.1.123不同批次可能不同工控机需要配置为同一网段的静态 IP比如 192.168.1.100。这里我踩过一个很典型的坑网口插上了、IP 也配了但ping不通后来发现是机械臂控制柜的网口和工控机直连时需要关闭工控机的防火墙以及检查控制柜是否处于手动模式。Aubo 控制柜只有在自动/远程模式才允许外部指令下发否则驱动连接上也会报错或者无法执行运动。编译方面aubo_robot依赖 MoveIt所以还需要提前安装moveit、moveit_visual_tools等包。用catkin_make编译即可但要注意个别版本的aubo_driver对tf和actionlib的 API 兼容性有差异如果编译报错优先检查这些依赖包的版本。2.2 D435i 驱动与相机参数设置D435i 的驱动分三层底层是librealsense中间是realsense-ros封装上层就是用户的视觉节点。安装librealsense推荐直接用 Intel 官方 apt 源或者从源码编译。源码编译的好处是能拿到最新特性但耗时较长并且需要安装libglfw3-dev、libssl-dev、libusb-1.0-0-dev等依赖。apt 源安装则方便得多版本也稳定我通常用 apt 安装。装完后先插上相机运行realsense-viewer这一步很重要不要急着写代码先把相机的固件、畸变参数、深度质量在 GUI 里确认一遍。D435i 出厂前自带内参标定结果一般不用重新标定但如果工作环境温差大、相机受过震动后深度精度可能下降这时需要做动态标定Dynamic Calibration。具体操作是在realsense-viewer里点击校准选项打印官方的标定目标板按提示拍摄多帧不同姿态的图像计算并写入标定参数。在相机参数设置上有几点建议深度流和彩色流的帧率尽量设为一致例如 30fps分辨率不必追求最高RGB 640x480、深度 640x480 已经足够做目标识别和位姿估计更高的分辨率只会徒增带宽占用和计算负担。如果发现画面有明显的亮度闪烁或深度噪声先检查是否插在 USB 3.0 口上D435i 在 USB 2.0 下虽然能用但传输带宽不足会导致深度流掉帧。2.3 图像与点云处理库的安装和取舍视觉处理环节依赖 OpenCV 和点云库。OpenCV 负责图像预处理、ArUco 标定板检测、轮廓提取等点云库则推荐 Open3D 或者 PCL。两者都能完成点云滤波、平面分割和聚类但体验上差异很大。我用 PCL 做过一段时间功能全面但 C 模板繁多、编译时间长Open3D 的 Python 接口简单直接调试效率高得多。实际项目中我倾向于 Open3D 做快速原型验证确认算法流程后再用 C 版本固化兼顾开发效率和运行性能。安装 Open3D 直接pip install open3d即可PCL 在 Ubuntu 下用apt install libpcl-dev。OpenCV 如果源码编译会比较折腾建议用apt install libopencv-dev或者 Python 的opencv-python包。这里要留意版本兼容如果realsense-ros的版本对 OpenCV 有依赖就优先采用apt安装的版本避免自编译的 OpenCV 和 ROS 包链接冲突。3. D435i从原始深度流到干净点云3.1 对齐与分辨率设定D435i 的深度相机和 RGB 相机在硬件上位置不同导致两路图像存在视差。如果不做对齐直接用深度图的像素坐标去对应彩色图的像素会出现明显的错位。最典型的症状就是检测到的物体边界在彩色图上是准的但实际上裁剪出来的点云区域要么多了背景点、要么少了一部分物体表面。解决办法有两种。第一种是在realsense-ros的 launch 文件里设置align_depth : true让驱动自动输出对齐后的深度图。第二种是在自己的节点里调用rs2::align处理每条深度流。注意align方括号中必须写明对齐的目标流比如要对齐到彩色流就是rs2::align(RS2_STREAM_COLOR)。我实际测试下来驱动层面的对齐精度够用而且不占额外代码量优先推荐。分辨率的选择也影响后续点云质量。D435i 在近距离0.3m 到 1m深度精度较好超过 2m 后噪声明显增加。对于桌面抓取场景相机架设高度一般距离工作台 0.5m 到 0.8m这个距离下 640x480 的深度分辨率已经能比较清晰地分辨出几厘米尺寸的目标物体。如果设成 1280x720点云数量翻倍但边缘噪声也会更明显还拖慢处理速度。3.2 点云预处理三板斧直通滤波、体素降采样与统计滤波拿到原始点云后直接做识别效果通常很不理想。工作台、墙面、桌面上的杂物都会混在点云里而且深度噪声会产生漂浮的离群点。我习惯按固定顺序做三步预处理。第一步是直通滤波只保留工作台区域的点云。以相机固定在工作台上方为例沿着相机坐标系把 X、Y、Z 三个方向都裁剪到合理范围。比如 Z 方向深度方向只保留 0.2m 到 1.0mX 和 Y 根据视野范围裁到正负 0.5m 左右。这一步立竿见影能去背景点、降低后续计算量。注意裁剪范围不要过于精确到贴合目标否则机械臂稍一抖动物体边缘的点就被裁掉了。第二步是体素降采样把点云划分为若干小立方体voxel用每个立方体内所有点的重心替代整组点。体素尺寸一般设置为 0.005m 到 0.01m。这个操作在不明显损失几何信息的前提下能把点云数量从几十万压到几万后续平面分割和聚类的计算速度会快很多倍。第三步是统计滤波去除离群噪点。原理是对每个点计算它到 k 个最近邻的平均距离距离平均值明显高于全局阈值的点判定为离群点并删除。这里 k 通常取 20 左右阈值倍数取 1.0 到 2.0。对于 D435i 这种主动立体相机在反射面、深色物体边缘容易产生孤立噪点统计滤波能有效清理。这三步做完留在点云里的基本就是工作台平面和待抓取物体了接下来就可以进入定位环节。4. 手眼标定整个系统的精度基石4.1 标定方案选择与原理抓取任务里最核心的一组坐标变换是把相机坐标系下的物体位姿变换到机械臂基坐标系下。D435i 装在固定支架上、不随机械臂运动所以属于eye-to-hand眼在外布局如果相机装在机械臂末端那属于eye-in-hand眼在手。两种布局的标定流程有差异原理本质都是求解一个变换矩阵。以 eye-to-hand 为例需要标定的是相机坐标系到机械臂基坐标系的变换。常用做法是让机械臂末端夹持一个标定板移动机械臂到多个不同的位姿每到一个位姿同时记录两件事一是机械臂末端在基坐标系下的位姿从控制柜或 ROS 的 TF 树获取二是标定板在相机坐标系下的位姿通过检测 ArUco 码或棋盘格角点求得。因为标定板固定在机械臂末端所以标定板到末端的变换是固定值我们可以通过这些测量数据求解出相机到基座的固定变换。具体的数学形式是 AXXB 问题其中 A 是机械臂末端的位姿变换B 是标定板在相机系下的位姿变换X 就是待求的相机到基座的变换。OpenCV 提供了calibrateHandEye函数支持 Tsai、Park、Horaud 等多种求解算法直接用就行。4.2 实操流程从打印标定板到写出变换矩阵实际操作中我用的标定板是 7x5 的 ArUco 板每个格子边长 30mm打印后贴在刚性平板上确保标定时不弯折。标定板固定在机械臂末端时要尽量贴平不能有倾斜翘起否则会引入系统性误差。标定流程可以按下面步骤执行启动相机、机械臂和标定采集节点确保能同时拿到图像和机械臂位姿数据手动或半自动控制机械臂让末端带着标定板以不同的高度、角度、朝向出现在相机视野中至少采集 15 到 20 组数据每组数据保存内容包括机械臂当前末端位姿平移向量 四元数或旋转矩阵以及 ArUco 板在相机系下的位姿同样记录六自由度信息所有样本统一格式后调用 OpenCV 的calibrateHandEye传入机械臂末端的旋转矩阵和平移向量、标定板在相机系下的旋转矩阵和平移向量输出结果就是相机到机械臂基座的变换矩阵保存成文件。有几个细节值得单独强调机械臂移动的位姿之间要有明显的姿态差异比如俯仰、偏航都要变化如果只在同一平面内平移方程会退化标定结果不可靠标定板要在视野的不同区域分别出现不要集中在画面中心每改变一个位姿机械臂停稳后再采集数据运动过程中的抖动会使数据不平滑。完成标定后一定要做验证。方法是在工作台上放一个已知坐标的标记点用相机检测它的位置通过刚标定出的变换矩阵映射到机械臂基坐标系下再控制机械臂末端移动到该点观察误差。如果误差在几毫米以内说明标定基本可用如果误差在 1cm 以上优先检查标定数据的质量和分布而不是盲目调整算法。4.3 D435i 内参标定的补充说明D435i 出厂内参精度对一般抓取任务足够但如果发现图像畸变明显或者标定板角点检测总是不准可以考虑做内参标定。虽然有realsense-viewer的动态标定功能但在需要更高精度的场合用 OpenCV 的棋盘格标定流程也能做得到的是针孔模型内参和畸变系数。D435i 支持畸变校正操作时要注意标定板在不同距离和角度下的拍摄数量尽量覆盖整个画面避免畸变系数在边缘位置失效。内参标定完成后把新内参嵌入到算法流程里替换掉rs2::intrinsics返回的默认参数。注意realsense-ros的发布参数不一定直接允许修改内参需要自行在后处理中完成去畸变。5. 目标识别与抓取位姿计算5.1 工作台平面提取与目标聚类预处理后的点云首先要分离背景平面和目标物。RANSAC 平面分割是首选方案先拟合工作台平面并确定平面方程的法向量然后把平面附近的点全部移除剩下的就是目标物体的点云聚类。这里的一个重要参数是 RANSAC 的平面距离阈值一般取 0.005m 到 0.015m。阈值太小会误把物体底面点当成平面点删掉阈值太大则会把少量平面点遗留在目标点云里。调参时建议先把点云可视化观察平面拟合的效果再决定阈值方向不要盲目调数字。平面移除后用欧几里得聚类把点云分成若干个独立的物体簇。每个簇的最小点数阈值可以过滤掉零碎噪声最大点数可以防止多个物体粘连成一个大簇。这一步的效果直接决定了后续对每个目标是否能单独计算位姿。在桌面上有多个物体的情况下我一般会把聚类距离阈值设为 2cm 到 3cm物体间距小于这个值时会被聚成一团需要适当放宽距离阈值或者改用基于法向量的区域生长聚类。5.2 抓取点计算质心、最小包围盒与姿态角得到物体点云簇以后需要计算抓取位置和抓取姿态。最简单可靠的方法是计算点云的质心作为抓取位置然后计算点云的最小包围盒OBB以包围盒的主轴方向作为物体的朝向参考。这里我推荐用最小包围盒而不是主轴分析原因在于实际物体的点云往往不是理想的对称形状。主轴分析PCA容易受到物体表面残缺点的影响使主轴方向发生偏移而 Open3D 的compute_min_oriented_bounding_box()基于点云几何信息计算稳定性更好。用包围盒可以得到三个方向的尺寸对于长方体、圆柱体等常见目标能比较可靠地确定抓取方向。抓取姿态还需要考虑机械臂末端执行器比如二指夹爪的接近方向。通常我们希望夹爪从垂直于工作台的方向接近物体也就是沿着基坐标系 Z 轴向下抓。如果物体表面有倾斜则需要根据包围盒的顶面法向量或者平面拟合来确定接近向量避免夹爪与物体表面产生角度偏差导致抓取失败。具体的坐标转换在代码里这样处理import open3d as o3d import numpy as np # pcd 为预处理后的目标点云簇 obb pcd.get_oriented_bounding_box() center obb.get_center() extent obb.get_extent() R obb.R # 3x3 旋转矩阵 # 抓取点位置相机坐标系 grasp_pos_cam center.astype(np.float32) # 接近方向取包围盒的最小尺寸轴或者指定为竖直向下 approach_vec R[:, 1] # 具体取哪个轴取决于坐标系定义实际使用时还要考虑夹爪的开口宽度和物体尺寸的匹配关系如果物体尺寸接近夹爪开口极限微小的位姿误差就可能导致抓取失败。6. 机械臂执行从坐标到关节角的最后一公里6.1 坐标变换链路与 TF 管理视觉识别出的目标位姿在相机坐标系下必须经过刚标定得到的变换矩阵映射到机械臂基坐标系才能生成运动指令。整个变换链路是目标物(相机系) → 相机到基座标系变换 → 目标物(基座标系) → 机械臂正逆解 → 关节角在 ROS 里这条链路可以用 TF 树管理camera_color_optical_frame是相机彩色光学的坐标系base_link是机械臂基坐标系两者之间的静态变换就是手眼标定的结果。启动时可以通过static_transform_publisher发布这个静态变换后续代码里用tf2查询变换即可完成坐标转换。需要注意坐标系方向的一致性。Aubo i5 的base_link坐标系定义为 X 轴朝前、Y 轴朝左、Z 轴朝上而相机坐标系通常是 Z 轴朝前指向被拍摄物体、Y 轴朝下。两个坐标系虽然都是右手系但不加变换直接混用轻则位置偏移、重则机械臂运动到错误位置甚至触发安全事故。所以每次标定后务必先用可视化工具如 RViz检查坐标轴朝向再把变换矩阵接入规划管线。6.2 MoveIt 规划与 SDK 下发两种执行方式机械臂执行环节推荐优先用 MoveIt因为可以拿到避障、轨迹规划和可视化支持。Aubo 的aubo_moveit_config包已经配置好了规划组直接用move_group_interface就能设置目标位姿并规划执行。关键代码片段如下import rospy from moveit_commander import MoveGroupCommander rospy.init_node(grasp_node) group MoveGroupCommander(aubo_i5) group.set_planning_time(5.0) group.set_goal_position_tolerance(0.001) group.set_goal_orientation_tolerance(0.01) # target_pose 是目标物在机械臂基坐标系下的抓取位姿 group.set_pose_target(target_pose, end_effector_linktool0) plan group.plan() group.execute(plan, waitTrue)注意end_effector_link的命名要确认清楚Aubo 驱动里可能是tool0或wrist3_Link取决于具体的 URDF 定义。如果用 SDK 的方式下发则可以直接调用 Aubo 提供的moveL、moveJ等接口传入笛卡尔坐标和姿态欧拉角或四元数。SDK 方式控制直接、响应快但没有内置避障适合程序内部已规划好路径的简单抓取MoveIt 方式更安全也更容易在 RViz 里调试是更好的起点。6.3 抓取策略与轨迹避让除了目标点本身机械臂从初始位置运动到抓取点的路径也要设计。推荐分两步规划先规划一个“预抓取点”位置在目标点正上方约 15cm 到 20cm 处姿态与目标点一致机械臂先直线运动到预抓取点再以较慢速度垂直下降到抓取点夹爪闭合再抬升回到预抓取点。这样做的好处是机械臂的运动路径清晰不容易碰到工作台周围的其他物体而且下降距离短、速度快减少了视觉误差带来的碰撞风险。如果目标点位于工作台边缘生成预抓取点时还要考虑机械臂的容忍度不要让预抓取点和目标点之间的直线路径越过机械臂的运动奇异区域。一个简单有效的方法是在所有路径点生成后先做逆解可行性和碰撞检测检测不过就重新生成预抓取点位置或者调整接近姿态。7. 常见问题与调试实录7.1 深度图和彩色图错位怎么办现象彩色图像中目标检测框正确但点云目标区域明显偏移或者点云包含大量工作台外的点。排查思路先确认是否启用了深度-彩色对齐如果用的是realsense-ros检查 launch 文件里align_depth是否设置如果自写节点确认rs2::align是否应用在每条深度帧上。再确认图像分辨率是否一致深度图和彩色图的分辨率不一致时对齐结果容易异常。最后检查相机固件旧固件在部分分辨率组合下有对齐 bug升级固件通常能解决。7.2 标定误差总是偏大的调试如果验证时误差超过 1cm不要急着重新标定先按顺序检查三件事标定板是否平整、机械臂末端位姿读数是否稳定、标定数据是否覆盖了足够的位姿空间。我在实际调试中发现最常出问题的是末端位姿读数存在时间差相机图像采集和机械臂位姿记录不在同一时刻机械臂运动中产生的时间错位会使标定结果出现系统性偏差。解决方法是让机械臂到达每个位姿后停顿 0.5 到 1 秒再采集或者提高采集线程的同步精度。7.3 逆解失败怎么办现象目标点在机械臂可达范围内但在 RViz 里规划失败提示 IK 无解或运动轨迹越界。常见原因包括抓取姿态定义得不合理比如末端始终要求竖直向下而目标在工作台边缘机械臂的腕部关节已经进入奇异区。解决方法是允许抓取方向在一定范围内小幅度倾斜或者调整预抓取点位置使机械臂以更合理的姿态进入目标点。另外set_pose_target指定的目标位姿如果带有微小误差也可能导致逆解失败可以适当放宽位置和姿态容差。7.4 机械臂无法接收指令的排查顺序现象驱动节点启动报错或者程序下发指令后机械臂无反应。排查顺序先看机械臂控制柜状态确认处于远程模式且未急停再看工控机与机械臂的网络连通性用ping测试最后检查驱动节点 log确认是否成功建立 TCP 连接。如果连接正常但指令无响应多半是运动指令格式问题例如末端连杆名称不对或者目标位姿超出运动范围。Aubo 控制柜默认的安全保护逻辑会拒绝超出关节限制的目标所以指令下发前最好先做一次关节范围预检。8. 一点个人体会整套项目跑通下来我最大的感触是视觉抓取的难点不在单个环节而在环节之间的坐标系和时序衔接。标定结果差一点点目标识别再准也会在抓取时放大成厘米级偏差点云预处理做不好识别算法再先进也拿不到干净的输入。所以调试时一定要建立清晰的验证习惯每完成一个环节就单独验证不要等整条链路搭完再排查问题。最后聊一个使用细节D435i 的深度相机对黑色、吸光材质和透明物体的深度恢复效果很差这是主动立体视觉的物理特性决定的算法再优化也有限。实际抓取时尽量选择颜色较浅、表面不反光的物体作为初期测试目标待流程稳定后再扩展到更复杂的材质。另外夹爪的指尖最好有一些弹性材料能够补偿末端位置和实际抓取点之间几毫米的偏差这个小改动能让成功率上升不少。希望这份实践记录能帮你少走一些弯路。如果拿到源码想扩展可以尝试从单个物体抓取升级到多物体分类拣选或者把固定 eye-to-hand 改成相机随动的抓取方案无非是在标定环节多做一些工作整体的处理框架是通用的。本文还有配套的精品资源点击获取