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_POINT_TO_PLANE_WEIGHTED_HPP_
00040 #define PCL_REGISTRATION_TRANSFORMATION_ESTIMATION_POINT_TO_PLANE_WEIGHTED_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>
00046
00047
00049 template <typename PointSource, typename PointTarget, typename MatScalar>
00050 pcl::registration::TransformationEstimationPointToPlaneWeighted<PointSource, PointTarget, MatScalar>::TransformationEstimationPointToPlaneWeighted ()
00051 : tmp_src_ ()
00052 , tmp_tgt_ ()
00053 , tmp_idx_src_ ()
00054 , tmp_idx_tgt_ ()
00055 , warp_point_ (new WarpPointRigid6D<PointSource, PointTarget, MatScalar>)
00056 , correspondence_weights_ ()
00057 , use_correspondence_weights_ (true)
00058 {
00059 };
00060
00062 template <typename PointSource, typename PointTarget, typename MatScalar> void
00063 pcl::registration::TransformationEstimationPointToPlaneWeighted<PointSource, PointTarget, MatScalar>::estimateRigidTransformation (
00064 const pcl::PointCloud<PointSource> &cloud_src,
00065 const pcl::PointCloud<PointTarget> &cloud_tgt,
00066 Matrix4 &transformation_matrix) const
00067 {
00068
00069
00070 if (cloud_src.points.size () != cloud_tgt.points.size ())
00071 {
00072 PCL_ERROR ("[pcl::registration::TransformationEstimationPointToPlaneWeighted::estimateRigidTransformation] ");
00073 PCL_ERROR ("Number or points in source (%zu) differs than target (%zu)!\n",
00074 cloud_src.points.size (), cloud_tgt.points.size ());
00075 return;
00076 }
00077 if (cloud_src.points.size () < 4)
00078 {
00079 PCL_ERROR ("[pcl::registration::TransformationEstimationPointToPlaneWeighted::estimateRigidTransformation] ");
00080 PCL_ERROR ("Need at least 4 points to estimate a transform! Source and target have %zu points!\n",
00081 cloud_src.points.size ());
00082 return;
00083 }
00084
00085 if (correspondence_weights_.size () != cloud_src.size ())
00086 {
00087 PCL_ERROR ("[pcl::registration::TransformationEstimationPointToPlaneWeighted::estimateRigidTransformation] ");
00088 PCL_ERROR ("Number of weights (%zu) differs than number of points (%zu)!\n",
00089 correspondence_weights_.size (), cloud_src.points.size ());
00090 return;
00091 }
00092
00093 int n_unknowns = warp_point_->getDimension ();
00094 VectorX x (n_unknowns);
00095 x.setZero ();
00096
00097
00098 tmp_src_ = &cloud_src;
00099 tmp_tgt_ = &cloud_tgt;
00100
00101 OptimizationFunctor functor (static_cast<int> (cloud_src.points.size ()), this);
00102 Eigen::NumericalDiff<OptimizationFunctor> num_diff (functor);
00103 Eigen::LevenbergMarquardt<Eigen::NumericalDiff<OptimizationFunctor>, MatScalar> lm (num_diff);
00104 int info = lm.minimize (x);
00105
00106
00107 PCL_DEBUG ("[pcl::registration::TransformationEstimationPointToPlaneWeighted::estimateRigidTransformation]");
00108 PCL_DEBUG ("LM solver finished with exit code %i, having a residual norm of %g. \n", info, lm.fvec.norm ());
00109 PCL_DEBUG ("Final solution: [%f", x[0]);
00110 for (int i = 1; i < n_unknowns; ++i)
00111 PCL_DEBUG (" %f", x[i]);
00112 PCL_DEBUG ("]\n");
00113
00114
00115 warp_point_->setParam (x);
00116 transformation_matrix = warp_point_->getTransform ();
00117
00118 tmp_src_ = NULL;
00119 tmp_tgt_ = NULL;
00120 }
00121
00123 template <typename PointSource, typename PointTarget, typename MatScalar> void
00124 pcl::registration::TransformationEstimationPointToPlaneWeighted<PointSource, PointTarget, MatScalar>::estimateRigidTransformation (
00125 const pcl::PointCloud<PointSource> &cloud_src,
00126 const std::vector<int> &indices_src,
00127 const pcl::PointCloud<PointTarget> &cloud_tgt,
00128 Matrix4 &transformation_matrix) const
00129 {
00130 if (indices_src.size () != cloud_tgt.points.size ())
00131 {
00132 PCL_ERROR ("[pcl::registration::TransformationEstimationPointToPlaneWeighted::estimateRigidTransformation] Number or points in source (%zu) differs than target (%zu)!\n", indices_src.size (), cloud_tgt.points.size ());
00133 return;
00134 }
00135
00136 if (correspondence_weights_.size () != indices_src.size ())
00137 {
00138 PCL_ERROR ("[pcl::registration::TransformationEstimationPointToPlaneWeighted::estimateRigidTransformation] ");
00139 PCL_ERROR ("Number of weights (%zu) differs than number of points (%zu)!\n",
00140 correspondence_weights_.size (), indices_src.size ());
00141 return;
00142 }
00143
00144
00145
00146 transformation_matrix.setIdentity ();
00147
00148 const int nr_correspondences = static_cast<const int> (cloud_tgt.points.size ());
00149 std::vector<int> indices_tgt;
00150 indices_tgt.resize(nr_correspondences);
00151 for (int i = 0; i < nr_correspondences; ++i)
00152 indices_tgt[i] = i;
00153
00154 estimateRigidTransformation(cloud_src, indices_src, cloud_tgt, indices_tgt, transformation_matrix);
00155 }
00156
00158 template <typename PointSource, typename PointTarget, typename MatScalar> inline void
00159 pcl::registration::TransformationEstimationPointToPlaneWeighted<PointSource, PointTarget, MatScalar>::estimateRigidTransformation (
00160 const pcl::PointCloud<PointSource> &cloud_src,
00161 const std::vector<int> &indices_src,
00162 const pcl::PointCloud<PointTarget> &cloud_tgt,
00163 const std::vector<int> &indices_tgt,
00164 Matrix4 &transformation_matrix) const
00165 {
00166 if (indices_src.size () != indices_tgt.size ())
00167 {
00168 PCL_ERROR ("[pcl::registration::TransformationEstimationPointToPlaneWeighted::estimateRigidTransformation] Number or points in source (%zu) differs than target (%zu)!\n", indices_src.size (), indices_tgt.size ());
00169 return;
00170 }
00171
00172 if (indices_src.size () < 4)
00173 {
00174 PCL_ERROR ("[pcl::IterativeClosestPointNonLinear::estimateRigidTransformationLM] ");
00175 PCL_ERROR ("Need at least 4 points to estimate a transform! Source and target have %zu points!",
00176 indices_src.size ());
00177 return;
00178 }
00179
00180 if (correspondence_weights_.size () != indices_src.size ())
00181 {
00182 PCL_ERROR ("[pcl::registration::TransformationEstimationPointToPlaneWeighted::estimateRigidTransformation] ");
00183 PCL_ERROR ("Number of weights (%zu) differs than number of points (%zu)!\n",
00184 correspondence_weights_.size (), indices_src.size ());
00185 return;
00186 }
00187
00188
00189 int n_unknowns = warp_point_->getDimension ();
00190 VectorX x (n_unknowns);
00191 x.setConstant (n_unknowns, 0);
00192
00193
00194 tmp_src_ = &cloud_src;
00195 tmp_tgt_ = &cloud_tgt;
00196 tmp_idx_src_ = &indices_src;
00197 tmp_idx_tgt_ = &indices_tgt;
00198
00199 OptimizationFunctorWithIndices functor (static_cast<int> (indices_src.size ()), this);
00200 Eigen::NumericalDiff<OptimizationFunctorWithIndices> num_diff (functor);
00201 Eigen::LevenbergMarquardt<Eigen::NumericalDiff<OptimizationFunctorWithIndices>, MatScalar> lm (num_diff);
00202 int info = lm.minimize (x);
00203
00204
00205 PCL_DEBUG ("[pcl::registration::TransformationEstimationPointToPlaneWeighted::estimateRigidTransformation] LM solver finished with exit code %i, having a residual norm of %g. \n", info, lm.fvec.norm ());
00206 PCL_DEBUG ("Final solution: [%f", x[0]);
00207 for (int i = 1; i < n_unknowns; ++i)
00208 PCL_DEBUG (" %f", x[i]);
00209 PCL_DEBUG ("]\n");
00210
00211
00212 warp_point_->setParam (x);
00213 transformation_matrix = warp_point_->getTransform ();
00214
00215 tmp_src_ = NULL;
00216 tmp_tgt_ = NULL;
00217 tmp_idx_src_ = tmp_idx_tgt_ = NULL;
00218 }
00219
00221 template <typename PointSource, typename PointTarget, typename MatScalar> inline void
00222 pcl::registration::TransformationEstimationPointToPlaneWeighted<PointSource, PointTarget, MatScalar>::estimateRigidTransformation (
00223 const pcl::PointCloud<PointSource> &cloud_src,
00224 const pcl::PointCloud<PointTarget> &cloud_tgt,
00225 const pcl::Correspondences &correspondences,
00226 Matrix4 &transformation_matrix) const
00227 {
00228 const int nr_correspondences = static_cast<const int> (correspondences.size ());
00229 std::vector<int> indices_src (nr_correspondences);
00230 std::vector<int> indices_tgt (nr_correspondences);
00231 for (int i = 0; i < nr_correspondences; ++i)
00232 {
00233 indices_src[i] = correspondences[i].index_query;
00234 indices_tgt[i] = correspondences[i].index_match;
00235 }
00236
00237 if (use_correspondence_weights_)
00238 {
00239 correspondence_weights_.resize (nr_correspondences);
00240 for (size_t i = 0; i < nr_correspondences; ++i)
00241 correspondence_weights_[i] = correspondences[i].weight;
00242 }
00243
00244 estimateRigidTransformation (cloud_src, indices_src, cloud_tgt, indices_tgt, transformation_matrix);
00245 }
00246
00248 template <typename PointSource, typename PointTarget, typename MatScalar> int
00249 pcl::registration::TransformationEstimationPointToPlaneWeighted<PointSource, PointTarget, MatScalar>::OptimizationFunctor::operator () (
00250 const VectorX &x, VectorX &fvec) const
00251 {
00252 const PointCloud<PointSource> & src_points = *estimator_->tmp_src_;
00253 const PointCloud<PointTarget> & tgt_points = *estimator_->tmp_tgt_;
00254
00255
00256 estimator_->warp_point_->setParam (x);
00257
00258
00259 for (int i = 0; i < values (); ++i)
00260 {
00261 const PointSource & p_src = src_points.points[i];
00262 const PointTarget & p_tgt = tgt_points.points[i];
00263
00264
00265 Vector4 p_src_warped;
00266 estimator_->warp_point_->warpPoint (p_src, p_src_warped);
00267
00268
00269 fvec[i] = estimator_->correspondence_weights_[i] * estimator_->computeDistance (p_src_warped, p_tgt);
00270 }
00271 return (0);
00272 }
00273
00275 template <typename PointSource, typename PointTarget, typename MatScalar> int
00276 pcl::registration::TransformationEstimationPointToPlaneWeighted<PointSource, PointTarget, MatScalar>::OptimizationFunctorWithIndices::operator() (
00277 const VectorX &x, VectorX &fvec) const
00278 {
00279 const PointCloud<PointSource> & src_points = *estimator_->tmp_src_;
00280 const PointCloud<PointTarget> & tgt_points = *estimator_->tmp_tgt_;
00281 const std::vector<int> & src_indices = *estimator_->tmp_idx_src_;
00282 const std::vector<int> & tgt_indices = *estimator_->tmp_idx_tgt_;
00283
00284
00285 estimator_->warp_point_->setParam (x);
00286
00287
00288 for (int i = 0; i < values (); ++i)
00289 {
00290 const PointSource & p_src = src_points.points[src_indices[i]];
00291 const PointTarget & p_tgt = tgt_points.points[tgt_indices[i]];
00292
00293
00294 Vector4 p_src_warped;
00295 estimator_->warp_point_->warpPoint (p_src, p_src_warped);
00296
00297
00298 fvec[i] = estimator_->correspondence_weights_[i] * estimator_->computeDistance (p_src_warped, p_tgt);
00299 }
00300 return (0);
00301 }
00302
00303 #endif