visit_correspondences.h
Go to the documentation of this file.
1 /* -------------------------------------------------------------------------
2  * A repertory of multi primitive-to-primitive (MP2P) ICP algorithms in C++
3  * Copyright (C) 2018-2024 Jose Luis Blanco, University of Almeria
4  * See LICENSE for license information.
5  * ------------------------------------------------------------------------- */
12 #pragma once
13 
14 #include <mp2p_icp/Pairings.h>
16 #include <mrpt/core/optional_ref.h>
17 #include <mrpt/math/TPoint3D.h>
18 
19 namespace mp2p_icp
20 {
25 {
27 };
28 
30 template <class LAMBDA, class LAMBDA2>
32  const Pairings& in, const WeightParameters& wp, const mrpt::math::TPoint3D& ct_local,
33  const mrpt::math::TPoint3D& ct_global, OutlierIndices& in_out_outliers, LAMBDA lambda_each_pair,
34  LAMBDA2 lambda_final, bool normalize_relative_point_vectors,
35  const mrpt::optional_ref<VisitCorrespondencesStats>& outStats = std::nullopt)
36 {
37  using mrpt::math::TPoint3D;
38  using mrpt::math::TVector3D;
39 
40  const auto nPt2Pt = in.paired_pt2pt.size();
41  const auto nPt2Ln = in.paired_pt2ln.size();
42  const auto nPt2Pl = in.paired_pt2pl.size();
43  const auto nLn2Ln = in.paired_ln2ln.size();
44  const auto nPl2Pl = in.paired_pl2pl.size();
45 
46  ASSERTMSG_(nPt2Ln == 0, "This solver cannot handle point-to-line pairings.");
47  ASSERTMSG_(nPt2Pl == 0, "This solver cannot handle point-to-plane pairings yet.");
48 
49  const auto nAllMatches = nPt2Pt + nLn2Ln + nPl2Pl;
50 
52 
53  // weight of points, block by block:
54  auto point_weights = in.point_weights;
55  if (point_weights.empty())
56  {
57  // Default, equal weights:
58  point_weights.emplace_back(nPt2Pt, 1.0);
59  }
60 
61  auto cur_point_block_weights = point_weights.begin();
62  std::size_t cur_point_block_start = 0;
63 
64  // Normalized weights for attitude "waXX":
65  double waPoints, waLines, waPlanes;
66  {
67  const auto wPt = wp.pair_weights.pt2pt, wLi = wp.pair_weights.ln2ln,
68  wPl = wp.pair_weights.pl2pl;
69 
70  ASSERTMSG_(wPt + wLi + wPl > .0, "All, point, line, plane attidude weights, are <=0 (!)");
71 
72  const auto k = 1.0 / (wPt * nPt2Pt + wLi * nLn2Ln + wPl * nPl2Pl);
73  waPoints = wPt * k;
74  waLines = wLi * k;
75  waPlanes = wPl * k;
76  }
77 
78  // Accumulator of robust kernel terms (and other user-provided weights)
79  // to normalize the final linear equation at the end:
80  double w_sum = .0;
81 
82  const robust_sqrt_weight_func_t robustSqrtWeightFunc =
84 
85  OutlierIndices new_outliers;
86  new_outliers.point2point.reserve(in_out_outliers.point2point.size());
87 
88  auto it_next_outlier = in_out_outliers.point2point.begin();
89 
90  // Terms contributed by points & vectors have now the uniform form of
91  // unit vectors:
92  for (std::size_t i = 0; i < nAllMatches; i++)
93  {
94  // Skip outlier?
95  if (it_next_outlier != in_out_outliers.point2point.end() && i == *it_next_outlier)
96  {
97  ++it_next_outlier;
98  // also copy idx:
99  new_outliers.point2point.push_back(i);
100  continue;
101  }
102 
103  // Get "bi" (this/global) & "ri" (other/local) vectors:
104  TVector3D bi, ri;
105  double wi = .0;
106 
107  // Points, lines, planes, are all stored in sequence:
108  if (i < nPt2Pt)
109  {
110  // point-to-point pairing: normalize(point-centroid)
111  const auto& p = in.paired_pt2pt[i];
112  wi = waPoints;
113 
114  if (i >= cur_point_block_start + cur_point_block_weights->first)
115  {
116  ASSERT_(cur_point_block_weights != point_weights.end());
117  ++cur_point_block_weights; // move to next block
118  cur_point_block_start = i;
119  }
120  wi *= cur_point_block_weights->second;
121  // (solution will be normalized via w_sum a the end)
122 
123  bi = p.global - ct_global;
124  ri = p.local - ct_local;
125 
126  const auto bi_n = bi.norm(), ri_n = ri.norm();
127 
128  if (bi_n < 1e-4 || ri_n < 1e-4)
129  {
130  // In the rare event of a point (almost) exactly on the
131  // centroid, just discard it:
132  continue;
133  }
134 
135  // Horn requires regular relative vectors.
136  // OLAE requires unit vectors.
137  if (normalize_relative_point_vectors)
138  {
139  bi *= 1.0 / bi_n;
140  ri *= 1.0 / ri_n;
141  }
142 
143  // Note: ideally, both norms should be equal if noiseless and a
144  // real pairing. Let's use this property to detect outliers:
146  {
147  const double scale_mismatch = std::max(bi_n, ri_n) / std::min(bi_n, ri_n);
148  if (scale_mismatch > wp.scale_outlier_threshold)
149  {
150  // Discard this pairing:
151  new_outliers.point2point.push_back(i);
153 
154  continue; // Skip (same effect than: wi = 0)
155  }
156  }
157  }
158  else if (i < nPt2Pt + nLn2Ln)
159  {
160  // line-to-line pairing:
161  wi = waLines;
162 
163  const auto idxLine = i - nPt2Pt;
164 
165  bi = in.paired_ln2ln[idxLine].ln_global.getDirectorVector();
166  ri = in.paired_ln2ln[idxLine].ln_local.getDirectorVector();
167 
168  ASSERTDEB_LT_(std::abs(bi.norm() - 1.0), 0.01);
169  ASSERTDEB_LT_(std::abs(ri.norm() - 1.0), 0.01);
170  }
171  else
172  {
173  // plane-to-plane pairing:
174  wi = waPlanes;
175 
176  const auto idxPlane = i - (nPt2Pt + nLn2Ln);
177  bi = in.paired_pl2pl[idxPlane].p_global.plane.getNormalVector();
178  ri = in.paired_pl2pl[idxPlane].p_local.plane.getNormalVector();
179 
180  ASSERTDEB_LT_(std::abs(bi.norm() - 1.0), 0.01);
181  ASSERTDEB_LT_(std::abs(ri.norm() - 1.0), 0.01);
182  }
183 
184  // If we are about to apply a robust kernel, we need a reference
185  // attitude wrt which apply such kernel, i.e. the "current SE(3)
186  // estimation" inside a caller ICP loop.
187  if (robustSqrtWeightFunc)
188  {
189  ASSERT_(wp.currentEstimateForRobust.has_value());
190  const TVector3D ri2 = wp.currentEstimateForRobust->composePoint(ri);
191 
192  // mismatch between the two vectors:
193  const double errorSqr = mrpt::square(ri2.x - bi.x) + mrpt::square(ri2.y - bi.y) +
194  mrpt::square(ri2.z - bi.z);
195  wi *= robustSqrtWeightFunc(errorSqr);
196  }
197 
198  ASSERT_(wi > .0);
199  w_sum += wi;
200 
201  // Visit this pair:
202  lambda_each_pair(bi, ri, wi);
203 
204  } // for each match
205 
206  in_out_outliers = std::move(new_outliers);
207 
208  lambda_final(w_sum);
209 
210  // send out optional stats
211  if (outStats.has_value()) outStats.value().get() = stats;
212 
213 } // end visit_correspondences()
214 
217 } // namespace mp2p_icp
mp2p_icp::Pairings::paired_ln2ln
MatchedLineList paired_ln2ln
Definition: Pairings.h:89
mp2p_icp
Definition: covariance.h:17
mp2p_icp::VisitCorrespondencesStats::num_pairings_discarded_scale_outliers
uint32_t num_pairings_discarded_scale_outliers
Definition: visit_correspondences.h:26
mp2p_icp::robust_sqrt_weight_func_t
std::function< double(double)> robust_sqrt_weight_func_t
Definition: robust_kernels.h:37
mp2p_icp::Pairings
Definition: Pairings.h:76
mp2p_icp::WeightParameters::use_scale_outlier_detector
bool use_scale_outlier_detector
Definition: WeightParameters.h:35
mp2p_icp::WeightParameters::pair_weights
PairWeights pair_weights
See docs for PairWeights.
Definition: WeightParameters.h:46
mp2p_icp::OutlierIndices::point2point
std::vector< std::size_t > point2point
Definition: Pairings.h:174
mp2p_icp::Pairings::point_weights
std::vector< std::pair< std::size_t, double > > point_weights
Definition: Pairings.h:102
mp2p_icp::WeightParameters::robust_kernel_param
double robust_kernel_param
Definition: WeightParameters.h:56
mp2p_icp::PairWeights::pl2pl
double pl2pl
Weight of plane-to-plane pairs.
Definition: PairWeights.h:38
mp2p_icp::create_robust_kernel
robust_sqrt_weight_func_t create_robust_kernel(const RobustKernel kernel, const double kernelParam)
Definition: robust_kernels.h:49
mp2p_icp::PairWeights::ln2ln
double ln2ln
Weight of line-to-line pairs.
Definition: PairWeights.h:37
Pairings.h
Common types for all SE(3) optimal transformation methods.
WeightParameters.h
Common types for all SE(3) optimal transformation methods.
mp2p_icp::WeightParameters::currentEstimateForRobust
std::optional< mrpt::poses::CPose3D > currentEstimateForRobust
Definition: WeightParameters.h:54
mp2p_icp::Pairings::paired_pl2pl
MatchedPlaneList paired_pl2pl
Definition: Pairings.h:90
mp2p_icp::WeightParameters::scale_outlier_threshold
double scale_outlier_threshold
Definition: WeightParameters.h:43
mp2p_icp::Pairings::paired_pt2ln
MatchedPointLineList paired_pt2ln
Definition: Pairings.h:87
mp2p_icp::WeightParameters
Definition: WeightParameters.h:26
mp2p_icp::OutlierIndices
Definition: Pairings.h:172
mp2p_icp::visit_correspondences
void visit_correspondences(const Pairings &in, const WeightParameters &wp, const mrpt::math::TPoint3D &ct_local, const mrpt::math::TPoint3D &ct_global, OutlierIndices &in_out_outliers, LAMBDA lambda_each_pair, LAMBDA2 lambda_final, bool normalize_relative_point_vectors, const mrpt::optional_ref< VisitCorrespondencesStats > &outStats=std::nullopt)
Definition: visit_correspondences.h:31
mp2p_icp::VisitCorrespondencesStats
Definition: visit_correspondences.h:24
mp2p_icp::Pairings::paired_pt2pt
mrpt::tfest::TMatchingPairList paired_pt2pt
Definition: Pairings.h:86
mp2p_icp::Pairings::paired_pt2pl
MatchedPointPlaneList paired_pt2pl
Definition: Pairings.h:88
mp2p_icp::WeightParameters::robust_kernel
RobustKernel robust_kernel
Definition: WeightParameters.h:50
mp2p_icp::PairWeights::pt2pt
double pt2pt
Definition: PairWeights.h:32


mp2p_icp
Author(s):
autogenerated on Mon May 26 2025 02:45:50