如下图所示,在机器人身上各关节,转轮中心都有一个坐标系,在机器人外部应该还会有其他的坐标系,如地图坐标系,全局坐标系。tf库的目的是实现系统中任一个点在所有坐标系之间的坐标变换,也就是说,只要给定一个坐标系下的一个点的坐标,就能获得这个点在其他坐标系的坐标。
假设有n个坐标系,那么他们之间的组合关系有c(n,2)个,如果n=4,那就是6种,如果n=100,那就是4950个,好多呀。不过,世界没那么复杂,我们可以给这些坐标系之间构建一个结构,比如单叉树或者单层多叉树,那么100个坐标系之间的关系,就可以用99个树杈搞定。tf里的选择则是多层多叉树。
维护一颗树,需要先设计一个树的结构,也就是一定要在树被风吹来吹去变换的时候,让小树杈找个大树杈依附,让大树杈找个树干依附,让树干有个根固定(所谓变换,就是找到俩树枝变换之间的通路,这个通路很可能要先找到根,再从根找到目标树枝)。(如果打算用tf解决你的坐标变换问题,请一定要先清晰的画出这棵树的结构,再开始写程序;因为这个结构是维护和使用的基础)。
那么该如何使用这棵树呢?如,坐标系a到坐标系b的变换是什么呢?很简单,用tf的tflisener监听某一个指定的从一个a frame到b frame的变换即可,当然前提是树上的树杈们能把a,b联通,并已经准备好。再重复一次,这个变换是a frame到b frame的变换,也表示了b frame在a frame的描述,也代表了把一个点在b frame里的坐标变换成在a frame里的坐标的坐标变换。有了这个变换,你就可以尽情的变换了。
这个结构的建立和维护靠的是tf提供的tfbroadcastor类的sendtransform接口。在tb第一次发布一个从已有的parent frame到新的child frame的坐标系变换时,这棵树就会添加一个树枝,之后就是维护。这里,提醒一下,在用tf时,一定要细心照料整棵大树,时刻保持这棵大树能够描述整个外部世界里的关系,不能有断裂。这样才能保证在风吹时,整个树都摆来摆去还保持稳定。
TF的实现的基本原理是,tb的类(broadcastor)里有个publisher,tl的类(listener)里有个subscriber,前者发布名为/tf的topic,后者订阅该topic,传送的消息tfmessage里包含了parent frameid和child frameid的信息。这个机制意味着,所有的tb会发布某一特定的parent到child的变换,而所有tl会收到所有的这些变换,然后tl利用一个tfbuffercore的数据结构维护一个完整的树结构及其状态。也就是说每一个tb都会广播一个变换,而tl会接收到所有这些变换,而每接收到一个,就要更新自己维护的这个树。基于此,tl在使用这棵树时,会用lookuptransform或waitfortransform来获得任意坐标系之间的变换。非常简单,对吧,但粗暴的也非常显然。那就是只要是一个tl,就要跟所有tb建立连接,就要收取所有的/tf消息,来维护一棵完整的树,并且,还要负责搜索这棵树,找到一条变换的路径,然后乘呀乘,并且每次都要如此。
a、各种数值计算的细节,你不用考虑,tf库可以帮你;
b、接口很简洁,会广播和监听就ok;
c、问题找的很准,那就是需要维护坐标系之间的关系;
d、提供了很多工具程序;
e、考虑了与时间相关的变换;
f、支持tf-prefix,可以在多机器人上用
g、基本能用,且不需要深入理解,死搬硬套就能用起来。
tf库的缺点还是那句话,简单粗暴!
a、树的结构很简单,但有时候很笨拙。举个例子吧。有部电影叫手机,葛优扮演的叫石头,范伟演的叫砖头,两个人是叔伯兄弟,从小到大的小伙伴,应该很熟悉,关系也很明确,但要放到树的结构下,就需要从下到上找共同先辈,然后从这个先辈再往下找,进而确定二者的关系,这个比较笨拙(这是因为tb广播的一般都是一个父坐标系和子坐标系的关系)。于是有了范伟坐在门槛上的一句台词:恁这是弄啥勒,恁奶不是俺奶?!b、每个tl都要维护同一颗树,这样的开销太大,主要是网络传输的负荷比较大。这一点,tf的设计者是完全承认的。举个例子吧,北方的有些地方的农村过年时要拜年,拜年要磕头,磕头的对象是写有逝去的先辈名字的树状图,一个同姓大家族里有很多小家庭,每个家里都有那么一张图,挨家拜年,街上人来人往,每个人都磕了很多头,磕的其实是同一张。如果有个祠堂,集中处理,维护一张图,就不用看到早早起床、满街跑的情况,效率也会高多了。
c、很难满足实时性的要求,这一点比较显然。要不tf也不会每个变换存10秒钟的数据,不过源码里好像是开了一个存100个消息的队列。
d、还有很多细节不易理解。比如,now()和time(0);比如,技术文档里的一些术语名词;比如,采用了机器人里的习惯,与飞行器,惯导,车辆里的习惯区别较大,使用时不能想当然。
参考来源:
http://blog.youkuaiyun.com/hcx25909/article/details/9255001
http://blog.exbot.net/archives/1686
https://www.ncnynl.com/archives/201708/1881.html
http://blog.youkuaiyun.com/start_from_scratch/article/details/50762293
https://www.cnblogs.com/xialuobo/p/6097806.html
http://www.sohu.com/a/201994780_715754(重要)