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

How does tf do interpolation?

asked 2011-06-16 21:06:19 -0500

miltos gravatar image

updated 2011-06-17 12:36:48 -0500

mmwise gravatar image

I am sending a tf transform every 3s. What happens when I try to transform a point with timestamp between these 3 seconds? Which transform is used? Does an interpolation happen?

Thanks

edit retag flag offensive close merge delete

3 Answers

Sort by ยป oldest newest most voted
8

answered 2011-06-17 04:05:34 -0500

Wim gravatar image

TF will do a linear interpolation between the transform right before and the transform right after. In practice almost every tf request will require an interpolation; the only time this does not happen is when you ask for a transform that has the exact same timestamp as a transform received by tf.

edit flag offensive delete link more

Comments

This is right see the TePRA paper for more info: http://wiki.ros.org/Papers/TePRA2013_...

tfoote gravatar image tfoote  ( 2017-12-05 20:27:24 -0500 )edit

What about extrapolation? (Asking for a position at a timestamp later than last transform) Does it work?

mescarra gravatar image mescarra  ( 2018-04-11 08:08:26 -0500 )edit
1

tf no longer allows extrapolation as it was determined to amplify noise in the system and cause bad behavior.

tfoote gravatar image tfoote  ( 2018-04-11 12:14:40 -0500 )edit

Ok, so whenever you ask for a transform with timestamp ros::Time::now(), what you get is the last transform, and that's it, right? What options do I have if I'm in a real-time environment which needs a precise localization and transforms don't come to me as frequently as I would need them?

mescarra gravatar image mescarra  ( 2018-05-23 14:32:01 -0500 )edit

I mean, I really need extrapolation, what can I do? Thanks

mescarra gravatar image mescarra  ( 2018-05-23 14:32:38 -0500 )edit
1

You cannot get precise localization faster than the information arrives. Extrapolation results should not be considered precise. You can either focus on making sure the data is available sooner, make your algorithm robust to using older data, or add applicatoin specific forward projection.

tfoote gravatar image tfoote  ( 2018-05-23 14:47:43 -0500 )edit
0

answered 2011-06-16 23:27:50 -0500

dornhege gravatar image

It should do the right thing, i.e. the earlier transform from the timestamp of the point is used - or you get a failure if there is not transform for that time.

As the transform is delayed it might be a good idea to use a tf::MessageFilter.

edit flag offensive delete link more
0

answered 2017-12-05 03:33:11 -0500

Will Chamberlain gravatar image

updated 2017-12-05 19:32:56 -0500

example code below for tf in Indigo (on Ubuntu 14.04) interpolating between the two transforms nearest in time . You will need to run a map server or similar to set up the /map frame.

note: I think that http://wiki.ros.org/tf/FAQ#How_does_t... is ambiguous in its description of interpolation.

(gvdhoorn: thanks for your help, and updated this into an answer rather than a question)

#include <ros/ros.h>

#include <string>

#include <geometry_msgs/Twist.h>
#include <geometry_msgs/Point.h>
#include <geometry_msgs/PointStamped.h>
#include <geometry_msgs/PoseStamped.h>

#include <tf/transform_listener.h>
#include <tf/transform_broadcaster.h>
#include <tf/LinearMath/Vector3.h>


int main(int argc, char** argv){ ros::init(argc, argv, "pose_repeater_service");

ros::NodeHandle node;

//  http://wiki.ros.org/tf/Overview/Broadcasting%20Transforms
//  http://wiki.ros.org/tf/Tutorials/Writing%20a%20tf%20broadcaster%20%28C%2B%2B%29
//  void sendTransform(const StampedTransform & transform);
//  void sendTransform(const geometry_msgs::TransformStamped & transform);

  static tf::TransformListener    tfListener(ros::Duration(100));
  static tf::TransformBroadcaster tfBroadcaster;
  tf::Transform transform;
    transform.setOrigin( tf::Vector3(0.0, 0.0, 0.0) );
  tf::Quaternion q(0.0, 0.0, 0.0, 1.0);
    q.setRPY(0, 0, 0);
  transform.setRotation(q);

  ros::Time time1;
  time1 = ros::Time::now();
  tfBroadcaster.sendTransform(tf::StampedTransform(transform, time1, "/map", "/turtle_bob"));
  tfBroadcaster.sendTransform(tf::StampedTransform(transform, time1, "/map", "/turtle_bob_1"));

  ros::Duration(1.0).sleep();
  ros::Time time2 = ros::Time::now();

    transform.setOrigin( tf::Vector3(5.0, 5.0, 0.0) );
    q = tf::Quaternion(0.0, 0.0, 0.707106781, 0.707106781);
    transform.setRotation(q);
  ros::Duration(1.0).sleep();
//  ros::Time time3(1000000,2000000);
  ros::Time time3;
  time3 = ros::Time::now();
  tfBroadcaster.sendTransform(tf::StampedTransform(transform, time3, "/map", "/turtle_bob"));
  tfBroadcaster.sendTransform(tf::StampedTransform(transform, time3, "/map", "/turtle_bob_2"));


  ros::Rate rate(10.0);
  int i_ = 0;
  while (node.ok()){
    transform.setOrigin( tf::Vector3(0.0, 2.0+(0.01*i_), 0.0) );
    transform.setRotation( tf::Quaternion(0, 0, 0, 1.0) );
    tfBroadcaster.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "map", "carrot1"));
    i_++;

    for(int j_=0; j_<=10; j_++) {        
        tf::StampedTransform transformFound;

//        ros::Time time_(1000000,1000000+(j_*100000));
        ros::Time time_;
        time_ = time2;
        uint64_t time2_ns = time2.toNSec()+(j_*100*1000*1000);

        time_.fromNSec(time2_ns);
            try{
              tfListener.waitForTransform("/turtle_bob", "/map", time_, ros::Duration(1.0)); //ros::Time(0)
              tfListener.lookupTransform( "/turtle_bob", "/map", time_, transformFound);
              tfBroadcaster.sendTransform(tf::StampedTransform(transformFound, ros::Time::now(), "map", "turtle_bob_2_1"));        
            }
            catch (tf::TransformException &ex) {
              ROS_ERROR("%s",ex.what());
              ros::Duration(1.0).sleep();
              continue;
            }
            try{
              tfListener.waitForTransform("/map", "/turtle_bob", time_, ros::Duration(1.0)); //ros::Time(0)
              tfListener.lookupTransform( "/map", "/turtle_bob", time_, transformFound);
              tfBroadcaster.sendTransform(tf::StampedTransform(transformFound, ros::Time::now(), "map", "turtle_bob_2_2"));        
            }
            catch (tf::TransformException &ex) {
              ROS_ERROR("%s",ex.what());
              ros::Duration(1.0).sleep();
              continue;
            }
        rate.sleep();
    }
    tfBroadcaster.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "map", "carrot1"));
    rate.sleep();
  }

return 0;

};
edit flag offensive delete link more

Comments

Please do not ask question by posting new answers, it does not make much sense.

Post this as a new question, or shorten it a little and post it as a comment under the accepted answer.

re: your question: TF hasn't changed much since the answer by @Wim, so I assume his answer is still correct.

gvdhoorn gravatar image gvdhoorn  ( 2017-12-05 03:44:31 -0500 )edit

Could you clarify what you are showing here? The code is rather confusing.

gvdhoorn gravatar image gvdhoorn  ( 2017-12-06 07:24:06 -0500 )edit

Question Tools

1 follower

Stats

Asked: 2011-06-16 21:06:19 -0500

Seen: 4,613 times

Last updated: Dec 05 '17