ros2 / ros2/geometry2

`waitForTransform()` throws an exception even though the future should be ready

Open
#348 0 comments 0 reactions 1 assignee View on GitHub

@clalancette is already working on this.

Since Dec 3, 2020.

Dominant language
C++
Stars
153
Forks
256
Avg merge
3d 23h
Merged PRs (30d)
14

Description

Bug report

Required Info:

  • Operating System: Ubuntu 20.04
  • Installation type: Binaries
  • Version or commit hash: Foxy
  • DDS implementation: rmw_cyclonedds_cpp
  • Client library (if applicable): rclcpp
Steps to reproduce issue

I made a simple test package with one node that sends two transforms and one node that requests a transform that can be interpolated from those two.

git clone git@github.com:nnmm/tf2_example.git
cd tf2_example
git checkout 5b837b82b15555f1cd5f35df3987b8e95c172e19 # for reproducibility in case the main branch changes
colcon build
source install/setup.bash
ros2 launch wait_for_transform wait_for_transform.launch.xml \
        executor:=single \
        method:=wft_wait_for \
        request_time:=newest \
        send_first_tf:=during \
        send_second_tf:=after

It doesn't matter whether the second transform is sent during or after the waiting period.
The code that makes the request request looks essentially like this (wft_wait_for method in receiver.cpp):

auto future = tf_buffer_.waitForTransform("a", "b", tf2::TimePointZero, timeout_, callback_);
auto status = future.wait_for(timeout_);
if (status == std::future_status::deferred) {
  RCLCPP_INFO(get_logger(), "Status is deferred");
} else if (status == std::future_status::timeout) {
  RCLCPP_INFO(get_logger(), "Status is timeout");
} else {
  RCLCPP_INFO(get_logger(), "Status is ready, calling future.get()");
  const auto lu_time = tf2_ros::fromMsg(future.get().header.stamp);
}
Expected behavior

The most recent transform is requested, so as soon as the first transform arrives (which happens during the waiting period), I should be able to obtain the transform.

Actual behavior

The future has status ready as you'd hope, but an exception is thrown by get():

[receiver-2] [INFO] [1605268518.458370419] [receiver.callback]: Calling get() ...
[receiver-2] [INFO] [1605268518.458434859] [receiver]: Status is ready, calling future.get()
[receiver-2] terminate called after throwing an instance of 'tf2::LookupException'

Additional information

I haven't done much with futures before, but this seems like the way it could plausibly work, given https://github.com/ros2/geometry2/issues/347 and https://github.com/ros2/geometry2/issues/346 (only guessing since there is no documentation).

The timeout given to waitForTransform doesn't seem to matter anymore, only the timeout given to wait_for().

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.