ROS 中TF學習


1.什么是TF

TF是處理機器人不同位置坐標系的一個包,機器人不同部位和世界的坐標系以  tree structure 的形式存儲起來,TF可以使任何兩個坐標系之間的點 向量相互轉化。

機器人系統是有很多坐標系系統,並且每一個坐標系系統都隨時間變化,tf 可以幫助你解決這些問題:頭 坐標系跟世界坐標系是什么關系,柵格圖中物體的位置跟我地盤有什么關系?在地圖坐標系中,底盤的位置跟現在有什么關系?

tf實例講解:

古月君 http://blog.csdn.net/hcx25909/article/details/9255001   

http://wiki.ros.org/tf/Tutorials/tf%20and%20Time%20%28Python%29

1.1 How to broadcast transforms

 1  #!/usr/bin/env python     
 2   import roslib  
 3   roslib.load_manifest('learning_tf') 
 4   import rospy 
 5    
 6    import tf
 7   import turtlesim.msg
 8   #使用 tf 完成坐標變換,訂閱這個topic "turtleX/pose" 並且對每一條msg進行以下計算
 9   def handle_turtle_pose(msg, turtlename):
10       br = tf.TransformBroadcaster()   #將turtlebot的坐標系發到 tf tree中
11       br.sendTransform((msg.x, msg.y, 0),
12                        tf.transformations.quaternion_from_euler(0, 0, msg.theta),  #使用四元數完成坐標變換
13                        rospy.Time.now(),               #
14                       turtlename,
15                        "world")
16  
17   if __name__ == '__main__':
18       rospy.init_node('turtle_tf_broadcaster')  #添加新的節點
19       turtlename = rospy.get_param('~turtle')#
20       rospy.Subscriber('/%s/pose' % turtlename,   #發布的信息內容
21                        turtlesim.msg.Pose,
22                        handle_turtle_pose,
23                        turtlename)
24       rospy.spin()

 

1.2  Running the broadcaster

 <launch>
    <!-- Turtlesim Node-->
    <node pkg="turtlesim" type="turtlesim_node" name="sim"/>
    <node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>

    <node name="turtle1_tf_broadcaster" pkg="learning_tf" type="turtle_tf_broadcaster.py" respawn="false" output="screen" >
      <param name="turtle" type="string" value="turtle1" />
    </node>
    <node name="turtle2_tf_broadcaster" pkg="learning_tf" type="turtle_tf_broadcaster.py" respawn="false" output="screen" >
      <param name="turtle" type="string" value="turtle2" /> 
    </node>

  </launch>
rosrun tf tf_echo /world /turtle1   可以查看turtle的位置確實通過廣播發到了tf .

1.3How to create a tf listener

 

 1 #!/usr/bin/env python  
 2 import roslib
 3 roslib.load_manifest('learning_tf')
 4 import rospy
 5 import math
 6 import tf     #tf 里面有定義訂閱者的函數
 7 import geometry_msgs.msg
 8 import turtlesim.srv
 9 
10 if __name__ == '__main__':
11     rospy.init_node('tf_turtle')
12 
13     listener = tf.TransformListener()  #定義listener  一旦定義listener  ,他就開始接受信息,並且可以緩沖10S.
14 
15     rospy.wait_for_service('spawn')   #等待服務。 spwn ,這個服務可以創建另一只烏龜
16     spawner = rospy.ServiceProxy('spawn', turtlesim.srv.Spawn)
17     spawner(4, 2, 0, 'turtle2')   #位置 跟名字
18 
19     turtle_vel = rospy.Publisher('turtle2/cmd_vel', geometry_msgs.msg.Twist,queue_size=1)
20    #這一段是我們真正做的工作,我們使 turtle1是父坐標系,turtle2是子坐標系,然后就調用了listener.lookupTransform
21 rate = rospy.Rate(10.0)
22   while not rospy.is_shutdown(): 
23       try: 
24        (trans,rot) = listener.lookupTransform('/turtle2', '/turtle1', rospy.Time(0))    #可以緩沖10S內最近的信息。
25       except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException): 
26       continue 
27    angular = 4 * math.atan2(trans[1], trans[0]) 
28    linear = 0.5 * math.sqrt(trans[0] ** 2 + trans[1] ** 2) 
29    cmd = geometry_msgs.msg.Twist() 
30    cmd.linear.x = linear 
31    cmd.angular.z = angular 
32    turtle_vel.publish(cmd) 
33    rate.sleep()

 

 

  在launch 里面加入 

  <launch>
    ...
 <node pkg="learning_tf" type="turtle_tf_listener.py"  name="listener" />  </launch>

1.4 Adding a frame

往tf  tree 里面加入額外的坐標系。這跟創建一個tf boardcaster有點類似,為什么要加入坐標系呢?在tf 樹中是不能構成回路的、只能有一個父坐標系,但是可以有很多子坐標系

。我們先前創造的世界中有 三個坐標系,父坐標系:世界坐標系   兩個子:   turtle1坐標系跟 ,turtle2坐標系。

  1 #!/usr/bin/env python  
  2 import roslib
  3 roslib.load_manifest('learning_tf')
  4 
  5 import rospy
  6 import tf
  7 
  8 if __name__ == '__main__':
  9     rospy.init_node('my_tf_broadcaster')
 10     br = tf.TransformBroadcaster()
 11     rate = rospy.Rate(10.0)
 12     while not rospy.is_shutdown():
 13         br.sendTransform((0.0, 2.0, 0.0),
 14                          (0.0, 0.0, 0.0, 1.0),
 15                          rospy.Time.now(),
 16                          "carrot1",
 17                          "turtle1")   #carrot 1 是tuttle的子坐標系
 18         rate.sleep()

  

 在Launch文件中加入下列, 

  <launch>
    ...
 <node pkg="learning_tf" type="fixed_tf_broadcaster.py"  name="broadcaster_fixed" />  </launch>

 如果將listener 中的代碼修改

1 (trans,rot) = listener.lookupTransform("/turtle2", "/carrot1", rospy.Time(0))

1.5 Broadcasting a moving frame

 1 #!/usr/bin/env python  
 2 import roslib
 3 roslib.load_manifest('learning_tf')
 4 
 5 import rospy
 6 import tf
 7 import math
 8 
 9 if __name__ == '__main__':
10     rospy.init_node('my_tf_broadcaster')
11     br = tf.TransformBroadcaster()
12     rate = rospy.Rate(10.0)
13     while not rospy.is_shutdown():
14         t = rospy.Time.now().to_sec() * math.pi
15         br.sendTransform((2.0 * math.sin(t), 2.0 * math.cos(t), 0.0),
16                          (0.0, 0.0, 0.0, 1.0),
17                          rospy.Time.now(),
18                          "carrot1",
19                          "turtle1")
20         rate.sleep()

 


免責聲明!

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



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