整个过程分为以下三步
- aruco_ros 的配置使用
- easy_handeye 的配置使用
- 标定过程
aruco 的配置使用
- clone aruco 项目 到 ros 工作空间。
- 前往 aruco marker 生成网站 打印 marker,注意:一定要选择original,其它版本的检测不出
- 修改 single.launch 文件(如果要使用多 marker,请自行配置)。下面是我的 single.launch 文件,可做参考,我会将每个参数说明。
<launch>
<arg name="markerId" default="582"/>
<arg name="markerSize" default="0.1"/> <!-- in m -->
<arg name="eye" default="left"/>
<arg name="marker_frame" default="camera_marker"/>
<arg name="ref_frame" default=""/> <!-- leave empty and the pose will be published wrt param parent_name -->
<arg name="corner_refinement" default="LINES" /> <!-- NONE, HARRIS, LINES, SUBPIX -->
<node pkg="aruco_ros" type="single" name="aruco_single">
<remap from="/camera_info" to="/camera_info" />
<remap from="/image" to="/image_raw" />
<param name="image_is_rectified" value="True"/>
<param name="marker_size" value="$(arg markerSize)"/>
<param name="marker_id" value="$(arg markerId)"/>
<param name="reference_frame" value="stereo_gazebo_left_camera_optical_frame"/> <!-- frame in which the marker pose will be refered -->
<param name="camera_frame" value="stereo_gazebo_left_camera_optical_frame"/>
<param name="marker_frame" value="$(arg marker_frame)" />
<param name="corner_refinement" value="$(arg corner_refinement)" />
</node>
</launch>
- /camera_info: 填入相机的内参 topic,这个topic一般由启动相机的节点发布,例如我用的是 uvc_camera 启动相机,他就会发布相机内参 topic。
- /image: 图片 topic,同样我的也是由 uvc_camera 发布的,要填什么具体看你这个节点的名字。
- reference_frame: marker 坐标系的参考坐标系,我们要获得的是marker 和相机的相对位姿,所以这里设置为相机坐标系,即和 camera_frame 一样。
- camera_frame: 相机坐标系,随便写个名字
- marker_frame:marker 坐标系,随便写个名字
easy_handeye的配置使用
- clone easy_handeye项目 到 ros 工作空间。
- 在 easy_handeye/docs/example_launch 文件夹下复制一份 launch 文件到 easy_handeye/easy_handeye/launch 文件夹下。这里注意一下,你可以将启动机械臂、相机、aruco、easy_handey的程序放到一个launch文件下一起启动(如 easy_handey 给的 example),也可以分别启动。为了清晰,我选择分开启动。所以这个复制的 launch 文件中我删去了启动机械臂和 aruco 的部分,只剩下启动手眼标定的部分。
- 修改复制的 launch 文件。下面是我的该 launch 文件的配置
<launch>
<arg name="namespace_prefix" default="aubo_kinect_handeyecalibration" />
<!-- start easy_handeye -->
<include file="$(find easy_handeye)/launch/calibrate.launch" >
<arg name="namespace_prefix" value="$(arg namespace_prefix)" />
<arg name="eye_on_hand" value="true" />
<arg name="tracking_base_frame" value="stereo_gazebo_left_camera_optical_frame" />
<!-- camera_marker -->
<arg name="tracking_marker_frame" value="camera_marker" />
<arg name="robot_base_frame" value="base_link" />
<arg name="robot_effector_frame" value="wrist3_Link" />
<arg name="freehand_robot_movement" value="false" />
<arg name="robot_velocity_scaling" value="0.5" />
<arg name="robot_acceleration_scaling" value="0.2" />
</include>
</launch>
- eye_on_hand: true 时相机在机械臂上,marker固定。反之相反。
- tracking_base_frame: marker的坐标系的参考坐标系,这里写相机坐标系的参考坐标系,也就是相机坐标系。
- tracking_marker_frame: marker 坐标系,即 aruco 设置的 marker_frame
注意: 看似这些坐标系设置的挺乱,他的原则就是,这些坐标系放在一起组成一个集合,其中每个坐标系要能通过其他坐标系,得到每个坐标系之间的相互转换关系。所以上述两个launch文件提到的坐标系写法可以有很多,我选择了比较简单的。
标定过程
依次启动机械臂、相机、aruco、easy_hand。没问题就会出现三个在启动 easy_handeye 后会出现三个窗口。
- 将机械臂移动至 marker 在相机中出现(你可以使用rqt_image_view image:=(image的topic),rqt窗口里选择 aruco_ros/result–好像是这个名字…),就能看见图片和检测结果。
- 点击 check starting pose ,这步是确定marker 相对于相机的位姿。
- 你可以使用 easy_handeye 的自动化程序来移动机械臂标定,即点击next_pose…。但是这个自动移动机械臂经常时相机照不到marker,我建议手动移动机械臂,移动到哪?后面我会写出注意点。移动到合适的位置后,点击 take_sample。
- 获得一些sample后,点击 compute 就能看到标定结果了。
如何移动机械臂获取sample
easy_handeye 作者给出建议:
- Maximize rotation between poses.
- Minimize the distance from the target to the camera of the tracking system.
- Minimize the translation between poses.
- Use redundant poses.
- Calibrate the camera intrinsics if necessary / applicable.
- Calibrate the robot if necessary / applicable.
这就好了吗??
如果真这么容易就好了!
问题即解决方案
- ’module’ object has no attribute 'CALIB_HAND_EYE_TSAI’
将 handeye_calibration_backend_opencv.py 文件中 import cv2 改为
import sys
sys.path.remove('/opt/ros/kinetic/lib/python2.7/dist-packages')
import cv2
sys.path.append('/opt/ros/kinetic/lib/python2.7/dist-packages')
这个问题是由于 ros 安装的 python 和自己系统中安装的 python 调用时出问题,具体什么问题?我不知道。出处
如果还不行,卸载掉opencv相关包,重新安装opencv_contrib_python。如python版本也是2.7的话,将其版本指定 “==4.2.0.32”,具体支持见 opencv-python版本对应
- xxx and xxx not part of the same tree.Tf has two or more unconnected trees.
这个问题是这两个坐标系不能联系起来,即一个坐标系通过已知的坐标系,求得另一个坐标系。一般是 aruco 中 reference_frame 和 camera_frame 设置不对,把这两个设为一样通常可解决。同时easy_hanyeye 里复制的launch文件中要参考 single.launch 设置对。
- Requested time xxx but the latest data is at time xxx…
代码问题,将easy_handeye 中文件 handeye_sample.py 65行(左右)time = Time.now() 改为 time=Time(0)
可能有些问题忘了,一些细节没说清楚,请大家评论区批评指正。有问题评论我会回复。