transformation_estimation_lm.hpp
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) 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_ */


pcl
Author(s): Open Perception
autogenerated on Mon Oct 6 2014 03:18:51