region_growing_multiple_plane_segmentation_nodelet.cpp
Go to the documentation of this file.
00001 // -*- mode: c++ -*-
00002 /*********************************************************************
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2014, JSK Lab
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/o2r other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of the JSK Lab nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
00034  *********************************************************************/
00035 
00036 #include "jsk_pcl_ros/pcl_conversion_util.h"
00037 #include "jsk_pcl_ros/geo_util.h"
00038 #include "jsk_pcl_ros/region_growing_multiple_plane_segmentation.h"
00039 #include <pcl/segmentation/conditional_euclidean_clustering.h>
00040 #include <pcl/sample_consensus/method_types.h>
00041 #include <pcl/sample_consensus/model_types.h>
00042 #include <pcl/segmentation/sac_segmentation.h>
00043 
00044 namespace jsk_pcl_ros
00045 {
00046 
00047   void RegionGrowingMultiplePlaneSegmentation::onInit()
00048   {
00049     DiagnosticNodelet::onInit();
00050 
00051     srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> > (*pnh_);
00052     dynamic_reconfigure::Server<Config>::CallbackType f =
00053       boost::bind (
00054         &RegionGrowingMultiplePlaneSegmentation::configCallback, this, _1, _2);
00055     srv_->setCallback (f);
00056 
00057     pub_polygons_ = advertise<jsk_recognition_msgs::PolygonArray>(
00058       *pnh_, "output/polygons", 1);
00059     pub_inliers_ = advertise<jsk_recognition_msgs::ClusterPointIndices>(
00060       *pnh_, "output/inliers", 1);
00061     pub_coefficients_ = advertise<jsk_recognition_msgs::ModelCoefficientsArray>(
00062       *pnh_, "output/coefficients", 1);
00063     pub_clustering_result_ = advertise<jsk_recognition_msgs::ClusterPointIndices>(
00064       *pnh_, "output/clustering_result", 1);
00065   }
00066 
00067   void RegionGrowingMultiplePlaneSegmentation::subscribe()
00068   {
00069     sub_input_.subscribe(*pnh_, "input", 1);
00070     sub_normal_.subscribe(*pnh_, "input_normal", 1);
00071     sync_
00072       = boost::make_shared<
00073       message_filters::Synchronizer<NormalSyncPolicy> >(100);
00074     sync_->connectInput(sub_input_, sub_normal_);
00075     sync_->registerCallback(
00076       boost::bind(&RegionGrowingMultiplePlaneSegmentation::segment, this,
00077                   _1, _2));
00078   }
00079 
00080   void RegionGrowingMultiplePlaneSegmentation::unsubscribe()
00081   {
00082     sub_input_.unsubscribe();
00083     sub_normal_.unsubscribe();
00084   }
00085 
00086   void RegionGrowingMultiplePlaneSegmentation::configCallback(
00087     Config &config, uint32_t level)
00088   {
00089     boost::mutex::scoped_lock lock(mutex_);
00090     angular_threshold_ = config.angular_threshold;
00091     distance_threshold_ = config.distance_threshold;
00092     max_curvature_ = config.max_curvature;
00093     min_size_ = config.min_size;
00094     max_size_ = config.max_size;
00095     cluster_tolerance_ = config.cluster_tolerance;
00096     ransac_refine_outlier_distance_threshold_
00097       = config.ransac_refine_outlier_distance_threshold;
00098     ransac_refine_max_iterations_
00099       = config.ransac_refine_max_iterations;
00100   }
00101 
00102   void RegionGrowingMultiplePlaneSegmentation::ransacEstimation(
00103     const pcl::PointCloud<pcl::PointXYZRGB>::Ptr& cloud,
00104     const pcl::PointIndices::Ptr& indices,
00105     pcl::PointIndices& inliers,
00106     pcl::ModelCoefficients& coefficient)
00107   {
00108     pcl::SACSegmentation<pcl::PointXYZRGB> seg;
00109     seg.setOptimizeCoefficients (true);
00110     seg.setMethodType (pcl::SAC_RANSAC);
00111     seg.setDistanceThreshold (ransac_refine_outlier_distance_threshold_);
00112     seg.setInputCloud(cloud);
00113     seg.setIndices(indices);
00114     seg.setMaxIterations (ransac_refine_max_iterations_);
00115     seg.setModelType (pcl::SACMODEL_PLANE);
00116     seg.segment(inliers, coefficient);
00117   }
00118   
00119   void RegionGrowingMultiplePlaneSegmentation::segment(
00120     const sensor_msgs::PointCloud2::ConstPtr& msg,
00121     const sensor_msgs::PointCloud2::ConstPtr& normal_msg)
00122   {
00123     boost::mutex::scoped_lock lock(mutex_);
00124     vital_checker_->poke();
00125     pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);
00126     pcl::PointCloud<pcl::Normal>::Ptr normal(new pcl::PointCloud<pcl::Normal>);
00127     pcl::fromROSMsg(*msg, *cloud);
00128     pcl::fromROSMsg(*normal_msg, *normal);
00129     // concatenate fields
00130     pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr
00131       all_cloud (new pcl::PointCloud<pcl::PointXYZRGBNormal>);
00132     pcl::concatenateFields(*cloud, *normal, *all_cloud);
00133     pcl::PointIndices::Ptr indices (new pcl::PointIndices);
00134     for (size_t i = 0; i < all_cloud->points.size(); i++) {
00135       if (!isnan(all_cloud->points[i].x) &&
00136           !isnan(all_cloud->points[i].y) &&
00137           !isnan(all_cloud->points[i].z) &&
00138           !isnan(all_cloud->points[i].normal_x) &&
00139           !isnan(all_cloud->points[i].normal_y) &&
00140           !isnan(all_cloud->points[i].normal_z) &&
00141           !isnan(all_cloud->points[i].curvature)) {
00142         if (all_cloud->points[i].curvature < max_curvature_) {
00143           indices->indices.push_back(i);
00144         }
00145       }
00146     }
00147     pcl::ConditionalEuclideanClustering<pcl::PointXYZRGBNormal> cec (true);
00148     
00149     // vector of pcl::PointIndices
00150     pcl::IndicesClustersPtr clusters (new pcl::IndicesClusters);
00151     cec.setInputCloud (all_cloud);
00152     cec.setIndices(indices);
00153     cec.setClusterTolerance(cluster_tolerance_);
00154     cec.setMinClusterSize(min_size_);
00155     //cec.setMaxClusterSize(max_size_);
00156     {
00157       boost::mutex::scoped_lock lock2(global_custom_condigion_function_mutex);
00158       setCondifionFunctionParameter(angular_threshold_, distance_threshold_);
00159       cec.setConditionFunction(
00160         &RegionGrowingMultiplePlaneSegmentation::regionGrowingFunction);
00161       //ros::Time before = ros::Time::now();
00162       cec.segment (*clusters);
00163       // ros::Time end = ros::Time::now();
00164       // ROS_INFO("segment took %f sec", (before - end).toSec());
00165     }
00166     // Publish raw cluster information 
00167     // pcl::IndicesCluster is typdefed as std::vector<pcl::PointIndices>
00168     jsk_recognition_msgs::ClusterPointIndices ros_clustering_result;
00169     ros_clustering_result.cluster_indices
00170       = pcl_conversions::convertToROSPointIndices(*clusters, msg->header);
00171     ros_clustering_result.header = msg->header;
00172     pub_clustering_result_.publish(ros_clustering_result);
00173 
00174     // estimate planes
00175     std::vector<pcl::PointIndices::Ptr> all_inliers;
00176     std::vector<pcl::ModelCoefficients::Ptr> all_coefficients;
00177     jsk_recognition_msgs::PolygonArray ros_polygon;
00178     ros_polygon.header = msg->header;
00179     for (size_t i = 0; i < clusters->size(); i++) {
00180       pcl::PointIndices::Ptr plane_inliers(new pcl::PointIndices);
00181       pcl::ModelCoefficients::Ptr plane_coefficients(new pcl::ModelCoefficients);
00182       pcl::PointIndices::Ptr cluster = boost::make_shared<pcl::PointIndices>((*clusters)[i]);
00183       ransacEstimation(cloud, cluster,
00184                        *plane_inliers, *plane_coefficients);
00185       if (plane_inliers->indices.size() > 0) {
00186         ConvexPolygon::Ptr convex
00187           = convexFromCoefficientsAndInliers<pcl::PointXYZRGB>(
00188             cloud, plane_inliers, plane_coefficients);
00189         if (convex) {
00190           {
00191             // check direction consistency of coefficients and convex
00192             Eigen::Vector3f coefficient_normal(plane_coefficients->values[0],
00193                                                plane_coefficients->values[1],
00194                                                plane_coefficients->values[2]);
00195             if (convex->getNormalFromVertices().dot(coefficient_normal) < 0) {
00196               convex = boost::make_shared<ConvexPolygon>(convex->flipConvex());
00197             }
00198           }
00199           // Normal should direct to origin
00200           {
00201             Eigen::Vector3f p = convex->getPointOnPlane();
00202             Eigen::Vector3f n = convex->getNormal();
00203             if (p.dot(n) > 0) {
00204               convex = boost::make_shared<ConvexPolygon>(convex->flipConvex());
00205               Eigen::Vector3f new_normal = convex->getNormal();
00206               plane_coefficients->values[0] = new_normal[0];
00207               plane_coefficients->values[1] = new_normal[1];
00208               plane_coefficients->values[2] = new_normal[2];
00209               plane_coefficients->values[3] = convex->getD();
00210             }
00211           }
00212           
00213           geometry_msgs::PolygonStamped polygon;
00214           polygon.polygon = convex->toROSMsg();
00215           polygon.header = msg->header;
00216           ros_polygon.polygons.push_back(polygon);
00217           all_inliers.push_back(plane_inliers);
00218           all_coefficients.push_back(plane_coefficients);
00219         }
00220       }
00221     }
00222     
00223     jsk_recognition_msgs::ClusterPointIndices ros_indices;
00224     ros_indices.cluster_indices =
00225       pcl_conversions::convertToROSPointIndices(all_inliers, msg->header);
00226     ros_indices.header = msg->header;
00227     pub_inliers_.publish(ros_indices);
00228     jsk_recognition_msgs::ModelCoefficientsArray ros_coefficients;
00229     ros_coefficients.header = msg->header;
00230     ros_coefficients.coefficients =
00231       pcl_conversions::convertToROSModelCoefficients(
00232         all_coefficients, msg->header);
00233     pub_coefficients_.publish(ros_coefficients);
00234     pub_polygons_.publish(ros_polygon);
00235   }
00236 
00237   double RegionGrowingMultiplePlaneSegmentation::global_angular_threshold = 0.0;
00238   double RegionGrowingMultiplePlaneSegmentation::global_distance_threshold = 0.0;
00239   boost::mutex RegionGrowingMultiplePlaneSegmentation::global_custom_condigion_function_mutex;
00240 }
00241 
00242 #include <pluginlib/class_list_macros.h>
00243 PLUGINLIB_EXPORT_CLASS (jsk_pcl_ros::RegionGrowingMultiplePlaneSegmentation, nodelet::Nodelet);


jsk_pcl_ros
Author(s): Yohei Kakiuchi
autogenerated on Wed Sep 16 2015 04:36:48