Bootstrap

ROS2教程(11) - use time、Traveling in time、调试 - Linux

use time

更新监听节点

让我们回到<the_work_ws>/src/learning_tf2_cpp/src/turtle_tf2_listener.cpp,查看

lookupTransform()的调用。

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

我们可以看到,通过tf2::TimePointZero指定了一个为0的时间。

注意:tf2包有自己的时间类型 tf2::TimePoint,它与rclcpp::Time不同。tf2_ros包中的很多API会自动在rclcpp::Timetf2::TimePoint之间转换。rclcpp::Time(0, 0, this->get_clock()->get_clock_type()) 本可以在此处使用,但它无论如何都会被转换成tf2::TimePointZero

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

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

现在尝试运行launch文件。

ros2 launch learning_tf2_cpp turtle_tf2_demo.launch.py

会发现运行失败了,“它告诉你数据不存在”,输出如下:

[INFO] [1629873136.345688064] [listener]: Could not transform turtle2 to turtle1: 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]

缓冲区是工作原理:首先,每个监听器都有一个缓冲区,用于存储来自不同tf2广播器的所有坐标变换。其次,当广播器发出一个转换时,该转换需要一些时间才能进入缓冲区(通常是几毫秒)。因此,当在请求帧转换时,应该等待几毫秒才能收到该信息。

修复监听节点

tf2提供了一个很好的__等待转换__的工具,可以通过在lookupTransform()中添加超时参数来使用它。修复监听节点,请按如下所示编辑代码(添加最后一个超时参数):

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

lookupTransform()可以接受四个参数,其中第四个代表在等待超时的时间内阻塞。

检查结果

ros2 launch learning_tf2_cpp turtle_tf2_demo.launch.py

您应该注意到,lookupTransform()运行时会阻塞,直到两个乌龟之间的转换可用为止(这通常需要几毫秒)。一旦达到超时时间,若转换仍不可用就会引发异常。

Traveling in time

本教程将带我们更进一步,揭示一个强大的tf2技巧:the time travel。 简而言之,tf2库的一个关键特性是它能够在时间和空间上转换数据。

tf的the time travel功能可用于各种任务,例如长时间监控机器人的姿态。我们将使用该功能并对turtle2进行编程,使其跟随carrot1但落后5秒。

Time travel

现在我们想让乌龟2不再实时跟随让carrot,而是跟随去carrot的5s前的轨迹,我们编辑<the_work_ws>/src/learning_tf2_cpp/src/turtle_tf2_listener.cpp

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

高级 API

rclcpp::Time now = this->get_clock()->now();
rclcpp::Time when = now - rclcpp::Duration(5, 0);
t = tf_buffer_->lookupTransform(
    toFrameRel, // 目标框架
    now, // 转换时间
    fromFrameRel, // Source frame 
    when, // source frame 被 evaluated 的时间
    "world", // 不随时间变化的坐标系
    50ms); // 可用的等待时间

现在,tf2计算从世界坐标系到海龟2的转换。

ros2 launch learning_tf2_cpp turtle_tf2_fixed_frame_demo.launch.py

调试

  • 查看从坐标系base_linkcamera_link的转换
ros2 run tf2_ros tf2_echo base_link camera_link
  • 检查时间戳,使用tf2_monitor工具来监视对应的帧情况
ros2 run tf2_ros tf2_monitor turtle2 turtle1
;