iterative closest points
CEV ICP algorithm library
Loading...
Searching...
No Matches
vanilla.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 <cassert>
7#include <cstdlib>
8#include "../icp.h"
9#include <Eigen/Core>
10#include <Eigen/SVD>
11
12/* #name Vanilla */
13
14/* #desc The vanilla algorithm for ICP will match the point-cloud centers
15exactly and then iterate until an optimal rotation has been found. */
16
17namespace icp {
18 struct Vanilla final : public ICP {
19 std::vector<icp::Vector> a_rot;
20
21 Vanilla(): ICP() {}
22 ~Vanilla() override {}
23
24 void setup() override {
25 if (a_rot.size() < a.size()) {
26 a_rot.resize(a.size());
27 }
28 }
29
30 void iterate() override {
31 const size_t n = a.size();
32 const size_t m = b.size();
33
34 for (size_t i = 0; i < n; i++) {
35 a_rot[i] = transform.rotation * a[i];
36 }
37
38 /*
39 #step
40 Matching Step: match closest points.
41
42 Sources:
43 https://arxiv.org/pdf/2206.06435.pdf
44 https://web.archive.org/web/20220615080318/https://www.cs.technion.ac.il/~cs236329/tutorials/ICP.pdf
45 https://en.wikipedia.org/wiki/Iterative_closest_point
46 https://courses.cs.duke.edu/spring07/cps296.2/scribe_notes/lecture24.pdf
47 -> use k-d tree
48 */
49 for (size_t i = 0; i < n; i++) {
50 matches[i].sq_dist = std::numeric_limits<double>::infinity();
51 for (size_t j = 0; j < m; j++) {
52 // Point-to-point matching
53 double dist_ij = (b[j] - a_rot[i]).squaredNorm();
54
55 if (dist_ij < matches[i].sq_dist) {
56 matches[i].sq_dist = dist_ij;
57 matches[i].pair = j;
58 }
59 }
60 }
61
62 /*
63 #step
64 Transformation Step: determine optimal transformation.
65
66 The translation vector is determined by the displacement between
67 the centroids of both point clouds. The rotation matrix is
68 calculated via singular value decomposition.
69
70 Sources:
71 https://courses.cs.duke.edu/spring07/cps296.2/scribe_notes/lecture24.pdf
72 */
74
75 Matrix N{};
76 for (size_t i = 0; i < n; i++) {
77 N += a[i] * b[matches[i].pair].transpose();
78 }
79 auto svd = N.jacobiSvd(Eigen::ComputeFullU | Eigen::ComputeFullV);
80 const Matrix U = svd.matrixU();
81 const Matrix V = svd.matrixV();
82 transform.rotation = V * U.transpose();
83 }
84 };
85
86 static bool static_initialization = []() {
87 assert(ICP::register_method("vanilla",
88 [](const ICP::Config& config __unused) -> std::unique_ptr<ICP> {
89 return std::make_unique<Vanilla>();
90 }));
91 return true;
92 }();
93}
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
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
std::vector< Vector > a
The source point cloud relative to its centroid.
Definition icp.h:66
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
Definition geo.cpp:9
Eigen::Matrix2d Matrix
Definition geo.h:16
Matrix rotation
Definition geo.h:21
Vector translation
Definition geo.h:20