small_gicp
optimizer.hpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright 2024 Kenji Koide
2 // SPDX-License-Identifier: MIT
3 #pragma once
4 
5 #include <iostream>
8 
9 namespace small_gicp {
10 
14 
15  template <
16  typename TargetPointCloud,
17  typename SourcePointCloud,
18  typename TargetTree,
19  typename CorrespondenceRejector,
20  typename TerminationCriteria,
21  typename Reduction,
22  typename Factor,
23  typename GeneralFactor>
25  const TargetPointCloud& target,
26  const SourcePointCloud& source,
27  const TargetTree& target_tree,
28  const CorrespondenceRejector& rejector,
29  const TerminationCriteria& criteria,
30  Reduction& reduction,
31  const Eigen::Isometry3d& init_T,
32  std::vector<Factor>& factors,
33  GeneralFactor& general_factor) const {
34  //
35  if (verbose) {
36  std::cout << "--- GN optimization ---" << std::endl;
37  }
38 
39  RegistrationResult result(init_T);
40  for (int i = 0; i < max_iterations && !result.converged; i++) {
41  // Linearize
42  auto [H, b, e] = reduction.linearize(target, source, target_tree, rejector, result.T_target_source, factors);
43  general_factor.update_linearized_system(target, source, target_tree, result.T_target_source, &H, &b, &e);
44 
45  // Solve linear system
46  const Eigen::Matrix<double, 6, 1> delta = (H + lambda * Eigen ::Matrix<double, 6, 6>::Identity()).ldlt().solve(-b);
47 
48  if (verbose) {
49  std::cout << "iter=" << i << " e=" << e << " lambda=" << lambda << " dt=" << delta.tail<3>().norm() << " dr=" << delta.head<3>().norm() << std::endl;
50  }
51 
52  result.converged = criteria.converged(delta);
53  result.T_target_source = result.T_target_source * se3_exp(delta);
54  result.iterations = i;
55  result.H = H;
56  result.b = b;
57  result.error = e;
58  }
59 
60  result.num_inliers = std::count_if(factors.begin(), factors.end(), [](const auto& factor) { return factor.inlier(); });
61 
62  return result;
63  }
64 
65  bool verbose;
67  double lambda;
68 };
69 
73 
74  template <
75  typename TargetPointCloud,
76  typename SourcePointCloud,
77  typename TargetTree,
78  typename CorrespondenceRejector,
79  typename TerminationCriteria,
80  typename Reduction,
81  typename Factor,
82  typename GeneralFactor>
84  const TargetPointCloud& target,
85  const SourcePointCloud& source,
86  const TargetTree& target_tree,
87  const CorrespondenceRejector& rejector,
88  const TerminationCriteria& criteria,
89  Reduction& reduction,
90  const Eigen::Isometry3d& init_T,
91  std::vector<Factor>& factors,
92  GeneralFactor& general_factor) const {
93  //
94  if (verbose) {
95  std::cout << "--- LM optimization ---" << std::endl;
96  }
97 
98  double lambda = init_lambda;
99  RegistrationResult result(init_T);
100  for (int i = 0; i < max_iterations && !result.converged; i++) {
101  // Linearize
102  auto [H, b, e] = reduction.linearize(target, source, target_tree, rejector, result.T_target_source, factors);
103  general_factor.update_linearized_system(target, source, target_tree, result.T_target_source, &H, &b, &e);
104 
105  // Lambda iteration
106  bool success = false;
107  for (int j = 0; j < max_inner_iterations; j++) {
108  // Solve with damping
109  const Eigen::Matrix<double, 6, 1> delta = (H + lambda * Eigen::Matrix<double, 6, 6>::Identity()).ldlt().solve(-b);
110 
111  // Validte new solution
112  const Eigen::Isometry3d new_T = result.T_target_source * se3_exp(delta);
113  double new_e = reduction.error(target, source, new_T, factors);
114  general_factor.update_error(target, source, new_T, &e);
115 
116  if (verbose) {
117  std::cout << "iter=" << i << " inner=" << j << " e=" << e << " new_e=" << new_e << " lambda=" << lambda << " dt=" << delta.tail<3>().norm()
118  << " dr=" << delta.head<3>().norm() << std::endl;
119  }
120 
121  if (new_e <= e) {
122  // Error decreased, decrease lambda
123  result.converged = criteria.converged(delta);
124  result.T_target_source = new_T;
125  lambda /= lambda_factor;
126  success = true;
127 
128  break;
129  } else {
130  // Failed to decrease error, increase lambda
131  lambda *= lambda_factor;
132  }
133  }
134 
135  result.iterations = i;
136  result.H = H;
137  result.b = b;
138  result.error = e;
139 
140  if (!success) {
141  break;
142  }
143  }
144 
145  result.num_inliers = std::count_if(factors.begin(), factors.end(), [](const auto& factor) { return factor.inlier(); });
146 
147  return result;
148  }
149 
150  bool verbose;
153  double init_lambda;
154  double lambda_factor;
155 };
156 
157 } // namespace small_gicp
Definition: flat_container.hpp:12
Eigen::Isometry3d se3_exp(const Eigen::Matrix< double, 6, 1 > &a)
SE3 expmap (Rotation-first).
Definition: lie.hpp:77
GaussNewton optimizer.
Definition: optimizer.hpp:12
GaussNewtonOptimizer()
Definition: optimizer.hpp:13
RegistrationResult optimize(const TargetPointCloud &target, const SourcePointCloud &source, const TargetTree &target_tree, const CorrespondenceRejector &rejector, const TerminationCriteria &criteria, Reduction &reduction, const Eigen::Isometry3d &init_T, std::vector< Factor > &factors, GeneralFactor &general_factor) const
Definition: optimizer.hpp:24
double lambda
Damping factor (Increasing this makes optimization slow but stable)
Definition: optimizer.hpp:67
bool verbose
If true, print debug messages.
Definition: optimizer.hpp:65
int max_iterations
Max number of optimization iterations.
Definition: optimizer.hpp:66
LevenbergMarquardt optimizer.
Definition: optimizer.hpp:71
int max_inner_iterations
Max number of inner iterations (lambda-trial)
Definition: optimizer.hpp:152
bool verbose
If true, print debug messages.
Definition: optimizer.hpp:150
LevenbergMarquardtOptimizer()
Definition: optimizer.hpp:72
double lambda_factor
Lambda increase factor.
Definition: optimizer.hpp:154
double init_lambda
Initial lambda (damping factor)
Definition: optimizer.hpp:153
int max_iterations
Max number of optimization iterations.
Definition: optimizer.hpp:151
RegistrationResult optimize(const TargetPointCloud &target, const SourcePointCloud &source, const TargetTree &target_tree, const CorrespondenceRejector &rejector, const TerminationCriteria &criteria, Reduction &reduction, const Eigen::Isometry3d &init_T, std::vector< Factor > &factors, GeneralFactor &general_factor) const
Definition: optimizer.hpp:83
Registration result.
Definition: registration_result.hpp:11
Eigen::Isometry3d T_target_source
Estimated transformation.
Definition: registration_result.hpp:21
Eigen::Matrix< double, 6, 6 > H
Final information matrix.
Definition: registration_result.hpp:27
size_t iterations
Number of optimization iterations.
Definition: registration_result.hpp:24
Eigen::Matrix< double, 6, 1 > b
Final information vector.
Definition: registration_result.hpp:28
size_t num_inliers
Number of inliear points.
Definition: registration_result.hpp:25
bool converged
If the optimization converged.
Definition: registration_result.hpp:23
double error
Final error.
Definition: registration_result.hpp:29
Registration termination criteria.
Definition: termination_criteria.hpp:10
bool converged(const Eigen::Matrix< double, 6, 1 > &delta) const
Check the convergence.
Definition: termination_criteria.hpp:17