41#ifndef PCL_REGISTRATION_IMPL_GICP_HPP_
42#define PCL_REGISTRATION_IMPL_GICP_HPP_
44#include <pcl/registration/exceptions.h>
48template <
typename Po
intSource,
typename Po
intTarget>
49template <
typename Po
intT>
56 if (k_correspondences_ >
int(cloud->size())) {
57 PCL_ERROR(
"[pcl::GeneralizedIterativeClosestPoint::computeCovariances] Number or "
58 "points in cloud (%lu) is less than k_correspondences_ (%lu)!\n",
87 for (
int j = 0; j < k_correspondences_; j++) {
94 cov(0, 0) +=
pt.x *
pt.x;
96 cov(1, 0) +=
pt.y *
pt.x;
97 cov(1, 1) +=
pt.y *
pt.y;
99 cov(2, 0) +=
pt.z *
pt.x;
100 cov(2, 1) +=
pt.z *
pt.y;
101 cov(2, 2) +=
pt.z *
pt.z;
104 mean /=
static_cast<double>(k_correspondences_);
106 for (
int k = 0; k < 3; k++)
107 for (
int l = 0; l <= k; l++) {
108 cov(k, l) /=
static_cast<double>(k_correspondences_);
109 cov(k, l) -= mean[k] * mean[l];
110 cov(l, k) = cov(k, l);
114 Eigen::JacobiSVD<Eigen::Matrix3d>
svd(cov, Eigen::ComputeFullU);
116 Eigen::Matrix3d
U =
svd.matrixU();
119 for (
int k = 0; k < 3; k++) {
120 Eigen::Vector3d
col =
U.col(k);
124 cov += v *
col *
col.transpose();
129template <
typename Po
intSource,
typename Po
intTarget>
180 g[3] = matricesInnerProd(
dR_dPhi,
R);
182 g[5] = matricesInnerProd(
dR_dPsi,
R);
185template <
typename Po
intSource,
typename Po
intTarget>
198 "[pcl::GeneralizedIterativeClosestPoint::estimateRigidTransformationBFGS] Need "
199 "at least 4 points to estimate a transform! Source and target have "
204 Vector6d x = Vector6d::Zero();
222 OptimizationFunctorWithIndices functor(
this);
224 bfgs.parameters.sigma = 0.01;
225 bfgs.parameters.rho = 0.01;
226 bfgs.parameters.tau1 = 9;
227 bfgs.parameters.tau2 = 0.05;
228 bfgs.parameters.tau3 = 0.5;
229 bfgs.parameters.order = 3;
244 PCL_DEBUG(
"[pcl::registration::TransformationEstimationBFGS::"
245 "estimateRigidTransformation]");
246 PCL_DEBUG(
"BFGS solver finished with exit code %i \n",
result);
252 SolverDidntConvergeException,
253 "[pcl::" << getClassName()
254 <<
"::TransformationEstimationBFGS::estimateRigidTransformation] BFGS "
255 "solver didn't converge!");
258template <
typename Po
intSource,
typename Po
intTarget>
266 int m =
static_cast<int>(gicp_->tmp_idx_src_->size());
267 for (
int i = 0; i <
m; ++i) {
270 (*gicp_->tmp_src_)[(*gicp_->tmp_idx_src_)[i]].getVector4fMap();
273 (*gicp_->tmp_tgt_)[(*gicp_->tmp_idx_tgt_)[i]].getVector4fMap();
278 Eigen::Vector3d
temp(gicp_->mahalanobis((*gicp_->tmp_idx_src_)[i]) * res);
286template <
typename Po
intSource,
typename Po
intTarget>
296 Eigen::Matrix3d
R = Eigen::Matrix3d::Zero();
297 int m =
static_cast<int>(gicp_->tmp_idx_src_->size());
298 for (
int i = 0; i <
m; ++i) {
301 (*gicp_->tmp_src_)[(*gicp_->tmp_idx_src_)[i]].getVector4fMap();
304 (*gicp_->tmp_tgt_)[(*gicp_->tmp_idx_tgt_)[i]].getVector4fMap();
310 Eigen::Vector3d
temp(gicp_->mahalanobis((*gicp_->tmp_idx_src_)[i]) * res);
316 pp = gicp_->base_transformation_ *
p_src;
320 g.head<3>() *= 2.0 /
m;
322 gicp_->computeRDerivative(x,
R, g);
325template <
typename Po
intSource,
typename Po
intTarget>
334 Eigen::Matrix3d
R = Eigen::Matrix3d::Zero();
335 const int m =
static_cast<int>(gicp_->tmp_idx_src_->size());
336 for (
int i = 0; i <
m; ++i) {
339 (*gicp_->tmp_src_)[(*gicp_->tmp_idx_src_)[i]].getVector4fMap();
342 (*gicp_->tmp_tgt_)[(*gicp_->tmp_idx_tgt_)[i]].getVector4fMap();
347 Eigen::Vector3d
temp(gicp_->mahalanobis((*gicp_->tmp_idx_src_)[i]) * res);
354 pp = gicp_->base_transformation_ *
p_src;
360 g.head<3>() *=
double(2.0 /
m);
362 gicp_->computeRDerivative(x,
R, g);
365template <
typename Po
intSource,
typename Po
intTarget>
388template <
typename Po
intSource,
typename Po
intTarget>
397 const std::size_t N = indices_->
size();
399 mahalanobis_.resize(N, Eigen::Matrix3d::Identity());
401 if ((!target_covariances_) || (target_covariances_->empty())) {
406 if ((!input_covariances_) || (input_covariances_->empty())) {
407 input_covariances_.reset(
new MatricesVector);
411 base_transformation_ = Eigen::Matrix4f::Identity();
414 double dist_threshold = corr_dist_threshold_ * corr_dist_threshold_;
420 while (!converged_) {
426 Eigen::Matrix4d
transform_R = Eigen::Matrix4d::Zero();
427 for (std::size_t i = 0; i < 4; i++)
428 for (std::size_t j = 0; j < 4; j++)
429 for (std::size_t k = 0; k < 4; k++)
434 for (std::size_t i = 0; i < N; i++) {
436 query.getVector4fMap() = transformation_ *
query.getVector4fMap();
439 PCL_ERROR(
"[pcl::%s::computeTransformation] Unable to find a nearest neighbor "
440 "in the target dataset for point %d in the source!\n",
441 getClassName().
c_str(),
449 Eigen::Matrix3d&
C1 = (*input_covariances_)[i];
450 Eigen::Matrix3d&
C2 = (*target_covariances_)[
nn_indices[0]];
451 Eigen::Matrix3d&
M = mahalanobis_[i];
455 Eigen::Matrix3d
temp =
M *
R.transpose();
468 previous_transformation_ = transformation_;
471 rigid_transformation_estimation_(
475 for (
int k = 0; k < 4; k++) {
476 for (
int l = 0; l < 4; l++) {
479 ratio = 1. / rotation_epsilon_;
481 ratio = 1. / transformation_epsilon_;
483 ratio * std::abs(previous_transformation_(k, l) - transformation_(k, l));
488 }
catch (PCLException&
e) {
489 PCL_DEBUG(
"[pcl::%s::computeTransformation] Optimization issue %s\n",
490 getClassName().
c_str(),
496 if (nr_iterations_ >= max_iterations_ ||
delta < 1) {
498 PCL_DEBUG(
"[pcl::%s::computeTransformation] Convergence reached. Number of "
499 "iterations: %d out of %d. Transformation difference: %f\n",
500 getClassName().
c_str(),
503 (transformation_ - previous_transformation_).array().
abs().
sum());
504 previous_transformation_ = transformation_;
507 PCL_DEBUG(
"[pcl::%s::computeTransformation] Convergence failed\n",
508 getClassName().
c_str());
510 final_transformation_ = previous_transformation_ *
guess;
516template <
typename Po
intSource,
typename Po
intTarget>
519 Eigen::Matrix4f&
t,
const Vector6d& x)
const
523 R = Eigen::AngleAxisf(
static_cast<float>(x[5]), Eigen::Vector3f::UnitZ()) *
524 Eigen::AngleAxisf(
static_cast<float>(x[4]), Eigen::Vector3f::UnitY()) *
525 Eigen::AngleAxisf(
static_cast<float>(x[3]), Eigen::Vector3f::UnitX());
526 t.topLeftCorner<3, 3>().
matrix() =
R *
t.topLeftCorner<3, 3>().
matrix();
527 Eigen::Vector4f T(
static_cast<float>(x[0]),
528 static_cast<float>(x[1]),
529 static_cast<float>(x[2]),
Iterator class for point clouds with or without given indices.
ConstCloudIterator(const PointCloud< PointT > &cloud)
std::size_t size() const
Size of the range the iterator is going through.
void computeCovariances(typename pcl::PointCloud< PointT >::ConstPtr cloud, const typename pcl::search::KdTree< PointT >::Ptr tree, MatricesVector &cloud_covariances)
compute points covariances matrices according to the K nearest neighbors.
void applyState(Eigen::Matrix4f &t, const Vector6d &x) const
compute transformation matrix from transformation matrix
void computeTransformation(PointCloudSource &output, const Eigen::Matrix4f &guess) override
Rigid transformation computation method with initial guess.
void computeRDerivative(const Vector6d &x, const Eigen::Matrix3d &R, Vector6d &g) const
Computes rotation matrix derivative.
void estimateRigidTransformationBFGS(const PointCloudSource &cloud_src, const pcl::Indices &indices_src, const PointCloudTarget &cloud_tgt, const pcl::Indices &indices_tgt, Eigen::Matrix4f &transformation_matrix)
Estimate a rigid rotation transformation between a source and a target point cloud using an iterative...
std::vector< Eigen::Matrix3d, Eigen::aligned_allocator< Eigen::Matrix3d > > MatricesVector
Eigen::Matrix< double, 6, 1 > Vector6d
An exception that is thrown when the number of correspondents is not equal to the minimum required.
shared_ptr< const PointCloud< PointT > > ConstPtr
bool initComputeReciprocal()
Internal computation when reciprocal lookup is needed.
shared_ptr< KdTree< PointT, Tree > > Ptr
void transformPointCloud(const pcl::PointCloud< PointT > &cloud_in, pcl::PointCloud< PointT > &cloud_out, const Eigen::Matrix< Scalar, 4, 4 > &transform, bool copy_all_fields)
Apply a rigid transform defined by a 4x4 matrix.
@ NegativeGradientEpsilon
IndicesAllocator<> Indices
Type used for indices in PCL.
const Eigen::Map< const Eigen::Vector4f, Eigen::Aligned > Vector4fMapConst
BFGSSpace::Status checkGradient(const Vector6d &g) override
void df(const Vector6d &x, Vector6d &df) override
double operator()(const Vector6d &x) override
void fdf(const Vector6d &x, double &f, Vector6d &df) override
A point structure representing Euclidean xyz coordinates, and the RGB color.