openni_tracking.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Point Cloud Library (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2012-, Open Perception, Inc.
00006  *
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of the copyright holder(s) nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  */
00037 #include <pcl/tracking/tracking.h>
00038 #include <pcl/tracking/particle_filter.h>
00039 #include <pcl/tracking/kld_adaptive_particle_filter_omp.h>
00040 #include <pcl/tracking/particle_filter_omp.h>
00041 
00042 #include <pcl/tracking/coherence.h>
00043 #include <pcl/tracking/distance_coherence.h>
00044 #include <pcl/tracking/hsv_color_coherence.h>
00045 #include <pcl/tracking/normal_coherence.h>
00046 
00047 #include <pcl/tracking/approx_nearest_pair_point_cloud_coherence.h>
00048 #include <pcl/tracking/nearest_pair_point_cloud_coherence.h>
00049 
00050 #include <pcl/point_cloud.h>
00051 #include <pcl/point_types.h>
00052 #include <pcl/io/openni_grabber.h>
00053 #include <pcl/console/parse.h>
00054 #include <pcl/common/time.h>
00055 #include <pcl/common/centroid.h>
00056 
00057 #include <pcl/visualization/cloud_viewer.h>
00058 #include <pcl/visualization/pcl_visualizer.h>
00059 
00060 #include <pcl/io/pcd_io.h>
00061 
00062 #include <pcl/filters/passthrough.h>
00063 #include <pcl/filters/project_inliers.h>
00064 #include <pcl/filters/voxel_grid.h>
00065 #include <pcl/filters/approximate_voxel_grid.h>
00066 #include <pcl/filters/extract_indices.h>
00067 
00068 #include <pcl/features/normal_3d.h>
00069 #include <pcl/features/normal_3d_omp.h>
00070 #include <pcl/features/integral_image_normal.h>
00071 
00072 #include <pcl/sample_consensus/method_types.h>
00073 #include <pcl/sample_consensus/model_types.h>
00074 
00075 #include <pcl/segmentation/sac_segmentation.h>
00076 #include <pcl/segmentation/extract_polygonal_prism_data.h>
00077 #include <pcl/segmentation/extract_clusters.h>
00078 
00079 #include <pcl/surface/convex_hull.h>
00080 
00081 #include <pcl/search/pcl_search.h>
00082 #include <pcl/common/transforms.h>
00083 
00084 #include <boost/format.hpp>
00085 
00086 #define FPS_CALC_BEGIN                          \
00087     static double duration = 0;                 \
00088     double start_time = pcl::getTime ();        \
00089 
00090 #define FPS_CALC_END(_WHAT_)                    \
00091   {                                             \
00092     double end_time = pcl::getTime ();          \
00093     static unsigned count = 0;                  \
00094     if (++count == 10)                          \
00095     {                                           \
00096       std::cout << "Average framerate("<< _WHAT_ << "): " << double(count)/double(duration) << " Hz" <<  std::endl; \
00097       count = 0;                                                        \
00098       duration = 0.0;                                                   \
00099     }                                           \
00100     else                                        \
00101     {                                           \
00102       duration += end_time - start_time;        \
00103     }                                           \
00104   }
00105 
00106 using namespace pcl::tracking;
00107 
00108 template <typename PointType>
00109 class OpenNISegmentTracking
00110 {
00111 public:
00112   //typedef pcl::PointXYZRGBANormal RefPointType;
00113   typedef pcl::PointXYZRGBA RefPointType;
00114   //typedef pcl::PointXYZ RefPointType;
00115   typedef ParticleXYZRPY ParticleT;
00116   
00117   typedef pcl::PointCloud<PointType> Cloud;
00118   typedef pcl::PointCloud<RefPointType> RefCloud;
00119   typedef typename RefCloud::Ptr RefCloudPtr;
00120   typedef typename RefCloud::ConstPtr RefCloudConstPtr;
00121   typedef typename Cloud::Ptr CloudPtr;
00122   typedef typename Cloud::ConstPtr CloudConstPtr;
00123   //typedef KLDAdaptiveParticleFilterTracker<RefPointType, ParticleT> ParticleFilter;
00124   //typedef KLDAdaptiveParticleFilterOMPTracker<RefPointType, ParticleT> ParticleFilter;
00125   //typedef ParticleFilterOMPTracker<RefPointType, ParticleT> ParticleFilter;
00126   typedef ParticleFilterTracker<RefPointType, ParticleT> ParticleFilter;
00127   typedef typename ParticleFilter::CoherencePtr CoherencePtr;
00128   typedef typename pcl::search::KdTree<PointType> KdTree;
00129   typedef typename KdTree::Ptr KdTreePtr;
00130   OpenNISegmentTracking (const std::string& device_id, int thread_nr, double downsampling_grid_size,
00131                          bool use_convex_hull,
00132                          bool visualize_non_downsample, bool visualize_particles,
00133                          bool use_fixed)
00134   : viewer_ ("PCL OpenNI Tracking Viewer")
00135   , device_id_ (device_id)
00136   , new_cloud_ (false)
00137   , ne_ (thread_nr)
00138   , counter_ (0)
00139   , use_convex_hull_ (use_convex_hull)
00140   , visualize_non_downsample_ (visualize_non_downsample)
00141   , visualize_particles_ (visualize_particles)
00142   , downsampling_grid_size_ (downsampling_grid_size)
00143   {
00144     KdTreePtr tree (new KdTree (false));
00145     ne_.setSearchMethod (tree);
00146     ne_.setRadiusSearch (0.03);
00147     
00148     std::vector<double> default_step_covariance = std::vector<double> (6, 0.015 * 0.015);
00149     default_step_covariance[3] *= 40.0;
00150     default_step_covariance[4] *= 40.0;
00151     default_step_covariance[5] *= 40.0;
00152     
00153     std::vector<double> initial_noise_covariance = std::vector<double> (6, 0.00001);
00154     std::vector<double> default_initial_mean = std::vector<double> (6, 0.0);
00155     if (use_fixed)
00156     {
00157       boost::shared_ptr<ParticleFilterOMPTracker<RefPointType, ParticleT> > tracker
00158         (new ParticleFilterOMPTracker<RefPointType, ParticleT> (thread_nr));
00159       tracker_ = tracker;
00160     }
00161     else
00162     {
00163       boost::shared_ptr<KLDAdaptiveParticleFilterOMPTracker<RefPointType, ParticleT> > tracker
00164         (new KLDAdaptiveParticleFilterOMPTracker<RefPointType, ParticleT> (thread_nr));
00165       tracker->setMaximumParticleNum (500);
00166       tracker->setDelta (0.99);
00167       tracker->setEpsilon (0.2);
00168       ParticleT bin_size;
00169       bin_size.x = 0.1f;
00170       bin_size.y = 0.1f;
00171       bin_size.z = 0.1f;
00172       bin_size.roll = 0.1f;
00173       bin_size.pitch = 0.1f;
00174       bin_size.yaw = 0.1f;
00175       tracker->setBinSize (bin_size);
00176       tracker_ = tracker;
00177     }
00178     
00179     tracker_->setTrans (Eigen::Affine3f::Identity ());
00180     tracker_->setStepNoiseCovariance (default_step_covariance);
00181     tracker_->setInitialNoiseCovariance (initial_noise_covariance);
00182     tracker_->setInitialNoiseMean (default_initial_mean);
00183     tracker_->setIterationNum (1);
00184     
00185     tracker_->setParticleNum (400);
00186     tracker_->setResampleLikelihoodThr(0.00);
00187     tracker_->setUseNormal (false);
00188     // setup coherences
00189     ApproxNearestPairPointCloudCoherence<RefPointType>::Ptr coherence = ApproxNearestPairPointCloudCoherence<RefPointType>::Ptr
00190       (new ApproxNearestPairPointCloudCoherence<RefPointType> ());
00191     // NearestPairPointCloudCoherence<RefPointType>::Ptr coherence = NearestPairPointCloudCoherence<RefPointType>::Ptr
00192     //   (new NearestPairPointCloudCoherence<RefPointType> ());
00193     
00194     boost::shared_ptr<DistanceCoherence<RefPointType> > distance_coherence
00195       = boost::shared_ptr<DistanceCoherence<RefPointType> > (new DistanceCoherence<RefPointType> ());
00196     coherence->addPointCoherence (distance_coherence);
00197     
00198     boost::shared_ptr<HSVColorCoherence<RefPointType> > color_coherence
00199       = boost::shared_ptr<HSVColorCoherence<RefPointType> > (new HSVColorCoherence<RefPointType> ());
00200     color_coherence->setWeight (0.1);
00201     coherence->addPointCoherence (color_coherence);
00202     
00203     //boost::shared_ptr<pcl::search::KdTree<RefPointType> > search (new pcl::search::KdTree<RefPointType> (false));
00204     boost::shared_ptr<pcl::search::Octree<RefPointType> > search (new pcl::search::Octree<RefPointType> (0.01));
00205     //boost::shared_ptr<pcl::search::OrganizedNeighbor<RefPointType> > search (new pcl::search::OrganizedNeighbor<RefPointType>);
00206     coherence->setSearchMethod (search);
00207     coherence->setMaximumDistance (0.01);
00208     tracker_->setCloudCoherence (coherence);
00209   }
00210 
00211   bool
00212   drawParticles (pcl::visualization::PCLVisualizer& viz)
00213   {
00214     ParticleFilter::PointCloudStatePtr particles = tracker_->getParticles ();
00215     if (particles)
00216     {
00217       if (visualize_particles_)
00218       {
00219         pcl::PointCloud<pcl::PointXYZ>::Ptr particle_cloud (new pcl::PointCloud<pcl::PointXYZ> ());
00220         for (size_t i = 0; i < particles->points.size (); i++)
00221         {
00222           pcl::PointXYZ point;
00223           
00224           point.x = particles->points[i].x;
00225           point.y = particles->points[i].y;
00226           point.z = particles->points[i].z;
00227           particle_cloud->points.push_back (point);
00228         }
00229         
00230         {
00231           pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> blue_color (particle_cloud, 250, 99, 71);
00232           if (!viz.updatePointCloud (particle_cloud, blue_color, "particle cloud"))
00233             viz.addPointCloud (particle_cloud, blue_color, "particle cloud");
00234         }
00235       }
00236       return true;
00237     }
00238     else
00239     {
00240       PCL_WARN ("no particles\n");
00241       return false;
00242     }
00243   }
00244   
00245   void
00246   drawResult (pcl::visualization::PCLVisualizer& viz)
00247   {
00248     ParticleXYZRPY result = tracker_->getResult ();
00249     Eigen::Affine3f transformation = tracker_->toEigenMatrix (result);
00250     // move a little bit for better visualization
00251     transformation.translation () += Eigen::Vector3f (0.0f, 0.0f, -0.005f);
00252     RefCloudPtr result_cloud (new RefCloud ());
00253 
00254     if (!visualize_non_downsample_)
00255       pcl::transformPointCloud<RefPointType> (*(tracker_->getReferenceCloud ()), *result_cloud, transformation);
00256     else
00257       pcl::transformPointCloud<RefPointType> (*reference_, *result_cloud, transformation);
00258 
00259     {
00260       pcl::visualization::PointCloudColorHandlerCustom<RefPointType> red_color (result_cloud, 0, 0, 255);
00261       if (!viz.updatePointCloud (result_cloud, red_color, "resultcloud"))
00262         viz.addPointCloud (result_cloud, red_color, "resultcloud");
00263     }
00264     
00265   }
00266   
00267   void
00268   viz_cb (pcl::visualization::PCLVisualizer& viz)
00269   {
00270     boost::mutex::scoped_lock lock (mtx_);
00271     
00272     if (!cloud_pass_)
00273     {
00274       boost::this_thread::sleep (boost::posix_time::seconds (1));
00275       return;
00276     }
00277     
00278     if (new_cloud_ && cloud_pass_downsampled_)
00279     {
00280       CloudPtr cloud_pass;
00281       if (!visualize_non_downsample_)
00282         cloud_pass = cloud_pass_downsampled_;
00283       else
00284         cloud_pass = cloud_pass_;
00285       
00286       if (!viz.updatePointCloud (cloud_pass, "cloudpass"))
00287         {
00288           viz.addPointCloud (cloud_pass, "cloudpass");
00289           viz.resetCameraViewpoint ("cloudpass");
00290         }
00291     }
00292 
00293     if (new_cloud_ && reference_)
00294     {
00295       bool ret = drawParticles (viz);
00296       if (ret)
00297       {
00298         drawResult (viz);
00299         
00300         // draw some texts
00301         viz.removeShape ("N");
00302         viz.addText ((boost::format ("number of Reference PointClouds: %d") % tracker_->getReferenceCloud ()->points.size ()).str (),
00303                      10, 20, 20, 1.0, 1.0, 1.0, "N");
00304         
00305         viz.removeShape ("M");
00306         viz.addText ((boost::format ("number of Measured PointClouds:  %d") % cloud_pass_downsampled_->points.size ()).str (),
00307                      10, 40, 20, 1.0, 1.0, 1.0, "M");
00308         
00309         viz.removeShape ("tracking");
00310         viz.addText ((boost::format ("tracking:        %f fps") % (1.0 / tracking_time_)).str (),
00311                      10, 60, 20, 1.0, 1.0, 1.0, "tracking");
00312         
00313         viz.removeShape ("downsampling");
00314         viz.addText ((boost::format ("downsampling:    %f fps") % (1.0 / downsampling_time_)).str (),
00315                      10, 80, 20, 1.0, 1.0, 1.0, "downsampling");
00316         
00317         viz.removeShape ("computation");
00318         viz.addText ((boost::format ("computation:     %f fps") % (1.0 / computation_time_)).str (),
00319                      10, 100, 20, 1.0, 1.0, 1.0, "computation");
00320 
00321         viz.removeShape ("particles");
00322         viz.addText ((boost::format ("particles:     %d") % tracker_->getParticles ()->points.size ()).str (),
00323                      10, 120, 20, 1.0, 1.0, 1.0, "particles");
00324         
00325       }
00326     }
00327     new_cloud_ = false;
00328   }
00329 
00330   void filterPassThrough (const CloudConstPtr &cloud, Cloud &result)
00331   {
00332     FPS_CALC_BEGIN;
00333     pcl::PassThrough<PointType> pass;
00334     pass.setFilterFieldName ("z");
00335     pass.setFilterLimits (0.0, 10.0);
00336     //pass.setFilterLimits (0.0, 1.5);
00337     //pass.setFilterLimits (0.0, 0.6);
00338     pass.setKeepOrganized (false);
00339     pass.setInputCloud (cloud);
00340     pass.filter (result);
00341     FPS_CALC_END("filterPassThrough");
00342   }
00343 
00344   void euclideanSegment (const CloudConstPtr &cloud,
00345                          std::vector<pcl::PointIndices> &cluster_indices)
00346   {
00347     FPS_CALC_BEGIN;
00348     pcl::EuclideanClusterExtraction<PointType> ec;
00349     KdTreePtr tree (new KdTree ());
00350     
00351     ec.setClusterTolerance (0.05); // 2cm
00352     ec.setMinClusterSize (50);
00353     ec.setMaxClusterSize (25000);
00354     //ec.setMaxClusterSize (400);
00355     ec.setSearchMethod (tree);
00356     ec.setInputCloud (cloud);
00357     ec.extract (cluster_indices);
00358     FPS_CALC_END("euclideanSegmentation");
00359   }
00360   
00361   void gridSample (const CloudConstPtr &cloud, Cloud &result, double leaf_size = 0.01)
00362   {
00363     FPS_CALC_BEGIN;
00364     double start = pcl::getTime ();
00365     pcl::VoxelGrid<PointType> grid;
00366     //pcl::ApproximateVoxelGrid<PointType> grid;
00367     grid.setLeafSize (float (leaf_size), float (leaf_size), float (leaf_size));
00368     grid.setInputCloud (cloud);
00369     grid.filter (result);
00370     //result = *cloud;
00371     double end = pcl::getTime ();
00372     downsampling_time_ = end - start;
00373     FPS_CALC_END("gridSample");
00374   }
00375   
00376   void gridSampleApprox (const CloudConstPtr &cloud, Cloud &result, double leaf_size = 0.01)
00377   {
00378     FPS_CALC_BEGIN;
00379     double start = pcl::getTime ();
00380     //pcl::VoxelGrid<PointType> grid;
00381     pcl::ApproximateVoxelGrid<PointType> grid;
00382     grid.setLeafSize (static_cast<float> (leaf_size), static_cast<float> (leaf_size), static_cast<float> (leaf_size));
00383     grid.setInputCloud (cloud);
00384     grid.filter (result);
00385     //result = *cloud;
00386     double end = pcl::getTime ();
00387     downsampling_time_ = end - start;
00388     FPS_CALC_END("gridSample");
00389   }
00390   
00391   void planeSegmentation (const CloudConstPtr &cloud,
00392                           pcl::ModelCoefficients &coefficients,
00393                           pcl::PointIndices &inliers)
00394   {
00395     FPS_CALC_BEGIN;
00396     pcl::SACSegmentation<PointType> seg;
00397     seg.setOptimizeCoefficients (true);
00398     seg.setModelType (pcl::SACMODEL_PLANE);
00399     seg.setMethodType (pcl::SAC_RANSAC);
00400     seg.setMaxIterations (1000);
00401     seg.setDistanceThreshold (0.03);
00402     seg.setInputCloud (cloud);
00403     seg.segment (inliers, coefficients);
00404     FPS_CALC_END("planeSegmentation");
00405   }
00406 
00407   void planeProjection (const CloudConstPtr &cloud,
00408                         Cloud &result,
00409                         const pcl::ModelCoefficients::ConstPtr &coefficients)
00410   {
00411     FPS_CALC_BEGIN;
00412     pcl::ProjectInliers<PointType> proj;
00413     proj.setModelType (pcl::SACMODEL_PLANE);
00414     proj.setInputCloud (cloud);
00415     proj.setModelCoefficients (coefficients);
00416     proj.filter (result);
00417     FPS_CALC_END("planeProjection");
00418   }
00419 
00420   void convexHull (const CloudConstPtr &cloud,
00421                    Cloud &,
00422                    std::vector<pcl::Vertices> &hull_vertices)
00423   {
00424     FPS_CALC_BEGIN;
00425     pcl::ConvexHull<PointType> chull;
00426     chull.setInputCloud (cloud);
00427     chull.reconstruct (*cloud_hull_, hull_vertices);
00428     FPS_CALC_END("convexHull");
00429   }
00430 
00431   void normalEstimation (const CloudConstPtr &cloud,
00432                          pcl::PointCloud<pcl::Normal> &result)
00433   {
00434     FPS_CALC_BEGIN;
00435     ne_.setInputCloud (cloud);
00436     ne_.compute (result);
00437     FPS_CALC_END("normalEstimation");
00438   }
00439   
00440   void tracking (const RefCloudConstPtr &cloud)
00441   {
00442     double start = pcl::getTime ();
00443     FPS_CALC_BEGIN;
00444     tracker_->setInputCloud (cloud);
00445     tracker_->compute ();
00446     double end = pcl::getTime ();
00447     FPS_CALC_END("tracking");
00448     tracking_time_ = end - start;
00449   }
00450 
00451   void addNormalToCloud (const CloudConstPtr &cloud,
00452                          const pcl::PointCloud<pcl::Normal>::ConstPtr &normals,
00453                          RefCloud &result)
00454   {
00455     result.width = cloud->width;
00456     result.height = cloud->height;
00457     result.is_dense = cloud->is_dense;
00458     for (size_t i = 0; i < cloud->points.size (); i++)
00459     {
00460       RefPointType point;
00461       point.x = cloud->points[i].x;
00462       point.y = cloud->points[i].y;
00463       point.z = cloud->points[i].z;
00464       point.rgba = cloud->points[i].rgba;
00465       // point.normal[0] = normals->points[i].normal[0];
00466       // point.normal[1] = normals->points[i].normal[1];
00467       // point.normal[2] = normals->points[i].normal[2];
00468       result.points.push_back (point);
00469     }
00470   }
00471 
00472   void extractNonPlanePoints (const CloudConstPtr &cloud,
00473                               const CloudConstPtr &cloud_hull,
00474                               Cloud &result)
00475   {
00476     pcl::ExtractPolygonalPrismData<PointType> polygon_extract;
00477     pcl::PointIndices::Ptr inliers_polygon (new pcl::PointIndices ());
00478     polygon_extract.setHeightLimits (0.01, 10.0);
00479     polygon_extract.setInputPlanarHull (cloud_hull);
00480     polygon_extract.setInputCloud (cloud);
00481     polygon_extract.segment (*inliers_polygon);
00482     {
00483       pcl::ExtractIndices<PointType> extract_positive;
00484       extract_positive.setNegative (false);
00485       extract_positive.setInputCloud (cloud);
00486       extract_positive.setIndices (inliers_polygon);
00487       extract_positive.filter (result);
00488     }
00489   }
00490 
00491   void removeZeroPoints (const CloudConstPtr &cloud,
00492                          Cloud &result)
00493   {
00494     for (size_t i = 0; i < cloud->points.size (); i++)
00495     {
00496       PointType point = cloud->points[i];
00497       if (!(fabs(point.x) < 0.01 &&
00498             fabs(point.y) < 0.01 &&
00499             fabs(point.z) < 0.01) &&
00500           !pcl_isnan(point.x) &&
00501           !pcl_isnan(point.y) &&
00502           !pcl_isnan(point.z))
00503         result.points.push_back(point);
00504     }
00505 
00506     result.width = static_cast<pcl::uint32_t> (result.points.size ());
00507     result.height = 1;
00508     result.is_dense = true;
00509   }
00510   
00511   void extractSegmentCluster (const CloudConstPtr &cloud,
00512                               const std::vector<pcl::PointIndices> cluster_indices,
00513                               const int segment_index,
00514                               Cloud &result)
00515   {
00516     pcl::PointIndices segmented_indices = cluster_indices[segment_index];
00517     for (size_t i = 0; i < segmented_indices.indices.size (); i++)
00518     {
00519       PointType point = cloud->points[segmented_indices.indices[i]];
00520       result.points.push_back (point);
00521     }
00522     result.width = pcl::uint32_t (result.points.size ());
00523     result.height = 1;
00524     result.is_dense = true;
00525   }
00526   
00527   void
00528   cloud_cb (const CloudConstPtr &cloud)
00529   {
00530     boost::mutex::scoped_lock lock (mtx_);
00531     double start = pcl::getTime ();
00532     FPS_CALC_BEGIN;
00533     cloud_pass_.reset (new Cloud);
00534     cloud_pass_downsampled_.reset (new Cloud);
00535     pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients ());
00536     pcl::PointIndices::Ptr inliers (new pcl::PointIndices ());
00537     filterPassThrough (cloud, *cloud_pass_);
00538     if (counter_ < 10)
00539     {
00540       gridSample (cloud_pass_, *cloud_pass_downsampled_, downsampling_grid_size_);
00541     }
00542     else if (counter_ == 10)
00543     {
00544       //gridSample (cloud_pass_, *cloud_pass_downsampled_, 0.01);
00545       cloud_pass_downsampled_ = cloud_pass_;
00546       CloudPtr target_cloud;
00547       if (use_convex_hull_)
00548       {
00549         planeSegmentation (cloud_pass_downsampled_, *coefficients, *inliers);
00550         if (inliers->indices.size () > 3)
00551         {
00552           CloudPtr cloud_projected (new Cloud);
00553           cloud_hull_.reset (new Cloud);
00554           nonplane_cloud_.reset (new Cloud);
00555           
00556           planeProjection (cloud_pass_downsampled_, *cloud_projected, coefficients);
00557           convexHull (cloud_projected, *cloud_hull_, hull_vertices_);
00558           
00559           extractNonPlanePoints (cloud_pass_downsampled_, cloud_hull_, *nonplane_cloud_);
00560           target_cloud = nonplane_cloud_;
00561         }
00562         else
00563         {
00564           PCL_WARN ("cannot segment plane\n");
00565         }
00566       }
00567       else
00568       {
00569         PCL_WARN ("without plane segmentation\n");
00570         target_cloud = cloud_pass_downsampled_;
00571       }
00572       
00573       if (target_cloud != NULL)
00574       {
00575         PCL_INFO ("segmentation, please wait...\n");
00576         std::vector<pcl::PointIndices> cluster_indices;
00577         euclideanSegment (target_cloud, cluster_indices);
00578         if (cluster_indices.size () > 0)
00579         {
00580           // select the cluster to track
00581           CloudPtr temp_cloud (new Cloud);
00582           extractSegmentCluster (target_cloud, cluster_indices, 0, *temp_cloud);
00583           Eigen::Vector4f c;
00584           pcl::compute3DCentroid<RefPointType> (*temp_cloud, c);
00585           int segment_index = 0;
00586           double segment_distance = c[0] * c[0] + c[1] * c[1];
00587           for (size_t i = 1; i < cluster_indices.size (); i++)
00588           {
00589             temp_cloud.reset (new Cloud);
00590             extractSegmentCluster (target_cloud, cluster_indices, int (i), *temp_cloud);
00591             pcl::compute3DCentroid<RefPointType> (*temp_cloud, c);
00592             double distance = c[0] * c[0] + c[1] * c[1];
00593             if (distance < segment_distance)
00594             {
00595               segment_index = int (i);
00596               segment_distance = distance;
00597             }
00598           }
00599           
00600           segmented_cloud_.reset (new Cloud);
00601           extractSegmentCluster (target_cloud, cluster_indices, segment_index, *segmented_cloud_);
00602           //pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>);
00603           //normalEstimation (segmented_cloud_, *normals);
00604           RefCloudPtr ref_cloud (new RefCloud);
00605           //addNormalToCloud (segmented_cloud_, normals, *ref_cloud);
00606           ref_cloud = segmented_cloud_;
00607           RefCloudPtr nonzero_ref (new RefCloud);
00608           removeZeroPoints (ref_cloud, *nonzero_ref);
00609           
00610           PCL_INFO ("calculating cog\n");
00611           
00612           RefCloudPtr transed_ref (new RefCloud);
00613           pcl::compute3DCentroid<RefPointType> (*nonzero_ref, c);
00614           Eigen::Affine3f trans = Eigen::Affine3f::Identity ();
00615           trans.translation ().matrix () = Eigen::Vector3f (c[0], c[1], c[2]);
00616           //pcl::transformPointCloudWithNormals<RefPointType> (*ref_cloud, *transed_ref, trans.inverse());
00617           pcl::transformPointCloud<RefPointType> (*nonzero_ref, *transed_ref, trans.inverse());
00618           CloudPtr transed_ref_downsampled (new Cloud);
00619           gridSample (transed_ref, *transed_ref_downsampled, downsampling_grid_size_);
00620           tracker_->setReferenceCloud (transed_ref_downsampled);
00621           tracker_->setTrans (trans);
00622           reference_ = transed_ref;
00623           tracker_->setMinIndices (int (ref_cloud->points.size ()) / 2);
00624         }
00625         else
00626         {
00627           PCL_WARN ("euclidean segmentation failed\n");
00628         }
00629       }
00630     }
00631     else
00632     {
00633       //normals_.reset (new pcl::PointCloud<pcl::Normal>);
00634       //normalEstimation (cloud_pass_downsampled_, *normals_);
00635       //RefCloudPtr tracking_cloud (new RefCloud ());
00636       //addNormalToCloud (cloud_pass_downsampled_, normals_, *tracking_cloud);
00637       //tracking_cloud = cloud_pass_downsampled_;
00638       
00639       //*cloud_pass_downsampled_ = *cloud_pass_;
00640       //cloud_pass_downsampled_ = cloud_pass_;
00641       gridSampleApprox (cloud_pass_, *cloud_pass_downsampled_, downsampling_grid_size_);
00642       tracking (cloud_pass_downsampled_);
00643     }
00644     
00645     new_cloud_ = true;
00646     double end = pcl::getTime ();
00647     computation_time_ = end - start;
00648     FPS_CALC_END("computation");
00649     counter_++;
00650   }
00651       
00652   void
00653   run ()
00654   {
00655     pcl::Grabber* interface = new pcl::OpenNIGrabber (device_id_);
00656     boost::function<void (const CloudConstPtr&)> f =
00657       boost::bind (&OpenNISegmentTracking::cloud_cb, this, _1);
00658     interface->registerCallback (f);
00659     
00660     viewer_.runOnVisualizationThread (boost::bind(&OpenNISegmentTracking::viz_cb, this, _1), "viz_cb");
00661     
00662     interface->start ();
00663       
00664     while (!viewer_.wasStopped ())
00665       boost::this_thread::sleep(boost::posix_time::seconds(1));
00666     interface->stop ();
00667   }
00668   
00669   pcl::visualization::CloudViewer viewer_;
00670   pcl::PointCloud<pcl::Normal>::Ptr normals_;
00671   CloudPtr cloud_pass_;
00672   CloudPtr cloud_pass_downsampled_;
00673   CloudPtr plane_cloud_;
00674   CloudPtr nonplane_cloud_;
00675   CloudPtr cloud_hull_;
00676   CloudPtr segmented_cloud_;
00677   CloudPtr reference_;
00678   std::vector<pcl::Vertices> hull_vertices_;
00679   
00680   std::string device_id_;
00681   boost::mutex mtx_;
00682   bool new_cloud_;
00683   pcl::NormalEstimationOMP<PointType, pcl::Normal> ne_; // to store threadpool
00684   boost::shared_ptr<ParticleFilter> tracker_;
00685   int counter_;
00686   bool use_convex_hull_;
00687   bool visualize_non_downsample_;
00688   bool visualize_particles_;
00689   double tracking_time_;
00690   double computation_time_;
00691   double downsampling_time_;
00692   double downsampling_grid_size_;
00693   };
00694 
00695 void
00696 usage (char** argv)
00697 {
00698   std::cout << "usage: " << argv[0] << " <device_id> [-C] [-g]\n\n";
00699   std::cout << "  -C:  initialize the pointcloud to track without plane segmentation"
00700             << std::endl;
00701   std::cout << "  -D: visualizing with non-downsampled pointclouds."
00702             << std::endl;
00703   std::cout << "  -P: not visualizing particle cloud."
00704             << std::endl;
00705   std::cout << "  -fixed: use the fixed number of the particles."
00706             << std::endl;
00707   std::cout << "  -d <value>: specify the grid size of downsampling (defaults to 0.01)."
00708             << std::endl;
00709 }
00710 
00711 int
00712 main (int argc, char** argv)
00713 {
00714   bool use_convex_hull = true;
00715   bool visualize_non_downsample = false;
00716   bool visualize_particles = true;
00717   bool use_fixed = false;
00718 
00719   double downsampling_grid_size = 0.01;
00720   
00721   if (pcl::console::find_argument (argc, argv, "-C") > 0)
00722     use_convex_hull = false;
00723   if (pcl::console::find_argument (argc, argv, "-D") > 0)
00724     visualize_non_downsample = true;
00725   if (pcl::console::find_argument (argc, argv, "-P") > 0)
00726     visualize_particles = false;
00727   if (pcl::console::find_argument (argc, argv, "-fixed") > 0)
00728     use_fixed = true;
00729   pcl::console::parse_argument (argc, argv, "-d", downsampling_grid_size);
00730   if (argc < 2)
00731   {
00732     usage (argv);
00733     exit (1);
00734   }
00735   
00736   std::string device_id = std::string (argv[1]);
00737 
00738   if (device_id == "--help" || device_id == "-h")
00739   {
00740     usage (argv);
00741     exit (1);
00742   }
00743   
00744   // open kinect
00745   OpenNISegmentTracking<pcl::PointXYZRGBA> v (device_id, 8, downsampling_grid_size,
00746                                               use_convex_hull,
00747                                               visualize_non_downsample, visualize_particles,
00748                                               use_fixed);
00749   v.run ();
00750 }


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:26:56