void PlaneSegmentationPclRgbAlgorithm::getBiggestPlaneInliersDownsampling(pcl::PointIndices::Ptr inliers, pcl::ModelCoefficients::Ptr coefficients, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud) { pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_downsampled (new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_seg (new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr ground_hull (new pcl::PointCloud<pcl::PointXYZ>); // downsampling pcl::VoxelGrid<pcl::PointXYZ> grid_objects_; grid_objects_.setLeafSize (pointcloud_downsample_size, pointcloud_downsample_size, pointcloud_downsample_size); grid_objects_.setDownsampleAllData (false); grid_objects_.setInputCloud (cloud); grid_objects_.filter (*cloud_downsampled); // segment plane if (choose_plane_by_distance) getNearestBigPlaneInliers(inliers, coefficients, cloud_downsampled); else getBiggestPlaneInliers(inliers, coefficients, cloud_downsampled); // check if the plane exists if (inliers->indices.size() == 0) { // if plane doesn't exist a black image will be returned ROS_WARN_STREAM("Plane segmentation: couldn't find plane."); return; } // copy inliers pcl::ProjectInliers<pcl::PointXYZ> proj; proj.setModelType(pcl::SACMODEL_PLANE); proj.setInputCloud(cloud_downsampled); proj.setModelCoefficients(coefficients); proj.setIndices (inliers); proj.filter(*cloud_seg); // remove NaN pcl::PassThrough<pcl::PointXYZ> pass; pass.setInputCloud (cloud_seg); pass.filter (*cloud_seg); // get biggest cluster if (plane_clustering) cloud_seg = getBiggestClusterPC(cloud_seg); // Create a Convex Hull representation of the projected inliers pcl::ConvexHull<pcl::PointXYZ> chull; chull.setInputCloud(cloud_seg); chull.setDimension(2); chull.reconstruct(*ground_hull); // Extract only those outliers that lie inside the ground plane's convex hull pcl::PointIndices::Ptr object_indices (new pcl::PointIndices); pcl::ExtractPolygonalPrismData<pcl::PointXYZ> hull_limiter; hull_limiter.setInputCloud(cloud); hull_limiter.setInputPlanarHull(ground_hull); hull_limiter.setHeightLimits(plane_min_height, plane_max_height); hull_limiter.segment(*object_indices); *inliers = *object_indices; }
void PclExtractor::cloudCallback(const Cloud2Msg::ConstPtr& cloud2Msg_input) { boost::mutex::scoped_lock(mutex_); sensor_msgs::PointCloud2 output; sensor_msgs::PointCloud2 convex_hull; sensor_msgs::PointCloud2 object_msg; sensor_msgs::PointCloud2 nonObject_msg; pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::fromROSMsg (*cloud2Msg_input, *cloud); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_p(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_f(new pcl::PointCloud<pcl::PointXYZ>); pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients); pcl::PointIndices::Ptr inliers(new pcl::PointIndices); // *** Normal estimation // Create the normal estimation class and pass the input dataset to it pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne; ne.setInputCloud(cloud); // Creating the kdTree object for the search method of the extraction pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>); ne.setSearchMethod(tree); // output dataset pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>); // use all neighbors in a sphere of radius 3cm ne.setRadiusSearch(0.3); // compute the features ne.compute(*cloud_normals); // *** End of normal estimation // *** Plane Estimation From Normals Start // Create the segmentation object pcl::SACSegmentationFromNormals<pcl::PointXYZ, pcl::Normal> seg; // Optional seg.setOptimizeCoefficients(true); // Mandatory // seg.setModelType(pcl::SACMODEL_PARALLEL_PLANE); seg.setModelType(pcl::SACMODEL_PLANE); // seg.setModelType(pcl::SACMODEL_PERPENDICULAR_PLANE); //y가 z // const Eigen::Vector3f z_axis(0,-1.0,0); // seg.setAxis(z_axis); // seg.setEpsAngle(seg_setEpsAngle_); seg.setMethodType(pcl::SAC_RANSAC); seg.setMaxIterations (seg_setMaxIterations_); seg.setDistanceThreshold(seg_setDistanceThreshold_); seg.setNormalDistanceWeight(seg_setNormalDistanceWeight_); // seg.setProbability(seg_probability_); seg.setInputCloud((*cloud).makeShared()); seg.setInputNormals(cloud_normals); seg.segment(*inliers, *coefficients); std::cerr <<"input: "<<cloud->width*cloud->height<<"Model inliers: " << inliers->indices.size () << std::endl; if (inliers->indices.size () == 0) { ROS_ERROR ("Could not estimate a planar model for the given dataset."); } // *** End of Plane Estimation // *** Plane Estimation Start // Create the segmentation object /* pcl::SACSegmentation<pcl::PointXYZ> seg; // Optional //seg.setOptimizeCoefficients(true); // Mandatory seg.setModelType(pcl::SACMODEL_PARALLEL_PLANE); // seg.setModelType(pcl::SACMODEL_PLANE); // seg.setModelType(pcl::SACMODEL_PERPENDICULAR_PLANE); //y가 z const Eigen::Vector3f z_axis(0,-1.0,0); seg.setAxis(z_axis); seg.setEpsAngle(seg_setEpsAngle_); seg.setMethodType(pcl::SAC_RANSAC); seg.setMaxIterations (seg_setMaxIterations_); seg.setDistanceThreshold(seg_setDistanceThreshold_); seg.setInputCloud((*cloud).makeShared()); seg.segment(*inliers, *coefficients); std::cerr <<"input: "<<cloud->width*cloud->height<<"Model inliers: " << inliers->indices.size () << std::endl; if (inliers->indices.size () == 0) { ROS_ERROR ("Could not estimate a planar model for the given dataset."); } // *** End of Plane Estimation */ pcl::ExtractIndices<pcl::PointXYZ> extract; // Extrat the inliers extract.setInputCloud(cloud); extract.setIndices(inliers); pcl::PointCloud<pcl::PointXYZ>::Ptr ground_hull(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projected(new pcl::PointCloud<pcl::PointXYZ>); if ((int)inliers->indices.size() > minPoints_) { extract.setNegative(false); extract.filter(*cloud_p); pcl::toROSMsg(*cloud_p, output); std::cerr << "PointCloud representing the planar component: " << cloud_p->width * cloud_p->height << " data points." << std::endl; // Step 3c. Project the ground inliers pcl::ProjectInliers<pcl::PointXYZ> proj; proj.setModelType(pcl::SACMODEL_PLANE); proj.setInputCloud(cloud_p); proj.setModelCoefficients(coefficients); proj.filter(*cloud_projected); // Step 3d. Create a Convex Hull representation of the projected inliers pcl::ConvexHull<pcl::PointXYZ> chull; //chull.setInputCloud(cloud_p); chull.setInputCloud(cloud_projected); chull.setDimension(chull_setDimension_);//2D chull.reconstruct(*ground_hull); pcl::toROSMsg(*ground_hull, convex_hull); //pcl::toROSMsg(*ground_hull, convex_hull); ROS_INFO ("Convex hull has: %d data points.", (int) ground_hull->points.size ()); // Publish the data plane_pub_.publish (output); hull_pub_.publish(convex_hull); } // Create the filtering object extract.setNegative(true); extract.filter(*cloud_f); ROS_INFO ("Cloud_f has: %d data points.", (int) cloud_f->points.size ()); // cloud.swap(cloud_f); pcl::PointCloud<pcl::PointXYZ>::Ptr object(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr nonObject(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointIndices::Ptr object_indices(new pcl::PointIndices); // cloud statictical filter pcl::PointCloud<pcl::PointXYZ>::Ptr cloudStatisticalFiltered (new pcl::PointCloud<pcl::PointXYZ>); pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor; sor.setInputCloud(cloud_f); sor.setMeanK(sor_setMeanK_); sor.setStddevMulThresh(sor_setStddevMulThresh_); sor.filter(*cloudStatisticalFiltered); pcl::ExtractIndices<pcl::PointXYZ> exObjectIndices; //exObjectIndices.setInputCloud(cloud_f); exObjectIndices.setInputCloud(cloudStatisticalFiltered); exObjectIndices.setIndices(object_indices); exObjectIndices.filter(*object); exObjectIndices.setNegative(true); exObjectIndices.filter(*nonObject); ROS_INFO ("Object has: %d data points.", (int) object->points.size ()); pcl::toROSMsg(*object, object_msg); object_pub_.publish(object_msg); //pcl::toROSMsg(*nonObject, nonObject_msg); //pcl::toROSMsg(*cloud_f, nonObject_msg); pcl::toROSMsg(*cloudStatisticalFiltered, nonObject_msg); nonObject_pub_.publish(nonObject_msg); }