|
Point Cloud Library (PCL)
1.6.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: transformation_estimation_lm.hpp 5155 2012-03-17 21:45:48Z rusu $ 00037 * 00038 */ 00039 #ifndef PCL_REGISTRATION_TRANSFORMATION_ESTIMATION_LM_HPP_ 00040 #define PCL_REGISTRATION_TRANSFORMATION_ESTIMATION_LM_HPP_ 00041 00042 #include <pcl/registration/warp_point_rigid.h> 00043 #include <pcl/registration/warp_point_rigid_6d.h> 00044 #include <pcl/registration/distances.h> 00045 #include <unsupported/Eigen/NonLinearOptimization> 00047 template <typename PointSource, typename PointTarget> void 00048 pcl::registration::TransformationEstimationLM<PointSource, PointTarget>::estimateRigidTransformation ( 00049 const pcl::PointCloud<PointSource> &cloud_src, 00050 const pcl::PointCloud<PointTarget> &cloud_tgt, 00051 Eigen::Matrix4f &transformation_matrix) 00052 { 00053 00054 // <cloud_src,cloud_src> is the source dataset 00055 if (cloud_src.points.size () != cloud_tgt.points.size ()) 00056 { 00057 PCL_ERROR ("[pcl::registration::TransformationEstimationLM::estimateRigidTransformation] "); 00058 PCL_ERROR ("Number or points in source (%zu) differs than target (%zu)!\n", 00059 cloud_src.points.size (), cloud_tgt.points.size ()); 00060 return; 00061 } 00062 if (cloud_src.points.size () < 4) // need at least 4 samples 00063 { 00064 PCL_ERROR ("[pcl::registration::TransformationEstimationLM::estimateRigidTransformation] "); 00065 PCL_ERROR ("Need at least 4 points to estimate a transform! Source and target have %zu points!\n", 00066 cloud_src.points.size ()); 00067 return; 00068 } 00069 00070 // If no warp function has been set, use the default (WarpPointRigid6D) 00071 if (!warp_point_) 00072 warp_point_.reset (new WarpPointRigid6D<PointSource, PointTarget>); 00073 00074 int n_unknowns = warp_point_->getDimension (); 00075 Eigen::VectorXd x (n_unknowns); 00076 x.setZero (); 00077 00078 // Set temporary pointers 00079 tmp_src_ = &cloud_src; 00080 tmp_tgt_ = &cloud_tgt; 00081 00082 OptimizationFunctor functor (static_cast<int> (cloud_src.points.size ()), this); 00083 Eigen::NumericalDiff<OptimizationFunctor> num_diff (functor); 00084 Eigen::LevenbergMarquardt<Eigen::NumericalDiff<OptimizationFunctor>, double> lm (num_diff); 00085 int info = lm.minimize (x); 00086 00087 // Compute the norm of the residuals 00088 PCL_DEBUG ("[pcl::registration::TransformationEstimationLM::estimateRigidTransformation]"); 00089 PCL_DEBUG ("LM solver finished with exit code %i, having a residual norm of %g. \n", info, lm.fvec.norm ()); 00090 PCL_DEBUG ("Final solution: [%f", x[0]); 00091 for (int i = 1; i < n_unknowns; ++i) 00092 PCL_DEBUG (" %f", x[i]); 00093 PCL_DEBUG ("]\n"); 00094 00095 // Return the correct transformation 00096 Eigen::VectorXf params = x.cast<float> (); 00097 warp_point_->setParam (params); 00098 transformation_matrix = warp_point_->getTransform (); 00099 00100 tmp_src_ = NULL; 00101 tmp_tgt_ = NULL; 00102 } 00103 00105 template <typename PointSource, typename PointTarget> void 00106 pcl::registration::TransformationEstimationLM<PointSource, PointTarget>::estimateRigidTransformation ( 00107 const pcl::PointCloud<PointSource> &cloud_src, 00108 const std::vector<int> &indices_src, 00109 const pcl::PointCloud<PointTarget> &cloud_tgt, 00110 Eigen::Matrix4f &transformation_matrix) 00111 { 00112 if (indices_src.size () != cloud_tgt.points.size ()) 00113 { 00114 PCL_ERROR ("[pcl::registration::TransformationEstimationLM::estimateRigidTransformation] Number or points in source (%zu) differs than target (%zu)!\n", indices_src.size (), cloud_tgt.points.size ()); 00115 return; 00116 } 00117 00118 // <cloud_src,cloud_src> is the source dataset 00119 transformation_matrix.setIdentity (); 00120 00121 const int nr_correspondences = static_cast<const int> (cloud_tgt.points.size ()); 00122 std::vector<int> indices_tgt; 00123 indices_tgt.resize(nr_correspondences); 00124 for (int i = 0; i < nr_correspondences; ++i) 00125 indices_tgt[i] = i; 00126 00127 estimateRigidTransformation(cloud_src, indices_src, cloud_tgt, indices_tgt, transformation_matrix); 00128 } 00129 00131 template <typename PointSource, typename PointTarget> inline void 00132 pcl::registration::TransformationEstimationLM<PointSource, PointTarget>::estimateRigidTransformation ( 00133 const pcl::PointCloud<PointSource> &cloud_src, 00134 const std::vector<int> &indices_src, 00135 const pcl::PointCloud<PointTarget> &cloud_tgt, 00136 const std::vector<int> &indices_tgt, 00137 Eigen::Matrix4f &transformation_matrix) 00138 { 00139 if (indices_src.size () != indices_tgt.size ()) 00140 { 00141 PCL_ERROR ("[pcl::registration::TransformationEstimationLM::estimateRigidTransformation] Number or points in source (%zu) differs than target (%zu)!\n", indices_src.size (), indices_tgt.size ()); 00142 return; 00143 } 00144 00145 if (indices_src.size () < 4) // need at least 4 samples 00146 { 00147 PCL_ERROR ("[pcl::IterativeClosestPointNonLinear::estimateRigidTransformationLM] "); 00148 PCL_ERROR ("Need at least 4 points to estimate a transform! Source and target have %zu points!", 00149 indices_src.size ()); 00150 return; 00151 } 00152 00153 // If no warp function has been set, use the default (WarpPointRigid6D) 00154 if (!warp_point_) 00155 warp_point_.reset (new WarpPointRigid6D<PointSource, PointTarget>); 00156 00157 int n_unknowns = warp_point_->getDimension (); // get dimension of unknown space 00158 Eigen::VectorXd x (n_unknowns); 00159 x.setConstant (n_unknowns, 0); 00160 00161 // Set temporary pointers 00162 tmp_src_ = &cloud_src; 00163 tmp_tgt_ = &cloud_tgt; 00164 tmp_idx_src_ = &indices_src; 00165 tmp_idx_tgt_ = &indices_tgt; 00166 00167 OptimizationFunctorWithIndices functor (static_cast<int> (indices_src.size ()), this); 00168 Eigen::NumericalDiff<OptimizationFunctorWithIndices> num_diff (functor); 00169 Eigen::LevenbergMarquardt<Eigen::NumericalDiff<OptimizationFunctorWithIndices> > lm (num_diff); 00170 int info = lm.minimize (x); 00171 00172 // Compute the norm of the residuals 00173 PCL_DEBUG ("[pcl::registration::TransformationEstimationLM::estimateRigidTransformation]"); 00174 PCL_DEBUG ("LM solver finished with exit code %i, having a residual norm of %g. \n", info, lm.fvec.norm ()); 00175 PCL_DEBUG ("Final solution: [%f", x[0]); 00176 for (int i = 1; i < n_unknowns; ++i) 00177 PCL_DEBUG (" %f", x[i]); 00178 PCL_DEBUG ("]\n"); 00179 00180 // Return the correct transformation 00181 Eigen::VectorXf params = x.cast<float> (); 00182 warp_point_->setParam (params); 00183 transformation_matrix = warp_point_->getTransform (); 00184 00185 tmp_src_ = NULL; 00186 tmp_tgt_ = NULL; 00187 tmp_idx_src_ = tmp_idx_tgt_ = NULL; 00188 } 00189 00191 template <typename PointSource, typename PointTarget> inline void 00192 pcl::registration::TransformationEstimationLM<PointSource, PointTarget>::estimateRigidTransformation ( 00193 const pcl::PointCloud<PointSource> &cloud_src, 00194 const pcl::PointCloud<PointTarget> &cloud_tgt, 00195 const pcl::Correspondences &correspondences, 00196 Eigen::Matrix4f &transformation_matrix) 00197 { 00198 const int nr_correspondences = static_cast<const int> (correspondences.size ()); 00199 std::vector<int> indices_src (nr_correspondences); 00200 std::vector<int> indices_tgt (nr_correspondences); 00201 for (int i = 0; i < nr_correspondences; ++i) 00202 { 00203 indices_src[i] = correspondences[i].index_query; 00204 indices_tgt[i] = correspondences[i].index_match; 00205 } 00206 00207 estimateRigidTransformation(cloud_src, indices_src, cloud_tgt, indices_tgt, transformation_matrix); 00208 } 00209 00211 template <typename PointSource, typename PointTarget> int 00212 pcl::registration::TransformationEstimationLM<PointSource, PointTarget>::OptimizationFunctor::operator () ( 00213 const Eigen::VectorXd &x, Eigen::VectorXd &fvec) const 00214 { 00215 const PointCloud<PointSource> & src_points = *estimator_->tmp_src_; 00216 const PointCloud<PointTarget> & tgt_points = *estimator_->tmp_tgt_; 00217 00218 // Initialize the warp function with the given parameters 00219 Eigen::VectorXf params = x.cast<float> (); 00220 estimator_->warp_point_->setParam (params); 00221 00222 // Transform each source point and compute its distance to the corresponding target point 00223 for (int i = 0; i < values (); ++i) 00224 { 00225 const PointSource & p_src = src_points.points[i]; 00226 const PointTarget & p_tgt = tgt_points.points[i]; 00227 00228 // Transform the source point based on the current warp parameters 00229 PointSource p_src_warped; 00230 estimator_->warp_point_->warpPoint (p_src, p_src_warped); 00231 00232 // Estimate the distance (cost function) 00233 fvec[i] = estimator_->computeDistance (p_src_warped, p_tgt); 00234 } 00235 return (0); 00236 } 00237 00239 template <typename PointSource, typename PointTarget> int 00240 pcl::registration::TransformationEstimationLM<PointSource, PointTarget>::OptimizationFunctorWithIndices::operator() ( 00241 const Eigen::VectorXd &x, Eigen::VectorXd &fvec) const 00242 { 00243 const PointCloud<PointSource> & src_points = *estimator_->tmp_src_; 00244 const PointCloud<PointTarget> & tgt_points = *estimator_->tmp_tgt_; 00245 const std::vector<int> & src_indices = *estimator_->tmp_idx_src_; 00246 const std::vector<int> & tgt_indices = *estimator_->tmp_idx_tgt_; 00247 00248 // Initialize the warp function with the given parameters 00249 Eigen::VectorXf params = x.cast<float> (); 00250 estimator_->warp_point_->setParam (params); 00251 00252 // Transform each source point and compute its distance to the corresponding target point 00253 for (int i = 0; i < values (); ++i) 00254 { 00255 const PointSource & p_src = src_points.points[src_indices[i]]; 00256 const PointTarget & p_tgt = tgt_points.points[tgt_indices[i]]; 00257 00258 // Transform the source point based on the current warp parameters 00259 PointSource p_src_warped; 00260 estimator_->warp_point_->warpPoint (p_src, p_src_warped); 00261 00262 // Estimate the distance (cost function) 00263 fvec[i] = estimator_->computeDistance (p_src_warped, p_tgt); 00264 } 00265 return (0); 00266 } 00267 /* 00269 template <typename PointSource, typename PointTarget> inline double 00270 pcl::registration::TransformationEstimationLM<PointSource, PointTarget>::computeMedian (double *fvec, int m) 00271 { 00272 double median; 00273 // Copy the values to vectors for faster sorting 00274 std::vector<double> data (m); 00275 memcpy (&data[0], fvec, sizeof (double) * m); 00276 00277 std::sort (data.begin (), data.end ()); 00278 00279 int mid = data.size () / 2; 00280 if (data.size () % 2 == 0) 00281 median = (data[mid-1] + data[mid]) / 2.0; 00282 else 00283 median = data[mid]; 00284 return (median); 00285 } 00286 */ 00287 00288 //#define PCL_INSTANTIATE_TransformationEstimationLM(T,U) template class PCL_EXPORTS pcl::registration::TransformationEstimationLM<T,U>; 00289 00290 #endif /* PCL_REGISTRATION_TRANSFORMATION_ESTIMATION_LM_HPP_ */
1.7.6.1