iterative closest points
CEV ICP algorithm library
Loading...
Searching...
No Matches
icp.cpp
Go to the documentation of this file.
1/*
2 * @author Ethan Uppal
3 * @copyright Copyright (C) 2024 Ethan Uppal. All rights reserved.
4 */
5
6#include <numeric>
7#include "icp.h"
8
9namespace icp {
10 static Methods* global;
11
13
14 void ICP::setup() {}
15
16 void ICP::begin(const std::vector<Vector>& a, const std::vector<Vector>& b,
17 RBTransform t) {
18 // Initial transform guess
19 this->transform = t;
20
21 // Copy in point clouds
22 this->a = a;
23 this->b = b;
24
25 // Set relative to centroid
26 a_cm = get_centroid(this->a);
27 b_cm = get_centroid(this->b);
28 for (Vector& point: this->a) {
29 point -= a_cm;
30 }
31 for (Vector& point: this->b) {
32 point -= b_cm;
33 }
34
35 // Cost is infinite initially
36 previous_cost = std::numeric_limits<double>::infinity();
37 current_cost = std::numeric_limits<double>::infinity();
38
39 // Ensure arrays are the right size
40 const size_t n = this->a.size();
41 if (matches.size() < n) {
42 matches.resize(n);
43 matches.resize(n);
44 }
45
46 // Per-instance customization routine
47 setup();
48 }
49
50 double ICP::calculate_cost() const {
51 double sum_squares{};
52 for (auto& match: matches) {
53 sum_squares += match.sq_dist;
54 }
55 return std::sqrt(sum_squares / a.size());
56 }
57
59 double convergence_threshold) {
60 ConvergenceReport result{};
61
62 // Repeat until convergence
63 while (current_cost > convergence_threshold || current_cost == INFINITY
64 || result.iteration_count < burn_in) {
65 // Store previous iteration results
67 RBTransform previous_transform = transform;
68
69 iterate();
70
71 // If cost rose, revert to previous transformation/cost and
72 // exit
75 && result.iteration_count > burn_in) {
76 transform = previous_transform;
78 break;
79 }
80
81 result.iteration_count++;
82 }
83
84 result.final_cost = current_cost;
85
86 return result;
87 }
88
90 return transform;
91 }
92
93 static void ensure_methods_exists() {
94 if (!global) {
95 global = new Methods();
96 }
97 }
98
99 bool ICP::register_method(std::string name,
100 std::function<std::unique_ptr<ICP>(const ICP::Config&)> constructor) {
101 ensure_methods_exists();
102 global->registered_method_constructors.push_back(constructor);
103 global->registered_method_names.push_back(name);
104 return true;
105 }
106
107 const std::vector<std::string>& ICP::registered_methods() {
108 ensure_methods_exists();
109 return global->registered_method_names;
110 }
111
112 std::unique_ptr<ICP> ICP::from_method(std::string name,
113 const ICP::Config& config) {
114 ensure_methods_exists();
115 size_t index = std::find(global->registered_method_names.begin(),
116 global->registered_method_names.end(), name)
117 - global->registered_method_names.begin();
118 return global->registered_method_constructors[index](config);
119 }
120
121 bool ICP::is_registered_method(std::string name) {
122 return std::find(global->registered_method_names.begin(),
123 global->registered_method_names.end(), name)
124 != global->registered_method_names.end();
125 }
126}
Configuration for ICP instances.
Definition icp.h:97
static bool register_method(std::string name, std::function< std::unique_ptr< ICP >(const Config &)> constructor)
Registers a new ICP method that can be created with constructor, returning false if name has already ...
Definition icp.cpp:99
double previous_cost
Keeps track of the previous cost to ensure that progress is being made.
Definition icp.h:73
virtual void setup()
Definition icp.cpp:14
static std::unique_ptr< ICP > from_method(std::string name, const Config &params=Config())
Factory constructor for the ICP method name with configuration config.
Definition icp.cpp:112
RBTransform transform
The current point cloud transformation that is being optimized.
Definition icp.h:57
Vector b_cm
The centroid of the destination point cloud.
Definition icp.h:63
ICP()
Definition icp.cpp:12
Vector a_cm
The centroid of the source point cloud.
Definition icp.h:60
ConvergenceReport converge(size_t burn_in, double convergence_threshold)
Perform ICP for the point clouds a and b provided with ICP::begin until the cost is below convergence...
Definition icp.cpp:58
double current_cost
The RMS (root mean square) cost of the current transformation.
Definition icp.h:76
std::vector< Vector > a
The source point cloud relative to its centroid.
Definition icp.h:66
static const std::vector< std::string > & registered_methods()
Returns a current list of the names of currently registered ICP methods.
Definition icp.cpp:107
std::vector< Vector > b
The destination point cloud relative to its centroid.
Definition icp.h:69
std::vector< Match > matches
The pairing of each point in a to its closest in b.
Definition icp.h:79
void begin(const std::vector< Vector > &a, const std::vector< Vector > &b, RBTransform t)
Begins the ICP process for point clouds a and b with an initial guess for the transform t.
Definition icp.cpp:16
const RBTransform & current_transform() const
The current transform.
Definition icp.cpp:89
virtual void iterate()=0
Perform one iteration of ICP for the point clouds a and b provided with ICP::begin.
double calculate_cost() const
Computes the cost of the current transformation.
Definition icp.cpp:50
static bool is_registered_method(std::string name)
Whether name is a registered ICP method.
Definition icp.cpp:121
Definition geo.cpp:9
Eigen::Vector2d Vector
Definition geo.h:15
Vector get_centroid(const std::vector< Vector > &points)
Definition geo.cpp:10
The result of running ICP::converge.
Definition icp.h:87
std::vector< std::function< std::unique_ptr< ICP >(const ICP::Config &)> registered_method_constructors)
Definition icp.h:186
std::vector< std::string > registered_method_names
Definition icp.h:184
Rigid-body transformation.
Definition geo.h:19