使用时间 (C++)

目标 了解如何在特定时间获取变换,并等待变换在 tf2 树上可用。 lookupTransform() 功能。

辅导水平: 中级

时间 10 分钟

背景介绍

在之前的教程中,我们通过编写一个 tf2 广播公司 和一个 tf2 监听器.我们还学会了如何 为变换树添加新帧 并了解了 tf2 如何跟踪坐标帧树。该树会随时间变化,tf2 会为每次变换存储时间快照(默认情况下最多 10 秒)。到目前为止,我们使用 lookupTransform() 函数来获取该 tf2 树中最新的可用变换,但不知道该变换是在什么时间记录的。本教程将教你如何获取特定时间的变换。

任务

1 更新监听节点

让我们回到我们结束的地方 添加框架教程.转到 learning_tf2_cpp 包装。打开 turtle_tf2_listener.cpp 并看看 lookupTransform() 打电话:

尝试 {
    t = tf_buffer_->;查找变换(
       toFrameRel,
       fromFrameRel,
       tf2::时间点零);
} 捕捉 ( tf2::转换异常 及样品; ) {

您可以看到,我们通过调用 tf2::TimePointZero.

备注

"(《世界人权宣言》) tf2 软件包有自己的时间类型 tf2::TimePointrclcpp::Time.软件包中的许多应用程序接口 tf2_ros 自动转换为 rclcpp::Timetf2::TimePoint.

rclcpp::Time(0、 0, this->get_clock()->get_clock_type()) 本可以在这里使用,但它会被转换为 tf2::TimePointZero 不管怎么说

对于 tf2,时间 0 表示缓冲区中 "最新可用 "的变换。现在,修改这一行以获取当前时间的变换、 this->get_clock()->now():

rclcpp::时间 现在 = ->;获取时钟()->;现在();
尝试 {
    t = tf_buffer_->;查找变换(
        toFrameRel, fromFrameRel,
        现在);
} 捕捉 ( tf2::转换异常 及样品; ) {

现在构建软件包并尝试运行启动文件。

ros2 launch learning_tf2_cpp turtle_tf2_demo_launch.py

你会发现它失败了,输出类似下面的内容:

[INFO] [1629873136.345688064] [listener]:无法将 turtle2 转换为 turtle1:查找将
需要推断未来。要求的时间为 1629873136.345539,但最新数据
是在时间 1629873136.338804,从画面 [乌龟 1] 向上看变换到画面 [乌龟 2] 时

它会告诉你该帧不存在或数据在未来。

要理解为什么会出现这种情况,我们需要了解缓冲区是如何工作的。首先,每个监听器都有一个缓冲区,用于存储来自不同 tf2 广播器的所有坐标变换。其次,当广播者发送变换时,变换进入缓冲区需要一些时间(通常是几毫秒)。因此,当您在 "现在 "时间请求帧变换时,您需要等待几毫秒才能收到该信息。

2 修复监听节点

tf2 提供了一个很好的工具,可以等待变换可用。使用方法是在 lookupTransform().要解决这个问题,请按下图所示编辑代码(添加最后一个超时参数):

rclcpp::时间 现在 = ->;获取时钟()->;现在();
尝试 {
    t = tf_buffer_->;查找变换(
        toFrameRel,
        fromFrameRel,
        现在,
        50毫秒);
} 捕捉 ( tf2::转换异常 及样品; ) {

"(《世界人权宣言》) lookupTransform() 可以接受四个参数,其中最后一个参数是可选的超时时间。在超时之前,它会阻塞一段时间。

3 检查结果

现在您可以构建软件包并运行启动文件。

ros2 launch learning_tf2_cpp turtle_tf2_demo_launch.py

您应该注意到 lookupTransform() 实际上会阻塞,直到两只海龟之间的变换可用(通常需要几毫秒)。一旦超时(本例中为 50 毫秒),只有在变换仍不可用时才会出现异常。

摘要

在本教程中,您将学习如何在特定时间戳获取变换,以及在使用 lookupTransform() 功能。