Gazebo | Ignition | Community
Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Looks like the problem is that when you receive a laser scan, its timestamp is later than all the available /tf data. This is a common issue in a distributed system, and is what message filters were designed to address. You should try using a message filter.

In the meantime, to help understand the problem, below is a slightly modified version of the code you pointed to. In this version, I added a sleep to the laser scan callback to allow for /tf data to be received before trying to transform the latest scan. By default, this sleep would block receipt of all data, including /tf; so I created a multithreaded spinner. What you should see if you run this program is that at first transforms will fail as your /tf subscriber hooks up and starts getting data; then they'll start succeeding.

Again, don't use the code here; use message filters instead.

#include <ros/ros.h>
#include <tf/transform_listener.h>
#include <laser_geometry/laser_geometry.h>

class My_Filter {
     public:
        My_Filter();
        void scanCallback(const sensor_msgs::LaserScan::ConstPtr& scan);
     private:
        ros::NodeHandle node_;
        laser_geometry::LaserProjection projector_;
        tf::TransformListener tfListener_;

        ros::Publisher point_cloud_publisher_;
        ros::Subscriber scan_sub_;
};

My_Filter::My_Filter(){
        scan_sub_ = node_.subscribe<sensor_msgs::LaserScan> ("/multisense_sl/laser/scan", 100, &My_Filter::scanCallback, this);
        point_cloud_publisher_ = node_.advertise<sensor_msgs::PointCloud2> ("/cloud", 100, false);
        tfListener_.setExtrapolationLimit(ros::Duration(0.1));
}

void My_Filter::scanCallback(const sensor_msgs::LaserScan::ConstPtr& scan){
    // Sleep a little so that we have a better chance of having current /tf data
    // before trying to transfrom this latest /scan.
    ros::Duration(0.1).sleep();
    sensor_msgs::PointCloud2 cloud;
    try
    {
      projector_.transformLaserScanToPointCloud("pelvis", *scan, cloud, tfListener_);
    }
    catch(tf::TransformException& e)
    {
      printf("failed to transform: %s\n", e.what());
      return;
    }
    printf("success\n");
    point_cloud_publisher_.publish(cloud);
}

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

    My_Filter filter;

    // Start up two threads, one to handle /tf messages and the other for /scan
    // messages.
    ros::MultiThreadedSpinner spinner(2);
    spinner.spin();

    return 0;
}