iterative closest points
CEV ICP algorithm library
Loading...
Searching...
No Matches
trimmed.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 Trimmed */
13
14/* #conf "overlap_rate" A `double` between 0 and 1 for the overlap rate. The
15 default is 1. */
16
17/* #desc Trimmed ICP is identical to \ref vanilla_icp with the addition of an
18overlap rate parameter, which specifies the percentage of points between the two
19point sets that have correspondences. When the overlap rate is 1, the algorithm
20reduces to vanilla. */
21
22namespace icp {
23 struct Trimmed final : public ICP {
24 double overlap_rate;
25 std::vector<icp::Vector> a_rot;
26
27 Trimmed(double overlap_rate): ICP(), overlap_rate(overlap_rate) {}
28 ~Trimmed() override {}
29
30 void setup() override {
31 if (a_rot.size() < a.size()) {
32 a_rot.resize(a.size());
33 }
34 }
35
36 void iterate() override {
37 size_t n = a.size();
38 const size_t m = b.size();
39
40 for (size_t i = 0; i < n; i++) {
41 a_rot[i] = transform.rotation * a[i];
42 }
43
44 /* #step Matching Step: see \ref vanilla_icp
45 for details. */
46 for (size_t i = 0; i < n; i++) {
47 matches[i].point = i;
48 matches[i].sq_dist = std::numeric_limits<double>::infinity();
49 for (size_t j = 0; j < m; j++) {
50 // Point-to-point matching
51 double dist_ij = (b[j] - a_rot[i]).squaredNorm();
52
53 if (dist_ij < matches[i].sq_dist) {
54 matches[i].sq_dist = dist_ij;
55 matches[i].pair = j;
56 }
57 }
58 }
59
60 /*
61 #step
62 Trimming Step
63
64 Matches are considered in increasing order of distance.
65
66 Sources:
67 https://ieeexplore.ieee.org/abstract/document/1047997
68 */
69 std::sort(matches.begin(), matches.end(),
70 [](const auto& a, const auto& b) {
71 return a.sq_dist < b.sq_dist;
72 });
73 n = (size_t)(overlap_rate * n);
74
75 /*
76 #step
77 Transformation Step: see \ref vanilla_icp for details.
78 */
80
81 Matrix N{};
82 for (size_t i = 0; i < n; i++) {
83 N += a[matches[i].point] * b[matches[i].pair].transpose();
84 }
85 auto svd = N.jacobiSvd(Eigen::ComputeFullU | Eigen::ComputeFullV);
86 const Matrix U = svd.matrixU();
87 const Matrix V = svd.matrixV();
88 transform.rotation = V * U.transpose();
89 }
90 };
91
92 static bool static_initialization = []() {
93 assert(ICP::register_method("trimmed",
94 [](const ICP::Config& config) -> std::unique_ptr<ICP> {
95 double overlap_rate = config.get<double>("overlap_rate", 1.0);
96 assert(overlap_rate >= 0 && overlap_rate <= 1);
97 return std::make_unique<Trimmed>(overlap_rate);
98 }));
99 return true;
100 }();
101}
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