天天看點

ROS與Navigation之0--TF基礎知識

如下圖所示,在機器人身上各關節,轉輪中心都有一個坐标系,在機器人外部應該還會有其他的坐标系,如地圖坐标系,全局坐标系。tf庫的目的是實作系統中任一個點在所有坐标系之間的坐标變換,也就是說,隻要給定一個坐标系下的一個點的坐标,就能獲得這個點在其他坐标系的坐标。

ROS與Navigation之0--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消息,來維護一棵完整的樹,并且,還要負責搜尋這棵樹,找到一條變換的路徑,然後乘呀乘,并且每次都要如此。

ROS與Navigation之0--TF基礎知識

        上圖例子描述了三個參考系之間的聯系。三個節點分别是三個參考系,而/world是其他兩個烏龜參考系的父參考系。還包含一些調試需要的發送頻率、最近時間等資訊。tf提供了一個tf_echo工具來檢視兩個廣播參考系之間的關系。我們可以看一下第二隻烏龜坐标在第一隻烏龜坐标系的關系:

ROS與Navigation之0--TF基礎知識
ROS與Navigation之0--TF基礎知識

上圖是在前一個圖的基礎上增加了一個坐标系,這個坐标系是在turtle1下面的,也就是說,carrot1坐标系是建立在turtle1坐标系基礎上的,或者說tb釋出的是一個turtle1坐标系到carrot1坐标系的變換。 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.csdn.net/hcx25909/article/details/9255001

http://blog.exbot.net/archives/1686

https://www.ncnynl.com/archives/201708/1881.html

http://blog.csdn.net/start_from_scratch/article/details/50762293

https://www.cnblogs.com/xialuobo/p/6097806.html

http://www.sohu.com/a/201994780_715754(重要)