|
Point Cloud Library (PCL)
1.4.0
|
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2010, Willow Garage, Inc. 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * * Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * * Redistributions in binary form must reproduce the above 00014 * copyright notice, this list of conditions and the following 00015 * disclaimer in the documentation and/or other materials provided 00016 * with the distribution. 00017 * * Neither the name of Willow Garage, Inc. nor the names of its 00018 * contributors may be used to endorse or promote products derived 00019 * from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 * 00034 * $Id: gicp.h 3756 2011-12-31 23:54:41Z rusu $ 00035 * 00036 */ 00037 00038 #ifndef PCL_GICP_H_ 00039 #define PCL_GICP_H_ 00040 00041 #include "pcl/registration/icp.h" 00042 #include "pcl/registration/bfgs.h" 00043 00044 namespace pcl 00045 { 00056 template <typename PointSource, typename PointTarget> 00057 class GeneralizedIterativeClosestPoint : public IterativeClosestPoint<PointSource, PointTarget> 00058 { 00059 using IterativeClosestPoint<PointSource, PointTarget>::reg_name_; 00060 using IterativeClosestPoint<PointSource, PointTarget>::getClassName; 00061 using IterativeClosestPoint<PointSource, PointTarget>::indices_; 00062 using IterativeClosestPoint<PointSource, PointTarget>::target_; 00063 using IterativeClosestPoint<PointSource, PointTarget>::input_; 00064 using IterativeClosestPoint<PointSource, PointTarget>::tree_; 00065 using IterativeClosestPoint<PointSource, PointTarget>::nr_iterations_; 00066 using IterativeClosestPoint<PointSource, PointTarget>::max_iterations_; 00067 using IterativeClosestPoint<PointSource, PointTarget>::previous_transformation_; 00068 using IterativeClosestPoint<PointSource, PointTarget>::final_transformation_; 00069 using IterativeClosestPoint<PointSource, PointTarget>::transformation_; 00070 using IterativeClosestPoint<PointSource, PointTarget>::transformation_epsilon_; 00071 using IterativeClosestPoint<PointSource, PointTarget>::converged_; 00072 using IterativeClosestPoint<PointSource, PointTarget>::corr_dist_threshold_; 00073 using IterativeClosestPoint<PointSource, PointTarget>::inlier_threshold_; 00074 using IterativeClosestPoint<PointSource, PointTarget>::min_number_correspondences_; 00075 using IterativeClosestPoint<PointSource, PointTarget>::update_visualizer_; 00076 00077 typedef pcl::PointCloud<PointSource> PointCloudSource; 00078 typedef typename PointCloudSource::Ptr PointCloudSourcePtr; 00079 typedef typename PointCloudSource::ConstPtr PointCloudSourceConstPtr; 00080 00081 typedef pcl::PointCloud<PointTarget> PointCloudTarget; 00082 typedef typename PointCloudTarget::Ptr PointCloudTargetPtr; 00083 typedef typename PointCloudTarget::ConstPtr PointCloudTargetConstPtr; 00084 00085 typedef PointIndices::Ptr PointIndicesPtr; 00086 typedef PointIndices::ConstPtr PointIndicesConstPtr; 00087 00088 typedef typename pcl::KdTree<PointSource> InputKdTree; 00089 typedef typename pcl::KdTree<PointSource>::Ptr InputKdTreePtr; 00090 00091 typedef Eigen::Matrix<double, 6, 1> Vector6d; 00092 00093 public: 00095 GeneralizedIterativeClosestPoint () 00096 : k_correspondences_(20), 00097 gicp_epsilon_(0.001), rotation_epsilon_(2e-3), 00098 input_covariances_(0), target_covariances_(0), mahalanobis_(0), 00099 max_inner_iterations_(20) 00100 { 00101 min_number_correspondences_ = 4; 00102 reg_name_ = "GeneralizedIterativeClosestPoint"; 00103 max_iterations_ = 200; 00104 transformation_epsilon_ = 5e-4; 00105 corr_dist_threshold_ = 5.; 00106 rigid_transformation_estimation_ = 00107 boost::bind (&GeneralizedIterativeClosestPoint<PointSource, PointTarget>::estimateRigidTransformationBFGS, 00108 this, _1, _2, _3, _4, _5); 00109 input_tree_.reset (new pcl::KdTreeFLANN<PointSource>); 00110 } 00111 00115 inline void 00116 setInputCloud (const PointCloudSourceConstPtr &cloud) 00117 { 00118 if (cloud->points.empty ()) 00119 { 00120 PCL_ERROR ("[pcl::%s::setInputInput] Invalid or empty point cloud dataset given!\n", getClassName ().c_str ()); 00121 return; 00122 } 00123 PointCloudSource input = *cloud; 00124 // Set all the point.data[3] values to 1 to aid the rigid transformation 00125 for (size_t i = 0; i < input.size (); ++i) 00126 input[i].data[3] = 1.0; 00127 00128 input_ = input.makeShared (); 00129 input_tree_->setInputCloud (input_); 00130 input_covariances_.reserve (input_->size ()); 00131 } 00132 00136 inline void 00137 setInputTarget (const PointCloudTargetConstPtr &target) 00138 { 00139 pcl::Registration<PointSource, PointTarget>::setInputTarget(target); 00140 target_covariances_.reserve (target_->size ()); 00141 } 00142 00151 void 00152 estimateRigidTransformationBFGS (const PointCloudSource &cloud_src, 00153 const std::vector<int> &indices_src, 00154 const PointCloudTarget &cloud_tgt, 00155 const std::vector<int> &indices_tgt, 00156 Eigen::Matrix4f &transformation_matrix); 00157 00159 inline const Eigen::Matrix3d& mahalanobis(size_t index) const 00160 { 00161 assert(index < mahalanobis_.size()); 00162 return mahalanobis_[index]; 00163 } 00164 00172 void 00173 computeRDerivative(const Vector6d &x, const Eigen::Matrix3d &R, Vector6d &g) const; 00174 00180 inline void 00181 setRotationEpsilon (double epsilon) { rotation_epsilon_ = epsilon; } 00182 00186 inline double 00187 getRotationEpsilon () { return (rotation_epsilon_); } 00188 00195 void 00196 setCorrespondenceRandomness (int k) { k_correspondences_ = k; } 00197 00201 void 00202 getCorrespondenceRandomness () { return (k_correspondences_); } 00203 00204 private: 00205 00209 int k_correspondences_; 00210 00215 double gicp_epsilon_; 00216 00221 double rotation_epsilon_; 00222 00224 Eigen::Matrix4f base_transformation_; 00225 00227 boost::mutex tmp_mutex_; 00228 00230 const PointCloudSource *tmp_src_; 00231 00233 const PointCloudTarget *tmp_tgt_; 00234 00236 const std::vector<int> *tmp_idx_src_; 00237 00239 const std::vector<int> *tmp_idx_tgt_; 00240 00242 InputKdTreePtr input_tree_; 00243 00245 std::vector<Eigen::Matrix3d> input_covariances_; 00246 00248 std::vector<Eigen::Matrix3d> target_covariances_; 00249 00251 std::vector<Eigen::Matrix3d> mahalanobis_; 00252 00254 int max_inner_iterations_; 00255 00262 template<typename PointT> 00263 void computeCovariances(typename pcl::PointCloud<PointT>::ConstPtr cloud, 00264 const typename pcl::KdTree<PointT>::Ptr tree, 00265 std::vector<Eigen::Matrix3d>& cloud_covariances); 00266 00271 inline double 00272 matricesInnerProd(const Eigen::MatrixXd& mat1, const Eigen::MatrixXd& mat2) const 00273 { 00274 double r = 0.; 00275 size_t n = mat1.rows(); 00276 // tr(mat1^t.mat2) 00277 for(size_t i = 0; i < n; i++) 00278 for(size_t j = 0; j < n; j++) 00279 r += mat1 (j, i) * mat2 (i,j); 00280 return r; 00281 } 00282 00287 void 00288 computeTransformation (PointCloudSource &output, const Eigen::Matrix4f &guess); 00289 00295 inline bool 00296 searchForNeighbors (const PointSource &query, std::vector<int>& index, std::vector<float>& distance) 00297 { 00298 int k = tree_->nearestKSearch (query, 1, index, distance); 00299 if (k == 0) 00300 return (false); 00301 return (true); 00302 } 00303 00305 void applyState(Eigen::Matrix4f &t, const Vector6d& x) const; 00306 00308 struct OptimizationFunctorWithIndices : public BFGSDummyFunctor<double,6> 00309 { 00310 OptimizationFunctorWithIndices (const GeneralizedIterativeClosestPoint* gicp) 00311 : BFGSDummyFunctor<double,6> (), gicp_(gicp) {} 00312 double operator() (const Vector6d& x); 00313 void df(const Vector6d &x, Vector6d &df); 00314 void fdf(const Vector6d &x, double &f, Vector6d &df); 00315 00316 const GeneralizedIterativeClosestPoint *gicp_; 00317 }; 00318 00319 protected: 00320 boost::function<void(const pcl::PointCloud<PointSource> &cloud_src, 00321 const std::vector<int> &src_indices, 00322 const pcl::PointCloud<PointTarget> &cloud_tgt, 00323 const std::vector<int> &tgt_indices, 00324 Eigen::Matrix4f &transformation_matrix)> rigid_transformation_estimation_; 00325 }; 00326 } 00327 00328 #include "pcl/registration/impl/gicp.hpp" 00329 00330 #endif //#ifndef PCL_GICP_H_
1.7.6.1