ros的tf反应了一个机器人系统中,不同坐标系之间的关系。以自动驾驶汽车在一个固定园区内行驶为例,自动驾驶汽车有全局utm坐标,园区内地图坐标,然后车辆还装有激光雷达,摄像头等传感器,这些传感器相对于车辆也有对应的相对坐标。在自动驾驶算法里往往涉及这些坐标的输入输出转换调用等操作,如果不统一管理这些坐标系,那么坐标转换等算法将会带来很大麻烦,也不利于代码管理。所以tf就是为了解决这一痛点,让程序员能轻松的知道自己想要的坐标值。比如,我想知道t0时刻,车上相机相对于园区地图的坐标系的值,有了tf就可以轻松实现。
下图展示的是一个自动驾驶体系里坐标关系图,指令:rosrun rqt_tf_tree rqt_tf_tree

ROS后来又出了tf2,tf2可以看做是tf的扩展,相对于tf来说,tf2引入了相对静态坐标系,如激光雷达在车上安装的位置相对于车辆自身的坐标是恒不变的,那么这就是相对静态坐标系。又如车辆自身坐标系相对于园区地图来说是一直动态变化的,因为车辆在行驶,那么这个就是相对动态坐标系。另外tf2还使用了更多的ROS内置类型,使代码的复用率和可维护性得到了提高。当然代码的接口调用写法也发生了改变。tf2可以实现tf之前所有的功能,然后还加了新功能,但tf2并不是代码层级向下兼容tf的存在。如果之前用tf,现在转tf2,就需要大量重构代码。如果是新项目,那么建议直接使用tf2就可以了。
tf的代码的写法在官网的教学页里已经讲的很详细了
tf教学:http://wiki.ros.org/tf/Tutorials
tf2教学:http://wiki.ros.org/tf2/Tutorials
这里简单按教学目录里说说
Writing a tf2 static broadcaster
这一章教你在tf2里如何广播静态坐标系,frame_id字段代表参考坐标系,child_frame_id字段代表在frame_id参考坐标系下的静态子坐标系
Writing a tf2 broadcaster
这一章教你在tf2里如何广播普通坐标系,frame_id字段代表参考坐标系,child_frame_id字段代表在frame_id参考坐标系下的普通子坐标系,这一章里的broadcaster和上一章里的static broadcaster个人感觉没什么太大写法上的区别,更多的是概念上的区别,以及发布话题的区别,这一章的broadcaster是发布在/tf话题上的,上一章的static broadcaster是发布在/tf_static话题上的。
Writing a tf2 listener
这一章教你在tf2里如何接收想要的坐标系,比如想知道坐标系A的原点在坐标系B下的坐标是什么。
Adding a frame
这一章个人感觉和第2章讲的没什么本质区别,adding a frame其实也是broadcaster a new coordinate frame,和第2章的区别感觉就是第2章的发布的是在全局坐标系下(第0级坐标系)子坐标系(第1级坐标系)。那这一章就是发布在第1级坐标系下的第2级坐标系,在第2级坐标系下的第3级坐标系,等等…
Learning about tf2 and time
这一章教你在tf2里如何等待一个坐标系转换,直到它可用。主要针对ros::Time::now()场景,此场景代表想要现在的坐标,而不是最新的坐标,那现在时刻的坐标可能还没准备好,所以就需要等待,那么如何等待呢,就看这一章是怎么写的就行了。
Time travel with tf2
这一章主要教你了在tf2里,如何获得在过去一个时间点里想要的坐标和相应的坐标转换。
CLI:Command Line Interface, 命令行接口
rosrun rqt_tf_tree rqt_tf_tree: 查看实时的tf树结构
rosrun tf2_tools view_frames.py: 监听5秒,并将tf树存入一个pdf,之后可使用evince frames.pdf来查看该pdf
rosrun tf tf_echo [reference_frame] [target_frame]查看target_frame在reference_frame坐标下的坐标值