ARTICLE DETAIL

资讯详情

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

auboi5机械臂与D435i相机手眼标定实战:基于easy_handeye的完整指南

auboi5机械臂与D435i相机手眼标定实战:基于easy_handeye的完整指南 1. 项目概述与核心需求解析先介绍一下这个项目的整体情况。这里的核心任务非常明确auboi5机械臂配合Intel RealSense D435i深度相机做手眼标定使用了ROS社区里很常见的easy_handeye标定工具包。最终目的是搞清楚机械臂末端坐标系和相机坐标系之间的相对位姿关系也就是求外参矩阵。只有把这个外参标准了后面才能做视觉引导抓取、物体定位、避障这一系列下游应用。很多刚接触机器人和视觉融合的工程师一听到“手眼标定”头就大了。其实你把它拆开看本质就是解决一个“我的手到底有多准”的问题。机械臂知道自己各个关节的角度能算出末端执行器在世界坐标系的位姿相机能看到目标物体知道目标在相机坐标系的位姿。但这两个坐标系之间缺一个桥梁桥梁就是我们要标定的外参。标定完了相机“看到”的坐标才能换算成机械臂“够得着”的坐标整套系统才真正闭环。这个项目适合谁第一类是刚入门机器人视觉、准备做抓取项目的研究生和工程师第二类是已经在用easy_handeye但被各种报错和奇怪现象卡住的人。我会从原理、实操、踩坑三个层面完整梳理把我在实际标定过程中记录的问题、排查思路和最终解决方案都拿出来分享。标定这件事看似容易——把标定板往那一放采十几组数据跑一下就好了——但真正上手你就会发现坑全藏在细节里机械臂和相机的驱动冲突、TF树不完整、数据采集时手抖了一下导致结果偏差、aruco码识别率低……每一个都能让你折腾一整天。我用的环境是Ubuntu 18.04 ROS Melodic机械臂是遨博auboi5协作机械臂相机是Intel RealSense D435i。这套组合在实验室里非常常见所以如果你和我的环境接近直接对照操作就行。1.1 两种手眼模式的核心区别在手眼标定里首先要搞清楚你的系统属于哪种结构模式。很多人在这一步就懵了因为easy_handeye 支持两种模式eye-in-hand和eye-to-hand。eye-in-hand眼在手上相机安装在机械臂末端跟着机械臂一起动。标定板固定在世界某个位置不动。这种方案适合机械臂需要“凑近看”的场景比如抓取时相机要移到目标上方。eye-to-hand眼在手外相机固定安装在外部支架上机械臂末端装标定板用机械臂带着标定板在相机视野里摆姿势。这种方案适合监测全局场景比如工作台面整体监控。auboi5配D435i最常见的组合是eye-in-hand因为D435i体积小、重量轻挂在机械臂末端不构成多大的负载负担。我这次也是用 eye-in-hand 模式来做的。很多人问两种模式选哪种求解算法不一样吗其实easy_handeye底层调用的都是经典的Tsai-Lenz或者Park-Martin之类的AXXB求解方法。公式很直观机械臂末端的位姿变化A乘以相机外参X等于相机位姿变化B乘以外参X。求解这个矩阵方程X就是我们想要的外参。你只要记住一点不管哪种模式输入的都是机械臂末端位姿和相机观测到的标定板位姿只是数据的采集方式不同。1.2 为什么选择easy_handeye工具包市面上手眼标定工具有不少ROS里还有 handeye_calibration_calibrator商用软件里也有VisionPro、Halcon之类的标定模块。为什么我推荐easy_handeye有几点实际原因。第一它和ROS生态无缝集成。它基于rviz可视化界面操作能实时显示标定板的检测状态、机械臂和相机的TF树关系。你不需要自己去写数据记录和求解的程序采集够一定数量的点位后一键就能算出结果。第二它支持aruco码和棋盘格两种标定板。aruco码的优势是单张图片就能提供完整的位姿信息且检测鲁棒性非常好棋盘格的优势是角点精度高但需要所有角点完整可见才能解算位姿。实际操作中aruco码方便很多因为机械臂运动时会抖动棋盘格容易被部分遮挡导致检测失败。第三有图形化的数据管理。它能保存每一次采集的机械臂位姿和相机观测位姿方便排查哪些数据点是离群值。这一点非常重要因为手眼标定对数据质量极其敏感——一两组差数据就能让最终结果偏移好几毫米。2. 环境准备与工具链部署2.1 驱动安装与版本兼容性在开始标定之前环境配置是第一道坎。auboi5需要使用遨博官方提供的ROS驱动包D435i则要用realsense-ros包。这两个东西单独用都没问题但放在同一个ROS工作空间里编译时偶尔会遇到依赖冲突。我的建议是使用独立的ROS工作空间分别编译然后用source叠加的方式加载。比如主工作空间是catkin_ws存放auboi5的驱动和各种自定义功能包另一个工作空间realsense_ws专门放realsense-ros和相关依赖。这样两边互不干扰编译顺序也不会出问题。具体编译步骤大致如下# 编译auboi5驱动工作空间 cd ~/catkin_ws catkin_make source devel/setup.bash # 编译realsense工作空间 cd ~/realsense_ws catkin_make source devel/setup.bash # 每次新开终端时把两个工作空间都source上 echo source ~/catkin_ws/devel/setup.bash ~/.bashrc echo source ~/realsense_ws/devel/setup.bash ~/.bashrc有个细节需要注意easay_handeye 这个包最好放在主工作空间里编译因为它需要依赖你定义的机械臂URDF模型、move_group等接口。编译前先确认能不能正常打开rviz并显示auboi5的模型。2.2 标定板的制作与内参准备标定板是精度的重要来源之一。easy_handeye默认支持aruco码你不需要自己生成它会在aruco_ros包里提供现成的标定板但你也可以自己用在线生成器生成一个PDF打印出来。打印时有几个注意点纸张要平整最好贴在硬质塑料板或者亚克力板上别直接贴在纸板上。翘边会导致位姿解算偏差。一格的实际边长要量准。标定板参数里的marker_size是单格的边长如果量错1毫米最终外参会偏出好几毫米。我习惯用游标卡尺量三个不同位置的格子取平均值确保误差在0.1毫米以内。分辨率要高。用激光打印机打印不要用喷墨喷墨容易晕染导致边缘模糊。相机内参这块easy_handeye不会替你做需要提前单独标定。D435i虽然有出厂内参但为了精度还是建议用ROS的camera_calibration工具重新标一遍。标定方法很成熟打印一张棋盘格用roslaunch realsense2_camera rs_rgb.launch打开彩色流然后用camera_calibration节点标定rgb内参。rosrun camera_calibration cameracalibrator.py --size 8x6 --square 0.025 image:/camera/color/image_raw camera:/camera/color这里--size 8x6是内角点数--square 0.025是棋盘格每格边长单位米。采集足够多不同姿态的图片后点击CALIBRATE系统会自动生成内参矩阵和畸变系数。务必把标定结果保存下来后面在easy_handeye的launch文件里直接指定内参文件路径否则默认内参不准会导致标定结果偏差。2.3 easy_handeye安装与launch文件配置easy_handeye 在ROS Melodic下的源码安装很直接cd ~/catkin_ws/src git clone https://github.com/ros-vision-ros/easy_handeye.git cd .. rosdep install --from-paths src --ignore-src -r -y catkin_make安装完成后最关键的是配置launch文件。easy_handeye提供了两种标定启动方式handeye_calibration.launch和handeye_calibration_target.launch。前者用于eye-in-hand相机在手上后者用于eye-to-hand相机在外。我们这里用的是前者。launch文件里需要改几项核心配置launch !-- 相机组 -- arg namecamera_namespace default/camera / arg namecamera_color_topic default/camera/color/image_raw / arg namecamera_info_topic default/camera/color/camera_info / !-- 标定板 -- arg namemarker_size default0.032 / arg namemarker_id default100 / !-- 机械臂组 -- arg namerobot_urdf default$(find my_aubo_description)/urdf/auboi5.urdf / arg namerobot_base_frame defaultbase_link / arg namerobot_effector_frame defaulttool0 / arg namecallback_thread default2 / /launchmarker_size你务必填标定板单格的实际边长单位是米。marker_id要和标定板上的id对应。robot_effector_frame填auboi5的末端工具坐标系遨博默认一般是tool0如果你修改过TCP记得要用自建的坐标系名。3. 标定实操流程与关键环节3.1 启动完整标定链路所有驱动准备好之后需要一个接一个地启动节点。启动顺序有讲究我踩过几次坑之后总结了一套标准流程第一步启动机械臂驱动和move_grouproslaunch aubo_driver aubo_driver.launch robot_ip:192.168.1.100 roslaunch aubo_moveit_config move_group.launch注意 aubo_driver 的IP要改成你实际机械臂控制柜的IP地址。move_group不是标定必需的但如果你希望在rviz里拖拽示教规划运动还是建议开着。第二步启动D435i相机roslaunch realsense2_camera rs_camera.launch如果你发现彩色图像有延迟或异常可以在launch里加align_depth:true开启深度对齐但标定只需要彩色图像所以实际不必开。第三步启动easy_handeye标定节点roslaunch easy_handeye handeye_calibration.launch启动后rviz里会加载机械臂模型和一个标定板跟踪窗口。如果一切正常你能在rviz中看到相机图像上叠加了aruco码的坐标轴。3.2 数据采集的策略与技巧这一步是整个标定过程中最考验耐心的环节。easy_handeye的工作流程是你控制机械臂运动到某个位姿让标定板出现在相机视野的某个位置然后在界面上点击“Plan”规划末端运动、点击“Execute”执行、之后点击“Take Sample”采样。重复十几二十次最后点击“Compute”求解。我第一次做这个标定随便采集了十几个点运动范围很小结果外参误差有2厘米还多。后来总结了几个关键策略标定误差直接降到了毫米级覆盖整个视野不要让标定板一直待在画面中心。要让它在画面的九个区域都出现过左上、中上、右上、中间、左下、中下、右下等这样能充分约束相机的所有内参数和外参数。变动姿态而非位置机械臂末端除了平移变化一定要大幅改变姿态即改变末端绕x、y、z轴的旋转角。如果姿态不变AXXB方程在旋转分量上自由度不足解出来会很飘。标定板与相机平面夹角要有一定倾斜不要总让标定板正对相机夹角约30度、45度都可以倾斜姿态能提供更多有效约束。运动要平滑采集要稳定机械臂运动到位后等模型在rviz中完全稳定下来再点击take sample。机械臂停止后其实还有微小抖动最好加一个短暂延时。实际操作中我一般采20到25组数据每一组都换一个姿态确保数据点分布足够分散。3.3 求解参数验证与结果判断全部数据采集完成后点击“Compute”easy_handeye会弹出求解结果并按四种算法分别输出。常用的是OpenCVTsai-Lenz、OpenCVPark-Martin、MATLABDanillidis等。界面会显示每个算法的误差通常以像素为单位。我个人习惯取OpenCV的Tsai-Lenz结果作为最终外参再手动验证一下用rviz里的“Publish”按钮把外参发到TF树然后让机械臂末端移动到标定板上方某个点用相机检测标定板中心位置换算到机械臂坐标系下和实际末端位置对比。简单验证命令# 发布外参到TF rosrun tf2_ros static_transform_publisher x y z yaw pitch roll camera_link tool0然后看机械臂末端在rviz中是否“贴”在标定板的中心上。误差小于5毫米基本可接受小于2毫米算非常好了。还有一种快速验证方法让机械臂带着相机在不同距离观察同一个点外参如果正确该点在机械臂坐标系下的坐标应基本不变。如果位置漂移很大说明外参不准需要重新标定或者排查数据质量。4. 常见问题与排查技巧实录4.1 aruco码检测不稳定这是最常见的现象标定板明明在视野里但rviz里就是显示不出坐标轴或者检测框一直在闪烁。排查步骤从易到难检查marker_size是否和实际尺寸一致。实际尺寸30mm但你参数填了32mm检测虽然能解算但位姿会整体放大或缩小。把相机分辨率降低到640x480再试试。D435i在1280x720下aruco检测对模糊和反光非常敏感降分辨率之后识别率明显上升。检查光环境过于强烈的直射光或反光会让边缘提取失效尽可能用柔和的漫射光照明。4.2 标定结果跳变异常大如果你两次标定结果差了好几厘米大概率是以下几个原因问题现象可能原因解决方案两次标定结果差5cm以上机械臂URDF中的tool0定义错误检查robot_effector_frame是不是真正的TCP误差指示小但实际验证偏差大数据点姿态变化不够增加大幅旋转姿态的数据点每次Compute结果略有漂移数据点采集时末端有抖动运动完成后等待2-3秒再采样验证时机械臂碰不到目标相机内参标定偏差大重新标定相机内参并加载正确文件还有一个容易被忽略的问题机械臂的轨迹插值方式。有些机械臂默认走关节空间插值末端路径可能画弧线但如果采集时刻末端位姿是通过URDF正确读出的就不影响标定结果。反而是如果你在机械臂运动中添加了工具坐标系补偿比如末端装了气爪但没改TCP会造成系统性偏差。4.3 TF树不完整导致变量报错easy_handeye运行时报Lookup would require extrapolation into the past这类TF相关的错误很常见。这说明它需要的坐标变换关系中某个父系坐标没连上。排查方法rosrun tf2_tools view_frames.py生成TF树PDF重点看base_link-tool0这条链是否连续以及camera_link是否有父系。如果没有你需要给相机模型添加一个静态TF比如camera_link挂载到tool0下就算初始外参未知也先用零值占位这样easy_handeye才能构建完整的变换链。node pkgtf2_ros typestatic_transform_publisher namecamera_tf args0 0 0 0 0 0 tool0 camera_link /4.4 求解报错但数据看起来正常有几次我遇到点击Compute之后报Not enough valid samples或者解算失败。这时需要检查是否有离群数据点。easy_handeye界面里可以逐条查看数据对应每一条数据你能看到重投影误差。一个很实用的操作把误差明显偏大的那几组数据删掉重新计算。因为机械臂在某个位姿可能抖动太大或者标定板被部分遮挡检测出的位姿质量差。保留的数据点不用多15到20组干净数据的效果远好于30组里混了几个脏数据的结果。4.5 标定板坐标系与机械臂坐标系不一致最后想强调一点标定板放在桌上时它的坐标原点在世界坐标系的哪个位置其实无所谓因为手眼标定求的是两个坐标系之间的相对变换不是绝对位置。但如果标定板在采集过程中移动了位置比如被碰了一下那这组数据就废了。所以实际操作中标定板一定要固定好建议用重物压住或用双面胶固定在工作台上。5. 精度验证与后续扩展思路5.1 用实际抓取验证标定结果标定完成后纸上算出来的误差再小最终还是要看实际能不能用。我习惯做一个简单的引导抓取测试在工作区放置一个已知尺寸的方块用D435i识别它的中心坐标然后通过标定得到的外参换算到机械臂坐标系下控制auboi5末端移动到该坐标。如果抓取位置偏移不超过5毫米这个标定结果就可以放心投入使用了。如果发现偏移呈线性增长比如距离相机越远偏差越大通常问题出在相机内参上需要回头重新标内参。如果偏移是固定的大约几厘米那大概率是外参的平移分量有误可能是数据采集时标定板没固定好或者机械臂TCP和URDF定义不一致。5.2 从手眼标定到视觉伺服标定完成之后你获得的不仅仅是一组外参数值更是一条完整的视觉-机械臂闭环通路。接下来可以做的事情非常多基于D435i的深度信息实现目标物体3D定位与抓取配合MoveIt的规划能力做动态避障和轨迹规划加一个物体检测模型如YOLO把检测框的中心像素坐标通过相机内参和外参映射到机械臂坐标系实现“识别-定位-抓取”全流程自动化。我个人在实际操作中的体会是手眼标定就是一个不断和误差做斗争的过程所有误差源都不可忽略相机内参不准、标定板不平整、机械臂末端抖动、数据采集覆盖不够。但只要你耐下心把每个环节逐一排查干净标定精度完全可以达到毫米级后面做视觉引导项目会省心非常多。最后再分享一个小技巧标定完成后把外参写进URDF的xacro文件里替换掉原来占位的tf树之后每次启动都不用重新发布静态外参整个系统干净利落。
返回列表