ROS中base_link, odom, fixed_frame, target_frame和虛擬大地圖map的關系


前面已經介紹了如何使用URDF建造機器人小車並顯示在Rviz的仿真環境里面,但是小車是靜止的。下面介紹如何讓它在Rviz里面動起來,並理清URDF,TF 和 odom 的關系。

1. ROS中base_link, odom, fixed_frame, target_frame和虛擬大地圖map的關系

一般在urdf文件中都要定義base_link,它代表了機器人的主干,其它所有的frame都是相對於base_link定義並粘在一起的。它們一起相對於大地圖map移動,讓機器人移動就是向tf發布 geometry_msgs::TransformStamped 消息通知ros  base_linke相對於map的tf轉換關系。先看一下這幾個概念在ros中的定義

map

map是虛擬世界中的固定frame, 它的Z軸指向正上方,也就是天空。一個時間點上移動機器人的姿態相對於map不應該出現明顯的漂移。如果一個map是不連續穩定的那就意味着機器人的位置在任何一個時間點上都會是變化的。

一般激光地位儀等設備會連續的計算map的位置因而造成它的不穩定性,這也使它不能成為一個好的參照體frame.

 

odom

 

odom是一個很好的固定世界參照frame.機器人的姿態相對odom而言是隨時間是經常可變,所以在長遠中它不是一個好的全局參照系。但在某一時間點而言它相對機器人的位置是不變的。

典型的 odom frame 是通過運動源來計算出來的, 例如輪子運動,視覺偏移等.

odom frame 的准確性使它在局部參照系中是很有用的。但是不適合作全局參照frame.

各個Frames的關系

frame之間是按樹狀結構組織的。所以每個frame只有一個父節點和任意多個子節點。 上述幾個frame的關系:

map --> odom --> base_link

Frame Authorities

odombase_link的坐標轉換是從運動源計算出來廣播的。

mapbase_link的坐標轉換是被定位模塊計算出來的. 但定位模塊並不發布mapbase_link的轉換. 相反它先接受從odombase_link的轉換, 再計算並廣播mapodom的位置轉換關系。

fixed_frame

RViz中認定的大世界就是fixed_frame

target_frame

Rviz中視覺跟蹤的frame是 target_frame

 

2. RViz如何動態確定各個frame之間的坐標轉換

先看一下啟動RViz的launch文件,里面定要了服務於RViz的參數和node

[html]  view plain copy
 
 
 
  1. <launch>  
  2.     <arg name="model" />  
  3.     <arg name="gui" default="False" />  
  4.     <param name="robot_description" textfile="$(arg model)" />  
  5.     <param name="use_gui" value="$(arg gui)"/>  
  6.     <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />  
  7.     <node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />  
  8.     <node name="rviz" pkg="rviz" type="rviz" args="-d $(find sp1s)/urdf.rviz" required="true" />  
  9. </launch>  
"robot_description" 參數定義了urdf文件的路徑,它被 robot_state_publisher節點使用。該節點解析urdf文件后將各個frame的狀態發布給tf. 因此在rviz里面就看到各個frame(link)之間的tf轉換顯示OK.否則會顯示warning.

 

"joint_state_publisher"節點獲取urdf里面定義的rotate link並發布坐標轉換給tf.否則會顯示warning. 注意:"joint_state_publisher" 是python寫的,只支持ascii編碼,不支持Unicode,如果發現RViz報告下面錯誤:

"No transform from [front_left] to [base_link]"

那就是因為urdf文件是Unicode編碼的。

3. geometry_msgs/TransformStamped 消息的作用和機構

geometry_msgs/TransformStamped  就是通知ROS 兩個frame之間的tf轉換關系。當兩個frame之間關系經常變化,如輪子移動,手臂關節移動等,則需要編寫node來實時發布。查看該消息結構:

[html]  view plain copy
 
 
 
  1. <span style="font-size:18px;">rosmsg show -r geometry_msgs/TransformStamped  
  2. # This expresses a transform from coordinate frame header.frame_id  
  3. # to the coordinate frame child_frame_id  
  4. #  
  5. # This message is mostly used by the   
  6. <href="http://www.ros.org/wiki/tf">tf</a> package.   
  7. # See its documentation for more information.  
  8.   
  9. Header header  
  10. string child_frame_id # the frame id of the child frame  
  11. Transform <strong><span style="color:#FF0000;">transform</span></strong>  
  12.   
  13. </span>  
Transform其中transform就是我們關心的 tf 轉換關系,child_frame_id是"base_link", header.frame_id 則是'odom'. 查看geometry_msgs/transform:

[html]  view plain copy
 
 
 
  1. rosmsg show -r geometry_msgs/Transform  
  2. # This represents the transform between two coordinate frames in free space.  
  3.   
  4. Vector3 <strong><span style="color:#FF0000;">translation</span></strong>  
  5. Quaternion rotation  
  6.   
  7. rosmsg show -r Vector3  
  8. [geometry_msgs/Vector3]:  
  9. # This represents a vector in free space.   
  10.   
  11. float64 x  
  12. float64 y  
  13. float64 z   
這里的x, y, z 就定義了兩個frame的tf轉換關系。

4. RViz中如何定義 base_link 和 odom 之間的 tf 坐標轉換

要移動機器人,就需要向tf發布geometry_msgs/TransformStamped 消息通知ros  base_linke相對於map的tf轉換關系,也就是說告訴ROS運動的base_link相對於不動的odom位置偏移。這里的odom frame並不能定義在urdf文件里面,它是一個虛擬的。我們只需要RViz知道fixed_frame就是odom就可以了。所以在urdf.rviz文件中這樣定義虛擬odom:

 

[html]  view plain copy
 
 
 
  1. <span style="font-size:18px;">Global Options:  
  2.     Background Color: 48; 48; 48  
  3.     Fixed Frame: <strong><span style="color:#FF0000;">/odom</span></strong>  
  4.     Target Frame: <Fixed Frame>  
  5.     Frame Rate: 30</span>  

如果現在啟動 RViz來觀察機器人:

[html]  view plain copy
 
 
 
  1. <span style="font-size:18px;">roslaunch sp1s display.launch model:=urdf/sp1s.urdf </span>  

肯定會得到錯誤警告,而且RViz中無法顯示完整的機器人:

 

"No transform from [odom] to [base_link]"

這個錯誤很容易理解,沒有任何地方定義odom和base_link之間的tf關系,他們之間是連續變化的,我們當然不能在任何地方寫固定偏移量定義tf transform.

 

但是我們可以寫一個node來不斷的發送geometry_msgs/TransformStamped消息。被發送對象就是tf。 ROS官方有個實例完整代碼如何發布odom到base_link的變換,代碼實例直接拷貝並在本地編譯。這個例子不斷向odom主題發送消息更改odom與base_link之間的位移,位移的軌跡就是一個圓周。這個node名字叫 odom_publisher. 它其實做了兩件事情:

1. 向 tf 發送geometry_msgs/TransformStamped 消息, 就是讓機器人運動起來。

2. 向odom主題發送nav_msgs/Odometry導航消息,報告角速度,線速度和巡航角度。這部分代碼相對本文來講不是必須的。


同"joint_state_publisher" node一樣,“ odom_publisher”需要在RViz啟動之前啟動,添加它的啟動項。修改后的dispaly.launch文件:

 

[html]  view plain copy
 
 
 
  1. <launch>  
  2. <arg name="model" />  
  3. <arg name="gui" default="False" />  
  4. <param name="robot_description" textfile="$(arg model)" />  
  5. <param name="use_gui" value="$(arg gui)"/>  
  6.        <strong><span style="color:#FF0000;"><node name="odom_publisher" pkg="sp1s" type="odom_publisher" /></span></strong>  
  7.        <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />  
  8. <node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />  
  9. <node name="rviz" pkg="rviz" type="rviz"  args="-d  $(find sp1s)/urdf.rviz" required="true"/>  
  10. lt;/launch></span>  


再次打開RViz:

[html]  view plain copy
 
 
 
  1. roslaunch sp1s display.launch model:=urdf/sp1s.urdf   

 

這次就看到機器人在地圖空間中做規則的圓周運動了! 因為RViz收到了odom_publisher向tf發送的坐標轉換內容。

 

 

4. RViz中觀察移動軌跡

 

“ odom_publisher”中還向 odom主題發布了nav_msgs/Odometry導航消息,這樣就可以在RViz中顯示運動軌跡了。在RViz中點擊 'add',選中Odometry,配置該dispaly的topic為 "odom" 就可以看到不斷變化的運動軌跡了。這是因為nav_msgs/Odometry中包含了線速度,角速度和巡航角度,所以RViz可以顯示出來。

 

 

5.odom frame和 odom  topic

 

這兩個完全是不同的東西,很容易混淆。一個是地圖上的一個參照系,一個是topic用來接收導航輸入的。名字一樣,純屬巧合!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM