ros2 从零开始30 使用时间c++
2026/7/13 8:33:07 网站建设 项目流程

ros2 从零开始30 使用时间c++

前言

背景

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

实践

本次不另外创建包,我们使用《编写静态广播C++》。

1.更新turtle_tf2_listener.cpp

learning_tf2_cpp/src目录下,打开文件turtle_tf2_listener.cpp,找到使用lookupTransform的地方:

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

[!TIP]
tf2包有自己的时间类型tf2::TimePoint,与rclcpp::Time不同,tf2_ros的许多API接口都会自动转换tf2::TimePointrclcpp::Time
rclcpp::Time(0, 0, this->get_clock()->get_clock_type())在tf2_ros使用时,无例外地会被转换为tf2::TimePointZero

我们指定时间参数为tf2::TimePointZero,也就是0 ,对于tf2, 时间0代表最新(后)有效的变换。现在修改成当前时间this->get_clock()->now()

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

编译运行后,我们看看输出

root@bc2bf85b2e4a:~/ros2_ws# ros2 launch learning_tf2_cpp turtle_tf2_demo_launch.xml[turtle_tf2_listener-4][INFO][1782209830.117096765][listener]: Could not transform turtle2 to turtle1: Lookup would require extrapolation into the future. Requestedtime1782209830.116734but the latest data is attime1782209830.109609, when looking up transform from frame[turtle1]to frame[turtle2][turtle_tf2_listener-4][INFO][1782209831.118229913][listener]: Could not transform turtle2 to turtle1: Lookup would require extrapolation into the future. Requestedtime1782209831.118175but the latest data is attime1782209831.116723, when looking up transform from frame[turtle1]to frame[turtle2][turtle_tf2_listener-4][INFO][1782209832.120139239][listener]: Could not transform turtle2 to turtle1: Lookup would require extrapolation into the future. Requestedtime1782209832.120042but the latest data is attime1782209832.108938, when looking up transform from frame[turtle1]to frame[turtle2]

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

2 修复该问题

tf2 提供一个很好的方法,就是等待这个数据可用。我们将使用lookupTransform()的超时参数,修改如下:

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

现在lookupTransform会阻塞等待50ms。

3 检查结果

重新编译运行,查看结果。

root@bc2bf85b2e4a:~/ros2_ws# ros2 launch learning_tf2_cpp turtle_tf2_demo_launch.xml

你应该注意到,lookupTransform()确实会阻塞直到两只乌龟的帧数据有效(通常会消耗几毫秒),一旦达到超时(50ms)仍然无数据可用,则依然会抛出异常。

总结

这个章节介绍了lookupTransform()的超时机制。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询