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
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
00113 typedef pcl::PointXYZRGBA RefPointType;
00114
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
00124
00125
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
00189 ApproxNearestPairPointCloudCoherence<RefPointType>::Ptr coherence = ApproxNearestPairPointCloudCoherence<RefPointType>::Ptr
00190 (new ApproxNearestPairPointCloudCoherence<RefPointType> ());
00191
00192
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
00204 boost::shared_ptr<pcl::search::Octree<RefPointType> > search (new pcl::search::Octree<RefPointType> (0.01));
00205
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
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
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
00337
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);
00352 ec.setMinClusterSize (50);
00353 ec.setMaxClusterSize (25000);
00354
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
00367 grid.setLeafSize (float (leaf_size), float (leaf_size), float (leaf_size));
00368 grid.setInputCloud (cloud);
00369 grid.filter (result);
00370
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
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
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
00466
00467
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
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
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
00603
00604 RefCloudPtr ref_cloud (new RefCloud);
00605
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
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
00634
00635
00636
00637
00638
00639
00640
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_;
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
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 }