plane_segmentation_pcl_rgb_alg.cpp
Go to the documentation of this file.
00001 #include "plane_segmentation_pcl_rgb_alg.h"
00002 
00003 PlaneSegmentationPclRgbAlgorithm::PlaneSegmentationPclRgbAlgorithm(void)
00004 {
00005 }
00006 
00007 PlaneSegmentationPclRgbAlgorithm::~PlaneSegmentationPclRgbAlgorithm(void)
00008 {
00009 }
00010 
00011 void PlaneSegmentationPclRgbAlgorithm::config_update(Config& new_cfg, uint32_t level)
00012 {
00013         this->lock();
00014         
00015         this->pointcloud_downsample      = new_cfg.pointcloud_downsample;
00016         this->pointcloud_downsample_size = new_cfg.pointcloud_downsample_size;
00017         this->choose_plane_by_distance   = new_cfg.choose_plane_by_distance;
00018         this->choose_nearest_plane       = new_cfg.choose_nearest_plane;
00019         this->plane_size_thresh          = new_cfg.plane_size_thresh;
00020         this->plane_min_height           = new_cfg.plane_min_height;
00021         this->plane_max_height           = new_cfg.plane_max_height;
00022         this->plane_segm_iterations      = new_cfg.plane_segm_iterations;
00023         this->plane_clustering           = new_cfg.plane_clustering;
00024         this->plane_min_cluster_size     = new_cfg.plane_min_cluster_size;
00025         this->plane_min_cluster_distance = new_cfg.plane_min_cluster_distance;
00026         this->plane_segm_probability     = new_cfg.plane_segm_probability;
00027         
00028         // save the current configuration
00029         this->config_=new_cfg;
00030         
00031         this->unlock();
00032 }
00033 
00034 // PlaneSegmentationPclRgbAlgorithm Public API
00035 pcl::PointCloud<pcl::PointXYZRGB>::Ptr PlaneSegmentationPclRgbAlgorithm::segmentBiggestPlane (pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_rgb_orig, 
00036                                                                                               pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_orig, 
00037                                                                                               pcl::ModelCoefficients::Ptr coefficients)
00038 {
00039         pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_rgb_dst (new pcl::PointCloud<pcl::PointXYZRGB>);
00040         
00041         // we will need a copy of the pointcloud
00042         *cloud_rgb_dst = *cloud_rgb_orig; 
00043         
00044         // Plane segmentation indices
00045         pcl::PointIndices::Ptr inliers (new pcl::PointIndices ());
00046         
00047         // Downsample to improve performance
00048         if (pointcloud_downsample)
00049                 getBiggestPlaneInliersDownsampling(inliers, coefficients, cloud_orig);
00050         else
00051                 getBiggestPlaneInliers(inliers, coefficients, cloud_orig);
00052         
00053         
00054         // set all points but inliers to black
00055         for (size_t i = 0; i < cloud_rgb_dst->size(); ++i)
00056         {
00057                 cloud_rgb_dst->at(i).rgb = 0;
00058         }
00059         
00060         for (size_t i = 0; i < inliers->indices.size(); ++i)
00061         {
00062                 cloud_rgb_dst->at(inliers->indices[i]).rgb = cloud_rgb_orig->at(inliers->indices[i]).rgb;
00063         }
00064         
00065         // coefficients should be always pointing to the camera. If they are not, they will be inverted
00066         fixPlaneCoefficientsOrientation(coefficients);
00067         
00068         return cloud_rgb_dst;
00069 }
00070 
00071 
00072 void PlaneSegmentationPclRgbAlgorithm::getBiggestPlaneInliersDownsampling(pcl::PointIndices::Ptr inliers,
00073                                                                           pcl::ModelCoefficients::Ptr coefficients,
00074                                                                           pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
00075 {
00076         pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_downsampled (new pcl::PointCloud<pcl::PointXYZ>);
00077         pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_seg (new pcl::PointCloud<pcl::PointXYZ>);
00078         pcl::PointCloud<pcl::PointXYZ>::Ptr ground_hull (new pcl::PointCloud<pcl::PointXYZ>);
00079         
00080         // downsampling
00081         pcl::VoxelGrid<pcl::PointXYZ> grid_objects_;
00082         grid_objects_.setLeafSize (pointcloud_downsample_size, pointcloud_downsample_size, pointcloud_downsample_size);
00083         grid_objects_.setDownsampleAllData (false);
00084         
00085         grid_objects_.setInputCloud (cloud);
00086         grid_objects_.filter (*cloud_downsampled);
00087         
00088         // segment plane
00089         if (choose_plane_by_distance)
00090                 getNearestBigPlaneInliers(inliers, coefficients, cloud_downsampled);
00091         else
00092                 getBiggestPlaneInliers(inliers, coefficients, cloud_downsampled);
00093         
00094         // check if the plane exists
00095         if (inliers->indices.size() == 0) {
00096                 // if plane doesn't exist a black image will be returned
00097                 ROS_WARN_STREAM("Plane segmentation: couldn't find plane.");
00098                 return;
00099         }
00100         
00101         // copy inliers
00102         pcl::ProjectInliers<pcl::PointXYZ> proj;
00103         proj.setModelType(pcl::SACMODEL_PLANE);
00104         proj.setInputCloud(cloud_downsampled);
00105         proj.setModelCoefficients(coefficients);
00106         proj.setIndices (inliers);
00107         proj.filter(*cloud_seg);
00108         
00109         // remove NaN
00110         pcl::PassThrough<pcl::PointXYZ> pass;
00111         pass.setInputCloud (cloud_seg);
00112         pass.filter (*cloud_seg);
00113         
00114         // get biggest cluster
00115         if (plane_clustering)
00116                 cloud_seg = getBiggestClusterPC(cloud_seg);
00117         
00118         // Create a Convex Hull representation of the projected inliers
00119         pcl::ConvexHull<pcl::PointXYZ> chull;
00120         chull.setInputCloud(cloud_seg);
00121         chull.setDimension(2);
00122         chull.reconstruct(*ground_hull);
00123         
00124         
00125         // Extract only those outliers that lie inside the ground plane's convex hull
00126         pcl::PointIndices::Ptr object_indices (new pcl::PointIndices);
00127         pcl::ExtractPolygonalPrismData<pcl::PointXYZ> hull_limiter;
00128         hull_limiter.setInputCloud(cloud);
00129         hull_limiter.setInputPlanarHull(ground_hull);
00130         hull_limiter.setHeightLimits(plane_min_height, plane_max_height);
00131         hull_limiter.segment(*object_indices);
00132         
00133         *inliers = *object_indices;
00134 }
00135 
00136 
00137 void PlaneSegmentationPclRgbAlgorithm::getNearestBigPlaneInliers(pcl::PointIndices::Ptr inliers,
00138                                                                  pcl::ModelCoefficients::Ptr coefficients,
00139                                                                  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_orig)
00140 {
00141         pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_seg (new pcl::PointCloud<pcl::PointXYZ>);
00142         pcl::PointIndices::Ptr inliers_first (new pcl::PointIndices ());
00143         pcl::PointIndices::Ptr inliers_second (new pcl::PointIndices ());
00144         pcl::ModelCoefficients::Ptr coefficients_first (new pcl::ModelCoefficients);
00145         pcl::ModelCoefficients::Ptr coefficients_second (new pcl::ModelCoefficients);
00146         pcl::ExtractIndices<pcl::PointXYZ> extract;
00147         float dist1, dist2;
00148         pcl::PointXYZ p_orig = pcl::PointXYZ(0,0,0);
00149         ROS_DEBUG("Get nearest big plane.");
00150         
00151         // Get biggest plane
00152         getBiggestPlaneInliers(inliers_first, coefficients_first, cloud_orig);
00153         
00154         // check if first plane exists
00155         if (inliers_first->indices.size () == 0) // no plane
00156                 return;
00157         
00158         //dist1 = euclideanDistance(cloud_orig->at(inliers_first->indices[0]), p_orig);
00159         dist1 = pointToPlaneDistance(p_orig, coefficients_first->values);
00160         
00161         // Remove plane from pointcloud
00162         extract.setInputCloud (cloud_orig);
00163         extract.setIndices (inliers_first);
00164         extract.setNegative (true);
00165         extract.filter (*cloud_seg);
00166         
00167         // Get second biggest plane
00168         getBiggestPlaneInliers(inliers_second, coefficients_second, cloud_seg);
00169         
00170         // check if the second plane exists
00171         if (inliers_second->indices.size () == 0) {
00172                 ROS_INFO_STREAM("Plane segmentation: couldn't find a second plane. Choosing biggest one.");
00173                 *inliers = *inliers_first;
00174                 *coefficients = *coefficients_first;
00175                 return;
00176         }
00177         
00178         //dist2 = euclideanDistance(cloud_seg->at(inliers_second->indices[0]), p_orig);
00179         dist2 = pointToPlaneDistance(p_orig, coefficients_second->values);
00180         
00181         ROS_DEBUG_STREAM("Dist 1 is "<<dist1);
00182         ROS_DEBUG_STREAM("Dist 2 is "<<dist2);
00183         
00184         // if first is nearest get its inliers 
00185         if ( ( (dist1 < dist2) && choose_nearest_plane ) || ( (dist1 > dist2) && !choose_nearest_plane ) ) {
00186                 ROS_DEBUG("Chose biggest plane.");
00187                 *inliers = *inliers_first;
00188                 *coefficients = *coefficients_first;
00189         }
00190         else { // else inliers would be of the second plane
00191                 ROS_DEBUG("Chose second biggest plane.");
00192                 *inliers = *inliers_second;
00193                 *coefficients = *coefficients_second;
00194                 *cloud_orig = *cloud_seg;
00195         }
00196         
00197         
00198 }
00199 
00200 
00201 void PlaneSegmentationPclRgbAlgorithm::getBiggestPlaneInliers(pcl::PointIndices::Ptr inliers,
00202                                                               pcl::ModelCoefficients::Ptr coefficients,
00203                                                               pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
00204 {
00205         // Create the segmentation object
00206         pcl::SACSegmentation<pcl::PointXYZ> seg;
00207         // Optional
00208         seg.setOptimizeCoefficients (true);
00209         // Iterations
00210         seg.setMaxIterations (plane_segm_iterations);
00211         // Probability
00212         seg.setProbability (plane_segm_probability);
00213         // Mandatory
00214         seg.setModelType (pcl::SACMODEL_PLANE);
00215         seg.setMethodType (pcl::SAC_RANSAC);
00216         seg.setDistanceThreshold (plane_size_thresh); // centimeters | from param server
00217         
00218         // segment
00219         seg.setInputCloud (cloud);
00220         seg.segment (*inliers, *coefficients);
00221 }
00222 
00223 
00224 void PlaneSegmentationPclRgbAlgorithm::fixPlaneCoefficientsOrientation(pcl::ModelCoefficients::Ptr coefs)
00225 {
00226         if (coefs->values.size() == 0) { // plane extraction failed
00227                 coefs->values.resize(4);
00228                 coefs->values[0] = 0;
00229                 coefs->values[1] = 0;
00230                 coefs->values[2] = 0;
00231                 coefs->values[3] = 0;
00232         }
00233         else if (coefs->values[2] < 0) {
00234                 coefs->values[0] = -coefs->values[0];
00235                 coefs->values[1] = -coefs->values[1];
00236                 coefs->values[2] = -coefs->values[2];
00237                 coefs->values[3] = -coefs->values[3];
00238         }
00239 }
00240 
00241 
00242 pcl::PointCloud<pcl::PointXYZ>::Ptr PlaneSegmentationPclRgbAlgorithm::getBiggestClusterPC (pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_orig)
00243 {
00244         pcl::EuclideanClusterExtraction<pcl::PointXYZ> pcl_cluster;
00245         // Min distance between two clusters
00246         pcl_cluster.setClusterTolerance (plane_min_cluster_distance);
00247         // Min number of points for a cluster
00248         pcl_cluster.setMinClusterSize (plane_min_cluster_size);
00249         
00250         ROS_DEBUG("Clustering");
00251         
00252         ROS_DEBUG_STREAM("Original pointcloud size is" << cloud_orig->points.size());
00253         
00254         std::vector<pcl::PointIndices> clusters;
00255         pcl_cluster.setInputCloud (cloud_orig);
00256         pcl_cluster.extract (clusters);
00257 
00258         //converts clusters into the PointCloud message
00259         pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZ>);
00260         
00261         ROS_DEBUG_STREAM("Number of clusters is " << clusters.size());
00262         
00263         if ((int)clusters.size () > 0 ) {
00264                 // get biggest cluster
00265                 size_t biggest_cluster = 0;
00266                 for (size_t j = 1; j < clusters.size (); ++j) {
00267                         if (clusters[biggest_cluster].indices.size () < clusters[j].indices.size ())
00268                                 biggest_cluster = j;
00269                 }
00270                 
00271                 ROS_DEBUG_STREAM("Biggest cluster is " << clusters[biggest_cluster].indices.size());
00272                 cloud_cluster->points.resize (clusters[biggest_cluster].indices.size ());
00273                 for (size_t j = 0; j < cloud_cluster->points.size (); ++j)
00274                 {
00275                         cloud_cluster->points[j].x = cloud_orig->points[clusters[biggest_cluster].indices[j]].x;
00276                         cloud_cluster->points[j].y = cloud_orig->points[clusters[biggest_cluster].indices[j]].y;
00277                         cloud_cluster->points[j].z = cloud_orig->points[clusters[biggest_cluster].indices[j]].z;
00278                 }
00279         }
00280         else
00281                 *cloud_cluster = *cloud_orig;
00282         
00283         return cloud_cluster;
00284 }


iri_plane_segmentation_pcl_rgb
Author(s): David Martinez
autogenerated on Fri Dec 6 2013 21:27:02