时间旅行(C++)

**目标:**学习有关tf2高级时间旅行功能的知识。

教程级别: 中级

时间: 10分钟

背景

在前面的教程中,我们讨论了:doc:tf2和时间的基础知识。本教程将带我们迈出一步,并介绍一个强大的tf2技巧:时间旅行。简而言之,tf2库的一个关键功能是它能够在时间和空间上对数据进行转换。

这个tf2时间旅行功能在各种任务中都很有用,比如长时间监测机器人的姿态或构建一个会跟随领导者“步伐”的跟随机器人。我们将利用这个时间旅行功能,在时间上回溯并编程“turtle2”在“carrot1”之后追踪5秒钟。

时间旅行

首先,让我们回到上一教程 :doc:`使用时间 <./Learning-About-Tf2-And-Time-Cpp>`结束的地方。进入你的``learning_tf2_cpp``软件包。

现在,不再让第二只乌龟去当前胡萝卜所在的位置,而是让第二只乌龟去第一个胡萝卜5秒钟前所在的位置。在``turtle_tf2_listener.cpp``文件中编辑``lookupTransform()``调用:

rclcpp::Time when = this->get_clock()->now() - rclcpp::Duration(5, 0);
t = tf_buffer_->lookupTransform(
    toFrameRel,
    fromFrameRel,
    when,
    50ms);

如果现在运行这段代码,在前5秒钟内,第二只乌龟将不知道该去哪里,因为我们还没有5秒钟的胡萝卜位置历史记录。但是在这5秒钟之后会发生什么呢?让我们试一试:

ros2 launch learning_tf2_cpp turtle_tf2_fixed_frame_demo.launch.py
../../../_images/turtlesim_delay1.png

现在你应该注意到,你的乌龟在像这个截图中一样无法控制地四处移动。让我们试着理解背后的原因。

  1. 在我们的代码中,我们向tf2提出了以下问题:“相对于5秒前的``turtle2``,``carrot1``的姿势是什么?” 这意味着我们控制第二只乌龟的位置是基于它5秒钟前的位置以及第一个胡萝卜5秒钟前的位置。

  2. 然而,我们真正想要问的是:“相对于当前``turtle2``的位置,``carrot1``在5秒钟前的姿势是什么?”

高级API用于查找变换(lookupTransform())

为了询问tf2这个特定问题,我们将使用一个高级API,使我们能够明确地指定何时获取指定的转换。这是通过调用``lookupTransform()``方法并使用附加参数来实现的。你的代码现在应该是这样的:

rclcpp::Time now = this->get_clock()->now();
rclcpp::Time when = now - rclcpp::Duration(5, 0);
t = tf_buffer_->lookupTransform(
    toFrameRel,
    now,
    fromFrameRel,
    when,
    "world",
    50ms);

``lookupTransform()``的高级API接受六个参数:

  1. 目标帧

  2. 要进行转换的时间

  3. 源帧

  4. 评估源帧的时间

  5. 在这种情况下,``world``帧是随时间不变的帧

  6. 等待目标帧可用的时间

总结一下,在后台,tf2会进行以下操作:它会计算从``carrot1``到``world``的变换。在``world``帧中,tf2会在过去到现在的时间上进行移动。而在当前时间,tf2会计算从``world``到``turtle2``的变换。

检查结果

让我们再次运行模拟,这次使用高级的时间旅行API:

ros2 launch learning_tf2_cpp turtle_tf2_fixed_frame_demo.launch.py
../../../_images/turtlesim_delay2.png

是的,第二只乌龟被定向到了第一根胡萝卜5秒前的位置!

总结

在本教程中,您已经了解了tf2的一项高级功能。您了解到tf2可以在时间上对数据进行转换,并学习了如何在turtlesim示例中实现该功能。tf2允许您回溯时间,并通过使用高级的``lookupTransform()`` API在旧的和当前的乌龟姿势之间进行帧转换。