small_gicp
icp_factor.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 <Eigen/Core>
6 #include <Eigen/Geometry>
10 
11 namespace small_gicp {
12 
14 struct ICPFactor {
15  struct Setting {};
16 
17  ICPFactor(const Setting& setting = Setting()) : target_index(std::numeric_limits<size_t>::max()), source_index(std::numeric_limits<size_t>::max()) {}
18 
19  template <typename TargetPointCloud, typename SourcePointCloud, typename TargetTree, typename CorrespondenceRejector>
20  bool linearize(
21  const TargetPointCloud& target,
22  const SourcePointCloud& source,
23  const TargetTree& target_tree,
24  const Eigen::Isometry3d& T,
25  size_t source_index,
26  const CorrespondenceRejector& rejector,
27  Eigen::Matrix<double, 6, 6>* H,
28  Eigen::Matrix<double, 6, 1>* b,
29  double* e) {
30  //
31  this->source_index = source_index;
32  this->target_index = std::numeric_limits<size_t>::max();
33 
34  const Eigen::Vector4d transed_source_pt = T * traits::point(source, source_index);
35 
36  size_t k_index;
37  double k_sq_dist;
38  if (!traits::nearest_neighbor_search(target_tree, transed_source_pt, &k_index, &k_sq_dist) || rejector(target, source, T, k_index, source_index, k_sq_dist)) {
39  return false;
40  }
41 
42  target_index = k_index;
43  const Eigen::Vector4d residual = traits::point(target, target_index) - transed_source_pt;
44 
45  Eigen::Matrix<double, 4, 6> J = Eigen::Matrix<double, 4, 6>::Zero();
46  J.block<3, 3>(0, 0) = T.linear() * skew(traits::point(source, source_index).template head<3>());
47  J.block<3, 3>(0, 3) = -T.linear();
48 
49  *H = J.transpose() * J;
50  *b = J.transpose() * residual;
51  *e = 0.5 * residual.squaredNorm();
52 
53  return true;
54  }
55 
56  template <typename TargetPointCloud, typename SourcePointCloud>
57  double error(const TargetPointCloud& target, const SourcePointCloud& source, const Eigen::Isometry3d& T) const {
58  if (target_index == std::numeric_limits<size_t>::max()) {
59  return 0.0;
60  }
61 
62  const Eigen::Vector4d residual = traits::point(target, target_index) - T * traits::point(source, source_index);
63  return 0.5 * residual.squaredNorm();
64  }
65 
66  bool inlier() const { return target_index != std::numeric_limits<size_t>::max(); }
67 
68  size_t target_index;
69  size_t source_index;
70 };
71 } // namespace small_gicp
size_t nearest_neighbor_search(const T &tree, const Eigen::Vector4d &point, size_t *k_index, double *k_sq_dist)
Find the nearest neighbor. If Traits<T>::nearest_neighbor_search is not defined, fallback to knn_sear...
Definition: traits.hpp:44
auto point(const T &points, size_t i)
Get i-th point. 4D vector is used to take advantage of SIMD intrinsics. The last element must be fill...
Definition: traits.hpp:40
Definition: flat_container.hpp:12
Eigen::Matrix3d skew(const Eigen::Vector3d &x)
Create skew symmetric matrix.
Definition: lie.hpp:13
Definition: icp_factor.hpp:15
Point-to-point per-point error factor.
Definition: icp_factor.hpp:14
bool linearize(const TargetPointCloud &target, const SourcePointCloud &source, const TargetTree &target_tree, const Eigen::Isometry3d &T, size_t source_index, const CorrespondenceRejector &rejector, Eigen::Matrix< double, 6, 6 > *H, Eigen::Matrix< double, 6, 1 > *b, double *e)
Definition: icp_factor.hpp:20
bool inlier() const
Definition: icp_factor.hpp:66
size_t source_index
Definition: icp_factor.hpp:69
double error(const TargetPointCloud &target, const SourcePointCloud &source, const Eigen::Isometry3d &T) const
Definition: icp_factor.hpp:57
ICPFactor(const Setting &setting=Setting())
Definition: icp_factor.hpp:17
size_t target_index
Definition: icp_factor.hpp:68