接着上述的工作,在将近一个月的摸索实践中,终于完成了抓取的工作。其中包含tf坐标系的转换以及最后位置的调试工作。
这一篇先讲述如果进行根据camera_link以及base_link之间的转换关系完成一个点、一组点的进阶坐标转换。接着之前的手眼标定,连接起相机以及机械手臂的tf_tree.
#rosrun rqt_tf_tree rqt_tf_tree
这里要注意在camera_link中包含的子树camera_rgb_optical_frame以及camera_rgb_frame两个坐标系是不同的,从rviz里面来看其position大致重合,但是orentation是不一样的,而且相机检测到的可乐罐的位置坐标所属是在camera_rgb_optical_frame下的,所以在转换过程中(TF点的transform)一定要注意函数里面的参数是什么意思,坐标系代表的是哪一个坐标系,不然不清不楚在后面的位置标定过程中会出现很多错误。
开始tf转换过程的总结。首先当然是参考的我们官网教程,不可否认,虽然在他人的csdn博客可以学到或者拿到想看的内容,但是相比之下还是官网内容比较详细,如果某句程序、函数不懂可以很快的理解并修改。下面是核心的subscriber以及publisher(c++版本以及python版本)
http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29
http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28python%29
以及依然可以替代参考的几篇csdn博客
https://blog.csdn.net/Will_Ye/article/details/79485964
https://blog.csdn.net/start_from_scratch/article/details/50762293/
https://blog.csdn.net/Will_Ye/article/details/79996311
由开发流程来看,首先要查看所要得到的物体位置信息(如何挖数据),接着要转换一个点从camera_link到base_link下,接着便是将物体的实时位置从camera_rgb_optical_frame到base_link坐标系下面。
这里插一个在pyhon里面查看所用到的函数:
ipython()
help(tf.TransformBroadcaster.sendTransform)
可以查看该函数的参数及相关信息。
-----------------------------------------------------1---------------------------------------------------------
1.查看物体位置信息:
之前已经提到RecognizedObjectArray这个数组存放的是物体的位置信息,包括position orentation 以及header等等。这个数组是linemod算法在识别到物体位置以后将位置存储到这里(并且以话题的形式publish消息,所以我们能在rviz里面看到物体的标定位置)
下面是之前定义存放识别到物体信息存放的数组位置listener.py(写的一个简单的判断打印物体信息的位置)
#!/usr/bin/env python
#coding=utf-8
import rospy
# from std_msgs.msg import String
from object_recognition_msgs.msg import RecognizedObjectArray
def callback(data):
if len(data.objects)>0:
print "coke detected~~~~~~~~~~~~~~~~~~~~"
rospy.loginfo(rospy.get_caller_id() + 'heard %s', data.objects[0].pose.pose.pose)
# rospy.loginfo(rospy.get_caller_id() + 'heard %s', data.objects[0].pose)
else:
print "nothing detected................."
def listener():
# In ROS, nodes are uniquely named. If two nodes with the same
# name are launched, the previous one is kicked off. The
# anonymous=True flag means that rospy will choose a unique
# name for our 'listener' node so that multiple listeners can
# run simultaneously.
rospy.init_node('listener', anonymous=True)
rospy.Subscriber('recognized_object_array', RecognizedObjectArray, callback)
# spin() simply keeps python from exiting until this node is stopped
rospy.spin()
if __name__ == '__main__':
listener()
---------------------------------------关于import-----------------------------------------
from A模块 import B函数=import A 使用A.B(参数)。要注意的是虽然使用from import以后不需要在函数名加前缀,但是B函数只默认是A模块的函数(如果同名的话),这样同名但是分属不同模块 不同功能的函数就会造成冲突。所以优先使用import ,之后使用 A模块.B函数(C参数)的形式。
------------------------------------------------------------------------------------------------
这个程序只是打印物体的位置信息并且加了一个简单的判断,让我们来看为什么要这样写(怎么来挖数据)。挖数据核心主要是rospy.Subscriber('recognized_object_array', RecognizedObjectArray, callback)用来订阅RecognizedObjectArray话题并且一旦接收到消息就调用回调函数callback。而另一句打印 rospy.loginfo(rospy.get_caller_id() + 'heard %s', data.objects[0].pose.pose.pose) ,前面的id没什么用,后面的回调函数先判断是不是空的内容(是否识别到物体),data指代了RecognizedObjectArray的所有信息,也就是一个形参。用下面的命令来查看数据:
#rosmsg show RecognizedObjectArray
用来查看发布的消息的类型以及包含的内容
这样来看data=RecognizedObjectArray,然后data.object[]=RecognizedObjectArray[],也就是指向消息的第二个变量object[]数组,如果用object[0]代表取当前检测到的第一个物体位置信息的数组信息。继续挖,data.object[]=RecognizedObjectArray[]包含了几个对象,比如header、type、confidence、pose(未截到图)等等以及他们对应的数据类型。运行listener来继续看
#rosrun ur10_rg