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
一. 前言
这一节要做的事情:使用 tf 的 now() 和 Time(0)的区别 。
为什么要讲这个,这是因为 ROS 的 tf 在进行坐标之间的转换变换不是实时的转换,它有一个缓冲器来存放一段时间的坐标转换数据,所以有时,可能没有当前时间的坐标转换数据,使用 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() 函数。
ROS Learning-021 learning_tf-05(编程) now() 和 Time(0) 的区别 (Python版)的更多相关文章
- ROS Learning-022 learning_tf-06(编程) 现在与过去中穿梭 (Python版) --- waitForTransformFull() 函数
ROS Indigo learning_tf-06 现在与过去中穿梭 (Python版) - waitForTransformFull() 函数 我使用的虚拟机软件:VMware Workstatio ...
- ROS Learning-015 learning_tf(编程) 编写一个监听器程序 (Python版)
ROS Indigo learning_tf-02 编写一个 监听器 程序 (Python版) 我使用的虚拟机软件:VMware Workstation 11 使用的Ubuntu系统:Ubuntu 1 ...
- ROS Learning-014 learning_tf(编程) 坐标系变换(tf)广播员 (Python版)
ROS Indigo learning_tf-01 坐标系变换(tf)广播员 (Python版) 我使用的虚拟机软件:VMware Workstation 11 使用的Ubuntu系统:Ubuntu ...
- ROS Learning-020 learning_tf-04(编程)让turtle2 海龟跟随turtle1海龟,并绕着 turtle1海龟转圈 (Python版)
ROS Indigo learning_tf-04 (编程)让 turtle2 海龟跟随 turtle1 海龟,并绕着 turtle1 海龟转圈 (Python版) 我使用的虚拟机软件:VMware ...
- ROS Learning-019 learning_tf-03(编程) 添加额外的坐标系 (Python版)
ROS Indigo learning_tf-03 添加额外的坐标系 (Python版) 我使用的虚拟机软件:VMware Workstation 11 使用的Ubuntu系统:Ubuntu 14.0 ...
- ROS Learning-011 beginner_Tutorials (编程) 编写 ROS 话题版的 Hello World 程序(Python版)
ROS Indigo beginner_Tutorials-10 编写 ROS 话题版的 Hello World 程序(Python版) 我使用的虚拟机软件:VMware Workstation 11 ...
- ROS Learning-013 beginner_Tutorials (编程) 编写ROS服务版的Hello World程序(Python版)
ROS Indigo beginner_Tutorials-12 编写ROS服务版的Hello World程序(Python版) 我使用的虚拟机软件:VMware Workstation 11 使用的 ...
- 【原】Learning Spark (Python版) 学习笔记(三)----工作原理、调优与Spark SQL
周末的任务是更新Learning Spark系列第三篇,以为自己写不完了,但为了改正拖延症,还是得完成给自己定的任务啊 = =.这三章主要讲Spark的运行过程(本地+集群),性能调优以及Spark ...
- Python黑帽编程1.2 基于VS Code构建Python开发环境
Python黑帽编程1.2 基于VS Code构建Python开发环境 0.1 本系列教程说明 本系列教程,采用的大纲母本为<Understanding Network Hacks Atta ...
随机推荐
- @angular/cli项目构建--Dynamic.Form(2)
form-item-control.service.ts update @Injectable() export class FormItemControlService { constructor( ...
- Codeforces Round #279 (Div. 2)B. Queue(构造法,数组下标的巧用)
这道题不错,思维上不难想到规律,但是如何写出优雅的代码比较考功力. 首先第一个人的序号可以确定,那么接下来所有奇数位的序号就可以一个连一个的确定了.然后a[i].first==0时的a[i].seco ...
- VSCode使用正则表达式进行内容替换
首先描述一下我要达到的目的: 1.源数据: 2.目标数据: 3.使用的正则表达式如下: (id: (\d+),) id: $2, \n order: $2,
- linux C gbk utf-8编码转换
http://blog.csdn.net/sealyao/article/details/5043138
- Redis底层探秘(二):链表和跳跃表
链表简介 链表提供了高效的节点重排能力,以及顺序性的节点访问方式,并且可以通过增删节点来灵活地跳转链表的长度. 作为一种常用数据结构,链表内置在很多高级的编程语言里面,因为Redis使用C语言并没有内 ...
- C#异步编程(二)用户模式线程同步
基元线程同步构造 多个线程同时访问共享数据时,线程同步能防止数据损坏.不需要线程同步是最理想的情况,因为线程同步存在许多问题. 第一个问题就是它比较繁琐,而且很容易写错. 第二个问题是,他们会损害性能 ...
- 反射ORM 三层(for sql server/mysql)
sql server and oracle 不同之处只在于: 1·参数@和: 2·自增和序列 RPROM.cs //(写错愕,应该是RPORM) RPROM.Insert(p1); //需求:DBS中 ...
- delphi VCL组件同名继承
当我们在扩展一个 vcl 组件功能的时候,既想保留IDE中能拖动大小与直接设置属性的功能,又想减少写创建与释放代码和安装扩展后新组件的麻烦,那么本文中的方法,就非常实用了. 以给TStringGrid ...
- 一次Mono解析Excel文档编码出错排查记录
最近在捯饬Asp.Net站点部署到Linux平台上面,在文档导入的操作中经过网上搜索采用了能够支持跨平台的ExcelDataReader组建.在本地windows上测试通过NuGet安装的组建,这货依 ...
- java 多线程系列基础篇(一)
多线程状态图: Thread类的两个方法比较: yield方法: Yield是一个静态的原生(native)方法 Yield告诉当前正在执行的线程把运行机会交给线程池中拥有相同优先级的线程. Yiel ...