Bootstrap

kinova与intel realsense D435手眼标定

背景

最近在做机器人抓取的相关研究,卡在手眼标定这一块了。网上也有一些大佬的博客在写,不过没有看到realsensekinova的相关实验。小弟在此试错一周,奉上此博客,希望对有需要的小伙伴有所帮助。标定大概是,先启动编写完成的launch文件(相机,机器人,moveit,easy_handeye等),然后手动采集20个点,计算得到机器人base到相机的坐标变换关系,然后进行save,会被默认保存在~/.ros/easy_handeye文件夹下的一个yaml文件,然后进行publish就可以将而这的坐标变换发布到tf中。

标定过程

机器人的手眼标定主要参考开源项目easy_handeye,我再稍微罗嗦一下步骤,需要具备一下几个方面的内容。

easy_handeye

cd ~/catkin_ws/src  # replace with path to your workspace
git clone https://github.com/IFL-CAMP/easy_handeye

cd ..  # now we are inside ~/catkin_ws
rosdep install -iyr --from-paths src


catkin build

需要先进行rosdep。这个过程我就报错了

错误1-缺少库transforms3d

rosdep error
解决方案

pip install transforms3d

运行easy_handeye
参考issue,需要先将calibrate.launch文件中的第十三行move_group的default value改为arm,如下

<arg name="move_group" default="arm"  doc="the name of move_group for the automatic robot motion with MoveIt!" />

这里需要编写一个launch文件,启动相机机器人moveit-kinova,以及easy_handeye,aruco等工具,我的launch文件放在代码部分

错误2-cv2.CALIB_HAND_EYE_TSAI

这个问题开始怀疑是opencv-python的版本不对,更换了几次,仍然有问题。后在issue74中有大佬给出解决方案,我的解决方案如下
1.首先安装opencv-contrib

python -m pip install opencv-contrib-python

2.在cv2.CALIB_HAND_EYE_TSAI报错的文件中作如下修改
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库位置不一样,所以import cv2是从ros的python库环境中导入,而我们的cv2是安装在计算机的python库中,所以需要先屏蔽掉默认的ros库导入,此时python的库已经切换到了计算机的python库。

错误3-Cannot calibrate from current position

这一个错误是由于未能调出image-view,无法采样,但是在rqt中我始终无法找到plugin菜单栏,报错Cannot calibrate from current position最后,不得已,我只能重新开启一个rqt(只需要运行rqt即可),选择空的rqt中的plugin栏目,选择image-view,topic选择**/aruco_track/result**,此时,只要相机视野中有坐标系,就可以进行采样操作了,这个过程由参考链接5得到启发

ros-realsense(d435)

参考ros-realsense自行安装
验证相机可用:

roslaunch realsense2_camera rs_camera.launch

然后就可以看到相机节点信息

kinova机器人ros驱动

参考ros-kinova自行安装
验证机器人可用:

roslaunch kinova_bringup kinova_robot.launch kinova_robotType:=j2n6s300

另还需要moveit工具进行轨迹规划
验证moveit

roslaunch j2n6s300_moveit_config j2n6s300_demo.launch

这个成功就表明在rviz内虚拟机器人与现实中的机器人的状态是同步的,并且可以在rviz中拖动机器人末端,进行轨迹规划(plan)和执行(execute)

重要:以上步骤配置完成可以看到三个图,见参考链接6,却一不可,如果可以手动进行规划,check starting pose那个图不需要使用,只要点击check starting pose没有错误就可。take sample那里也需要没有错误。

publish

采集完成20个点,计算,然后保存,最后进行publish

roslaunch easy_handeye calibrate.launch eye_on_hand:=true

相关代码

kinova_realsense.launch文件

需要注意的几个点(个人建议):
1.aruco
aruco中生成marker,我选择的是ID为14,size为100mm,保存pdf打印出来(对应于launch文件中的两个参数,“marker_size”,“marker_id”)。标定过程中保持marker不动,同时marker要处于平整的桌面上

错误2.几个工具都运行后,通过查看当前的tf变换,查看具体的frame名称
查看tf变换命令

rosrun rqt_tf_tree rqt_tf_tree

注意参数reference_frame,camera_frame,tracking_base_frame,tracking_marker_frame的value值(我参考easy_handeye作者编写)完成

<launch>
    <arg name="namespace_prefix" default="kinova_d435_handeyecalibration" />
 
    <!--<arg name="robot_ip" doc="The IP address of the UR5 robot" />-->
 
    <arg name="marker_size" value="0.1" />
    <arg name="marker_id" value="14" />
 
    <!-- start the Kinect -->
    <!--<include file="$(find realsense2_camera)/launch/ggcnn_points.launch" >-->
        <!--&lt;!&ndash;<arg name="depth_registration" value="true" />&ndash;&gt;-->
    <!--</include>-->

    <!-- <arg name="camera_frame" default="camera_rgb_optical_frame"/> -->
    <!-- <arg name="reference_frame" default="camera_rgb_optical_frame"/> -->
    <!-- <arg name="camera_marker" default="camera_link"/> -->
    <!-- start the Camera -->
    <include file="$(find realsense2_camera)/launch/rs_camera.launch" >
    </include>
 
    <!-- start ArUco -->
    <node name="aruco_tracker" pkg="aruco_ros" type="single">
        <remap from="/camera_info" to="/camera/color/camera_info" />
        <remap from="/image" to="/camera/color/image_raw" />
        <param name="image_is_rectified" value="true"/>
        <param name="marker_size"        value="$(arg marker_size)"/>
        <param name="marker_id"          value="$(arg marker_id)"/>
        <param name="reference_frame"    value="camera_link"/>
        <param name="camera_frame"       value="camera_depth_optical_frame"/>
        <!--<param name="camera_frame"       value="_color_optical_frame"/>-->
        <param name="marker_frame"       value="camera_marker" />
 
    </node>
 
    <!-- start the robot -->
    <include file="$(find kinova_bringup)/launch/kinova_robot.launch">
    </include>
    <include file="$(find j2n6s300_moveit_config)/launch/j2n6s300_demo.launch">
    </include>
 
    <!-- 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="camera_link" />
        <arg name="tracking_marker_frame" value="camera_marker" />
        <arg name="robot_base_frame" value="j2n6s300_link_base" />
        <arg name="robot_effector_frame" value="j2n6s300_link_6" />
        <!--disable automatic robot movement-->
        <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>

结果

最终标定结果

手眼标定结果

最终发布的tf变换

标定完成的tf变换

参考链接

参考链接1:kinova与kinect手眼标定1
参考链接2:kinova与kinect手眼标定2
参考链接3:easy_handeye issue19
参考链接4:easy_handeye issue74-对于我的问题解非常重要,其实就是我提的issue啦啦啦
参考链接5:rqt-plugin师兄的博客博客
参考链接6:师弟的博客

;