• 欢迎访问开心洋葱网站,在线教程,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站,欢迎加入开心洋葱 QQ群
  • 为方便开心洋葱网用户,开心洋葱官网已经开启复制功能!
  • 欢迎访问开心洋葱网站,手机也能访问哦~欢迎加入开心洋葱多维思维学习平台 QQ群
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏开心洋葱吧~~~~~~~~~~~~~!
  • 由于近期流量激增,小站的ECS没能经的起亲们的访问,本站依然没有盈利,如果各位看如果觉着文字不错,还请看官给小站打个赏~~~~~~~~~~~~~!

TF2中 监听者 对于 时间的控制 并实现 当前坐标系计算其它历史坐标系的坐标变换

人工智能 月照银海似蛟龙 2087次浏览 0个评论

1、TF2 和 时间

在之前的博客 TF2 监听者的例子中 , 可以 获取 坐标变换树中 最新的 信息。

坐标变换树随时间改变,TF2会存储1段时间,每个坐标系的变换信息(默认是10s)

当我们通过使用lookupTransform() 函数获得最新的有效坐标变换时,并不知道这个变化发生的具体时间。可能由于某种原因 得到了很久之前的 坐标变换,导致系统出现错误。

例如 在1s时产生了有效的坐标变换,后发生故障,在10s时,我们像以前一样获取坐标变换,此时依然可以成功获取,但是是1s时产生的,类似这种情况就不是我们想要的了。 下面 主要讲解避免这种情况的方法获取一个坐标变换在指定的时间

2、初步尝试 在指定时间获得 坐标变换

打开 TF2 监听者的例子 就是这篇博客写的

把 src/turtle_tf2_listener.cpp 这个文件 的 lookupTransform() 函数 进行 修改改成下面的形式

把坐标系设置为 乌龟2 和 乌龟1 , 时间 改 为 now

之前是这样

try{
    transformStamped = tfBuffer.lookupTransform("turtle2", "turtle1", ros::Time(0));
  } catch (tf2::TransformException &ex) {
    ROS_WARN("Could NOT transform turtle2 to turtle1: %s", ex.what());
  }

改成这样

try{
    transformStamped = tfBuffer.lookupTransform("turtle2", "turtle1", ros::Time::now());
  } catch (tf2::TransformException &ex) {
    ROS_WARN("Could NOT transform turtle2 to turtle1: %s", ex.what());
  }
  • ros::Time(0) 指的是 在buffer中最新可用的坐标变换
  • ros::Time::now() 指的是 当前的坐标变换

编译运行下

会发现乌龟2 不像 之前例子中会自动跑到乌龟1 处

坐标变换失败了,原因如下:

每一个监听者会用一个buffer取存储所有的坐标变换有广播者发布的。当广播者发布一个坐标变换,会花一点时间存在buffer中,通常时几毫秒(0.007s)。所有当请求一个坐标变换的时间为 ros::Time::now() 的时候,不会立马有,要等几毫秒。

所有上面直接写 ros::Time::now() 这个方式就失败了

3、等待坐标变换

TF2 提供了 一种方式 ,在指定的时间上,等待一段时间 有效的坐标变换到来。

lookupTransform()函数有第四个参数,就是做这个用的。

把该部分代码改成如下形式

try{
    transformStamped = tfBuffer.lookupTransform("turtle2", "turtle1", ros::Time::now(), 
                                                ros::Duration(3.0));
  } catch (tf2::TransformException &ex) {
    ROS_WARN("Could NOT transform turtle2 to turtle1: %s", ex.what());
  }

ros::Duration(3.0) 这个 就是 说明 在请求当前时刻的坐标变换时 允许等待 3 s 的时间。

改成这种方式 再编译 运行乌龟2 又会自动回到 乌龟1 上

在大部分的 TF2 使用的情况下 ros::Time(0) 使用的情况 更多些 。

ros::Time::now() 加 ros::Duration(3.0) 更加 严谨。

4、时间旅行

打开上面监听者的例子

打开 src/turtle_tf2_listener.cpp 这个文件

更改 这个部分代码

try{
    transformStamped = tfBuffer.lookupTransform("turtle2",      "turtle1", ros::Time::now(),ros::Duration(3.0));
    } catch (tf2::TransformException &ex) {
     ROS_WARN("Could NOT transform turtle2 to turtle1: %s", ex.what());
     }

现在不让第二只乌龟去第一只乌龟当前的位置了,而是去 5s 之前的位置。

代码 改成如下

try {
    ros::Time past = ros::Time::now() - ros::Duration(5.0);
    transformStamped = tfBuffer.lookupTransform("turtle2", "turtle1",
                       past, ros::Duration(1.0));
} catch (tf2::TransformException &ex) {
    ROS_WARN("Could NOT transform turtle2 to turtle1: %s", ex.what());
  }

编译运行

第1个5s,乌龟2 应该不会动,因为还没有 5s的历史数据。那之后的5s 呢。 试试

TF2中 监听者 对于 时间的控制 并实现 当前坐标系计算其它历史坐标系的坐标变换
乌龟2 在 乱动 , 为什么呢?

因为我们向 TF2 请求的是 相对于5s前乌龟1相对与5s前乌龟2 的 位置 。然后 作用在了 当前的 乌龟2的运动中。

那如何 获取 5秒前乌龟1的位置,相对与当前乌龟2的位置呢。

就是用下面 更高级 的 lookupTransform() 函数 API

5、更高级 的 lookupTransform() 函数 API

直接上代码

      try{
        ros::Time now = ros::Time::now();
        ros::Time past = now - ros::Duration(5.0);
        transformStamped = tfBuffer.lookupTransform("turtle2", now,
                             "turtle1", past,
                             "world", ros::Duration(1.0));
      } catch (tf2::TransformException &ex) {
        ROS_WARN("Could NOT transform turtle2 to turtle1: %s", ex.what());
      }

此时 lookupTransform() 函数 有 6 个 参数

1、从这个坐标系转换
2、 参数1 的 时刻
3、 转到这个坐标系
4、 参数3 的时刻
5、 一个 固定不变的坐标系
6、 时间 溢出时间

原理就是先求 参数 3 和参数4 到固定 坐标系的 变换 再求参数1 和参数2 的

6、检查结果

再编译运行

TF2中 监听者 对于 时间的控制 并实现 当前坐标系计算其它历史坐标系的坐标变换

第2 只 乌龟 现在 则 由 5s 前 的乌龟1 的位置 为导向了


开心洋葱 , 版权所有丨如未注明 , 均为原创丨未经授权请勿修改 , 转载请注明TF2中 监听者 对于 时间的控制 并实现 当前坐标系计算其它历史坐标系的坐标变换
喜欢 (0)

您必须 登录 才能发表评论!

加载中……