|
Point Cloud Library (PCL)
1.4.0
|
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Point Cloud Library (PCL) - www.pointclouds.org 00005 * Copyright (c) 2010-2011, Willow Garage, 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 Willow Garage, Inc. 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 * $Id: sac_model.h 3503 2011-12-12 06:07:28Z rusu $ 00037 * 00038 */ 00039 00040 #ifndef PCL_SAMPLE_CONSENSUS_MODEL_H_ 00041 #define PCL_SAMPLE_CONSENSUS_MODEL_H_ 00042 00043 #include <cfloat> 00044 #include <ctime> 00045 #include <limits.h> 00046 #include <set> 00047 #include <boost/random.hpp> 00048 00049 #include <pcl/console/print.h> 00050 #include <pcl/point_cloud.h> 00051 #include "pcl/sample_consensus/model_types.h" 00052 00053 namespace pcl 00054 { 00055 template<class T> class ProgressiveSampleConsensus; 00056 00062 template <typename PointT> 00063 class SampleConsensusModel 00064 { 00065 public: 00066 typedef typename pcl::PointCloud<PointT> PointCloud; 00067 typedef typename pcl::PointCloud<PointT>::ConstPtr PointCloudConstPtr; 00068 typedef typename pcl::PointCloud<PointT>::Ptr PointCloudPtr; 00069 00070 typedef boost::shared_ptr<SampleConsensusModel> Ptr; 00071 typedef boost::shared_ptr<const SampleConsensusModel> ConstPtr; 00072 00073 private: 00077 SampleConsensusModel (bool random = false) : radius_min_ (-DBL_MAX), radius_max_ (DBL_MAX) 00078 { 00079 // Create a random number generator object 00080 if (random) 00081 rng_alg_.seed (static_cast<unsigned> (std::time(0))); 00082 else 00083 rng_alg_.seed (12345u); 00084 00085 rng_dist_.reset (new boost::uniform_int<> (0, std::numeric_limits<int>::max ())); 00086 rng_gen_.reset (new boost::variate_generator<boost::mt19937&, boost::uniform_int<> > (rng_alg_, *rng_dist_)); 00087 } 00088 00089 public: 00094 SampleConsensusModel (const PointCloudConstPtr &cloud, bool random = false) : 00095 radius_min_ (-DBL_MAX), radius_max_ (DBL_MAX) 00096 { 00097 if (random) 00098 rng_alg_.seed (static_cast<unsigned> (std::time(0))); 00099 else 00100 rng_alg_.seed (12345u); 00101 00102 // Sets the input cloud and creates a vector of "fake" indices 00103 setInputCloud (cloud); 00104 00105 // Create a random number generator object 00106 rng_dist_.reset (new boost::uniform_int<> (0, std::numeric_limits<int>::max ())); 00107 rng_gen_.reset (new boost::variate_generator<boost::mt19937&, boost::uniform_int<> > (rng_alg_, *rng_dist_)); 00108 } 00109 00115 SampleConsensusModel (const PointCloudConstPtr &cloud, const std::vector<int> &indices, bool random = false) : 00116 input_ (cloud), 00117 radius_min_ (-DBL_MAX), radius_max_ (DBL_MAX) 00118 00119 { 00120 if (random) 00121 rng_alg_.seed (static_cast<unsigned> (std::time(0))); 00122 else 00123 rng_alg_.seed (12345u); 00124 00125 indices_.reset (new std::vector<int> (indices)); 00126 if (indices_->size () > input_->points.size ()) 00127 { 00128 PCL_ERROR ("[pcl::SampleConsensusModel] Invalid index vector given with size %lu while the input PointCloud has size %lu!\n", (unsigned long)indices_->size (), (unsigned long)input_->points.size ()); 00129 indices_->clear (); 00130 } 00131 shuffled_indices_ = *indices_; 00132 00133 // Create a random number generator object 00134 rng_dist_.reset (new boost::uniform_int<> (0, std::numeric_limits<int>::max ())); 00135 rng_gen_.reset (new boost::variate_generator<boost::mt19937&, boost::uniform_int<> > (rng_alg_, *rng_dist_)); 00136 }; 00137 00139 virtual ~SampleConsensusModel () {}; 00140 00146 void 00147 getSamples (int &iterations, std::vector<int> &samples) 00148 { 00149 // We're assuming that indices_ have already been set in the constructor 00150 if (indices_->size () < getSampleSize ()) 00151 { 00152 PCL_ERROR ("[pcl::SampleConsensusModel::getSamples] Can not select %lu unique points out of %lu!\n", 00153 (unsigned long)samples.size (), (unsigned long)indices_->size ()); 00154 // one of these will make it stop :) 00155 samples.clear (); 00156 iterations = INT_MAX - 1; 00157 return; 00158 } 00159 00160 // Get a second point which is different than the first 00161 samples.resize (getSampleSize()); 00162 for (unsigned int iter = 0; iter < max_sample_checks_; ++iter) 00163 { 00164 // Choose the random indices 00165 SampleConsensusModel<PointT>::drawIndexSample (samples); 00166 00167 // If it's a good sample, stop here 00168 if (isSampleGood (samples)) 00169 return; 00170 } 00171 PCL_DEBUG ("[pcl::SampleConsensusModel::getSamples] WARNING: Could not select %d sample points in %d iterations!\n", getSampleSize (), max_sample_checks_); 00172 samples.clear (); 00173 } 00174 00182 virtual bool 00183 computeModelCoefficients (const std::vector<int> &samples, 00184 Eigen::VectorXf &model_coefficients) = 0; 00185 00196 virtual void 00197 optimizeModelCoefficients (const std::vector<int> &inliers, 00198 const Eigen::VectorXf &model_coefficients, 00199 Eigen::VectorXf &optimized_coefficients) = 0; 00200 00206 virtual void 00207 getDistancesToModel (const Eigen::VectorXf &model_coefficients, 00208 std::vector<double> &distances) = 0; 00209 00218 virtual void 00219 selectWithinDistance (const Eigen::VectorXf &model_coefficients, 00220 const double threshold, 00221 std::vector<int> &inliers) = 0; 00222 00232 virtual int 00233 countWithinDistance (const Eigen::VectorXf &model_coefficients, 00234 const double threshold) = 0; 00235 00244 virtual void 00245 projectPoints (const std::vector<int> &inliers, 00246 const Eigen::VectorXf &model_coefficients, 00247 PointCloud &projected_points, 00248 bool copy_data_fields = true) = 0; 00249 00258 virtual bool 00259 doSamplesVerifyModel (const std::set<int> &indices, 00260 const Eigen::VectorXf &model_coefficients, 00261 const double threshold) = 0; 00262 00266 inline virtual void 00267 setInputCloud (const PointCloudConstPtr &cloud) 00268 { 00269 input_ = cloud; 00270 if (!indices_) 00271 indices_.reset (new std::vector<int> ()); 00272 if (indices_->empty ()) 00273 { 00274 // Prepare a set of indices to be used (entire cloud) 00275 indices_->resize (cloud->points.size ()); 00276 for (size_t i = 0; i < cloud->points.size (); ++i) 00277 (*indices_)[i] = (int) i; 00278 } 00279 shuffled_indices_ = *indices_; 00280 } 00281 00283 inline PointCloudConstPtr 00284 getInputCloud () const { return (input_); } 00285 00289 inline void 00290 setIndices (const boost::shared_ptr <std::vector<int> > &indices) 00291 { 00292 indices_ = indices; 00293 shuffled_indices_ = *indices_; 00294 } 00295 00299 inline void 00300 setIndices (const std::vector<int> &indices) 00301 { 00302 indices_.reset (new std::vector<int> (indices)); 00303 shuffled_indices_ = indices; 00304 } 00305 00307 inline boost::shared_ptr <std::vector<int> > 00308 getIndices () const { return (indices_); } 00309 00311 virtual SacModel 00312 getModelType () const = 0; 00313 00315 inline unsigned int 00316 getSampleSize () const 00317 { 00318 std::map<pcl::SacModel, unsigned int>::const_iterator it = SAC_SAMPLE_SIZE.find (getModelType ()); 00319 if (it == SAC_SAMPLE_SIZE.end ()) 00320 throw InvalidSACModelTypeException ("No sample size defined for given model type!\n"); 00321 return (it->second); 00322 } 00323 00330 inline void 00331 setRadiusLimits (const double &min_radius, const double &max_radius) 00332 { 00333 radius_min_ = min_radius; 00334 radius_max_ = max_radius; 00335 } 00336 00343 inline void 00344 getRadiusLimits (double &min_radius, double &max_radius) 00345 { 00346 min_radius = radius_min_; 00347 max_radius = radius_max_; 00348 } 00349 00350 friend class ProgressiveSampleConsensus<PointT>; 00351 00352 protected: 00356 inline void 00357 drawIndexSample (std::vector<int> &sample) 00358 { 00359 size_t sample_size = sample.size (); 00360 size_t index_size = shuffled_indices_.size (); 00361 for (unsigned int i = 0; i < sample_size; ++i) 00362 // The 1/(RAND_MAX+1.0) trick is when the random numbers are not uniformly distributed and for small modulo 00363 // elements, that does not matter (and nowadays, random number generators are good) 00364 //std::swap (shuffled_indices_[i], shuffled_indices_[i + (rand () % (index_size - i))]); 00365 std::swap (shuffled_indices_[i], shuffled_indices_[i + (rnd () % (index_size - i))]); 00366 std::copy (shuffled_indices_.begin (), shuffled_indices_.begin () + sample_size, sample.begin ()); 00367 } 00368 00372 virtual inline bool 00373 isModelValid (const Eigen::VectorXf &model_coefficients) = 0; 00374 00379 virtual bool 00380 isSampleGood (const std::vector<int> &samples) const = 0; 00381 00383 PointCloudConstPtr input_; 00384 00386 boost::shared_ptr <std::vector<int> > indices_; 00387 00389 static const unsigned int max_sample_checks_ = 1000; 00390 00394 double radius_min_, radius_max_; 00395 00397 std::vector<int> shuffled_indices_; 00398 00400 boost::mt19937 rng_alg_; 00401 00403 boost::shared_ptr<boost::uniform_int<> > rng_dist_; 00404 00406 boost::shared_ptr<boost::variate_generator< boost::mt19937&, boost::uniform_int<> > > rng_gen_; 00407 00409 inline int 00410 rnd () 00411 { 00412 return ((*rng_gen_) ()); 00413 } 00414 }; 00415 00419 template <typename PointT, typename PointNT> 00420 class SampleConsensusModelFromNormals 00421 { 00422 public: 00423 typedef typename pcl::PointCloud<PointNT>::ConstPtr PointCloudNConstPtr; 00424 typedef typename pcl::PointCloud<PointNT>::Ptr PointCloudNPtr; 00425 00426 typedef boost::shared_ptr<SampleConsensusModelFromNormals> Ptr; 00427 typedef boost::shared_ptr<const SampleConsensusModelFromNormals> ConstPtr; 00428 00430 SampleConsensusModelFromNormals () : normal_distance_weight_ (0.0) {}; 00431 00437 inline void 00438 setNormalDistanceWeight (const double w) 00439 { 00440 normal_distance_weight_ = w; 00441 } 00442 00444 inline double 00445 getNormalDistanceWeight () { return (normal_distance_weight_); } 00446 00452 inline void 00453 setInputNormals (const PointCloudNConstPtr &normals) 00454 { 00455 normals_ = normals; 00456 } 00457 00459 inline PointCloudNConstPtr 00460 getInputNormals () { return (normals_); } 00461 00462 protected: 00466 double normal_distance_weight_; 00467 00471 PointCloudNConstPtr normals_; 00472 }; 00473 00478 template<typename _Scalar, int NX=Eigen::Dynamic, int NY=Eigen::Dynamic> 00479 struct Functor 00480 { 00481 typedef _Scalar Scalar; 00482 enum { 00483 InputsAtCompileTime = NX, 00484 ValuesAtCompileTime = NY 00485 }; 00486 typedef Eigen::Matrix<Scalar,InputsAtCompileTime,1> InputType; 00487 typedef Eigen::Matrix<Scalar,ValuesAtCompileTime,1> ValueType; 00488 typedef Eigen::Matrix<Scalar,ValuesAtCompileTime,InputsAtCompileTime> JacobianType; 00489 00490 const int m_inputs, m_values; 00491 00492 Functor() : m_inputs(InputsAtCompileTime), m_values(ValuesAtCompileTime) {} 00493 Functor(int inputs, int values) : m_inputs(inputs), m_values(values) {} 00494 00495 int inputs() const { return m_inputs; } 00496 int values() const { return m_values; } 00497 }; 00498 } 00499 00500 #endif //#ifndef PCL_SAMPLE_CONSENSUS_MODEL_H_
1.7.6.1