• ROS tf-深入Time和TF


    博客转载自:https://www.ncnynl.com/archives/201702/1313.html

    ROS与C++入门教程-tf-深入Time和TF

    说明:

    • 介绍使用waitForTransform函数去等待TF树中的变换生效

    TF和Time

    • 在前面的教程中,我们了解了tf如何跟踪坐标系树。
    • 此树随时间变化,tf存储每个变换的时间快照(默认情况下最多为10秒)。
    • 直到现在,我们使用lookupTransform()函数来获取该tf树中最新的可用变换,而不知道什么时候记录变换。
    • 本教程将教您如何在特定时间获取转换。
    • 在上个教程的文件上修改:
    $ roscd learning_tf
    $ vim src/turtle_tf_listener.cpp
    
    • 找到代码:
    try{
        listener.lookupTransform("/turtle2", "/carrot1",  
            ros::Time(0), transform);
    • 修改为:
    try{
       listener.lookupTransform("/turtle2", "/turtle1",  
            ros::Time(0), transform);
    
    • 更改/turtle2跟随/turtle1,不是/carrot1,我们指定了时间为0,即获得最新有效的变换。
    • 改变获取当前时间的变换,即改为now(), 修改代码:
      try{
        listener.lookupTransform("/turtle2", "/turtle1",  
                                 ros::Time::now(), transform);
    • 编译运行:
      $ catkin_make
      $ roslaunch learning_tf start_demo.launch
    
    • lookupTransform()函数提示失败:
    [ERROR] [1287871653.885277559]: You requested a transform that is 0.018 miliseconds in the past, but the most recent transform in the tf buffer is 7.681 miliseconds old.                                                 
     When trying to transform between /turtle1 and /turtle2.  
    • 这是为什么? 每个监听器有一个缓冲区,它存储来自不同tf广播者的所有坐标变换。 当广播者发出变换时,变换进入缓冲区之前需要一些时间(通常是几个毫秒)。 因此,当您在时间“now”请求坐标系变换时,您应该等待几毫秒以获得该信息。

    等待变换

    • tf提供了一个很好的工具,它将等待,直到变换可用。
    • 修改代码为:
     try{
        ros::Time now = ros::Time::now();
        listener.waitForTransform("/turtle2", "/turtle1",
                                  now, ros::Duration(3.0));
        listener.lookupTransform("/turtle2", "/turtle1",
                                 now, transform);
    
    • waitForTransform() 四个参数:

      • 1.需要等待变换从坐标系turtle2
      • 2.到坐标系turtle1
      • 3.在now时间
      • 4.超时时间,不要等待超过此最大持续时间
    • 注意:使用ros::Time::now()是为了这个例子。通常这将是希望被转换的数据的时间戳。

    • 所以waitForTransform()实际上会阻塞直到两个海龟之间的变换可用(这通常需要几毫秒)

    • 或者如果变换不可用,直到达到超时。

    • 编译运行:

      $ catkin_make
      $ roslaunch learning_tf start_demo.launch
    • 但等待,您可能仍会看到错误一次(错误msg可能会有所不同):
    [ERROR] [1287872014.408401177]: You requested a transform that is 3.009 seconds in the past, but the tf buffer only has a history of 2.688 seconds.                                                                   
     When trying to transform between /turtle1 and /turtle2.
    

      

    这是因为turtle2需要非零时间来生成并开始发布tf帧。 因此,第一次请求现在时间的/turtle2坐标系可能不存在,当请求转换时,转换可能不存在,并且第一次失败。 在第一次变换之后,所有的变换都存在,
    并且乌龟的行为如预期的那样。

    检查结果

    • 现在,你应该能够使用箭头键(确保你的终端窗口是活跃的,而不是你的模拟器窗口),你会看到第二只乌龟跟随第一只乌龟!
    • 所以,你注意到乌龟的行为没有明显的区别。 这是因为实际的时间差只有几个毫秒。 但是为什么我们从Time(0)到now()进行这种改变? 只是教你关于tf缓冲区和与它相关的时间延迟。对于真实的tf用例,使用Time(0)通常是完全正常的。

    ROS与C++入门教程-tf-Time travel(时间穿梭

    说明:

    • 介绍tf的高级时间穿梭功能

    Time travel

    • 利用上一个教程的文件。
    • 打开src/turtle_tf_listener.cpp,找到25-30,如下:
      try{
        ros::Time now = ros::Time::now();
        listener.waitForTransform("/turtle2", "/turtle1",
                                  now, ros::Duration(1.0));
        listener.lookupTransform("/turtle2", "/turtle1",
                                 now, transform);
    • 现在,不是让turtle2去到turtle1当前时间的地方,而让turtle2去turtle1是5秒前的地方:
    try{
        ros::Time past = ros::Time::now() - ros::Duration(5.0);
        listener.waitForTransform("/turtle2", "/turtle1",
                                  past, ros::Duration(1.0));
        listener.lookupTransform("/turtle2", "/turtle1",
                                 past, transform);
    
    • 编译运行:
    $ make  or  catkin_make
    $ roslaunch learning_tf start_demo.launch
    
    • 你会期望看到什么? 在第一个5秒钟,第二只乌龟不知道去哪里,因为我们还没有第一只乌龟5秒的历史。

    • 但是这5秒后呢?效果图:

    • 类似截图,你的海龟是不可控制? 那么发生了什么?

    • 我们问TF:相对于/turtle2 5秒前,/turtle1 5秒前的姿势是什么?

    • 这意味着我们控制/turtle2基于5秒前的位置以及/turtle1在5秒前的位置。

    • 那应该问:相对于/turtle2目前的位置,/turtle1 5秒前的姿势是什么?

    高级API

    • 回答上面问题,依赖高级API,示例代码:
      try{
        ros::Time now = ros::Time::now();
        ros::Time past = now - ros::Duration(5.0);
        listener.waitForTransform("/turtle2", now,
                                  "/turtle1", past,
                                  "/world", ros::Duration(1.0));
        listener.lookupTransform("/turtle2", now,
                                 "/turtle1", past,
                                 "/world", transform);
    • 这个lookupTransform()API,有六个参数:

        1. 变换从坐标系turtle2
        1. 在now时间
        1. 到turtle1坐标系
        1. 在past时间
        1. 指定不随时间改变的坐标系,这里是world
        1. 变换结果保存的变量
    • waitForTransform()跟lookupTransform()一样有6个相应参数。

    • 效果图示:

    • 这个图显示了tf在后台做什么。

    • 在past时间,它计算从turtle1到world坐标系的变换。

    • 在world坐标系,tf时间从past到now。

    • 在now时间,tf计算从world到turtle2坐标系的变换。

    检查结果:

    • 编译运行:
    $ catkin_make
    $ roslaunch learning_tf start_demo.launch
    • 效果:turtle2是指向turtle1 5秒前的地方!
  • 相关阅读:
    【CSS】盒子模型的计算
    【CSS】定义元素的位置
    【Jenkins】安装插件
    安装【Jenkins】
    Python【unittest】模块
    Python【pyyaml】模块
    CentOS下安装gcc和gdb
    汇编学习笔记(15)综合研究
    汇编学习笔记(14)BIOS对键盘输入的处理
    汇编学习笔记(13)直接定址表
  • 原文地址:https://www.cnblogs.com/flyinggod/p/10811164.html
Copyright © 2020-2023  润新知