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