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

tf extrapolation exception using ros::Time(0)

asked 2012-07-08 16:36:32 -0600

joschu gravatar image

updated 2012-08-02 15:25:25 -0600

tfoote gravatar image

I'm trying to get the latest transform between two frames. What's wrong with this code?

listener.waitForTransform(target_frame, source_frame,      ros::Time(0),ros::Duration(.1));
tf::StampedTransform st;
listener.lookupTransform(target_frame, source_frame, ros::Time(0), st);


terminate called after throwing an instance of 'tf::ExtrapolationException'
  what():  Lookup would require extrapolation into the future.  Requested time 1341794988.800442521 but the latest data is at time 1341794988.782343800, when looking up transform from frame [/openni_rgb_optical_frame] to frame [/base_footprint]

EDIT: I got this error while playing back a bag file. When I set the parameter use_sim_time true, the error disappeared. I'm still mystified, though.

edit retag flag offensive close merge delete

4 Answers

Sort by » oldest newest most voted
6

answered 2012-08-02 15:20:37 -0600

tfoote gravatar image

This can happen if you have all links in your transform tree but they are not overlapping. This can happen if you have poor connectivity to part of your graph and part of the tree is significantly out of date.

The following test is an example: a->b is from t = 1,2,3 b->c is from 10,11,12 and it throws an extrapolation because there is no common time for which it can operate.

#include <tf/tf.h>
#include <gtest/gtest.h>


TEST(TimeCache, Repeatability)
{
  tf::Transformer tr;
  tf::StampedTransform t;
  t.setIdentity();
  t.child_frame_id_ = 'b';
  t.frame_id_ = 'a';

  t.stamp_ = ros::Time().fromNSec(1);
  tr.setTransform(t);

  t.stamp_ = ros::Time().fromNSec(2);
  tr.setTransform(t);

  t.stamp_ = ros::Time().fromNSec(3);
  tr.setTransform(t);

  t.child_frame_id_ = 'c';
  t.frame_id_ = 'b';

  t.stamp_ = ros::Time().fromNSec(10);
  tr.setTransform(t);

  t.stamp_ = ros::Time().fromNSec(11);
  tr.setTransform(t);

  t.stamp_ = ros::Time().fromNSec(12);
  tr.setTransform(t);


  std::string target = "a";
  std::string dest = "c";

  tr.lookupTransform(target, dest, ros::Time(), t);

}



int main(int argc, char **argv){
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
edit flag offensive delete link more
7

answered 2012-07-09 00:38:43 -0600

updated 2012-10-22 22:14:47 -0600

I don't think the waitForTransform is timing out, because it's throwing a tf::ExtrapolationException instead of returning. I've seen this error a lot (it was introduced in some TF update a few months back). I am not 100% sure what is happening (perhaps @tfoote can enlighten us).

What usually helps is something along those lines (warning, pseudocode):

time = ros::Time::now();  // or better msg->header.stamp, if available; never ros::Time(0)
success = false;
while (!success) {
  try {
    listener.waitForTransform(target_frame, source_frame, time, ros::Duration(3.0));
    listener.lookupTransform(target_frame, source_frame, time, st);
    success = true;
  } catch (tf::ExtrapolationException e) {
  }
  sleep(0.1);
}
edit flag offensive delete link more

Comments

What is bad in using ros::Time(0) instead?

niosus gravatar image niosus  ( 2012-10-22 22:51:46 -0600 )edit

It's been a while since I posted this, so I don't remember exactly. But I remember dimly that ros::Time(0) always caused the waitForTransform() to throw an exception with the specific transforms I tested with, whereas repeatedly waiting for a fixed time (as shown above) would succeed eventually.

Martin Günther gravatar image Martin Günther  ( 2012-10-23 02:54:15 -0600 )edit
1

answered 2012-07-08 17:00:32 -0600

Your waitForTransform call is likely timing out. You can look at the return value of waitForTransform to figure out if it stopped blocking because the transform is available, or because it timed out. Using a duration of 0.1 is also quite short.

edit flag offensive delete link more

Comments

nope, it wasn't timing out. I used a longer duration but it didn't help.

joschu gravatar image joschu  ( 2012-07-10 06:53:08 -0600 )edit
1

answered 2012-07-09 01:11:54 -0600

dornhege gravatar image

Actually I can't explain why this error can happen from this code and would consider it a bug in my understanding of the API.

What the error message says is that the buffer stores data to xxx.78, but you requested data at the time xxx.80 (i.e. later as in the buffer). This usually happens, when you request data with ros::Time::now(), which just isn't there, yet.

However, you are using 0 as the time, which according to the API docs, should mean to get the latest transform. So, if there is data in the buffer this should always work and you should not be able to get an ExtrapolationException.

Simple question: Are you sure it origins from that piece of code?

edit flag offensive delete link more

Comments

Yes. The error happens here.

joschu gravatar image joschu  ( 2012-07-10 06:59:03 -0600 )edit

Question Tools

2 followers

Stats

Asked: 2012-07-08 16:36:32 -0600

Seen: 8,150 times

Last updated: Oct 22 '12