Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ROS tf.transform cannot find a frame which actually exists (can be traced with rosrun tf tf_echo)

Doe someone experienced with ROS the following behavior: how is it possible that a tf.lookupTransform("map", "base_link", ros::Time(0), transform);

tells you that: "base_link" passed to lookupTransform argument target_frame does not exist but if i enter:

rosrun tf tf_echo base_link map
At time 1549633095.937
- Translation: [-0.005, 0.020, -0.129]
- Rotation: in Quaternion [0.033, 0.063, 0.002, 0.997]
            in RPY (radian) [0.066, 0.127, 0.009]

I can see that the frame not only exist but that there is an effective transformation available between map and base_link?

I am totally clueless about such weird behavior. Any help will be very very welcome. Indeed the program is working on my laptop but not on an Intel NUC.

The complete piece of code is given below (actually I have a segmentation fault during the creation of the costmap_2d::costmap2DROS and looks like it is because tf.transform is failing):

 #include <ros/ros.h>
 #include <tf/transform_listener.h>
 #include <costmap_2d/costmap_2d_ros.h>

 int main(int argc, char **argv) {

    ros::init(argc, argv, "hector_exploration_node");

    ros::NodeHandle nh;

    tf::TransformListener tf;

    tf::StampedTransform transform;

    try{

            tf.lookupTransform("/base_link", "/map", ros::Time(0), transform);
            std::cout << "transform exist\n";
    }
    catch (tf::TransformException ex){
            ROS_ERROR("%s",ex.what());
            ros::Duration(1.0).sleep();
     }

    std::cout << "before costmap\n";
    costmap_2d::Costmap2DROS costmap("global_costmap", tf);
    costmap.start();        
    ros::Rate rate(10);

    while (ros::ok()) 
            ros::spin();

    return 0;
}
like image 948
fabrice Avatar asked Feb 08 '19 16:02

fabrice


1 Answers

You try to perform the transformation immediately after you've created your tf listener, which is commonly a bad practice for the following reason: The listener's buffer, which carries all information about recent transformation, is literally empty. Therefore, any transform which looks-up the buffer does not find the frames it needs. It is good practice to wait for some time after the listener has been created so that the buffer can fill up. But instead of just sleeping, tf comes with its own implementation to wait for exactly the frames you are asking for: waitForTransform. It can be used as explained here. Therefore, you just have to extend your try block as follows:

try{
        tf.waitForTransform("/base_link", "/map", ros::Time(0), ros::Duration(3.0));
        tf.lookupTransform("/base_link", "/map", ros::Time(0), transform);
        std::cout << "transform exist\n";
}
like image 74
Tik0 Avatar answered Oct 08 '22 10:10

Tik0