Go to the documentation of this file.00001 #ifndef CLOUD_ALGOS_GRSD_H
00002 #define CLOUD_ALGOS_GRSD_H
00003 
00004 #include <float.h>
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 #include <sensor_msgs/PointCloud2.h>
00013 
00014 #include "octomap/octomap.h"
00015 #include "pcl_to_octree/octree/OcTreePCL.h"
00016 #include "pcl_to_octree/octree/OcTreeNodePCL.h"
00017 #include "pcl_to_octree/octree/OcTreeServerPCL.h"
00018 
00019 #include "pcl/io/io.h"
00020 #include <pcl/io/pcd_io.h>
00021 #include <pcl_cloud_algos/pcl_cloud_algos_point_types.h>
00022 #include <visualization_msgs/MarkerArray.h>
00023 
00024 
00025 
00026 #include <pcl_ros/publisher.h>
00027 
00028 
00029 #include "pcl/kdtree/tree_types.h"
00030 #include "pcl/kdtree/kdtree.h"
00031 #include "pcl/kdtree/kdtree_flann.h"
00032 #include "pcl/kdtree/organized_data.h"
00033 #include "pcl/features/feature.h"
00034 
00035 
00036 #include <pcl_cloud_algos/cloud_algos.h>
00037 
00038 #define NR_CLASS 5
00039 
00040 
00041 #define _sqr(c) ((c)*(c))
00042 #define _sqr_dist(a,b) ( _sqr(((a).x())-((b).x())) + _sqr(((a).y())-((b).y())) + _sqr(((a).z())-((b).z())) )
00043 
00044 namespace pcl_cloud_algos
00045 {
00046 
00047 struct IntersectedLeaf
00048 {
00049   double sqr_distance; 
00050   octomap::point3d centroid; 
00051 };
00052 
00053 inline bool
00054   histogramElementCompare (const std::pair<int, IntersectedLeaf> &p1, const std::pair<int, IntersectedLeaf> &p2)
00055 {
00056   return (p1.second.sqr_distance < p2.second.sqr_distance);
00057 }
00058 
00059 class GlobalRSD : public CloudAlgo
00060 {
00061  public:
00062 
00063   
00064   typedef sensor_msgs::PointCloud2 OutputType;
00065   typedef sensor_msgs::PointCloud2 InputType;
00066   typedef pcl::KdTree<pcl::PointNormal>::Ptr KdTreePtr;
00067   
00068   int point_label_; 
00069   double width_; 
00070   int step_; 
00071   
00072   int min_voxel_pts_; 
00073   bool publish_cloud_centroids_; 
00074   bool publish_cloud_vrsd_; 
00075   
00076   double min_radius_plane_;
00077   double min_radius_edge_;
00078   double min_radius_noise_, max_radius_noise_;
00079   double max_min_radius_diff_;
00080   bool publish_octree_;
00081   
00082   pcl::PointCloud<pcl::PointNormal> cloud_centroids_; 
00083   pcl::PointCloud<pcl::PointNormal> cloud_vrsd_; 
00084   
00085 
00086   
00087   static std::string default_input_topic ()
00088     {return std::string ("cloud_pcd");}
00089 
00090   
00091   static std::string default_output_topic ()
00092     {return std::string ("cloud_grsd");};
00093 
00094   
00095   static std::string default_node_name () 
00096     {return std::string ("global_rsd_node");};
00097 
00098   
00099   void init (ros::NodeHandle&);
00100   void pre  ();
00101   void post ();
00102   std::vector<std::string> requires ();
00103   std::vector<std::string> provides ();
00104   std::string process (const boost::shared_ptr<const InputType>&);
00105   boost::shared_ptr<const OutputType> output ();
00106 
00107   struct QueryPoint : public pcl::PointNormal
00108   {
00109     QueryPoint(float x, float y, float z) {this->x=x; this->y=y; this->z=z;}
00110   };
00111 
00112 
00113   
00114   GlobalRSD () : CloudAlgo ()
00115   {
00116     point_label_ = -1;
00117     width_ = 0.03;
00118     step_ = 0;
00119     min_voxel_pts_ = 1;
00120     nr_bins_ = (NR_CLASS+1)*(NR_CLASS+2)/2;
00121     min_radius_plane_ = 0.045;
00122     min_radius_noise_ = 0.030, max_radius_noise_ = 0.050;
00123     max_min_radius_diff_ = 0.01;
00124     min_radius_edge_ = 0.030;
00125     publish_octree_ = false;
00126   }
00127   ~GlobalRSD ()
00128   {
00129   }
00130 
00131   ros::Publisher createPublisher (ros::NodeHandle& nh)
00132   {
00133     ros::Publisher p = nh.advertise<OutputType> (default_output_topic (), 5);
00134     return p;
00135   }
00136 
00138   
00139   
00140   
00142   
00143   
00144   
00145   
00146   
00147   
00148   inline int
00149     setSurfaceType (pcl::PointCloud<pcl::PointNormal> cloud, std::vector<int> *indices, std::vector<int> *neighbors, double max_dist)
00150   {
00151     
00152     int div_d = 5;
00153     double plane_radius = 0.2;
00154 
00155     
00156     std::vector<std::vector<double> > min_max_angle_by_dist (div_d);
00157     for (int di=0; di<div_d; di++)
00158     {
00159       min_max_angle_by_dist[di].resize (2);
00160       min_max_angle_by_dist[di][0] = +DBL_MAX;
00161       min_max_angle_by_dist[di][1] = -DBL_MAX;
00162     }
00163 
00164     
00165     for (unsigned int i = 0; i < neighbors->size (); i++)
00166       for (unsigned int j = i; j < neighbors->size (); j++)
00167       {
00168         
00169         double cosine = cloud.points[i].normal[0] * cloud.points[j].normal[0] +
00170           cloud.points[i].normal[1] * cloud.points[j].normal[1] +
00171           cloud.points[i].normal[2] * cloud.points[j].normal[2];
00172         if (cosine > 1) 
00173           cosine = 1;
00174         if (cosine < -1) 
00175           cosine = -1;
00176         double angle  = acos (cosine);
00177         if (angle > M_PI/2) 
00178           angle = M_PI - angle;
00179         
00180 
00181         
00182         
00183         double dist = sqrt ((cloud.points[neighbors->at(i)].x - cloud.points[neighbors->at(j)].x) * (cloud.points[neighbors->at(i)].x - cloud.points[neighbors->at(j)].x) +
00184                             (cloud.points[neighbors->at(i)].y - cloud.points[neighbors->at(j)].y) * (cloud.points[neighbors->at(i)].y - cloud.points[neighbors->at(j)].y) +
00185                             (cloud.points[neighbors->at(i)].z - cloud.points[neighbors->at(j)].z) * (cloud.points[neighbors->at(i)].z - cloud.points[neighbors->at(j)].z));
00186         
00187 
00188         
00189         int bin_d = (int) floor (div_d * dist / max_dist);
00190 
00191         
00192         if (min_max_angle_by_dist[bin_d][0] > angle) 
00193           min_max_angle_by_dist[bin_d][0] = angle;
00194         if (min_max_angle_by_dist[bin_d][1] < angle) 
00195           min_max_angle_by_dist[bin_d][1] = angle;
00196       }
00197 
00198     
00199     double Amint_Amin = 0, Amint_d = 0;
00200     double Amaxt_Amax = 0, Amaxt_d = 0;
00201     for (int di=0; di<div_d; di++)
00202     {
00203       
00204       
00205       if (min_max_angle_by_dist[di][1] >= 0)
00206       {
00207         double p_min = min_max_angle_by_dist[di][0];
00208         double p_max = min_max_angle_by_dist[di][1];
00209         
00210         double f = (di+0.5)*max_dist/div_d;
00211         
00212         Amint_Amin += p_min * p_min;
00213         Amint_d += p_min * f;
00214         Amaxt_Amax += p_max * p_max;
00215         Amaxt_d += p_max * f;
00216       }
00217     }
00218     
00219     double max_radius;
00220     if (Amint_Amin == 0) 
00221       max_radius = plane_radius;
00222     else 
00223       max_radius = std::min (Amint_d/Amint_Amin, plane_radius);
00224     double min_radius;
00225     if (Amaxt_Amax == 0) 
00226       min_radius = plane_radius;
00227     else 
00228       min_radius = std::min (Amaxt_d/Amaxt_Amax, plane_radius);
00229     
00230 
00231     
00232     int type;
00233     if (min_radius > min_radius_plane_) 
00234       type = 1; 
00235     else if ((min_radius < min_radius_noise_) && (max_radius < max_radius_noise_))
00236       type = 0; 
00237     else if (max_radius - min_radius < max_min_radius_diff_) 
00238       type = 3; 
00239     else if (min_radius < min_radius_edge_) 
00240       type = 4; 
00241     else
00242       type = 2; 
00243 
00244     
00245     if (type >= NR_CLASS)
00246       type = -1;
00247 
00248     
00249     return type;
00250   }
00251 
00252   
00253   void
00254     setOctree (pcl::PointCloud<pcl::PointNormal> pointcloud_msg, double octree_res, int initial_label, double laser_offset = 0, double octree_maxrange = -1)
00255   {
00256     octomap_server::OctomapBinary octree_msg;
00257 
00258     octomap::point3d octomap_3d_point;
00259     octomap::Pointcloud octomap_pointcloud;
00260 
00261 
00262     
00263     for(unsigned int i =0; i < pointcloud_msg.points.size(); i++)
00264     {
00265       octomap_3d_point(0) = pointcloud_msg.points[i].x;
00266       octomap_3d_point(1) = pointcloud_msg.points[i].y;
00267       octomap_3d_point(2) = pointcloud_msg.points[i].z;
00268       octomap_pointcloud.push_back(octomap_3d_point);
00269     }
00270 
00271     
00272     octomap::pose6d offset_trans(0,0,-laser_offset,0,0,0);
00273     octomap::pose6d laser_pose(0,0,laser_offset,0,0,0);
00274     octomap_pointcloud.transform(offset_trans);
00275 
00276 
00277     octomap::ScanGraph* octomap_graph = new octomap::ScanGraph();
00278     octomap_graph->addNode(&octomap_pointcloud, laser_pose);
00279 
00280     
00281 
00282     
00283     octree_ = new octomap::OcTreePCL(octree_res);
00284     for (octomap::ScanGraph::iterator scan_it = octomap_graph->begin(); scan_it != octomap_graph->end(); scan_it++)
00285     {
00286       octree_->insertScan(**scan_it, octree_maxrange, false);
00287     }
00288     
00289     if (publish_octree_)
00290     {
00291       octomap_server::octomapMapToMsg(*octree_, octree_msg);
00292       octree_binary_publisher_.publish(octree_msg);
00293       ROS_INFO("Octree built and published");
00294     }
00295 
00296     std::list<octomap::OcTreeVolume> voxels, leaves;
00297     
00298     octree_->getLeafNodes(leaves);
00299     std::list<octomap::OcTreeVolume>::iterator it1;
00300     int cnt = 0;
00301 
00302     
00303     for( it1 = leaves.begin(); it1 != leaves.end(); ++it1)
00304     {
00305       ROS_DEBUG("Leaf Node %d : x = %f y = %f z = %f side length = %f ", cnt++, it1->first.x(), it1->first.y(), it1->first.z(), it1->second);
00306       octomap::point3d centroid;
00307       centroid(0) = it1->first.x(),  centroid(1) = it1->first.y(),  centroid(2) = it1->first.z();
00308       octomap::OcTreeNodePCL *octree_node = octree_->search(centroid);
00309       octree_node->setCentroid(centroid);
00310       octree_node->setLabel(initial_label);
00311     }
00312     
00313     
00314     for(unsigned int i = 0; i < pointcloud_msg.points.size(); i++)
00315     {
00316       octomap_3d_point(0) = pointcloud_msg.points[i].x;
00317       octomap_3d_point(1) = pointcloud_msg.points[i].y;
00318       octomap_3d_point(2) = pointcloud_msg.points[i].z;
00319       octomap::OcTreeNodePCL * octree_node1 = octree_->search(octomap_3d_point);
00320       octree_node1->set3DPointInliers(i);
00321     }
00322   }
00323   
00324 
00325  private:
00326 
00327   
00328   ros::NodeHandle nh_;
00329   
00330   pcl_ros::Publisher<pcl::PointNormal> pub_cloud_vrsd_;
00331   
00332   pcl_ros::Publisher<pcl::PointNormal> pub_cloud_centroids_;
00333   ros::Publisher octree_binary_publisher_;
00334 
00335   
00336   int nr_bins_;
00337 
00338   
00339   
00340   pcl::PointCloud<pcl::GRSDSignature21> cloud_grsd_; 
00341 
00342   
00343   octomap::OcTreePCL* octree_;
00344 };
00345 
00346 }
00347 #endif
00348