19 struct Vanilla final :
public ICP {
20 std::vector<icp::Vector> a_current;
24 ~Vanilla()
override {}
26 void setup()
override {
27 if (a_current.size() <
a.size()) {
28 a_current.resize(
a.size());
34 void iterate()
override {
35 const size_t n =
a.size();
36 const size_t m =
b.size();
38 for (
size_t i = 0; i < n; i++) {
57 for (
size_t i = 0; i < n; i++) {
58 matches[i].sq_dist = std::numeric_limits<double>::infinity();
59 for (
size_t j = 0; j < m; j++) {
61 double dist_ij = (
b[j] - a_current[i]).squaredNorm();
63 if (dist_ij <
matches[i].sq_dist) {
71 for (
size_t i = 0; i < n; i++) {
72 N += (a_current[i] - a_current_cm) * (
b[
matches[i].pair] - b_cm).transpose();
74 auto svd = N.jacobiSvd(Eigen::ComputeFullU | Eigen::ComputeFullV);
75 const Matrix U = svd.matrixU();
76 const Matrix V = svd.matrixV();
77 const Matrix R = V * U.transpose();
80 if (R.determinant() < 0) {
81 throw std::runtime_error(
82 "SVD determinant is negative. Got reflection instead of rotation.");
103 static bool static_initialization = []() {
105 [](
const ICP::Config& config) -> std::unique_ptr<ICP> {
106 return std::make_unique<Vanilla>();
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 ...
RBTransform transform
The current point cloud transformation that is being optimized.
std::vector< Vector > a
The source point cloud relative to its centroid.
std::vector< Vector > b
The destination point cloud relative to its centroid.
std::vector< Match > matches
The pairing of each point in a to its closest in b.
Vector get_centroid(const std::vector< Vector > &points)