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 #include "ros/ros.h"
00034
00035
00036 #include "pcl/console/parse.h"
00037
00038
00039 #include "pcl/io/pcd_io.h"
00040
00041 #include "pcl/surface/convex_hull.h"
00042
00043 #include "pcl/filters/voxel_grid.h"
00044 #include "pcl/filters/passthrough.h"
00045 #include "pcl/filters/extract_indices.h"
00046 #include "pcl/filters/project_inliers.h"
00047 #include "pcl/filters/statistical_outlier_removal.h"
00048
00049 #include "pcl/sample_consensus/method_types.h"
00050 #include "pcl/sample_consensus/impl/ransac.hpp"
00051
00052 #include "pcl/segmentation/sac_segmentation.h"
00053 #include "pcl/segmentation/extract_clusters.h"
00054 #include "pcl/segmentation/extract_polygonal_prism_data.h"
00055
00056
00057 #include "pcl/visualization/pcl_visualizer.h"
00058
00059
00060 #include "pcl_ias_sample_consensus/pcl_sac_model_orientation.h"
00061
00062
00063 #include "dos_pcl/segmentation/door_detection_by_color_and_fixture.h"
00064
00065
00066
00067
00068 typedef pcl::PointXYZ PointT;
00069
00070
00071
00072
00073
00074
00075 double height_of_floor = 0.025;
00076 double height_of_ceiling = 0.050;
00077 double height_of_walls = 0.750;
00078
00079
00080 double epsilon_angle = 0.010;
00081 double plane_threshold = 0.100;
00082 int minimum_plane_inliers = 1000;
00083 int maximum_plane_iterations = 1000;
00084
00085
00086 int minimum_size_of_plane_cluster = 100;
00087 double plane_inliers_clustering_tolerance = 0.100;
00088 int minimum_size_of_handle_cluster = 25;
00089 double handle_clustering_tolerance = 0.050;
00090
00091
00092 double cluster_tolerance = 0.020;
00093 double fixture_cluster_tolerance = 0.025;
00094 double center_radius = 0.085;
00095 double init_radius = 0.035;
00096 double color_radius = 0.050;
00097
00098 int std_limit = 2;
00099 int min_pts_per_cluster = 150;
00100 int fixture_min_pts_per_cluster = 150;
00101
00102
00103 bool step = false;
00104 bool clean = false;
00105 bool verbose = false;
00106 int size_of_points = 1;
00107
00108
00109 bool find_box_model = true;
00110 bool segmentation_by_color_and_fixture = false;
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 float getRGB (float r, float g, float b)
00126 {
00127 int res = (int (r * 255) << 16) | (int (g * 255) << 8) | int (b * 255);
00128 double rgb = *reinterpret_cast<float*>(&res);
00129 return (rgb);
00130 }
00131
00133
00134 void getMinAndMax (boost::shared_ptr<const pcl::PointCloud <PointT> > cloud_, Eigen::VectorXf model_coefficients, boost::shared_ptr<pcl::SACModelOrientation<pcl::Normal> > model, std::vector<int> &min_max_indices, std::vector<float> &min_max_distances)
00135 {
00136
00137 boost::shared_ptr<std::vector<int> > inliers = model->getIndices();
00138 boost::shared_ptr<std::vector<int> > indices = model->getIndices();
00139
00140
00141 min_max_indices.resize (6);
00142 min_max_distances.resize (6);
00143 min_max_distances[0] = min_max_distances[2] = min_max_distances[4] = +DBL_MAX;
00144 min_max_distances[1] = min_max_distances[3] = min_max_distances[5] = -DBL_MAX;
00145
00146
00147 Eigen::Vector3f nm;
00148 nm[0] = model_coefficients[0];
00149 nm[1] = model_coefficients[1];
00150 nm[2] = model_coefficients[2];
00151
00152 Eigen::Vector3f nc = model->axis_.cross (nm);
00153
00154
00155 for (std::vector<int>::iterator it = inliers->begin (); it != inliers->end (); it++)
00156
00157 {
00158
00159 Eigen::Vector3f point (cloud_->points[(*indices)[*it]].x, cloud_->points[(*indices)[*it]].y, cloud_->points[(*indices)[*it]].z);
00160
00161
00162 double dists[3];
00163 dists[0] = nm.dot(point);
00164 dists[1] = nc.dot(point);
00165 dists[2] = model->axis_.dot(point);
00166 for (int d=0; d<3; d++)
00167 {
00168 if (min_max_distances[2*d+0] > dists[d]) { min_max_distances[2*d+0] = dists[d]; min_max_indices[2*d+0] = *it; }
00169 if (min_max_distances[2*d+1] < dists[d]) { min_max_distances[2*d+1] = dists[d]; min_max_indices[2*d+1] = *it; }
00170 }
00171 }
00172
00173 }
00174
00175
00176
00178
00182
00183
00184 bool findBoxModel (boost::shared_ptr<const pcl::PointCloud <PointT> > cloud, pcl::PointCloud<pcl::Normal> nrmls, std::vector<double> &coeff, double eps_angle_ = 0.1, double success_probability_ = 0.99, int verbosity_level_ = 1)
00185 {
00186
00187 if (verbosity_level_ > 0) ROS_INFO ("[RobustBoxEstimation] Looking for box in a cluster of %u points", (unsigned)cloud->points.size ());
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 pcl::SACModelOrientation<pcl::Normal>::Ptr model = boost::make_shared<pcl::SACModelOrientation<pcl::Normal> >(nrmls.makeShared ());
00206
00207 model->axis_[0] = 0 ;
00208 model->axis_[1] = 0 ;
00209 model->axis_[2] = 1 ;
00210
00211
00212 if (verbosity_level_ > 0) ROS_INFO ("[RobustBoxEstimation] Axis is (%g,%g,%g) and maximum angular difference %g",
00213 model->axis_[0], model->axis_[1], model->axis_[2], eps_angle_);
00214
00215
00216 Eigen::VectorXf refined;
00217 std::vector<int> inliers;
00219 if (success_probability_ > 0 && success_probability_ < 1)
00220 {
00221 if (verbosity_level_ > 0) ROS_INFO ("[RobustBoxEstimation] Using RANSAC with stop probability of %g and model refinement", success_probability_);
00222
00223
00224 pcl::RandomSampleConsensus<pcl::Normal> *sac = new pcl::RandomSampleConsensus<pcl::Normal> (model, eps_angle_);
00225 sac->setProbability (success_probability_);
00226 if (!sac->computeModel ())
00227 {
00228 if (verbosity_level_ > -2) ROS_ERROR ("[RobustBoxEstimation] No model found using the angular threshold of %g!", eps_angle_);
00229 return false;
00230 }
00231
00232
00233 sac->getInliers(inliers);
00234 if (verbosity_level_ > 1) cerr << "number of inliers: " << inliers.size () << endl;
00235
00236 std::vector<int> best_sample;
00237 std::vector<int> best_inliers;
00238 Eigen::VectorXf model_coefficients;
00239 for (unsigned i = 0; i < cloud->points.size (); i++)
00240 {
00241 std::vector<int> selection (1);
00242 selection[0] = i;
00243 model->computeModelCoefficients (selection, model_coefficients);
00244
00245 model->selectWithinDistance (model_coefficients, eps_angle_, inliers);
00246 if (best_inliers.size () < inliers.size ())
00247 {
00248 best_inliers = inliers;
00249 best_sample = selection;
00250 }
00251 }
00252
00253
00254 if (best_inliers.size () > 0)
00255 {
00256 model->computeModelCoefficients (best_sample, refined);
00257
00259 inliers = best_inliers;
00260
00261
00262
00263
00264 }
00266
00267
00268
00269
00270
00271
00272
00273
00274 }
00275 else
00276 {
00277 if (verbosity_level_ > 0) ROS_INFO ("[RobustBoxEstimation] Using exhaustive search in %ld points", (long int) cloud->points.size ());
00278
00279
00280 std::vector<int> best_sample;
00281 std::vector<int> best_inliers;
00282 Eigen::VectorXf model_coefficients;
00283 for (unsigned i = 0; i < cloud->points.size (); i++)
00284 {
00285 std::vector<int> selection (1);
00286 selection[0] = i;
00287 model->computeModelCoefficients (selection, model_coefficients);
00288
00289 model->selectWithinDistance (model_coefficients, eps_angle_, inliers);
00290 if (best_inliers.size () < inliers.size ())
00291 {
00292 best_inliers = inliers;
00293 best_sample = selection;
00294 }
00295 }
00296
00297
00298 if (best_inliers.size () > 0)
00299 {
00300 model->computeModelCoefficients (best_sample, refined);
00301
00303 inliers = best_inliers;
00304
00305
00306
00307
00308 }
00309 else
00310 {
00311 if (verbosity_level_ > -2) ROS_ERROR ("[RobustBoxEstimation] No model found using the angular threshold of %g!", eps_angle_);
00312 return false;
00313 }
00314 }
00315
00316
00317 coeff[12+0] = model->axis_[0];
00318 coeff[12+1] = model->axis_[1];
00319 coeff[12+2] = model->axis_[2];
00320
00321
00322 coeff[9+0] = model->axis_[1]*refined[2] - model->axis_[2]*refined[1];
00323 coeff[9+1] = model->axis_[2]*refined[0] - model->axis_[0]*refined[2];
00324 coeff[9+2] = model->axis_[0]*refined[1] - model->axis_[1]*refined[0];
00325
00326
00327 refined[0] = - (model->axis_[1]*coeff[9+2] - model->axis_[2]*coeff[9+1]);
00328 refined[1] = - (model->axis_[2]*coeff[9+0] - model->axis_[0]*coeff[9+2]);
00329 refined[2] = - (model->axis_[0]*coeff[9+1] - model->axis_[1]*coeff[9+0]);
00330
00331 ROS_INFO("refined[0]: %f", refined[0]);
00332 ROS_INFO("refined[1]: %f", refined[1]);
00333 ROS_INFO("refined[2]: %f", refined[2]);
00334 coeff[6+0] = refined[0];
00335 coeff[6+1] = refined[1];
00336 coeff[6+2] = refined[2];
00337
00338
00339
00340
00341
00342
00343
00344 std::vector<int> min_max_indices;
00345 std::vector<float> min_max_distances;
00346
00347
00348
00349
00350
00351 getMinAndMax (cloud, refined, model, min_max_indices, min_max_distances);
00352
00353
00354
00355
00356
00357
00358
00359 coeff[3+0] = min_max_distances.at (1) - min_max_distances.at (0);
00360 coeff[3+1] = min_max_distances.at (3) - min_max_distances.at (2);
00361 coeff[3+2] = min_max_distances.at (5) - min_max_distances.at (4);
00362
00363
00364 double dist[3];
00365 dist[0] = min_max_distances[0] + coeff[3+0] / 2;
00366 dist[1] = min_max_distances[2] + coeff[3+1] / 2;
00367 dist[2] = min_max_distances[4] + coeff[3+2] / 2;
00368
00369
00370 coeff[0] = dist[0]*coeff[6+0] + dist[1]*coeff[9+0] + dist[2]*coeff[12+0];
00371 coeff[1] = dist[0]*coeff[6+1] + dist[1]*coeff[9+1] + dist[2]*coeff[12+1];
00372 coeff[2] = dist[0]*coeff[6+2] + dist[1]*coeff[9+2] + dist[2]*coeff[12+2];
00373
00374
00375
00376 if (verbosity_level_ > 0) ROS_INFO ("[RobustBoxEstimation] Cluster center x: %g, y: %g, z: %g", coeff[0], coeff[1], coeff[2]);
00377
00378
00379 if (verbosity_level_ > 0) ROS_INFO ("[RobustBoxEstimation] Dimensions x: %g, y: %g, z: %g",
00380 coeff[3+0], coeff[3+1], coeff[3+2]);
00381 if (verbosity_level_ > 0) ROS_INFO ("[RobustBoxEstimation] Direction vectors: \n\t%g %g %g \n\t%g %g %g \n\t%g %g %g",
00382 coeff[3+3], coeff[3+4], coeff[3+5],
00383 coeff[3+6], coeff[3+7], coeff[3+8],
00384 coeff[3+9], coeff[3+10],coeff[3+11]);
00385
00386 return true;
00387 }
00388
00389
00390
00391 void getAxesOrientedSurfaces (pcl::PointCloud<PointT> &input_cloud,
00392 pcl::PointCloud<pcl::Normal> &normals_cloud,
00393 Eigen::Vector3f axis,
00394 double epsilon_angle,
00395 double plane_threshold,
00396 int minimum_plane_inliers,
00397 int maximum_plane_iterations,
00398 int minimum_size_of_plane_cluster,
00399 double plane_inliers_clustering_tolerance,
00400 std::vector<pcl::PointCloud<PointT>::Ptr> &planar_surfaces,
00401 std::vector<std::string> &planar_surfaces_ids,
00402 std::vector<pcl::PointIndices::Ptr> &planar_surfaces_indices,
00403 std::vector<pcl::ModelCoefficients::Ptr> &planar_surfaces_coefficients,
00404 pcl::visualization::PCLVisualizer &viewer)
00405 {
00406
00407
00408 int plane_fit = 0;
00409
00410
00411 bool stop_planes = false;
00412
00413
00414
00415 int counter = 0;
00416
00417 do
00418 {
00419
00420 pcl::SACSegmentationFromNormals<PointT, pcl::Normal> segmentation_of_planes;
00421 pcl::PointIndices::Ptr plane_inliers (new pcl::PointIndices ());
00422 pcl::ModelCoefficients::Ptr plane_coefficients (new pcl::ModelCoefficients ());
00423
00424
00425 segmentation_of_planes.setOptimizeCoefficients (true);
00426 segmentation_of_planes.setModelType (pcl::SACMODEL_NORMAL_PLANE);
00427 segmentation_of_planes.setNormalDistanceWeight (0.05);
00428 segmentation_of_planes.setMethodType (pcl::SAC_RANSAC);
00429 segmentation_of_planes.setDistanceThreshold (plane_threshold);
00430 segmentation_of_planes.setMaxIterations (maximum_plane_iterations);
00431 segmentation_of_planes.setAxis (axis);
00432 segmentation_of_planes.setEpsAngle (epsilon_angle);
00433 segmentation_of_planes.setInputCloud (input_cloud.makeShared());
00434 segmentation_of_planes.setInputNormals (normals_cloud.makeShared());
00435
00436
00437 segmentation_of_planes.segment (*plane_inliers, *plane_coefficients);
00438
00439 if ( verbose )
00440 {
00441 ROS_INFO ("Plane has %5d inliers with parameters A = %f B = %f C = %f and D = %f found in maximum %d iterations", (int) plane_inliers->indices.size (),
00442 plane_coefficients->values [0], plane_coefficients->values [1], plane_coefficients->values [2], plane_coefficients->values [3], maximum_plane_iterations);
00443 }
00444
00445
00446 if ((int) plane_inliers->indices.size () < minimum_plane_inliers)
00447 {
00448 ROS_ERROR ("NOT ACCEPTED !");
00449
00450 counter++;
00451
00452 cerr <<" COUNTER = " << counter << endl ;
00453
00454
00455
00456 if ( counter == 25 )
00457 {
00458
00459 stop_planes = true;
00460 }
00461 }
00462 else
00463 {
00464 ROS_WARN ("ACCEPTED !");
00465
00466
00467 counter = 0;
00468
00469
00470
00471
00472
00473
00474 pcl::PointCloud<PointT>::Ptr pivot_input_cloud (new pcl::PointCloud<PointT> ());
00475
00476
00477 pcl::PointCloud<PointT>::Ptr plane_inliers_cloud (new pcl::PointCloud<PointT> ());
00478
00479
00480 pcl::ExtractIndices<PointT> extraction_of_plane_inliers;
00481
00482 extraction_of_plane_inliers.setInputCloud (input_cloud.makeShared());
00483
00484 extraction_of_plane_inliers.setIndices (plane_inliers);
00485
00486 extraction_of_plane_inliers.setNegative (false);
00487
00488 extraction_of_plane_inliers.filter (*plane_inliers_cloud);
00489
00490 extraction_of_plane_inliers.setNegative (true);
00491
00492 extraction_of_plane_inliers.filter (*pivot_input_cloud);
00493
00494
00495 input_cloud = *pivot_input_cloud;
00496
00497
00498 pcl::PointCloud<pcl::Normal>::Ptr pivot_normals_cloud (new pcl::PointCloud<pcl::Normal> ());
00499
00500
00501 pcl::ExtractIndices<pcl::Normal> extraction_of_normals;
00502
00503
00504 extraction_of_normals.setInputCloud (normals_cloud.makeShared());
00505
00506 extraction_of_normals.setNegative (true);
00507
00508 extraction_of_normals.setIndices (plane_inliers);
00509
00510 extraction_of_normals.filter (*pivot_normals_cloud);
00511
00512
00513 normals_cloud = *pivot_normals_cloud;
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00552
00553
00554 std::vector<pcl::PointIndices> plane_clusters;
00555
00556 pcl::KdTreeFLANN<PointT>::Ptr plane_clusters_tree (new pcl::KdTreeFLANN<PointT> ());
00557
00558
00559 pcl::EuclideanClusterExtraction<PointT> clustering_of_plane_inliers;
00560
00561 clustering_of_plane_inliers.setInputCloud (plane_inliers_cloud);
00562
00563 clustering_of_plane_inliers.setClusterTolerance (plane_inliers_clustering_tolerance);
00564
00565 clustering_of_plane_inliers.setMinClusterSize (minimum_size_of_plane_cluster);
00566
00567 clustering_of_plane_inliers.setSearchMethod (plane_clusters_tree);
00568
00569 clustering_of_plane_inliers.extract (plane_clusters);
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 std::vector<pcl::PointCloud<PointT>::Ptr> plane_clusters_clouds;
00588
00589 for (int c = 0; c < (int) plane_clusters.size(); c++)
00590 {
00591
00592 pcl::PointIndices::Ptr pointer_of_plane_cluster (new pcl::PointIndices (plane_clusters.at(c)));
00593 pcl::PointCloud<PointT>::Ptr cluster (new pcl::PointCloud<PointT>);
00594
00595
00596 pcl::ExtractIndices<PointT> extraction_of_plane_clusters;
00597
00598 extraction_of_plane_clusters.setInputCloud (plane_inliers_cloud);
00599
00600 extraction_of_plane_clusters.setIndices (pointer_of_plane_cluster);
00601
00602 extraction_of_plane_clusters.setNegative (false);
00603
00604 extraction_of_plane_clusters.filter (*cluster);
00605
00606
00607 plane_clusters_clouds.push_back (cluster);
00608
00609
00610 planar_surfaces.push_back (cluster);
00611
00612
00613 planar_surfaces_coefficients.push_back (plane_coefficients);
00614
00615
00616 planar_surfaces_indices.push_back (pointer_of_plane_cluster);
00617
00618 if ( verbose )
00619 {
00620 ROS_INFO (" Planar surface %d has %d points", c, (int) cluster->points.size());
00621 }
00622 }
00623
00624
00625
00626 for (int c = 0; c < (int) plane_clusters.size(); c++)
00627 {
00628
00629 std::stringstream id_of_surface;
00630 id_of_surface << "SURFACE_" << ros::Time::now();
00631
00632
00633 planar_surfaces_ids.push_back (id_of_surface.str());
00634
00635
00636 viewer.addPointCloud (plane_clusters_clouds.at(c), id_of_surface.str());
00637
00638
00639 viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, size_of_points, id_of_surface.str());
00640
00641
00642 if ( step )
00643 {
00644
00645 viewer.spin ();
00646 }
00647
00648
00649 if ( clean )
00650 {
00651
00652 viewer.removePointCloud (id_of_surface.str());
00653
00654 if ( step )
00655 {
00656
00657 viewer.spin ();
00658 }
00659 }
00660 }
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674 }
00675
00676
00677 plane_fit++;
00678
00679
00680
00681
00682
00683
00684 if ( (int) input_cloud.points.size () < minimum_plane_inliers )
00685 ROS_ERROR ("%d < %d | Stop !", (int) input_cloud.points.size (), minimum_plane_inliers);
00686 else
00687 if ( (int) input_cloud.points.size () > minimum_plane_inliers )
00688 ROS_INFO ("%d > %d | Continue... ", (int) input_cloud.points.size (), minimum_plane_inliers);
00689 else
00690 ROS_INFO ("%d = %d | Continue... ", (int) input_cloud.points.size (), minimum_plane_inliers);
00691
00692 } while ((int) input_cloud.points.size () > minimum_plane_inliers && stop_planes == false);
00693 }
00694
00695
00696
00698
00700 int main (int argc, char** argv)
00701 {
00702
00703
00704
00705
00706
00707
00708 if (argc < 2)
00709 {
00710 ROS_INFO (" ");
00711 ROS_INFO ("Syntax is: %s <input>.pcd <options>", argv[0]);
00712 ROS_INFO (" where <options> are:");
00713 ROS_INFO (" -height_of_floor X = Height of floor layer of point cloud data.");
00714 ROS_INFO (" -height_of_ceiling X = Height of ceiling layer of point cloud data.");
00715 ROS_INFO (" -height_of_walls X = Minimum height of walls in the point cloud data.");
00716 ROS_INFO (" ");
00717 ROS_INFO (" -epsilon_angle X = The maximum allowed difference between the plane normal and the given axis.");
00718 ROS_INFO (" -plane_threshold X = Distance to the fitted plane model.");
00719 ROS_INFO (" -minimum_plane_inliers X = Minimum number of inliers of the fitted plane in order to be accepted.");
00720 ROS_INFO (" -maximum_plane_iterations X = Maximum number of interations for fitting the plane model.");
00721 ROS_INFO (" ");
00722 ROS_INFO (" -minimum_size_of_plane_cluster = Minimum cluster size of plane inliers.");
00723 ROS_INFO (" -plane_inliers_clustering_tolerance = The clustering tolerance of plane inliers");
00724 ROS_INFO (" -minimum_size_of_handle_cluster = Minimum cluster size of handle points.");
00725 ROS_INFO (" -handle_clustering_tolerance = The clustering tolerance of handle points.");
00726 ROS_INFO (" ");
00727 ROS_INFO (" -step B = Wait or not wait.");
00728 ROS_INFO (" -clean B = Remove or not remove.");
00729 ROS_INFO (" -verbose B = Display step by step info.");
00730 ROS_INFO (" -size_of_points D = Set the size of points");
00731 ROS_INFO (" ");
00732 return (-1);
00733 }
00734
00735
00736 std::vector<int> pFileIndicesPCD = pcl::console::parse_file_extension_argument (argc, argv, ".pcd");
00737 if (pFileIndicesPCD.size () == 0)
00738 {
00739 ROS_ERROR ("No .pcd file given as input!");
00740 return (-1);
00741 }
00742
00743
00744 pcl::console::parse_argument (argc, argv, "-height_of_floor", height_of_floor);
00745 pcl::console::parse_argument (argc, argv, "-height_of_ceiling", height_of_ceiling);
00746 pcl::console::parse_argument (argc, argv, "-height_of_walls", height_of_walls);
00747
00748
00749 pcl::console::parse_argument (argc, argv, "-epsilon_angle", epsilon_angle);
00750 pcl::console::parse_argument (argc, argv, "-plane_threshold", plane_threshold);
00751 pcl::console::parse_argument (argc, argv, "-minimum_plane_inliers", minimum_plane_inliers);
00752 pcl::console::parse_argument (argc, argv, "-maximum_plane_iterations", maximum_plane_iterations);
00753
00754
00755 pcl::console::parse_argument (argc, argv, "-minimum_size_of_plane_cluster", minimum_size_of_plane_cluster);
00756 pcl::console::parse_argument (argc, argv, "-plane_inliers_clustering_tolerance", plane_inliers_clustering_tolerance);
00757 pcl::console::parse_argument (argc, argv, "-minimum_size_of_handle_cluster", minimum_size_of_handle_cluster);
00758 pcl::console::parse_argument (argc, argv, "-handle_clustering_tolerance", handle_clustering_tolerance);
00759
00760
00761 pcl::console::parse_argument (argc, argv, "-cluster_tolerance", cluster_tolerance);
00762 pcl::console::parse_argument (argc, argv, "-fixture_cluster_tolerance", fixture_cluster_tolerance);
00763 pcl::console::parse_argument (argc, argv, "-center_radius", center_radius);
00764 pcl::console::parse_argument (argc, argv, "-init_radius", init_radius);
00765 pcl::console::parse_argument (argc, argv, "-color_radius", color_radius);
00766
00767 pcl::console::parse_argument (argc, argv, "-std_limit", std_limit);
00768 pcl::console::parse_argument (argc, argv, "-min_pts_per_cluster", min_pts_per_cluster);
00769 pcl::console::parse_argument (argc, argv, "-fixture_min_pts_per_cluster", fixture_min_pts_per_cluster);
00770
00771
00772 pcl::console::parse_argument (argc, argv, "-step", step);
00773 pcl::console::parse_argument (argc, argv, "-clean", clean);
00774 pcl::console::parse_argument (argc, argv, "-verbose", verbose);
00775 pcl::console::parse_argument (argc, argv, "-size_of_points", size_of_points);
00776
00777
00778 pcl::console::parse_argument (argc, argv, "-find_box_model", find_box_model);
00779 pcl::console::parse_argument (argc, argv, "-segmentation_by_color_and_fixture", segmentation_by_color_and_fixture);
00780
00781
00782
00783
00784
00785
00786 srand (time(0));
00787
00788
00789 ros::Time::init();
00790
00791
00792 pcl::console::TicToc tt;
00793
00794
00795 tt.tic ();
00796
00797 if ( verbose )
00798 {
00799
00800 ROS_WARN ("Timer started !");
00801 }
00802
00803
00804
00805
00806
00807
00808 pcl::visualization::PCLVisualizer viewer ("3D VIEWER");
00809
00810 viewer.setBackgroundColor (0.0, 0.0, 0.0);
00811
00812 viewer.addCoordinateSystem (0.75f);
00813
00814 viewer.getCameraParameters (argc, argv);
00815
00816 viewer.updateCamera ();
00817
00818
00819
00820
00821
00822
00823 pcl::PointCloud<PointT>::Ptr input_cloud (new pcl::PointCloud<PointT> ());
00824
00825
00826 pcl::PointCloud<PointT>::Ptr auxiliary_input_cloud (new pcl::PointCloud<PointT> ());
00827
00828
00829 if (pcl::io::loadPCDFile (argv[pFileIndicesPCD[0]], *input_cloud) == -1)
00830 {
00831 ROS_ERROR ("Couldn't read file %s", argv[pFileIndicesPCD[0]]);
00832 return (-1);
00833 }
00834 ROS_INFO ("Loaded %d data points from %s with the following fields: %s", (int) (input_cloud->points.size ()), argv[pFileIndicesPCD[0]], pcl::getFieldsList (*input_cloud).c_str ());
00835
00836
00837
00838 viewer.addPointCloud (input_cloud, "INPUT");
00839
00840
00841 viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 0.0, 0.0, "INPUT");
00842
00843
00844 viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, size_of_points - 1, "INPUT");
00845
00846
00847 if ( step )
00848 {
00849
00850 viewer.spin ();
00851 }
00852
00853
00854 if ( clean )
00855 {
00856
00857 viewer.removePointCloud ("INPUT");
00858
00859
00860 if ( step )
00861 {
00862
00863 viewer.spin ();
00864 }
00865 }
00866
00867
00868
00869
00870
00871 pcl::io::loadPCDFile (argv [pFileIndicesPCD [0]], *auxiliary_input_cloud);
00872
00873
00874 std::string file = argv [pFileIndicesPCD[0]];
00875 size_t dot = file.find (".");
00876 size_t slash = file.find_last_of ("/");
00877 std::string directory = file.substr (slash, dot - slash);
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933 PointT point_with_minimum_height, point_with_maximum_height;
00934 pcl::getMinMax3D (*input_cloud, point_with_minimum_height, point_with_maximum_height);
00935 double height_of_cloud = point_with_maximum_height.z - point_with_minimum_height.z;
00936
00937 height_of_floor = height_of_cloud * height_of_floor;
00938 height_of_ceiling = height_of_cloud * height_of_ceiling;
00939 height_of_walls = height_of_cloud * height_of_walls;
00940
00941 if ( verbose )
00942 {
00943 ROS_INFO ("The point with minimum height is (%6.3f,%6.3f,%6.3f)", point_with_minimum_height.x, point_with_minimum_height.y, point_with_minimum_height.z);
00944 ROS_INFO ("The point with maximum height is (%6.3f,%6.3f,%6.3f)", point_with_maximum_height.x, point_with_maximum_height.y, point_with_maximum_height.z);
00945 ROS_INFO ("The height of point cloud is %5.3f meters", height_of_cloud);
00946
00947 ROS_INFO ("Height of floor is %5.3f meters", height_of_floor);
00948 ROS_INFO ("Height of ceiling is %5.3f meters", height_of_ceiling);
00949 ROS_INFO ("Height of walls is %5.3f meters", height_of_walls);
00950 }
00951
00952
00953
00954
00955
00956
00957
00958
00959 pcl::PassThrough<PointT> pass;
00960 pass.setInputCloud (input_cloud);
00961 pass.setFilterFieldName ("z");
00962
00963
00964 pcl::PointCloud<PointT>::Ptr floor_cloud (new pcl::PointCloud<PointT> ());
00965
00966
00967 pass.setFilterLimits (point_with_minimum_height.z, point_with_minimum_height.z + height_of_floor);
00968
00969
00970 pass.setFilterLimitsNegative (false);
00971 pass.filter (*floor_cloud);
00972 pass.setFilterLimitsNegative (true);
00973 pass.filter (*input_cloud);
00974
00975
00976 std::string floor_filename = argv [pFileIndicesPCD [0]];
00977 floor_filename.insert (dot, "-floor");
00978
00979
00980 pcl::io::savePCDFile (floor_filename, *floor_cloud);
00981
00982 if ( verbose )
00983 {
00984
00985 ROS_INFO ("The floor has %d points and was saved to data/floor.pcd", (int) floor_cloud->points.size ());
00986 }
00987
00988
00989 pcl::PointCloud<PointT>::Ptr ceiling_cloud (new pcl::PointCloud<PointT> ());
00990
00991
00992 pass.setFilterLimits (point_with_maximum_height.z - height_of_ceiling, point_with_maximum_height.z);
00993
00994
00995 pass.setFilterLimitsNegative (false);
00996 pass.filter (*ceiling_cloud);
00997 pass.setFilterLimitsNegative (true);
00998 pass.filter (*input_cloud);
00999
01000
01001 std::string ceiling_filename = argv [pFileIndicesPCD [0]];
01002 ceiling_filename.insert (dot, "-ceiling");
01003
01004
01005 pcl::io::savePCDFile (ceiling_filename, *ceiling_cloud);
01006
01007 if ( verbose )
01008 {
01009
01010 ROS_INFO ("The ceiling has %d points and was saved to data/ceiling.pcd", (int) ceiling_cloud->points.size ());
01011 }
01012
01013
01014 pcl::PointCloud<PointT>::Ptr walls_cloud (new pcl::PointCloud<PointT> ());
01015
01016
01017 *walls_cloud = *input_cloud;
01018
01019
01020 std::string walls_filename = argv [pFileIndicesPCD [0]];
01021 walls_filename.insert (dot, "-walls");
01022
01023
01024 pcl::io::savePCDFile (walls_filename, *walls_cloud);
01025
01026 if ( verbose )
01027 {
01028
01029 ROS_INFO ("The walls have %d points and were saved to data/walls.pcd", (int) walls_cloud->points.size ());
01030 }
01031
01032
01033
01034
01035
01036
01037
01038
01039 viewer.addPointCloud (floor_cloud, "FLOOR");
01040
01041 viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_COLOR, 1.0, 0.0, 0.0, "FLOOR");
01042
01043 viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, size_of_points - 1, "FLOOR");
01044
01045
01046 if ( step )
01047 {
01048
01049 viewer.spin ();
01050 }
01051
01052
01053 if ( clean )
01054 {
01055
01056 viewer.removePointCloud ("FLOOR");
01057
01058
01059 if ( step )
01060 {
01061
01062 viewer.spin ();
01063 }
01064 }
01065
01066
01067 viewer.addPointCloud (walls_cloud, "WALLS");
01068
01069 viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 1.0, 0.0, "WALLS");
01070
01071 viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, size_of_points - 1, "WALLS");
01072
01073
01074 if ( step )
01075 {
01076
01077 viewer.spin ();
01078 }
01079
01080
01081 if ( clean )
01082 {
01083
01084 viewer.removePointCloud ("WALLS");
01085
01086
01087 if ( step )
01088 {
01089
01090 viewer.spin ();
01091 }
01092 }
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133 viewer.removePointCloud ("INPUT");
01134
01135
01136 if ( step )
01137 {
01138
01139 viewer.spin ();
01140 }
01141
01142
01143 viewer.removePointCloud ("FLOOR");
01144
01145
01146 if ( step )
01147 {
01148
01149 viewer.spin ();
01150 }
01151
01152
01153
01154
01155
01156
01157 pcl::PointCloud<pcl::Normal>::Ptr normals_cloud (new pcl::PointCloud<pcl::Normal> ());
01158
01159 pcl::KdTreeFLANN<PointT>::Ptr normals_tree (new pcl::KdTreeFLANN<PointT> ());
01160
01161
01162 pcl::NormalEstimation<PointT, pcl::Normal> estimation_of_normals;
01163
01164 estimation_of_normals.setSearchMethod (normals_tree);
01165
01166 estimation_of_normals.setInputCloud (input_cloud);
01167
01168 estimation_of_normals.setKSearch (50);
01169
01170 estimation_of_normals.compute (*normals_cloud);
01171
01172 if ( verbose )
01173 {
01174 ROS_INFO ("Remaning cloud has %d points", (int) input_cloud->points.size());
01175 ROS_INFO ("With %d normals of course", (int) normals_cloud->points.size());
01176 }
01177
01179
01180
01181 Eigen::Vector3f X, Y, Z;
01182
01183 if (find_box_model)
01184 {
01185 pcl::VoxelGrid<PointT> vgrid;
01186 vgrid.setLeafSize (0.05, 0.05, 0.05);
01187 vgrid.setInputCloud (input_cloud);
01188 pcl::PointCloud<PointT>::Ptr cloud_downsampled (new pcl::PointCloud<PointT> ());
01189
01190 vgrid.filter (*cloud_downsampled);
01191 std::vector<double> coefficients (15, 0.0);
01192
01193
01194
01195 if ( findBoxModel (cloud_downsampled, *normals_cloud, coefficients) )
01196 {
01197 ROS_INFO("Box Model found");
01198 X = Eigen::Vector3f (coefficients [6+0], coefficients [6+1], coefficients [6+2]);
01199 Y = Eigen::Vector3f (coefficients [9+0], coefficients [9+1], coefficients [9+2]);
01200 Z = Eigen::Vector3f (coefficients[12+0], coefficients[12+1], coefficients[12+2]);
01201 }
01202
01203
01204 if ( step )
01205 {
01206
01207 viewer.spin ();
01208 }
01209
01211
01212 viewer.addPointCloud (cloud_downsampled, "DOWNSAMPLED");
01213
01214 viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 1.0, 0.0, "DOWNSAMPLED");
01215
01216 viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, size_of_points * 2, "DOWNSAMPLED");
01217
01218
01219 if ( step )
01220 {
01221
01222 viewer.spin ();
01223 }
01224
01225
01226 viewer.removePointCloud ("DOWNSAMPLED");
01227
01228
01229 if ( step )
01230 {
01231
01232 viewer.spin ();
01233 }
01234
01235
01236
01237 std::string downsampled_filename = argv [pFileIndicesPCD [0]];
01238 downsampled_filename.insert (dot, "-downsampled");
01239
01240
01241 pcl::io::savePCDFile (downsampled_filename, *cloud_downsampled);
01242 }
01243 else
01244 {
01245
01246 X = Eigen::Vector3f (1.0, 0.0, 0.0);
01247 Y = Eigen::Vector3f (0.0, 1.0, 0.0);
01248 Z = Eigen::Vector3f (0.0, 0.0, 1.0);
01249 }
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272 if ( verbose )
01273 {
01274 ROS_INFO ("The furniture surfaces will be detected along the following axes:");
01275 ROS_INFO (" X = Eigen::Vector3f (%8.5f, %8.5f, %8.5f)", X[0], X[1], X[2]);
01276 ROS_INFO (" Y = Eigen::Vector3f (%8.5f, %8.5f, %8.5f)", Y[0], Y[1], Y[2]);
01277 ROS_INFO (" Z = Eigen::Vector3f (%8.5f, %8.5f, %8.5f)", Z[0], Z[1], Z[2]);
01278
01279
01280 if ( step )
01281 {
01282
01283 viewer.spin ();
01284 }
01285 }
01286
01287
01288
01289
01290
01291
01292 std::vector<pcl::PointCloud<PointT>::Ptr> planar_surfaces;
01293
01294
01295 std::vector<std::string> planar_surfaces_ids;
01296
01297
01298 std::vector<pcl::PointIndices::Ptr> planar_surfaces_indices;
01299
01300
01301 std::vector<pcl::ModelCoefficients::Ptr> planar_surfaces_coefficients;
01302
01303
01304 pcl::PointCloud<PointT>::Ptr pivot_auxiliary_input_cloud (new pcl::PointCloud<PointT> ());
01305
01306
01307 *pivot_auxiliary_input_cloud = *input_cloud;
01308
01309 ROS_ERROR ("Z axis aligned planes");
01310
01311
01312 getAxesOrientedSurfaces (*input_cloud, *normals_cloud, Z, epsilon_angle, plane_threshold, minimum_plane_inliers, maximum_plane_iterations, minimum_size_of_plane_cluster, plane_inliers_clustering_tolerance, planar_surfaces, planar_surfaces_ids, planar_surfaces_indices, planar_surfaces_coefficients, viewer);
01313
01314 ROS_ERROR ("Y axis aligned planes");
01315
01316
01317 getAxesOrientedSurfaces (*input_cloud, *normals_cloud, Y, epsilon_angle, plane_threshold, minimum_plane_inliers, maximum_plane_iterations, minimum_size_of_plane_cluster, plane_inliers_clustering_tolerance, planar_surfaces, planar_surfaces_ids, planar_surfaces_indices, planar_surfaces_coefficients, viewer);
01318
01319 ROS_ERROR ("X axis aligned planes");
01320
01321
01322 getAxesOrientedSurfaces (*input_cloud, *normals_cloud, X, epsilon_angle, plane_threshold, minimum_plane_inliers, maximum_plane_iterations, minimum_size_of_plane_cluster, plane_inliers_clustering_tolerance, planar_surfaces, planar_surfaces_ids, planar_surfaces_indices, planar_surfaces_coefficients, viewer);
01323
01324
01325
01326
01327
01328
01329
01330
01331 viewer.removePointCloud ("FLOOR");
01332
01333
01334 viewer.removePointCloud ("WALLS");
01335
01336
01337 if ( step )
01338 {
01339
01340 viewer.spin ();
01341 }
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352 pcl::PointCloud<PointT>::Ptr furniture (new pcl::PointCloud<PointT> ());
01353
01354
01355 std::vector<std::string> type_of_furniture;
01356
01357 if ( verbose )
01358 {
01359 ROS_INFO (" ");
01360 ROS_INFO ("THERE ARE %d PLANAR SURFACES", (int) planar_surfaces.size());
01361 ROS_INFO ("AND THERE ARE %d STRING IDS", (int) planar_surfaces_ids.size());
01362 ROS_INFO (" ");
01363 }
01364
01365
01366 std::vector<pcl::PointCloud<PointT>::Ptr> furniture_surfaces;
01367
01368
01369 std::vector<std::string> furniture_surfaces_ids;
01370
01371
01372 std::vector<pcl::PointCloud<PointT>::Ptr> surfaces_of_walls;
01373
01374
01375 std::vector<std::string> surfaces_of_walls_ids;
01376
01377
01378 std::vector<pcl::PointCloud<PointT>::Ptr> horizontal_furniture_surfaces;
01379
01380
01381 std::vector<pcl::PointCloud<PointT>::Ptr> vertical_furniture_surfaces;
01382
01383
01384 std::vector<std::string> projs_ids;
01385
01386 for (int surface = 0; surface < (int) planar_surfaces.size(); surface++)
01387 {
01388
01389 PointT point_with_minimum_3D_values, point_with_maximum_3D_values;
01390 pcl::getMinMax3D (*planar_surfaces.at (surface), point_with_minimum_3D_values, point_with_maximum_3D_values);
01391
01392 if ( verbose )
01393 {
01394 ROS_INFO ("FOR PLANAR SURFACE %2d MIN HEIGHT IS %f AND MAX IS %f METERS", surface, point_with_minimum_3D_values.z, point_with_maximum_3D_values.z);
01395 }
01396
01397 if ( point_with_maximum_3D_values.z > height_of_walls )
01398 {
01399
01400 surfaces_of_walls.push_back (planar_surfaces.at (surface));
01401
01402
01403 surfaces_of_walls_ids.push_back (planar_surfaces_ids.at (surface));
01404
01405
01406 viewer.removePointCloud (planar_surfaces_ids.at (surface));
01407
01408
01409 if ( step )
01410 {
01411
01412 viewer.spin ();
01413 }
01414 }
01415 else
01416 {
01417
01418
01419
01420
01421 *furniture += *planar_surfaces.at (surface);
01422
01423
01424 if ( std::abs(planar_surfaces_coefficients.at (surface)->values[2]) > std::max (std::abs(planar_surfaces_coefficients.at (surface)->values[0]), std::abs(planar_surfaces_coefficients.at (surface)->values[1])) )
01425 {
01426 type_of_furniture.push_back ("HORIZONTAL");
01427 ROS_WARN ("HORIZONTAL");
01428
01429
01430 horizontal_furniture_surfaces.push_back (planar_surfaces.at (surface));
01431 }
01432 else
01433 {
01434 type_of_furniture.push_back ("VERTICAL");
01435 ROS_WARN ("VERTICAL");
01436
01437
01438 vertical_furniture_surfaces.push_back (planar_surfaces.at (surface));
01439 }
01440
01441 ROS_INFO (" planar surfaces indices size: %d ", (int) planar_surfaces_indices.at (surface)->indices.size());
01442 ROS_INFO (" table model: [%f, %f, %f, %f]", planar_surfaces_coefficients.at (surface)->values[0], planar_surfaces_coefficients.at (surface)->values[1], planar_surfaces_coefficients.at (surface)->values[2], planar_surfaces_coefficients.at (surface)->values[3]);
01443
01444
01445
01446
01447 pcl::PointCloud<PointT>::Ptr cloud_projected (new pcl::PointCloud<PointT> ());
01448
01449 pcl::ProjectInliers<PointT> proj_;
01450 proj_.setModelType (pcl::SACMODEL_NORMAL_PLANE);
01451 proj_.setInputCloud (planar_surfaces.at (surface));
01452 proj_.setModelCoefficients (planar_surfaces_coefficients.at (surface));
01453 proj_.filter (*cloud_projected);
01454
01455
01456
01457
01458
01459
01460
01461
01462 viewer.removePointCloud (planar_surfaces_ids.at (surface));
01463
01464
01465 if ( step )
01466 {
01467
01468 viewer.spin ();
01469 }
01470
01471
01472 std::stringstream id_of_proj;
01473 id_of_proj << "PROJ_" << ros::Time::now();
01474 viewer.addPointCloud (cloud_projected, id_of_proj.str());
01475
01476 viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, size_of_points * 2, id_of_proj.str());
01477
01478
01479 projs_ids.push_back (id_of_proj.str());
01480
01481
01482 if ( step )
01483 {
01484
01485 viewer.spin ();
01486 }
01487
01488
01489
01490 furniture_surfaces.push_back (cloud_projected);
01491
01492
01493 furniture_surfaces_ids.push_back (planar_surfaces_ids.at (surface));
01494 }
01495 }
01496
01497 if ( verbose )
01498 {
01499 ROS_INFO (" ");
01500 ROS_INFO ("%d FURNITURE SURFACES", (int) furniture_surfaces.size());
01501 ROS_INFO ("AND %d SURFACES OF WALLS", (int) surfaces_of_walls.size());
01502 ROS_INFO (" ");
01503 }
01504
01505 ROS_ERROR (" OVER !!! ");
01506
01507 if ( step )
01508 {
01509
01510 viewer.spin ();
01511 }
01512 ROS_ERROR (" OVER !!! ");
01513
01514 if ( step )
01515 {
01516
01517 viewer.spin ();
01518 }
01519 ROS_ERROR (" OVER !!! ");
01520
01521 if ( step )
01522 {
01523
01524 viewer.spin ();
01525 }
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535 pcl::PointCloud<PointT> fixtures;
01536
01537
01538 std::vector<std::string> handle_ids;
01539
01540
01541 std::vector<std::string> handles_clusters_ids;
01542
01543 for (int furniture = 0; furniture < (int) furniture_surfaces.size(); furniture++)
01544 {
01545
01546
01547 if ( type_of_furniture. at (furniture) == "VERTICAL" )
01548 {
01549
01550 ROS_WARN ("VERTICAL");
01551
01552 ROS_INFO ("Furniture surface %d has %d points", furniture, (int) furniture_surfaces.at (furniture)->points.size ());
01553
01554 pcl::PointCloud<PointT> cloud_hull;
01555
01556
01557 pcl::ConvexHull<PointT> chull_;
01558 chull_.setInputCloud (furniture_surfaces.at (furniture));
01559 ROS_ERROR (" BEFORE IT WORKS ");
01560 chull_.reconstruct (cloud_hull);
01561 ROS_ERROR (" AFTERWARDS NOT ");
01562
01563 ROS_INFO ("Convex hull %d has %d data points.", furniture, (int) cloud_hull.points.size ());
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580 pcl::PointIndices::Ptr cloud_object_indices (new pcl::PointIndices ());
01581
01582
01583 pcl::ExtractPolygonalPrismData<PointT> prism_;
01584 prism_.setHeightLimits (0.025, 0.100);
01585 prism_.setInputCloud (auxiliary_input_cloud);
01586 prism_.setInputPlanarHull (cloud_hull.makeShared());
01587 prism_.setViewPoint (0.0, 0.0, 1.5);
01588 prism_.segment (*cloud_object_indices);
01589
01590 ROS_INFO ("For %d the number of object point indices is %d", furniture, (int) cloud_object_indices->indices.size ());
01591
01592 if ( (int) cloud_object_indices->indices.size () != 0 )
01593 {
01594
01595
01596 pcl::PointCloud<PointT>::Ptr handle_cloud (new pcl::PointCloud<PointT> ());
01597 pcl::ExtractIndices<PointT> extraction_of_handle_inliers;
01598
01599 extraction_of_handle_inliers.setInputCloud (auxiliary_input_cloud);
01600
01601 extraction_of_handle_inliers.setIndices (cloud_object_indices);
01602
01603 extraction_of_handle_inliers.setNegative (false);
01604
01605 extraction_of_handle_inliers.filter (*handle_cloud);
01606
01607
01608
01609
01610
01611 fixtures += *handle_cloud;
01612
01613
01614 std::stringstream id_of_handle;
01615 id_of_handle << "HANDLE_" << ros::Time::now();
01616
01617 viewer.addPointCloud (handle_cloud, id_of_handle.str());
01618
01619 viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, size_of_points * 3, id_of_handle.str());
01620
01621 if ( step )
01622 {
01623
01624 viewer.spin ();
01625 }
01626
01627
01628
01629
01630 std::vector<pcl::PointIndices> handle_clusters;
01631
01632 pcl::KdTreeFLANN<PointT>::Ptr handle_clusters_tree (new pcl::KdTreeFLANN<PointT> ());
01633
01634
01635 pcl::EuclideanClusterExtraction<PointT> clustering_of_handles;
01636
01637 clustering_of_handles.setInputCloud (handle_cloud);
01638
01639 clustering_of_handles.setClusterTolerance (handle_clustering_tolerance);
01640
01641 clustering_of_handles.setMinClusterSize (minimum_size_of_handle_cluster);
01642
01643 clustering_of_handles.setSearchMethod (handle_clusters_tree);
01644
01645 clustering_of_handles.extract (handle_clusters);
01646
01647
01648 std::vector<pcl::PointCloud<PointT>::Ptr> handle_clusters_clouds;
01649
01650
01651 std::vector<pcl::PointIndices::Ptr> handle_indices;
01652
01653 for (int c = 0; c < (int) handle_clusters.size(); c++)
01654 {
01655
01656 pcl::PointIndices::Ptr pointer_of_handle_cluster (new pcl::PointIndices (handle_clusters.at(c)));
01657 pcl::PointCloud<PointT>::Ptr cluster_of_handle (new pcl::PointCloud<PointT>);
01658
01659
01660 pcl::ExtractIndices<PointT> extraction_of_handle_clusters;
01661
01662 extraction_of_handle_clusters.setInputCloud (handle_cloud);
01663
01664 extraction_of_handle_clusters.setIndices (pointer_of_handle_cluster);
01665
01666 extraction_of_handle_clusters.setNegative (false);
01667
01668 extraction_of_handle_clusters.filter (*cluster_of_handle);
01669
01670
01671
01672
01673
01674
01675 pcl::SACSegmentation<PointT> segmentation_of_line;
01676 pcl::PointIndices::Ptr line_inliers (new pcl::PointIndices ());
01677 pcl::ModelCoefficients::Ptr line_coefficients (new pcl::ModelCoefficients ());
01678
01679
01680 segmentation_of_line.setOptimizeCoefficients (true);
01681 segmentation_of_line.setModelType (pcl::SACMODEL_LINE);
01682
01683 segmentation_of_line.setMethodType (pcl::SAC_RANSAC);
01684 segmentation_of_line.setDistanceThreshold (0.025);
01685 segmentation_of_line.setMaxIterations (maximum_plane_iterations);
01686
01687 segmentation_of_line.setEpsAngle (epsilon_angle);
01688 segmentation_of_line.setInputCloud (cluster_of_handle);
01689
01690
01691
01692 segmentation_of_line.segment (*line_inliers, *line_coefficients);
01693
01694 if ( verbose )
01695 {
01696 ROS_INFO ("Line has %3d inliers with parameters P1 = (%6.3f,%6.3f,%6.3f) and P2 = (%6.3f,%6.3f,%6.3f) found in maximum %d iterations",
01697 (int) line_inliers->indices.size (), line_coefficients->values [0], line_coefficients->values [1], line_coefficients->values [2], line_coefficients->values [3], line_coefficients->values [4], line_coefficients->values [5], maximum_plane_iterations);
01698 }
01699
01700
01701 if ((int) line_inliers->indices.size () < 10 )
01702 {
01703 ROS_WARN ("NOT ACCEPTED !");
01704 }
01705 else
01706 {
01707 ROS_WARN ("ACCEPTED !");
01708
01709
01710
01711
01712
01713
01714 pcl::PointCloud<PointT>::Ptr line_inliers_cloud (new pcl::PointCloud<PointT> ());
01715
01716
01717 pcl::ExtractIndices<PointT> extraction_of_line;
01718
01719 extraction_of_line.setInputCloud (cluster_of_handle);
01720
01721 extraction_of_line.setIndices (line_inliers);
01722
01723
01724 extraction_of_line.setNegative (false);
01725
01726 extraction_of_line.filter (*line_inliers_cloud);
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740 std::stringstream id_of_line;
01741 id_of_line << "LINE_" << ros::Time::now();
01742
01743
01744 viewer.addPointCloud (line_inliers_cloud, id_of_line.str());
01745
01746 viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, size_of_points * 4, id_of_line.str());
01747
01748
01749 if ( step )
01750 {
01751
01752 viewer.spin ();
01753 }
01754
01755
01756 handles_clusters_ids.push_back (id_of_line.str());
01757
01758 }
01759
01760
01761
01762
01763
01764
01765
01766 if ( verbose )
01767 {
01768 ROS_INFO (" Cluster of handle %d has %d points", c, (int) cluster_of_handle->points.size());
01769 }
01770
01771
01772 std::stringstream id_of_handle_cluster;
01773 id_of_handle_cluster << "HANDLE_CLUSTER_" << ros::Time::now();
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801 handle_clusters_clouds.push_back (cluster_of_handle);
01802
01803
01804 handle_indices.push_back (pointer_of_handle_cluster);
01805
01806
01807 handle_ids.push_back (id_of_handle.str());
01808
01809
01810
01811
01812 }
01813
01814
01815 viewer.removePointCloud (id_of_handle.str());
01816 }
01817 }
01818 }
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869 pcl::PointCloud<PointT>::Ptr furniture_and_fixtures (new pcl::PointCloud<PointT> ());
01870 *furniture_and_fixtures += *furniture;
01871 *furniture_and_fixtures += fixtures;
01872
01873
01874 std::string furniture_and_fixtures_filename = argv [pFileIndicesPCD [0]];
01875 furniture_and_fixtures_filename.insert (dot, "-furniture_and_fixtures");
01876
01877
01878 pcl::io::savePCDFile (furniture_and_fixtures_filename, *furniture_and_fixtures);
01879
01880 if ( verbose )
01881 {
01882 ROS_WARN (" ");
01883 ROS_WARN ("FURNITURE HAS %d POINTS", (int) furniture->points.size());
01884 ROS_WARN ("FIXTURES HAVE %d POINTS", (int) fixtures.points.size());
01885 ROS_WARN (" ");
01886 }
01887
01888
01889 if ( step )
01890 {
01891
01892 viewer.spin ();
01893 }
01894
01895
01896 if ( step )
01897 {
01898
01899 viewer.spin ();
01900 }
01901
01902
01903 if ( step )
01904 {
01905
01906 viewer.spin ();
01907 }
01908
01909
01910
01912
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01942
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106 if ( verbose )
02107 {
02108
02109 ROS_WARN ("Finished in %5.3g [s] !", tt.toc ());
02110 }
02111
02112
02113 viewer.spin ();
02114
02115 return (0);
02116 }