41#ifndef PCL_NDT_2D_IMPL_H_
42#define PCL_NDT_2D_IMPL_H_
44#include <Eigen/Eigenvalues>
56template <
unsigned N = 3,
typename T =
double>
61 Eigen::Matrix<T, N, 1>
grad;
68 r.hessian = Eigen::Matrix<T, N, N>::Zero();
69 r.grad = Eigen::Matrix<T, N, 1>::Zero();
95template <
typename Po
intT>
119 Eigen::Vector2d
sx = Eigen::Vector2d::Zero();
120 Eigen::Matrix2d
sxx = Eigen::Matrix2d::Zero();
123 Eigen::Vector2d p(cloud[*i].x, cloud[*i].y);
125 sxx += p * p.transpose();
133 Eigen::Matrix2d
covar =
134 (
sxx - 2 * (
sx *
mean_.transpose())) /
static_cast<double>(
n_) +
137 Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d>
solver(
covar);
139 PCL_DEBUG(
"[pcl::NormalDist::estimateParams] NDT normal fit: adjusting "
142 Eigen::Matrix2d l =
solver.eigenvalues().asDiagonal();
143 Eigen::Matrix2d
q =
solver.eigenvectors();
180 Eigen::Matrix<double, 2, 3>
jacobian;
184 for (std::size_t i = 0; i < 3; i++)
191 for (std::size_t i = 0; i < 3; i++)
192 for (std::size_t j = 0; j < 3; j++)
196 (-
qt_cvi * ((i == 2 && j == 2) ?
d2q_didj : Eigen::Vector2d::Zero())) +
215template <
typename Po
intT>
223 const Eigen::Vector2f&
about,
224 const Eigen::Vector2f&
extent,
225 const Eigen::Vector2f& step)
234 for (std::size_t i = 0; i < cloud->size(); i++)
240 PCL_DEBUG(
"[pcl::NDTSingleGrid] NDT single grid %dx%d using %d/%d points\n",
248 for (
int x = 0; x <
cells_[0]; x++)
249 for (
int y = 0; y <
cells_[1]; y++)
281 Eigen::Vector2f
idxf;
282 for (std::size_t i = 0; i < 2; i++)
284 Eigen::Vector2i
idxi =
idxf.cast<
int>();
285 for (std::size_t i = 0; i < 2; i++)
307template <
typename Po
intT>
308class NDT2D :
public boost::noncopyable {
321 const Eigen::Vector2f&
about,
322 const Eigen::Vector2f&
extent,
323 const Eigen::Vector2f& step)
325 Eigen::Vector2f dx(step[0] / 2, 0);
326 Eigen::Vector2f
dy(0, step[1] / 2);
363template <
typename Po
intT>
364struct NumTraits<
pcl::ndt2d::NormalDist<PointT>> {
376 RequireInitialization = 1,
387template <
typename Po
intSource,
typename Po
intTarget>
390 PointCloudSource&
output,
const Eigen::Matrix4f&
guess)
397 if (
guess != Eigen::Matrix4f::Identity()) {
398 transformation_ =
guess;
407 Eigen::Matrix4f& transformation = transformation_;
411 const Eigen::Matrix3f
initial_rot(transformation.block<3, 3>(0, 0));
416 transformation(0, 3), transformation(1, 3),
z_rotation);
418 while (!converged_) {
421 previous_transformation_ = transformation;
428 PCL_DEBUG(
"[pcl::NormalDistributionsTransform2D::computeTransformation] NDT score "
429 "%f (x=%f,y=%f,r=%f)\n",
435 if (score.
value != 0) {
437 Eigen::EigenSolver<Eigen::Matrix3d>
solver;
440 for (
int i = 0; i < 3; i++)
450 PCL_DEBUG(
"[pcl::NormalDistributionsTransform2D::computeTransformation] adjust "
451 "hessian: %f: new eigenvalues:%f %f %f\n",
453 solver.eigenvalues()[0].real(),
454 solver.eigenvalues()[1].real(),
455 solver.eigenvalues()[2].real());
458 solver.eigenvalues()[1].real() >= 0 &&
459 solver.eigenvalues()[2].real() >= 0);
468 transformation.block<3, 3>(0, 0).
matrix() = Eigen::Matrix3f(Eigen::AngleAxisf(
470 transformation.block<3, 1>(0, 3).
matrix() =
478 PCL_ERROR(
"[pcl::NormalDistributionsTransform2D::computeTransformation] no "
479 "overlap: try increasing the size or reducing the step of the grid\n");
487 if (update_visualizer_)
488 update_visualizer_(
output, *indices_, *target_, *indices_);
494 transformation.inverse() * previous_transformation_;
503 if (nr_iterations_ >= max_iterations_ ||
504 ((transformation_epsilon_ > 0 &&
translation_sqr <= transformation_epsilon_) &&
505 (transformation_rotation_epsilon_ > 0 &&
506 cos_angle >= transformation_rotation_epsilon_)) ||
507 ((transformation_epsilon_ <= 0) &&
508 (transformation_rotation_epsilon_ > 0 &&
509 cos_angle >= transformation_rotation_epsilon_)) ||
510 ((transformation_epsilon_ > 0 &&
translation_sqr <= transformation_epsilon_) &&
511 (transformation_rotation_epsilon_ <= 0))) {
515 final_transformation_ = transformation;
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.
shared_ptr< const PointCloud< PointT > > ConstPtr
Build a Normal Distributions Transform of a 2D point cloud.
ValueAndDerivatives< 3, double > test(const PointT &transformed_pt, const double &cos_theta, const double &sin_theta) const
Return the 'score' (denormalised likelihood) and derivatives of score of the point p given this distr...
std::shared_ptr< SingleGrid > single_grids_[4]
NDT2D(PointCloudConstPtr cloud, const Eigen::Vector2f &about, const Eigen::Vector2f &extent, const Eigen::Vector2f &step)
Build a set of normal distributions modelling a 2D point cloud, and provide the value and derivatives...
NormalDist * normalDistForPoint(PointT const &p) const
Return the normal distribution covering the location of point p.
NDTSingleGrid(PointCloudConstPtr cloud, const Eigen::Vector2f &about, const Eigen::Vector2f &extent, const Eigen::Vector2f &step)
Eigen::Matrix< NormalDist, Eigen::Dynamic, Eigen::Dynamic > normal_distributions_
ValueAndDerivatives< 3, double > test(const PointT &transformed_pt, const double &cos_theta, const double &sin_theta) const
Return the 'score' (denormalised likelihood) and derivatives of score of the point p given this distr...
A normal distribution estimation class.
std::vector< std::size_t > pt_indices_
void addIdx(std::size_t i)
Store a point index to use later for estimating distribution parameters.
void estimateParams(const PointCloud &cloud, double min_covar_eigvalue_mult=0.001)
Estimate the normal distribution parameters given the point indices provided.
ValueAndDerivatives< 3, double > test(const PointT &transformed_pt, const double &cos_theta, const double &sin_theta) const
Return the 'score' (denormalised likelihood) and derivatives of score of the point p given this distr...
Eigen::Matrix2d covar_inv_
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.
static Real dummy_precision()
A point structure representing Euclidean xyz coordinates, and the RGB color.
Class to store vector value and first and second derivatives (grad vector and hessian matrix),...
Eigen::Matrix< T, N, N > hessian
static ValueAndDerivatives< N, T > Zero()
ValueAndDerivatives< N, T > & operator+=(ValueAndDerivatives< N, T > const &r)
Eigen::Matrix< T, N, 1 > grad