• ROS Learning-021 learning_tf-05(编程) now() 和 Time(0) 的区别 (Python版)


    ROS Indigo learning_tf-05 now()Time(0)的区别 (Python版) — waitForTransform() 函数

    我使用的虚拟机软件:VMware Workstation 11
    使用的Ubuntu系统:Ubuntu 14.04.4 LTS
    ROS 版本:ROS Indigo


    一. 前言

    这一节要做的事情:使用 tfnow()Time(0)的区别 。

    为什么要讲这个,这是因为 ROStf 在进行坐标之间的转换变换不是实时的转换,它有一个缓冲器来存放一段时间的坐标转换数据,所以有时,可能没有当前时间的坐标转换数据,使用 lookupTransform() 函数就可以得到你想的某个时间的坐标数据,前提是缓冲区里要有这个时间的坐标数据,tf 的坐标转换是自动计算的,所以有时,你想得到当前的时间的坐标转换数据,你调用 lookupTransform() 函数去获取,但是缓冲器里还没有来得及去计算现在的坐标转换数据,就是说:现在还没有。如果你非要获取,就会出错,所以你要使用 waitForTransform() 函数来等待 tf 的坐标转换线程得到你想要的时间点的坐标转换数据。
    简单的说:waitForTransform() 就是一个安全程序。

    什么意思,下面编写程序,让大家深入理解:


    二. 写程序


    1 . 讲解

    代码就是下面这个样子: learning_tf 软件包中的 nodes/turtle_tf_listener.py :
    将源代码中:

        ----
        rate = rospy.Rate(10.0)
        while not rospy.is_shutdown():
            try: 
                (trans,rot) = listener.lookupTransform('/turtle2', '/turtle1', rospy.Time(0))
            except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException):
                continue
        ----

    修改为:

        ----
        rate = rospy.Rate(10.0)
        listener.waitForTransform("/turtle2", "/turtle1", rospy.Time(), rospy.Duration(4.0))
        while not rospy.is_shutdown():
            try: 
                now = rospy.Time.now()
                     listener.waitForTransform('/turtle2', '/turtle1', now, rospy.Duration(4.0))         
                (trans,rot) = listener.lookupTransform('/turtle2', '/turtle1', now)
            except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException):
                continue
        ----

    Q: 如果你在 try 里使用了 waitForTransform() 函数,但是在 while 外并没有 waitForTransform() ,程序就不正常运行。 为什么必须要有while外的 waitForTransform() 函数?为什么要调用 waitForTransform() 函数?

    A: 在程序的开始,我们 再生/spawn 服务)了一个 turtle2 ,但是在 waitForTransform() 函数执行的时候,tf 里可能还没有 turtle2 坐标系,就是 turtle2 还没有 再生 完成。
    所以,第一个 waitForTransform() 函数将会等到 turtle2 坐标系 再生 完成。
    第二个 waitForTransform() 函数将会等到 now 时间的坐标系转换完成,在缓冲器中有。

    waitForTransform() 函数的4个形参:

    waitForTransform( [父类坐标系], [子类坐标系], [在这一时刻], rospy.Duration(4.0) )

    rospy.Duration(4.0) : 为 waitForTransform() 函数 的结束条件:最多等待 4 秒,如果提前得到了坐标的转换信息,直接结束等待。


    2 . 编写代码

    learning_tf 程序包中的 nodes 路径下,新建一个文件:turtle_tf_listener_timeTravel.py

    roscd learning_tf/node/
    gedit turtle_tf_listener_timeTravel.py

    下面是完整的程序。将这段程序复制到 turtle_tf_listener_timeTravel.py 文件里面:

    #!/usr/bin/env python
    
    import roslib
    roslib.load_manifest('learning_tf')
    import rospy
    import math
    import tf
    import geometry_msgs.msg
    import turtlesim.srv
    
    if __name__ == '__main__':
        rospy.init_node('tf_turtle')
        listener = tf.TransformListener()
    
        rospy.wait_for_service('spawn')
        spawner = rospy.ServiceProxy('spawn', turtlesim.srv.Spawn)
        spawner(4, 2, 0, 'turtle2')
    
        turtle_vel = rospy.Publisher('turtle2/cmd_vel', geometry_msgs.msg.Twist, queue_size=1)
    
        rate = rospy.Rate(10.0)
        listener.waitForTransform("/turtle2", "/turtle1", rospy.Time(), rospy.Duration(4.0))
        while not rospy.is_shutdown():
            try: 
                now = rospy.Time.now()
                listener.waitForTransform('/turtle2', '/turtle1', now, rospy.Duration(4.0))         
                (trans,rot) = listener.lookupTransform('/turtle2', '/turtle1', now)
            except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException):
                continue
    
            angular = 4 * math.atan2(trans[1], trans[0])
            linear  = 0.5 * math.sqrt(trans[0] ** 2 + trans[1] ** 2)
            cmd = geometry_msgs.msg.Twist()
            cmd.linear.x = linear
            cmd.angular.z = angular
            turtle_vel.publish(cmd)
            rate.sleep()
    

    给这个文件添加可执行权限:

    chmod 777 turtle_tf_listener_timeTravel.py

    3 . 编写启动文件

    learning_tf 程序包中的 launch 路径下,新建一个文件:start_demo5.launch:

    roscd learning_tf/launch/
    gedit start_demo5.launch

    将下面的代码拷贝进去。(下面这段代码就是通过 start_demo2.launch 文件改写的,基本和它一模一样)

    <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>
    
        <node pkg="learning_tf" type="turtle_tf_listener_timeTravel.py" name="listener" />
    
    </launch>

    4 . 运行

    运行 start_demo5.launch 这个启动脚本文件:

    $ roslaunch  learning_tf start_demo5.launch 

    运行效果:看起来和之前 “ 编写一个 监听器 程序 ”这一节的运行效果一样 。

    这里写图片描述

    Q: 你肯定会问这样的问题: rospy.Time.now()rospy.Time(0) 有什么不同吗?运行时的效果都一样?

    A: 虽然,你注意到 小海龟的行为 没有明显的变化。那是因为:实际的时间只差几毫秒的不同。但是我们为什么有时使用Time(0) ,有时使用 now()。我这里只是想告诉你:tf 缓冲和时间延迟是相关联的。在实际使用 tf 时,这2个可以认为是等同的。

    • Time(0) : 是 tf 缓存里的第一个 tf 信息。
    • now() : 是当前这个时间的 tf 信息。


    总结: 现在,我们知道了 now()Time(0) 的区别,那它们究竟有什么用呢?下一节,我带你在 ROS 中进行现在过去中的时间穿梭,你就知道了。
    下一节: 现在与过去中穿梭 (Python版) — waitForTransformFull() 函数。

  • 相关阅读:
    《web-Mail服务的搭建》
    VMware虚拟机三种联网方法及原理
    Java总结——常见Java集合实现细节(1)
    nginx静态资源缓存策略配置
    算术验证
    JPA学习
    Spring中AOP实现
    转:Spring中事物管理
    使用docker发布spring cloud应用
    综合使用spring cloud技术实现微服务应用
  • 原文地址:https://www.cnblogs.com/aobosir/p/5928559.html
Copyright © 2020-2023  润新知