Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
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
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
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
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
00162 cec.segment (*clusters);
00163
00164
00165 }
00166
00167
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
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
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
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);