ROS探索总结(十二)——坐标系统

  • 内容
  • 评论
  • 相关

        在机器人的控制中,坐标系统是非常重要的,在ROS使用tf软件库进行坐标转换。

        相关链接:http://www.ros.org/wiki/tf/Tutorials#Learning_tf

一、tf简介

        我们通过一个小小的实例来介绍tf的作用。

1、安装turtle包

  1. $ rosdep install turtle_tf rviz  
  2. $ rosmake turtle_tf rviz

2、运行demo

        运行简单的demo:
        $ roslaunch turtle_tf turtle_tf_demo.launch 
        然后就会看到两只小乌龟了。


        该例程中带有turtlesim仿真,可以在终端激活的情况下进行键盘控制。

        可以发现,第二只乌龟会跟随你移动的乌龟进行移动。

3、demo分析

        接下来我们就来看一看到底ROS做了什么事情。
        这个例程使用tf建立了三个参考系:a world frame, a turtle1 frame, and a turtle2 frame。然后使用tf broadcaster发布乌龟的参考系,并且使用tf listener计算乌龟参考系之间的差异,使得第二只乌龟跟随第一只乌龟。
        我们可以使用tf工具来具体研究。
       $ rosrun tf view_frames 
        然后会看到一些提示,并且生成了一个frames.pdf文件。


        该文件描述了参考系之间的联系。三个节点分别是三个参考系,而/world是其他两个乌龟参考系的父参考系。还包含一些调试需要的发送频率、最近时间等信息。
        tf还提供了一个tf_echo工具来查看两个广播参考系之间的关系。我们可以看一下第二只得乌龟坐标是怎么根据第一只乌龟得出来的。
 

          $ rosrun tf tf_echo turtle1 turtle2 
        控制一只乌龟,在终端中会看到第二只乌龟的坐标转换关系。


        我们也可以通过rviz的图形界面更加形象的看到这三者之间的关系。
        $ rosrun rviz rviz -d `rospack find turtle_tf`/rviz/turtle_rviz.vcg 

        移动乌龟,可以看到在rviz中的坐标会跟随变化。其中左下角的是/world,其他两个是乌龟的参考系。
       下面我们就来详细分析这个实例。

二、Writing a tf broadcaster

1、创建包

  1. $ roscd tutorials  
  2. $ roscreate-pkg learning_tf tf roscpp rospy turtlesim  
  3. $ rosmake learning_tf
 

2、broadcast transforms

        我们首先看一下如何把参考系发布到tf。
        代码文件:/nodes/turtle_tf_broadcaster.py
  1. #!/usr/bin/env python    
  2. import roslib  
  3. roslib.load_manifest('learning_tf')  
  4. import rospy  
  5.  
  6.  
  7. import tf  
  8. import turtlesim.msg  
  9.  
  10.  
  11. def handle_turtle_pose(msg, turtlename):  
  12.     br = tf.TransformBroadcaster()  
  13.     br.sendTransform((msg.x, msg.y, 0),  
  14.                      tf.transformations.quaternion_from_euler(0, 0, msg.theta),  
  15.                      rospy.Time.now(),  
  16.                      turtlename,  
  17.                      "world")  #发布乌龟的平移和翻转  
  18.  
  19.  
  20. if __name__ == '__main__':  
  21.     rospy.init_node('turtle_tf_broadcaster')  
  22.     turtlename = rospy.get_param('~turtle')   #获取海龟的名字(turtle1,turtle2)  
  23.     rospy.Subscriber('/%s/pose' % turtlename,  
  24.                      turtlesim.msg.Pose,  
  25.                      handle_turtle_pose,  
  26.                      turtlename)   #订阅 topic "turtleX/pose"  
  27.     rospy.spin()

        创建launch文件start_demo.launch: 
  1. <launch>  
  2.     <!-- Turtlesim Node-->  
  3.     <node pkg="turtlesim" type="turtlesim_node" name="sim"/>  
  4.     <node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>  
  5.  
  6.  
  7.     <node name="turtle1_tf_broadcaster" pkg="learning_tf" type="turtle_tf_broadcaster.py" respawn="false" output="screen" >  
  8.       <param name="turtle" type="string" value="turtle1" />  
  9.     </node>  
  10.     <node name="turtle2_tf_broadcaster" pkg="learning_tf" type="turtle_tf_broadcaster.py" respawn="false" output="screen" >  
  11.       <param name="turtle" type="string" value="turtle2" />   
  12.     </node>  
  13.  
  14.  
  15.   </launch>
        运行:
       $ roslaunch learning_tf start_demo.launch 
        可以看到界面中只有移植乌龟了,打开tf_echo的信息窗口:
       $ rosrun tf tf_echo /world /turtle1  

        world参考系的原点在最下角,对于turtle1的转换关系,其实就是turtle1在world参考系中所在的坐标位置以及旋转角度。

三、Writing a tf listener

        这一步,我们将看到如何使用tf进行参考系转换。首先写一个tf listener(nodes/turtle_tf_listener.py):

  1. #!/usr/bin/env python    
  2. import roslib  
  3. roslib.load_manifest('learning_tf')  
  4. import rospy  
  5. import math  
  6. import tf  
  7. import turtlesim.msg  
  8. import turtlesim.srv  
  9.  
  10. if __name__ == '__main__':  
  11.     rospy.init_node('tf_turtle')  
  12.  
  13.     listener = tf.TransformListener() #TransformListener创建后就开始接受tf广播信息,最多可以缓存10s  
  14.  
  15.     rospy.wait_for_service('spawn')  
  16.     spawner = rospy.ServiceProxy('spawn', turtlesim.srv.Spawn)  
  17.     spawner(4, 2, 0, 'turtle2')  
  18.  
  19.     turtle_vel = rospy.Publisher('turtle2/command_velocity', turtlesim.msg.Velocity)  
  20.  
  21.     rate = rospy.Rate(10.0)  
  22.     while not rospy.is_shutdown():  
  23.         try:  
  24.             (trans,rot) = listener.lookupTransform('/turtle2', '/turtle1', rospy.Time(0))  
  25.         except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException):  
  26.             continue  
  27.  
  28.         angular = 4 * math.atan2(trans[1], trans[0])  
  29.         linear = 0.5import rospy  
  30. trans[.atan2, trans[0
      p">&nbs  linear = ('turtle2/command_velocity'< (, rospy.Time(
                ="br
       leep1">
        while 
        rospy.spin

    name="sim"/> "turtle2_tf_broadcaster" pkg=&p;  class="st0">&"wp-geshi-highlight">
    1. ExtrapolationE 
    2.       "string" value="sim&quring" 
       
    3.   

    三、Writing a tf listener

    &#加ze="3"> &nb有必个">&#如"n=ze=sp;  &">bze=激光扫rokeolor=tfnunch&帮助h: 0px" a激光扫rok#000000" color="换成全局color=他两个是乌龟的参6px; background-color: rgb(255,255,255); text-indent: 0px; -webkit-text-stroke-width: 0px" align="left">  0px; padding-right: 0px">2、broadcast transforms

    <0000" &nbsze=树状n> e-ste需让/worl新sp; 移动成为已#4三ze="3"> eft"><0ze=sp; 移动乌龟urtle1的转换关系,其实就是turtle1在world参考系中所在的坐标位置以及旋转角度。
    n>

      0px; padding-right: 0px"> e-fixed frre>) ; color: " name="t6">2、broadcast transforms; fixed0">"learning_一步,我们将看到如何使用tf进行参考系转换。首先写一个tf listener(nodes/turtle_tf_listener.py):

    =&qu-highlight-wrap">
    1. #!/usr/bin/env python    
    2. import roslib  
    3. roslib.load_manifest(import rospy  
    4.  
      <_tf')
    5. math  import turtlesim.srv  
    6.  
    7. if __name__ == '__maipan> roslib  
    8.     rospy.init_node(, turtlename):  
    9.     br = tf.TransformBroadcast="br0">)  
    10.  
    11.     rate = rospy.Rate(10.0)  
    12.     while not rospy.is_shutdown()  
    13. &">transformations.quaternion2&">transformations.quaternion rate = rospyormations.
    14.              lass="li1">
            >&">transformations.quaternion>&">transformations.quaternion>&">transformations.quaternion1  rate = rospyormations.  
    15.              lassn class="br0">),  
    16.                      rospy.Time.now(&quoan class="carrot1sy0">=>Time.now(&quoan class=" class="st0">"span class="sy0">= rospy.ass="st0">&qu-highl&立sze=新sp; 移动sp;fbsp; 为0;<并且距离fbsp; 2米                    turtlename)="br
         leep1">
          while 
          rospy.spin 

      <...kw3">name="sim"/> "turtle2_tf_broadcaster" pkg="learning_ class="st0">&"p-geshi-highlight">
      1.       "string" value="sim&quring" 
         
      2.    
      和之前sp;效果roke。新b加sp; 移动并没#4b bsp; 产生什么影响。font      bsp;&nbs将0;
      height: 26px; background-color: rgb(255,255,255); text-indent: 0px; -webkit-text-stroke-width: 0px" align="left">如e1"> "class="s"r: " name="t6">e1"> height: 26px; background-color: rgb(255,255,255); text-indent: 0px; -webkit-text-stroke-width: 0px" align="left"> "ccarrot1"r: " name="t6">ckground-color: rgb(2 line-height: 26px; background-color: rgb(255,255,255); text-indent: 0px; -webkit-text-stroke-width: 0px" align="left"> e1"> height: 26px; background-color: rgb(255,255,255); text-indent: 0px; -webkit-text-stroke-width: 0px" align="left">如nbsp;     nbsp;  &     $ rosrun tf tf_echo /world /turtle1   n>

      <间3">< colocolor=i&nb变
        &nb关系,其实就是turtle1在world参考系中所在的坐标位置以及旋转角度。
      n>

        0px; padding-right: 0px"> e-mov pa frre>) ; color: " name="t6">2、broadcast transformscolor=设置可变">&nunch&修bbsp;&nleft&">,我们将看到如何使255,255,255); text-indent: 0px; -webkit-text-stroke-width: 0px" align="left">

      =&qu-highlight-wrap">
      1. #!/usr/bin/env python    
      2. import roslib  
      3. roslib.load_manifest(import rospy  
      4.  
        <_tf'
      5.  
        math
      6. ExtrapolationE import rospy  
      7. import turtlesim.srv  
      8.  
      9. if __name__ == '__maipan> roslib  
      10.     rospy.init_node(, turtlename):  
      11.     br = tf.TransformBroadcast="br0">)  
      12.  
      13.     rate = rospy.Rate10.0)  
      14.     while not rospy.is_shutdown)  
      15. ,  
      16.                      rospyss="sy0">,  to_sec
      17.     br   
      18.   piTime.nower()  
      19. transfan>
      20.    ii1">
            .quaternion2&">transfan>  
      21.   cos1">
            .quaternion   rate = rospyormations.  
      22.              lass="li1">
              >&">transformations.quaternion>&">transformations.quaternion>&">transformations.quaternion1  rate = rospyormations.  
      23.              lassn class="br0">),  
      24.                      rospy.Time.now(&quoan class="carrot1sy0">=>Time.now(&quoan class=" class="st0">"span class="sy0">= rospy.an>.now="br
           leep1">
            while m&qurclass=line-heigi class="li1">
              = clam&qurclass=b&# clam&qurclass=到pan class="br0">&# class="de1"> 
      25.    n>

        <0参现"
        n>

        ">,我adding-right: 0px; background-color: rgb(255,255,255)href%; border="liass=dium none;detail/hcx25909/5708199"dding-right: 0px;relterofollow" -height: 26px; cackground-color: border="liass=dium none;detail/hcx25909/5708199und-coloralor: rgb(255,255bsp;embedlor: rgb(2  &nbhite-sxt-ind15tran系bsp;&: itcinc"255bsphr; lolong>原创-stse-转>请注明">lolong> 转>自adding-right: 0px;href%; borderwww.guyuehome.com/">古月居oralorp255bsplolong>本-st链pan>址:lolong> adding-right: 0px;href%; borderwww.guyuehome.com/265">ROS探索总结(十二)——color=th: oralorp255255,25 lclasonan