ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

Understanding the timeout parameter in lookupTransform

asked 2020-05-05 00:09:30 -0500

Rufus gravatar image

updated 2020-05-05 00:18:27 -0500

I'm trying to understand a bit how lookupTransform works, specifically what the timeout parameter does. I've always assumed that the timeout makes lookupTransform wait for the specified transform for up to the specified duration before throwing an exception. However, looking at the source code, I can't quite connect the dots here...

In buffer.cpp, lookupTransform is defined as follows:

geometry_msgs::TransformStamped 
Buffer::lookupTransform(const std::string& target_frame, const std::string& source_frame,
                        const ros::Time& time, const ros::Duration timeout) const
{
  canTransform(target_frame, source_frame, time, timeout);
  return lookupTransform(target_frame, source_frame, time);
}

And canTransform is defined here:

bool
Buffer::canTransform(const std::string& target_frame, const std::string& source_frame, 
                     const ros::Time& time, const ros::Duration timeout, std::string* errstr) const
{
  // Clear the errstr before populating it if it's valid.
  if (errstr)
    {
      errstr->clear();
    }

  if (!checkAndErrorDedicatedThreadPresent(errstr))
    return false;

  // poll for transform if timeout is set
  ros::Time start_time = now_fallback_to_wall();
  const ros::Duration sleep_duration = timeout * CAN_TRANSFORM_POLLING_SCALE;
  while (now_fallback_to_wall() < start_time + timeout && 
         !canTransform(target_frame, source_frame, time) &&
         (now_fallback_to_wall()+ros::Duration(3.0) >= start_time) &&  //don't wait when we detect a bag loop
         (ros::ok() || !ros::isInitialized())) // Make sure we haven't been stopped (won't work for pytf)
    {
      sleep_fallback_to_wall(sleep_duration);
    }
  bool retval = canTransform(target_frame, source_frame, time, errstr);
  conditionally_append_timeout_info(errstr, start_time, timeout);
  return retval;
}

It seems timeout gets passed to canTransform where it blocks until either timeout expires or canTransform returns true, however, the time that gets passed into the inner canTransform doesn't seem to get updated, i.e. if it returns false, it always returns false throughout the duration.

Furthermore, the results of this (outer) canTransform is not used at all, and lookupTransform just gets called with the initial time argument.

It seems to me my previous interpretation of this timeout parameter was incorrect and that that this timeout is just a dumb wait, with which the initial time (before waiting) is used to lookup the transform afterwards.

So my question is, what is the point of this timeout parameter and is my interpretation of its function is correct? Also, what is the point of calling canTransform, both the outer one (in lookupTransform) and the inner one (in canTransform)?

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
0

answered 2020-05-05 05:29:15 -0500

gvdhoorn gravatar image

canTransform(..) is used primarily as a check (an extensive one, as it checks 4 predicates).

If it returns before the timeout expires, this means the requested transform is present in the underlying buffer. It it returns after the timeout expires, the transform is not available.

But BufferCore::lookupTransform(..) which is eventually called (so not Buffer::lookupTransform(..)) will check again whether the buffer contains the transform, regardless of why canTransform(..) returned.

So either the timeout expires, and the frame is not present (BufferCore::lookupTransform(..) will throw a LookupException), or the timeout is not hit and the frame is present (no exception).

For this to work the result of canTransform(..) itself does not need to be passed to the caller.

It does mean there is a chance of a race-condition, where after the timeout expires, the frame becomes available, or, between canTransform(..) returning before timeout expiry, the frame is pruned from the buffer.

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2020-05-05 00:09:30 -0500

Seen: 907 times

Last updated: May 05 '20