pointcloud_mapper.cpp
Go to the documentation of this file.
00001 #include <ros/ros.h>
00002 #include <pcl_ros/point_cloud.h>
00003 #include <pcl_ros/transforms.h>
00004 #include <tf/transform_listener.h>
00005 #include <pcl/point_types.h>
00006 #include <pcl/filters/voxel_grid.h>
00007 #include <pcl/filters/passthrough.h>
00008 
00013 class PointCloudMapper
00014 {
00015 public:
00016 
00017   typedef pcl::PointXYZRGB      Point;
00018   typedef pcl::PointCloud<pcl::PointXYZRGB> PointCloud;
00019 
00020   PointCloudMapper() :
00021     nh_(), nh_priv_("~")
00022   {
00023     nh_priv_.param("fixed_frame", fixed_frame_, std::string("/map"));
00024     // Read the parameters from the parameter server (set defaults)
00025     nh_priv_.param("x_filter_min", x_filter_min_, -30.0);
00026     nh_priv_.param("x_filter_max", x_filter_max_, 30.0);
00027     nh_priv_.param("y_filter_min", y_filter_min_, -30.0);
00028     nh_priv_.param("y_filter_max", y_filter_max_, 30.0);
00029     nh_priv_.param("z_filter_min", z_filter_min_, 2.0);
00030     nh_priv_.param("z_filter_max", z_filter_max_, 30.0);
00031     nh_priv_.param("voxel_size", voxel_size_, 0.1);
00032     nh_priv_.param("filter_map", filter_map_, false);
00033 
00034     cloud_sub_ = nh_.subscribe<sensor_msgs::PointCloud2>("input", 1, &PointCloudMapper::callback, this);
00035     cloud_pub_ = nh_priv_.advertise<sensor_msgs::PointCloud2>("output", 1, true);
00036 
00037     accumulated_cloud_.header.frame_id = fixed_frame_;
00038 
00039     ROS_INFO_STREAM("[PointCloudMapper params:\n" <<
00040                     "\t* Fixed frame:   " << fixed_frame_ << "\n" <<
00041                     "\t* Filter map:    " << filter_map_ << "\n" <<
00042                     "\t* Filter bounds: " << "( " << x_filter_min_ << ", " << y_filter_min_ << ", " << z_filter_min_ << ") and ( " << x_filter_max_ << ", " << y_filter_max_ << ", " << z_filter_max_ << ")" << "\n" <<
00043                     "\t* Voxel size:    " << voxel_size_);
00044 
00045     pub_timer_ = nh_.createWallTimer(ros::WallDuration(3.0), &PointCloudMapper::publishCallback, this);
00046   }
00047 
00048   void callback(const sensor_msgs::PointCloud2ConstPtr& cloud_msg)
00049   {
00050     PointCloud cloud;
00051     pcl::fromROSMsg(*cloud_msg, cloud);
00052     ROS_INFO_STREAM("Received cloud with " << cloud.points.size() << " points.");
00053 
00054     PointCloud transformed_cloud;
00055     tf::StampedTransform transform;
00056     try {
00057       tf_listener_.waitForTransform(fixed_frame_, cloud_msg->header.frame_id, cloud_msg->header.stamp, ros::Duration(5.0));
00058       tf_listener_.lookupTransform(fixed_frame_, cloud_msg->header.frame_id, cloud_msg->header.stamp, transform);
00059     } catch (tf::TransformException ex){
00060       ROS_ERROR("%s",ex.what());
00061       ros::Duration(1.0).sleep();
00062     }
00063 
00064     pcl_ros::transformPointCloud(cloud, transformed_cloud, tf::Transform(transform));
00065     bool success = true;
00066     if (success)
00067     {
00068       accumulated_cloud_ += transformed_cloud;
00069 
00070       if(filter_map_)
00071       {
00072         PointCloud::Ptr cloud_downsampled = filter(accumulated_cloud_.makeShared());
00073         accumulated_cloud_ = *cloud_downsampled;
00074       }
00075 
00076       ROS_INFO_STREAM("Map has " << accumulated_cloud_.points.size() << " points.");
00077 
00078       // Publish the cloud
00079       if (cloud_pub_.getNumSubscribers() > 0)
00080         cloud_pub_.publish(accumulated_cloud_);
00081       last_pub_time_ = ros::WallTime::now();
00082     }
00083     else
00084     {
00085       ROS_ERROR("Could not transform point cloud to %s", fixed_frame_.c_str());
00086     }
00087   }
00088 
00089   void publishCallback(const ros::WallTimerEvent&)
00090   {
00091     // Publish the accumulated cloud if last publication was more than 5 seconds before.
00092     ros::WallDuration elapsed_time = ros::WallTime::now() - last_pub_time_;
00093     if (cloud_pub_.getNumSubscribers() > 0 && elapsed_time.toSec() > 5.0) {
00094 
00095       sensor_msgs::PointCloud2 cloud_msg;
00096       pcl::toROSMsg(accumulated_cloud_, cloud_msg);
00097       cloud_pub_.publish(cloud_msg);
00098     }
00099   }
00100 
00101   PointCloud::Ptr filter(PointCloud::Ptr cloud)
00102   {
00103     // Copy the point cloud
00104     PointCloud::Ptr cloud_ptr(new PointCloud);
00105 
00106     // NAN and limit filtering
00107     PointCloud::Ptr cloud_filtered_ptr(new PointCloud);
00108     pcl::PassThrough<Point> pass_;
00109 
00110     // X-filtering
00111     pass_.setFilterFieldName("x");
00112     pass_.setFilterLimits(x_filter_min_, x_filter_max_);
00113     pass_.setInputCloud(cloud);
00114     pass_.filter(*cloud_filtered_ptr);
00115 
00116     // Y-filtering
00117     pass_.setFilterFieldName("y");
00118     pass_.setFilterLimits(y_filter_min_, y_filter_max_);
00119     pass_.setInputCloud(cloud_filtered_ptr);
00120     pass_.filter(*cloud_filtered_ptr);
00121 
00122     // Z-filtering
00123     pass_.setFilterFieldName("z");
00124     pass_.setFilterLimits(z_filter_min_, z_filter_max_);
00125     pass_.setInputCloud(cloud);
00126     pass_.filter(*cloud_filtered_ptr);
00127 
00128     // Downsampling using voxel grid
00129     pcl::VoxelGrid<Point> grid_;
00130     PointCloud::Ptr cloud_downsampled_ptr(new PointCloud);
00131     double plane_detection_voxel_size_ = voxel_size_;
00132 
00133     grid_.setLeafSize(plane_detection_voxel_size_,
00134                       plane_detection_voxel_size_,
00135                       plane_detection_voxel_size_);
00136     grid_.setDownsampleAllData(true);
00137     grid_.setInputCloud(cloud_filtered_ptr);
00138     grid_.filter(*cloud_downsampled_ptr);
00139 
00140     return cloud_downsampled_ptr;
00141   }
00142 
00143 private:
00144   // Filter parameters
00145   double x_filter_min_;
00146   double x_filter_max_;
00147   double y_filter_min_;
00148   double y_filter_max_;
00149   double z_filter_min_;
00150   double z_filter_max_;
00151   double voxel_size_;
00152   bool filter_map_;
00153 
00154   ros::NodeHandle nh_;
00155   ros::NodeHandle nh_priv_;
00156 
00157   ros::WallTimer pub_timer_;
00158 
00159   ros::Subscriber cloud_sub_;
00160   ros::Publisher cloud_pub_;
00161 
00162   std::string fixed_frame_;
00163   tf::TransformListener tf_listener_;
00164   PointCloud accumulated_cloud_;
00165   ros::WallTime last_pub_time_;
00166 };
00167 
00168 int main(int argc, char **argv)
00169 {
00170   ros::init(argc, argv, "cloud_mapper");
00171   PointCloudMapper mapper;
00172   ros::spin();
00173   return 0;
00174 }
00175 


pointcloud_tools
Author(s): Pep Lluis Negre
autogenerated on Sat Jun 8 2019 20:10:22