Matcher_Points_DistanceThreshold.cpp
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-2021 Jose Luis Blanco, University of Almeria
4  * See LICENSE for license information.
5  * ------------------------------------------------------------------------- */
14 #include <mrpt/core/exceptions.h>
15 #include <mrpt/core/round.h>
16 #include <mrpt/version.h>
17 
19 
20 using namespace mp2p_icp;
21 
23 {
24  mrpt::system::COutputLogger::setLoggerName(
25  "Matcher_Points_DistanceThreshold");
26 }
27 
29  const mrpt::containers::yaml& params)
30 {
32 
33  MCP_LOAD_REQ(params, threshold);
34  MCP_LOAD_OPT(params, pairingsPerPoint);
35 
36  ASSERT_(pairingsPerPoint >= 1);
37 }
38 
40  const mrpt::maps::CMetricMap& pcGlobalMap,
41  const mrpt::maps::CPointsMap& pcLocal,
42  const mrpt::poses::CPose3D& localPose, MatchState& ms,
43  [[maybe_unused]] const layer_name_t& globalName,
44  const layer_name_t& localName, Pairings& out) const
45 {
46  MRPT_START
47 
48  const auto* pcGlobalPtr =
49  dynamic_cast<const mrpt::maps::CPointsMap*>(&pcGlobalMap);
50  if (!pcGlobalPtr)
51  THROW_EXCEPTION_FMT(
52  "This class only supports global maps of point cloud types, but "
53  "found type '%s'",
54  pcGlobalMap.GetRuntimeClass()->className);
55  const auto& pcGlobal = *pcGlobalPtr;
56 
57  // Empty maps? Nothing to do
58  if (pcGlobal.empty() || pcLocal.empty()) return;
59 
61  pcLocal, localPose, maxLocalPointsPerLayer_, localPointsSampleSeed_);
62 
63  // Try to do matching only if the bounding boxes have some overlap:
64  if (!pcGlobal.boundingBox().intersection({tl.localMin, tl.localMax}))
65  return;
66 
67  // Prepare output: no correspondences initially:
68  out.paired_pt2pt.reserve(out.paired_pt2pt.size() + pcLocal.size());
69 
70  // Loop for each point in local map:
71  // --------------------------------------------------
72  const float maxDistForCorrespondenceSquared = mrpt::square(threshold);
73 
74  const auto& gxs = pcGlobal.getPointsBufferRef_x();
75  const auto& gys = pcGlobal.getPointsBufferRef_y();
76  const auto& gzs = pcGlobal.getPointsBufferRef_z();
77 
78  const auto& lxs = pcLocal.getPointsBufferRef_x();
79  const auto& lys = pcLocal.getPointsBufferRef_y();
80  const auto& lzs = pcLocal.getPointsBufferRef_z();
81 
82  // In order to find the closest association for each global point, we must
83  // first build this temporary list of *potential* associations, indexed by
84  // global point indices, and sorted by errSqr:
85  std::map<size_t, std::map<float, mrpt::tfest::TMatchingPair>>
86  candidateMatchesForGlobal;
87 
88  const auto lambdaAddPair = [this, &candidateMatchesForGlobal, &lxs, &lys,
89  &lzs, &gxs, &gys, &gzs, &ms, &globalName](
90  const size_t localIdx,
91  const size_t globalIdx, const float errSqr) {
92  // Filter out if global alread assigned:
94  ms.globalPairedBitField.point_layers.at(globalName).at(globalIdx))
95  return; // skip, global point already paired.
96 
97  // Save new correspondence:
98  auto& p = candidateMatchesForGlobal[globalIdx][errSqr];
99 
100  p.globalIdx = globalIdx;
101  p.localIdx = localIdx;
102  p.global = {gxs[globalIdx], gys[globalIdx], gzs[globalIdx]};
103  p.local = {lxs[localIdx], lys[localIdx], lzs[localIdx]};
104 
105  p.errorSquareAfterTransformation = errSqr;
106  };
107 
108  // Declared out of the loop to avoid memory reallocations (!)
109  std::vector<size_t> neighborIndices;
110  std::vector<float> neighborSqrDists;
111 
112  for (size_t i = 0; i < tl.x_locals.size(); i++)
113  {
114  const size_t localIdx = tl.idxs.has_value() ? (*tl.idxs)[i] : i;
115 
117  ms.localPairedBitField.point_layers.at(localName).at(localIdx))
118  continue; // skip, already paired.
119 
120  // For speed-up:
121  const float lx = tl.x_locals[i], ly = tl.y_locals[i],
122  lz = tl.z_locals[i];
123 
124  // Use a KD-tree to look for the nearnest neighbor(s) of:
125  // (x_local, y_local, z_local)
126  // In "this" (global/reference) points map.
127  if (pairingsPerPoint == 1)
128  {
129  float tentativeErrSqr;
130  const size_t tentativeGlobalIdx = pcGlobal.kdTreeClosestPoint3D(
131  lx, ly, lz, // Look closest to this guy
132  tentativeErrSqr // save here the min. distance squared
133  );
134 
135  // Distance below the threshold??
136  if (tentativeErrSqr < maxDistForCorrespondenceSquared)
137  lambdaAddPair(localIdx, tentativeGlobalIdx, tentativeErrSqr);
138  } // End of test_match
139  else
140  {
141  pcGlobal.kdTreeNClosestPoint3DIdx(
142  lx, ly, lz, pairingsPerPoint, neighborIndices,
143  neighborSqrDists);
144 
145  // Distance below the threshold??
146  for (size_t k = 0; k < neighborIndices.size(); k++)
147  {
148  const auto tentativeErrSqr = neighborSqrDists.at(k);
149  if (tentativeErrSqr >= maxDistForCorrespondenceSquared)
150  break; // skip this and the rest.
151 
152  lambdaAddPair(localIdx, neighborIndices.at(k), tentativeErrSqr);
153  }
154  }
155  } // For each local point
156 
157  // Now, process candidates pairing and store them in `out.paired_pt2pt`:
158  for (const auto& kv : candidateMatchesForGlobal)
159  {
160  const auto globalIdx = kv.first;
161 
163  ms.globalPairedBitField.point_layers.at(globalName).at(globalIdx))
164  continue; // skip, global point already paired.
165 
166  const auto& pairs = kv.second;
167  ASSERT_(!pairs.empty());
168 
169  // take the one with the smallest error (std::map sorts them by sqrErr):
170  const auto& bestPair = pairs.begin()->second;
171 
172  out.paired_pt2pt.emplace_back(bestPair);
173 
174  // Mark local & global points as already paired:
175  const auto localIdx = bestPair.localIdx;
176  ms.localPairedBitField.point_layers[localName].at(localIdx) = true;
177  ms.globalPairedBitField.point_layers[globalName].at(globalIdx) = true;
178  }
179 
180  MRPT_END
181 }
mp2p_icp::Matcher_Points_DistanceThreshold::initialize
void initialize(const mrpt::containers::yaml &params) override
Definition: Matcher_Points_DistanceThreshold.cpp:28
mp2p_icp
Definition: covariance.h:17
mp2p_icp::Matcher_Points_Base::TransformedLocalPointCloud
Definition: Matcher_Points_Base.h:82
mp2p_icp::Matcher
Definition: Matcher.h:70
mp2p_icp::Matcher_Points_Base::TransformedLocalPointCloud::y_locals
mrpt::aligned_std_vector< float > y_locals
Definition: Matcher_Points_Base.h:92
mp2p_icp::Matcher_Points_Base::allowMatchAlreadyMatchedGlobalPoints_
bool allowMatchAlreadyMatchedGlobalPoints_
Definition: Matcher_Points_Base.h:56
mp2p_icp::Pairings
Definition: Pairings.h:94
mp2p_icp::Matcher_Points_Base::allowMatchAlreadyMatchedPoints_
bool allowMatchAlreadyMatchedPoints_
Definition: Matcher_Points_Base.h:52
mp2p_icp::Matcher_Points_DistanceThreshold::pairingsPerPoint
unsigned int pairingsPerPoint
Definition: Matcher_Points_DistanceThreshold.h:55
mp2p_icp::Matcher_Points_DistanceThreshold::Matcher_Points_DistanceThreshold
Matcher_Points_DistanceThreshold()
Definition: Matcher_Points_DistanceThreshold.cpp:22
mp2p_icp::layer_name_t
std::string layer_name_t
Definition: layer_name_t.h:22
mp2p_icp::Matcher_Points_DistanceThreshold
Definition: Matcher_Points_DistanceThreshold.h:30
mp2p_icp::Matcher_Points_DistanceThreshold::threshold
double threshold
Definition: Matcher_Points_DistanceThreshold.h:54
mp2p_icp::Matcher_Points_Base::TransformedLocalPointCloud::idxs
std::optional< std::vector< std::size_t > > idxs
Definition: Matcher_Points_Base.h:89
mp2p_icp::Matcher_Points_DistanceThreshold::implMatchOneLayer
void implMatchOneLayer(const mrpt::maps::CMetricMap &pcGlobal, const mrpt::maps::CPointsMap &pcLocal, const mrpt::poses::CPose3D &localPose, MatchState &ms, const layer_name_t &globalName, const layer_name_t &localName, Pairings &out) const override
Definition: Matcher_Points_DistanceThreshold.cpp:39
mp2p_icp::Matcher_Points_Base::initialize
void initialize(const mrpt::containers::yaml &params) override
Definition: Matcher_Points_Base.cpp:123
mp2p_icp::Matcher_Points_Base::TransformedLocalPointCloud::z_locals
mrpt::aligned_std_vector< float > z_locals
Definition: Matcher_Points_Base.h:92
mp2p_icp::MatchState
Definition: Matcher.h:34
kitti-batch-convert.out
string out
Definition: kitti-batch-convert.py:7
Matcher_Points_DistanceThreshold.h
Pointcloud matcher: fixed distance thresholds.
mp2p_icp::Matcher_Points_Base::localPointsSampleSeed_
uint64_t localPointsSampleSeed_
Definition: Matcher_Points_Base.h:48
mp2p_icp::Matcher_Points_Base::maxLocalPointsPerLayer_
uint64_t maxLocalPointsPerLayer_
Definition: Matcher_Points_Base.h:47
IMPLEMENTS_MRPT_OBJECT
IMPLEMENTS_MRPT_OBJECT(metric_map_t, mrpt::serialization::CSerializable, mp2p_icp) using namespace mp2p_icp
mp2p_icp::Matcher_Points_Base::TransformedLocalPointCloud::x_locals
mrpt::aligned_std_vector< float > x_locals
Definition: Matcher_Points_Base.h:92
mp2p_icp::Matcher_Points_Base::transform_local_to_global
static TransformedLocalPointCloud transform_local_to_global(const mrpt::maps::CPointsMap &pcLocal, const mrpt::poses::CPose3D &localPose, const std::size_t maxLocalPoints=0, const uint64_t localPointsSampleSeed=0)
Definition: Matcher_Points_Base.cpp:173


mrpt_local_obstacles
Author(s): Jose-Luis Blanco-Claraco
autogenerated on Mon Aug 14 2023 02:09:03