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
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
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)
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
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
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
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
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
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)
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
00154 if (!warp_point_)
00155 warp_point_.reset (new WarpPointRigid6D<PointSource, PointTarget>);
00156
00157 int n_unknowns = warp_point_->getDimension ();
00158 Eigen::VectorXd x (n_unknowns);
00159 x.setConstant (n_unknowns, 0);
00160
00161
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
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
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
00219 Eigen::VectorXf params = x.cast<float> ();
00220 estimator_->warp_point_->setParam (params);
00221
00222
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
00229 PointSource p_src_warped;
00230 estimator_->warp_point_->warpPoint (p_src, p_src_warped);
00231
00232
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
00249 Eigen::VectorXf params = x.cast<float> ();
00250 estimator_->warp_point_->setParam (params);
00251
00252
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
00259 PointSource p_src_warped;
00260 estimator_->warp_point_->warpPoint (p_src, p_src_warped);
00261
00262
00263 fvec[i] = estimator_->computeDistance (p_src_warped, p_tgt);
00264 }
00265 return (0);
00266 }
00267
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 #endif