41 #ifndef PCL_REGISTRATION_NDT_IMPL_H_
42 #define PCL_REGISTRATION_NDT_IMPL_H_
46 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
49 unsigned int nr_threads)
53 threads_ = omp_get_num_procs();
55 threads_ = nr_threads;
56 PCL_DEBUG(
"[pcl::NormalDistributionsTransform::setNumberOfThreads] Setting "
57 "number of threads to %u.\n",
62 PCL_WARN(
"[pcl::NormalDistributionsTransform::setNumberOfThreads] "
63 "Parallelization is requested, but OpenMP is not available! Continuing "
64 "without parallelization.\n");
68 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
73 reg_name_ =
"NormalDistributionsTransform";
79 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
86 if (target_cells_.getCentroids()->empty()) {
87 PCL_ERROR(
"[%s::computeTransformation] Voxel grid is not searchable!\n",
88 getClassName().c_str());
93 const double gauss_c1 = 10 * (1 - outlier_ratio_);
94 const double gauss_c2 = outlier_ratio_ / pow(resolution_, 3);
95 const double gauss_d3 = -std::log(gauss_c2);
96 gauss_d1_ = -std::log(gauss_c1 + gauss_c2) - gauss_d3;
98 -2 * std::log((-std::log(gauss_c1 * std::exp(-0.5) + gauss_c2) - gauss_d3) /
101 if (guess != Matrix4::Identity()) {
103 final_transformation_ = guess;
109 point_jacobian_.setZero();
110 point_jacobian_.block<3, 3>(0, 0).setIdentity();
111 point_hessian_.setZero();
113 Eigen::Transform<Scalar, 3, Eigen::Affine, Eigen::ColMajor> eig_transformation;
114 eig_transformation.matrix() = final_transformation_;
117 Eigen::Matrix<double, 6, 1> transform, score_gradient;
118 Vector3 init_translation = eig_transformation.translation();
119 Vector3 init_rotation = eig_transformation.rotation().eulerAngles(0, 1, 2);
120 transform << init_translation.template cast<double>(),
121 init_rotation.template cast<double>();
123 Eigen::Matrix<double, 6, 6> hessian;
127 double score = computeDerivatives(score_gradient, hessian, output, transform);
129 while (!converged_) {
131 previous_transformation_ = transformation_;
135 Eigen::JacobiSVD<Eigen::Matrix<double, 6, 6>> sv(
136 hessian, Eigen::ComputeFullU | Eigen::ComputeFullV);
137 #if EIGEN_VERSION_AT_LEAST(3, 4, 0)
138 if (sv.info() != Eigen::ComputationInfo::Success) {
139 trans_likelihood_ = score /
static_cast<double>(input_->size());
141 PCL_ERROR(
"[%s::computeTransformation] JacobiSVD on hessian failed!\n",
142 getClassName().c_str());
147 Eigen::Matrix<double, 6, 1> delta = sv.solve(-score_gradient);
150 double delta_norm = delta.norm();
152 if (delta_norm == 0 || std::isnan(delta_norm)) {
153 trans_likelihood_ = score /
static_cast<double>(input_->size());
154 converged_ = delta_norm == 0;
159 delta_norm = computeStepLengthMT(transform,
163 transformation_epsilon_ / 2,
171 convertTransform(delta, transformation_);
176 if (update_visualizer_)
179 const double cos_angle =
180 0.5 * (transformation_.template block<3, 3>(0, 0).trace() - 1);
181 const double translation_sqr =
182 transformation_.template block<3, 1>(0, 3).squaredNorm();
186 if (nr_iterations_ >= max_iterations_ ||
187 ((transformation_epsilon_ > 0 && translation_sqr <= transformation_epsilon_) &&
188 (transformation_rotation_epsilon_ > 0 &&
189 cos_angle >= transformation_rotation_epsilon_)) ||
190 ((transformation_epsilon_ <= 0) &&
191 (transformation_rotation_epsilon_ > 0 &&
192 cos_angle >= transformation_rotation_epsilon_)) ||
193 ((transformation_epsilon_ > 0 && translation_sqr <= transformation_epsilon_) &&
194 (transformation_rotation_epsilon_ <= 0))) {
202 trans_likelihood_ = score /
static_cast<double>(input_->size());
205 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
208 Eigen::Matrix<double, 6, 1>& score_gradient,
209 Eigen::Matrix<double, 6, 6>& hessian,
211 const Eigen::Matrix<double, 6, 1>& transform,
212 bool compute_hessian)
214 score_gradient.setZero();
219 computeAngleDerivatives(transform);
221 std::vector<TargetGridLeafConstPtr> neighborhood;
222 std::vector<float> distances;
224 Eigen::Matrix<double, 3, 6> point_jacobian = Eigen::Matrix<double, 3, 6>::Zero();
225 point_jacobian.block<3, 3>(0, 0).setIdentity();
226 Eigen::Matrix<double, 18, 6> point_hessian = Eigen::Matrix<double, 18, 6>::Zero();
228 #pragma omp parallel num_threads(threads_) default(none) shared(score_gradient, hessian, trans_cloud, compute_hessian) firstprivate(neighborhood, distances, point_jacobian, point_hessian) reduction(+: score)
232 Eigen::Matrix<double, 6, 1> score_gradient_private =
233 Eigen::Matrix<double, 6, 1>::Zero();
234 Eigen::Matrix<double, 6, 6> hessian_private = Eigen::Matrix<double, 6, 6>::Zero();
235 #pragma omp for schedule(dynamic, 32)
238 for (std::ptrdiff_t idx = 0; idx < static_cast<std::ptrdiff_t>(input_->size());
241 const auto& x_trans_pt = trans_cloud[idx];
244 neighborhood.clear();
245 switch (search_method_) {
248 target_cells_.radiusSearch(x_trans_pt, resolution_, neighborhood, distances);
251 target_cells_.getAllNeighborsAtPoint(x_trans_pt, neighborhood);
254 target_cells_.getNeighborhoodAtPoint(x_trans_pt, neighborhood);
257 target_cells_.getFaceNeighborsAtPoint(x_trans_pt, neighborhood);
260 target_cells_.getVoxelAtPoint(x_trans_pt, neighborhood);
265 const Eigen::Vector3d x = (*input_)[idx].getVector3fMap().template cast<double>();
266 const Eigen::Vector3d x_trans_position =
267 x_trans_pt.getVector3fMap().template cast<double>();
269 for (
const auto& cell : neighborhood) {
271 const Eigen::Vector3d x_trans = x_trans_position - cell->getMean();
274 const Eigen::Matrix3d c_inv = cell->getInverseCov();
278 computePointDerivatives(
279 x, point_jacobian, compute_hessian ? &point_hessian :
nullptr);
282 score += updateDerivatives(score_gradient_private,
287 compute_hessian ? &point_hessian :
nullptr);
290 #pragma omp critical(accum_score_gradient)
292 score_gradient += score_gradient_private;
294 #pragma omp critical(accum_hessian)
296 hessian += hessian_private;
302 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
305 const Eigen::Matrix<double, 6, 1>& transform,
bool compute_hessian)
308 const auto calculate_cos_sin = [](
double angle,
double& c,
double& s) {
309 if (std::abs(angle) < 10e-5) {
319 double cx, cy, cz, sx, sy, sz;
320 calculate_cos_sin(transform(3), cx, sx);
321 calculate_cos_sin(transform(4), cy, sy);
322 calculate_cos_sin(transform(5), cz, sz);
326 angular_jacobian_.setZero();
327 angular_jacobian_.row(0).noalias() = Eigen::Vector4d(
328 (-sx * sz + cx * sy * cz), (-sx * cz - cx * sy * sz), (-cx * cy), 1.0);
329 angular_jacobian_.row(1).noalias() = Eigen::Vector4d(
330 (cx * sz + sx * sy * cz), (cx * cz - sx * sy * sz), (-sx * cy), 1.0);
331 angular_jacobian_.row(2).noalias() =
332 Eigen::Vector4d((-sy * cz), sy * sz, cy, 1.0);
333 angular_jacobian_.row(3).noalias() =
334 Eigen::Vector4d(sx * cy * cz, (-sx * cy * sz), sx * sy, 1.0);
335 angular_jacobian_.row(4).noalias() =
336 Eigen::Vector4d((-cx * cy * cz), cx * cy * sz, (-cx * sy), 1.0);
337 angular_jacobian_.row(5).noalias() =
338 Eigen::Vector4d((-cy * sz), (-cy * cz), 0, 1.0);
339 angular_jacobian_.row(6).noalias() =
340 Eigen::Vector4d((cx * cz - sx * sy * sz), (-cx * sz - sx * sy * cz), 0, 1.0);
341 angular_jacobian_.row(7).noalias() =
342 Eigen::Vector4d((sx * cz + cx * sy * sz), (cx * sy * cz - sx * sz), 0, 1.0);
344 if (compute_hessian) {
347 angular_hessian_.setZero();
348 angular_hessian_.row(0).noalias() = Eigen::Vector4d(
349 (-cx * sz - sx * sy * cz), (-cx * cz + sx * sy * sz), sx * cy, 0.0f);
350 angular_hessian_.row(1).noalias() = Eigen::Vector4d(
351 (-sx * sz + cx * sy * cz), (-cx * sy * sz - sx * cz), (-cx * cy), 0.0f);
353 angular_hessian_.row(2).noalias() =
354 Eigen::Vector4d((cx * cy * cz), (-cx * cy * sz), (cx * sy), 0.0f);
355 angular_hessian_.row(3).noalias() =
356 Eigen::Vector4d((sx * cy * cz), (-sx * cy * sz), (sx * sy), 0.0f);
359 angular_hessian_.row(4).noalias() = Eigen::Vector4d(
360 (-sx * cz - cx * sy * sz), (sx * sz - cx * sy * cz), 0, 0.0f);
361 angular_hessian_.row(5).noalias() = Eigen::Vector4d(
362 (cx * cz - sx * sy * sz), (-sx * sy * cz - cx * sz), 0, 0.0f);
364 angular_hessian_.row(6).noalias() =
365 Eigen::Vector4d((-cy * cz), (cy * sz), (-sy), 0.0f);
366 angular_hessian_.row(7).noalias() =
367 Eigen::Vector4d((-sx * sy * cz), (sx * sy * sz), (sx * cy), 0.0f);
368 angular_hessian_.row(8).noalias() =
369 Eigen::Vector4d((cx * sy * cz), (-cx * sy * sz), (-cx * cy), 0.0f);
371 angular_hessian_.row(9).noalias() =
372 Eigen::Vector4d((sy * sz), (sy * cz), 0, 0.0f);
373 angular_hessian_.row(10).noalias() =
374 Eigen::Vector4d((-sx * cy * sz), (-sx * cy * cz), 0, 0.0f);
375 angular_hessian_.row(11).noalias() =
376 Eigen::Vector4d((cx * cy * sz), (cx * cy * cz), 0, 0.0f);
378 angular_hessian_.row(12).noalias() =
379 Eigen::Vector4d((-cy * cz), (cy * sz), 0, 0.0f);
380 angular_hessian_.row(13).noalias() = Eigen::Vector4d(
381 (-cx * sz - sx * sy * cz), (-cx * cz + sx * sy * sz), 0, 0.0f);
382 angular_hessian_.row(14).noalias() = Eigen::Vector4d(
383 (-sx * sz + cx * sy * cz), (-cx * sy * sz - sx * cz), 0, 0.0f);
387 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
390 const Eigen::Vector3d& x,
391 Eigen::Matrix<double, 3, 6>& point_jacobian,
392 Eigen::Matrix<double, 18, 6>* point_hessian)
const
397 Eigen::Matrix<double, 8, 1> point_angular_jacobian =
398 angular_jacobian_ * Eigen::Vector4d(x[0], x[1], x[2], 0.0);
399 point_jacobian(1, 3) = point_angular_jacobian[0];
400 point_jacobian(2, 3) = point_angular_jacobian[1];
401 point_jacobian(0, 4) = point_angular_jacobian[2];
402 point_jacobian(1, 4) = point_angular_jacobian[3];
403 point_jacobian(2, 4) = point_angular_jacobian[4];
404 point_jacobian(0, 5) = point_angular_jacobian[5];
405 point_jacobian(1, 5) = point_angular_jacobian[6];
406 point_jacobian(2, 5) = point_angular_jacobian[7];
409 Eigen::Matrix<double, 15, 1> point_angular_hessian =
410 angular_hessian_ * Eigen::Vector4d(x[0], x[1], x[2], 0.0);
413 const Eigen::Vector3d a(0, point_angular_hessian[0], point_angular_hessian[1]);
414 const Eigen::Vector3d b(0, point_angular_hessian[2], point_angular_hessian[3]);
415 const Eigen::Vector3d c(0, point_angular_hessian[4], point_angular_hessian[5]);
416 const Eigen::Vector3d d = point_angular_hessian.block<3, 1>(6, 0);
417 const Eigen::Vector3d e = point_angular_hessian.block<3, 1>(9, 0);
418 const Eigen::Vector3d f = point_angular_hessian.block<3, 1>(12, 0);
423 point_hessian->block<3, 1>(9, 3) = a;
424 point_hessian->block<3, 1>(12, 3) = b;
425 point_hessian->block<3, 1>(15, 3) = c;
426 point_hessian->block<3, 1>(9, 4) = b;
427 point_hessian->block<3, 1>(12, 4) = d;
428 point_hessian->block<3, 1>(15, 4) = e;
429 point_hessian->block<3, 1>(9, 5) = c;
430 point_hessian->block<3, 1>(12, 5) = e;
431 point_hessian->block<3, 1>(15, 5) = f;
435 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
438 const Eigen::Vector3d& x,
bool compute_hessian)
440 computePointDerivatives(
441 x, point_jacobian_, compute_hessian ? &point_hessian_ :
nullptr);
444 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
447 Eigen::Matrix<double, 6, 1>& score_gradient,
448 Eigen::Matrix<double, 6, 6>& hessian,
449 const Eigen::Vector3d& x_trans,
450 const Eigen::Matrix3d& c_inv,
451 const Eigen::Matrix<double, 3, 6>& point_jacobian,
452 const Eigen::Matrix<double, 18, 6>* point_hessian)
const
455 double e_x_cov_x = std::exp(-gauss_d2_ * x_trans.dot(c_inv * x_trans) / 2);
458 const double score_inc = -gauss_d1_ * e_x_cov_x;
460 e_x_cov_x = gauss_d2_ * e_x_cov_x;
463 if (e_x_cov_x > 1 || e_x_cov_x < 0 || std::isnan(e_x_cov_x)) {
468 e_x_cov_x *= gauss_d1_;
470 for (
int i = 0; i < 6; i++) {
473 const Eigen::Vector3d cov_dxd_pi = c_inv * point_jacobian.col(i);
476 score_gradient(i) += x_trans.dot(cov_dxd_pi) * e_x_cov_x;
479 for (Eigen::Index j = 0; j < hessian.cols(); j++) {
482 e_x_cov_x * (-gauss_d2_ * x_trans.dot(cov_dxd_pi) *
483 x_trans.dot(c_inv * point_jacobian.col(j)) +
484 x_trans.dot(c_inv * point_hessian->block<3, 1>(3 * i, j)) +
485 point_jacobian.col(j).dot(cov_dxd_pi));
493 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
496 Eigen::Matrix<double, 6, 1>& score_gradient,
497 Eigen::Matrix<double, 6, 6>& hessian,
498 const Eigen::Vector3d& x_trans,
499 const Eigen::Matrix3d& c_inv,
500 bool compute_hessian)
const
502 return updateDerivatives(score_gradient,
507 compute_hessian ? &point_hessian_ :
nullptr);
510 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
520 for (std::size_t idx = 0; idx < input_->size(); idx++) {
522 const auto& x_trans_pt = trans_cloud[idx];
524 std::vector<TargetGridLeafConstPtr> neighborhood;
525 std::vector<float> distances;
528 switch (search_method_) {
531 target_cells_.radiusSearch(x_trans_pt, resolution_, neighborhood, distances);
534 target_cells_.getAllNeighborsAtPoint(x_trans_pt, neighborhood);
537 target_cells_.getNeighborhoodAtPoint(x_trans_pt, neighborhood);
540 target_cells_.getFaceNeighborsAtPoint(x_trans_pt, neighborhood);
543 target_cells_.getVoxelAtPoint(x_trans_pt, neighborhood);
547 for (
const auto& cell : neighborhood) {
549 const auto& x_pt = (*input_)[idx];
550 const Eigen::Vector3d x = x_pt.getVector3fMap().template cast<double>();
553 const Eigen::Vector3d x_trans =
554 x_trans_pt.getVector3fMap().template cast<double>() - cell->getMean();
557 const Eigen::Matrix3d c_inv = cell->getInverseCov();
561 computePointDerivatives(x);
564 updateHessian(hessian, x_trans, c_inv);
569 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
572 Eigen::Matrix<double, 6, 6>& hessian,
573 const Eigen::Vector3d& x_trans,
574 const Eigen::Matrix3d& c_inv,
575 const Eigen::Matrix<double, 3, 6>& point_jacobian,
576 const Eigen::Matrix<double, 18, 6>& point_hessian)
const
580 gauss_d2_ * std::exp(-gauss_d2_ * x_trans.dot(c_inv * x_trans) / 2);
583 if (e_x_cov_x > 1 || e_x_cov_x < 0 || std::isnan(e_x_cov_x)) {
588 e_x_cov_x *= gauss_d1_;
590 for (
int i = 0; i < 6; i++) {
593 const Eigen::Vector3d cov_dxd_pi = c_inv * point_jacobian.col(i);
595 for (Eigen::Index j = 0; j < hessian.cols(); j++) {
598 e_x_cov_x * (-gauss_d2_ * x_trans.dot(cov_dxd_pi) *
599 x_trans.dot(c_inv * point_jacobian.col(j)) +
600 x_trans.dot(c_inv * point_hessian.block<3, 1>(3 * i, j)) +
601 point_jacobian.col(j).dot(cov_dxd_pi));
606 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
609 Eigen::Matrix<double, 6, 6>& hessian,
610 const Eigen::Vector3d& x_trans,
611 const Eigen::Matrix3d& c_inv)
const
613 updateHessian(hessian, x_trans, c_inv, point_jacobian_, point_hessian_);
616 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
639 if (g_t * (a_l - a_t) > 0) {
647 if (g_t * (a_l - a_t) < 0) {
661 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
674 if (a_t == a_l && a_t == a_u) {
679 enum class EndpointsCondition { Case1, Case2, Case3, Case4 };
680 EndpointsCondition condition;
683 condition = EndpointsCondition::Case4;
685 else if (f_t > f_l) {
686 condition = EndpointsCondition::Case1;
688 else if (g_t * g_l < 0) {
689 condition = EndpointsCondition::Case2;
691 else if (std::fabs(g_t) <= std::fabs(g_l)) {
692 condition = EndpointsCondition::Case3;
695 condition = EndpointsCondition::Case4;
699 case EndpointsCondition::Case1: {
702 const double z = 3 * (f_t - f_l) / (a_t - a_l) - g_t - g_l;
703 const double w = std::sqrt(z * z - g_t * g_l);
705 const double a_c = a_l + (a_t - a_l) * (w - g_l - z) / (g_t - g_l + 2 * w);
710 a_l - 0.5 * (a_l - a_t) * g_l / (g_l - (f_l - f_t) / (a_l - a_t));
712 if (std::fabs(a_c - a_l) < std::fabs(a_q - a_l)) {
715 return 0.5 * (a_q + a_c);
718 case EndpointsCondition::Case2: {
721 const double z = 3 * (f_t - f_l) / (a_t - a_l) - g_t - g_l;
722 const double w = std::sqrt(z * z - g_t * g_l);
724 const double a_c = a_l + (a_t - a_l) * (w - g_l - z) / (g_t - g_l + 2 * w);
728 const double a_s = a_l - (a_l - a_t) / (g_l - g_t) * g_l;
730 if (std::fabs(a_c - a_t) >= std::fabs(a_s - a_t)) {
736 case EndpointsCondition::Case3: {
739 const double z = 3 * (f_t - f_l) / (a_t - a_l) - g_t - g_l;
740 const double w = std::sqrt(z * z - g_t * g_l);
741 const double a_c = a_l + (a_t - a_l) * (w - g_l - z) / (g_t - g_l + 2 * w);
745 const double a_s = a_l - (a_l - a_t) / (g_l - g_t) * g_l;
749 if (std::fabs(a_c - a_t) < std::fabs(a_s - a_t)) {
757 return std::min(a_t + 0.66 * (a_u - a_t), a_t_next);
759 return std::max(a_t + 0.66 * (a_u - a_t), a_t_next);
763 case EndpointsCondition::Case4: {
766 const double z = 3 * (f_t - f_u) / (a_t - a_u) - g_t - g_u;
767 const double w = std::sqrt(z * z - g_t * g_u);
769 return a_u + (a_t - a_u) * (w - g_u - z) / (g_t - g_u + 2 * w);
774 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
777 const Eigen::Matrix<double, 6, 1>& x,
778 Eigen::Matrix<double, 6, 1>& step_dir,
783 Eigen::Matrix<double, 6, 1>& score_gradient,
784 Eigen::Matrix<double, 6, 6>& hessian,
788 const double phi_0 = -score;
790 double d_phi_0 = -(score_gradient.dot(step_dir));
804 constexpr
int max_step_iterations = 10;
805 int step_iterations = 0;
808 constexpr
double mu = 1.e-4;
810 constexpr
double nu = 0.9;
813 double a_l = 0, a_u = 0;
817 double f_l = auxilaryFunction_PsiMT(a_l, phi_0, phi_0, d_phi_0, mu);
818 double g_l = auxilaryFunction_dPsiMT(d_phi_0, d_phi_0, mu);
820 double f_u = auxilaryFunction_PsiMT(a_u, phi_0, phi_0, d_phi_0, mu);
821 double g_u = auxilaryFunction_dPsiMT(d_phi_0, d_phi_0, mu);
825 bool interval_converged = (step_max - step_min) < 0, open_interval =
true;
827 double a_t = step_init;
828 a_t = std::min(a_t, step_max);
829 a_t = std::max(a_t, step_min);
831 Eigen::Matrix<double, 6, 1> x_t = x + step_dir * a_t;
834 convertTransform(x_t, final_transformation_);
843 score = computeDerivatives(score_gradient, hessian, trans_cloud, x_t,
true);
846 double phi_t = -score;
848 double d_phi_t = -(score_gradient.dot(step_dir));
851 double psi_t = auxilaryFunction_PsiMT(a_t, phi_t, phi_0, d_phi_0, mu);
853 double d_psi_t = auxilaryFunction_dPsiMT(d_phi_t, d_phi_0, mu);
858 while (!interval_converged && step_iterations < max_step_iterations &&
860 d_phi_t > -nu * d_phi_0 )) {
863 a_t = trialValueSelectionMT(a_l, f_l, g_l, a_u, f_u, g_u, a_t, psi_t, d_psi_t);
866 a_t = trialValueSelectionMT(a_l, f_l, g_l, a_u, f_u, g_u, a_t, phi_t, d_phi_t);
869 a_t = std::min(a_t, step_max);
870 a_t = std::max(a_t, step_min);
872 x_t = x + step_dir * a_t;
875 convertTransform(x_t, final_transformation_);
882 score = computeDerivatives(score_gradient, hessian, trans_cloud, x_t,
false);
887 d_phi_t = -(score_gradient.dot(step_dir));
890 psi_t = auxilaryFunction_PsiMT(a_t, phi_t, phi_0, d_phi_0, mu);
892 d_psi_t = auxilaryFunction_dPsiMT(d_phi_t, d_phi_0, mu);
895 if (open_interval && (psi_t <= 0 && d_psi_t >= 0)) {
896 open_interval =
false;
899 f_l += phi_0 - mu * d_phi_0 * a_l;
903 f_u += phi_0 - mu * d_phi_0 * a_u;
910 updateIntervalMT(a_l, f_l, g_l, a_u, f_u, g_u, a_t, psi_t, d_psi_t);
916 updateIntervalMT(a_l, f_l, g_l, a_u, f_u, g_u, a_t, phi_t, d_phi_t);
925 if (step_iterations) {
926 computeHessian(hessian, trans_cloud);
std::string reg_name_
The registration method name.
int max_iterations_
The maximum number of iterations the internal optimization should run for.
double transformation_epsilon_
The maximum difference between two consecutive transformations in order to consider convergence (user...
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.
IndicesAllocator<> Indices
Type used for indices in PCL.