• ROS Learning-022 learning_tf-06(编程) 现在与过去中穿梭 (Python版) --- waitForTransformFull() 函数


    ROS Indigo learning_tf-06 现在与过去中穿梭 (Python版) — waitForTransformFull() 函数

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


    一 . 前言

    这一节要做的事情:使用 tf 的一个强大功能:可以再现在与过去中穿梭。(就是:如何使用 waitForTransformFull() 函数。)

    我们不让 turtle2 跟随当前的 turtle1 的坐标, 而是让 turtle2 去跟随 过去turtle1 的坐标。
    一样,我们只需要改变 监听器 程序turtle_tf_listener.py )中的一点点代码就可以实现。我们就让 turtle2 去跟随5秒钟前的 turtle1 的坐标吧。

    跟随过去 的 程序编写

    1 . 重点讲解

    我们将之前编写的 监听器 程序turtle_tf_listener.py )里面的这一段代码:

            try:
                (trans, rot) = listener.lookupTransform('/turtle2', '/turtle1', rospy.Time(0))

    修改为:

            try: 
                now = rospy.Time.now()
                past = now - rospy.Duration(5.0)
                listener.waitForTransformFull('/turtle2', now, '/turtle1', now, '/world', rospy.Duration(4.0))         
                (trans,rot) = listener.lookupTransform('/turtle2', now, '/turtle1', past, '/world')

    我们来具体了解一下上面代码中出现的:lookupTransformFull() 函数,这个函数也是坐标系信息转换的功能。这个函数有6个形参: ( 其实它的功能和lookupTransform()函数的功能一样,只不过是个升级版函数 ) :

    1 . 父类坐标系节点名
    2 . 指定时间
    3 . 子类坐标系节点名
    4 . 指定时间
    5 . 指定不随时间改变的坐标系, 在这里是 “/world” 坐标系.

    通过 形参1形参2 就可以得到一个 姿态的信息(线速度和角速度),通过 形参3形参4 就可以得到另一个姿态的信息。

    图示 lookupTransformFull() 函数的作用:

    这里写图片描述

    解说一下这幅图的意思: lookupTransformFull() 函数 做了下面三步的事情。
    第1步 : 将 形参1 在指定的时间 形参2 时的姿态信息转换到 形参5 坐标系上;
    第2步 : 接着,将 形参3 在指定的时间 形参4 时的姿态信息转换到 形参5 坐标系上;
    第3步 : 最后,将 第1步 得到的姿态信息做为坐标原点(即:以 形参1 的位置做为参考坐标系),求出 第二步 得到的姿态信息 在 这个参考坐标中的姿态信息,将其做为 lookupTransformFull() 函数返回值输出。


    2 . 编写代码

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

    roscd learning_tf/node/
    gedit turtle_tf_listener_pastNow.py

    下面是完整的程序。将这段程序复制到 turtle_tf_listener_pastNow.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()
                past = now - rospy.Duration(5.0)
                listener.waitForTransformFull('/turtle2', now, '/turtle1', now, '/world', rospy.Duration(4.0))         
                (trans,rot) = listener.lookupTransform('/turtle2', now, '/turtle1', past, '/world')
            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_pastNow.py

    3 . 编写启动文件

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

    roscd learning_tf/launch/
    gedit start_demo6.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_pastNow.py" name="listener" />
    
    </launch>

    4 . 运行

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

    $ roslaunch  learning_tf start_demo6.launch 

    这次的运行效果,很不错,当前时间的 turtle2 小海龟 就在跟随这个 过去5秒钟之前的 turtle1 小海龟做运动。

    这里写图片描述

    搞定


    5 . 扩展: ROS 官方上的错误

    下面这段是 ROS 官网中的程序:(这个网站

            try: 
                now = rospy.Time.now()
                past = now - rospy.Duration(5.0)
                listener.waitForTransformFull('/turtle2', now, '/turtle1', past, '/world', rospy.Duration(4.0))         
                (trans,rot) = listener.lookupTransform('/turtle2', now, '/turtle1', past, '/world')

    这段代码是错误的。如果运行的话,会输出下面的错误信息:

    [listener-6] process has died [pid 8919, exit code 1, cmd /home/aobosir/catkin_ws/src/learning_tf/nodes/turtle_tf_listener_pastNow.py __name:=listener __log:=/home/aobosir/.ros/log/71c1eedc-75ad-11e6-8577-000c29fd0c33/listener-6.log].
    log file: /home/aobosir/.ros/log/71c1eedc-75ad-11e6-8577-000c29fd0c33/listener-6*.log

    这里写图片描述

    正确的代码就是:(这样就不会出现问题)

            try: 
                now = rospy.Time.now()
                past = now - rospy.Duration(5.0)
                listener.waitForTransformFull('/turtle2', now, '/turtle1', now, '/world', rospy.Duration(4.0))         
                (trans,rot) = listener.lookupTransform('/turtle2', now, '/turtle1', past, '/world')


    总结:
    现在,我们学会了如果在ROS 中进行不同时间段之间的 tf 转换。
    接下来,下一节,介绍:如果调试使用 tf 转换的程序(C++ 版)。


  • 相关阅读:
    Eclipse SVN忽略某些文件或文件夹方法
    在ORACLE中给已有数据的表增加、修改、删除一个字段(或一个列)或者多个字段(或多个列)的问题
    Java中IO流,输入输出流概述与总结
    Java面向对象之继承
    jquery-each()
    window.showModalDialog以及window.open用法简介
    struts1、ajax、jquery、json简单实例
    软件人才管理
    疑难杂症定位记录
    linux中断子系统
  • 原文地址:https://www.cnblogs.com/aobosir/p/5928558.html
Copyright © 2020-2023  润新知