使用时间(C++) [5840]

目标: 学习如何使用 lookupTransform() 函数在特定时间获取变换,并等待 tf2 树上的变换可用。 [5841]

教程级别: 中级 [16770]

时间: 10分钟 [16421]

背景 [16410]

在之前的教程中,我们通过编写 tf2 广播器tf2 监听器 来重新创建了乌龟演示。我们还学习了如何 向变换树中添加新帧,以及如何使用 tf2 来跟踪坐标帧的树结构。这个树随着时间的推移而改变,tf2 为每个变换存储了一个时间快照(默认为最近的 10 秒)。到目前为止,我们使用 lookupTransform() 函数来获取在 tf2 树中最新可用的变换,而不知道该变换是在何时记录的。本教程将教你如何在特定时间获取变换。 [5842]

任务 [16427]

1 tf2 和时间 [5843]

让我们回到上一个教程 添加一个帧 结束的地方。打开 learning_tf2_cpp 包中的 turtle_tf2_listener.cpp,并查看 lookupTransform() 的调用: [5844]

transformStamped = tf_buffer_->lookupTransform(
   toFrameRel,
   fromFrameRel,
   tf2::TimePointZero);

你可以看到我们通过调用 tf2::TimePointZero 指定了时间为 0。 [5845]

注解

tf2 包有自己的时间类型 tf2::TimePoint,与 rclcpp::Time 不同。在 tf2_ros 包中,许多 API 自动在 rclcpp::Timetf2::TimePoint 之间进行转换。 [5846]

rclcpp::Time(0, 0, this->get_clock()->get_clock_type()) 可以在此处使用,但它最终会被转换为 tf2::TimePointZero[5847]

对于 tf2,时间 0 表示缓冲区中的“最新可用”变换。现在,将此行更改为获取当前时间的变换,即 this->get_clock()->now(): [5848]

rclcpp::Time now = this->get_clock()->now();
transformStamped = tf_buffer_->lookupTransform(
   toFrameRel,
   fromFrameRel,
   now);

现在尝试运行启动文件。 [5849]

ros2 launch learning_tf2_cpp turtle_tf2_demo.launch.py

您会注意到它失败并输出类似于以下内容: [5850]

[INFO] [1629873136.345688064] [listener]: Could not transform turtle1 to turtle2: Lookup would
require extrapolation into the future.  Requested time 1629873136.345539 but the latest data
is at time 1629873136.338804, when looking up transform from frame [turtle1] to frame [turtle2]

它告诉您该帧不存在或数据位于未来。 [5851]

要理解为什么会发生这种情况,我们需要了解缓冲区的工作原理。首先,每个监听器都有一个缓冲区,用于存储来自不同tf2广播器的所有坐标转换。其次,当广播器发送一个转换时,需要一些时间才能将该转换放入缓冲区(通常需要几毫秒)。因此,当您在“现在”时间请求帧转换时,您应该等待几毫秒,以便该信息到达。 [5852]

2 等待转换 [5853]

tf2提供了一个很好的工具,可以等待直到转换可用。您可以通过向“lookupTransform()”添加一个超时参数来使用该工具。要修复这个问题,请按照下面的代码进行编辑(添加最后一个超时参数): [5854]

rclcpp::Time now = this->get_clock()->now();
transformStamped = tf_buffer_->lookupTransform(
   toFrameRel,
   fromFrameRel,
   now,
   50ms);

``lookupTransform()``可以接受四个参数,其中最后一个是可选的超时参数。它会阻塞最多该持续时间,直到超时。 [5855]

3 检查结果 [5856]

现在您可以运行启动文件。 [5857]

ros2 launch learning_tf2_cpp turtle_tf2_demo.launch.py

请注意,lookupTransform() 函数将阻塞直到两个乌龟之间的变换可用(通常需要几毫秒)。一旦超时时间到达(此例中为50毫秒),仅当变换仍不可用时才会引发异常。 [5858]

总结 [16454]

在本教程中,您学会了如何在特定时间戳获取变换,并在使用``lookupTransform()``函数时等待变换在tf2树上可用。 [5859]