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

Revision history [back]

click to hide/show revision 1
initial version

Can anyone tell me which of the answers above is correct for tf in Indigo - and does Python tf behave the same as C++ tf?

Can anyone tell me which of the answers above given is correct for tf in Indigo - and does Python tf behave the same as C++ tf?tf? i.e. does tf

  • interpolate between the two transforms nearest in time, or
  • return the nearest transform in time without interpolation

Can anyone tell me which of the answers given is correct for tf in Indigo - and does Python tf behave the same as C++ tf? i.e. does tf

  • interpolate between the two transforms nearest in time, or
  • return the nearest transform in time without interpolation

I think that http://wiki.ros.org/tf/FAQ#How_does_tf_deal_with_interpolation_and_extrapolation.3F claims that it does interpolation, but it's not totally unambiguous.

Can anyone tell me which of the answers given is correct example code below for tf in Indigo - and does Python tf behave the same as C++ tf? i.e. does tf

  • interpolate (on Ubuntu 14.04) interpolating between the two transforms nearest in time, or
  • return the nearest transform in time without interpolation
time

note: I think that http://wiki.ros.org/tf/FAQ#How_does_tf_deal_with_interpolation_and_extrapolation.3F claims that it does interpolation, but it's not totally unambiguous.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;

};

example code below for tf in Indigo (on Ubuntu 14.04) interpolating between the two transforms nearest in timetime . 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_tf_deal_with_interpolation_and_extrapolation.3F 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;

};