Matcher_Points_Base.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/random/random_shuffle.h>
15 
16 #include <chrono>
17 #include <numeric> // iota
18 #include <random>
19 
20 using namespace mp2p_icp;
21 
23  const metric_map_t& pcGlobal, const metric_map_t& pcLocal,
24  const mrpt::poses::CPose3D& localPose,
25  [[maybe_unused]] const MatchContext& mc, MatchState& ms,
26  Pairings& out) const
27 {
28  MRPT_START
29 
30  out = Pairings();
31 
32  // Analyze point cloud layers, one by one:
33  for (const auto& glLayerKV : pcGlobal.layers)
34  {
35  const auto& glLayerName = glLayerKV.first;
36 
37  // List of local layers to match against (and optional weights)
38  std::map<std::string, std::optional<double>> localLayers;
39 
40  if (!weight_pt2pt_layers.empty())
41  {
42  const auto itGlob = weight_pt2pt_layers.find(glLayerName);
43  // If we have weights and this layer is not listed, Skip it:
44  if (itGlob == weight_pt2pt_layers.end()) continue;
45 
46  for (const auto& kv : itGlob->second)
47  localLayers[kv.first] = kv.second;
48  }
49  else
50  {
51  // Default: match by identical layer names:
52  localLayers[glLayerName] = {};
53  }
54 
55  for (const auto& localWeight : localLayers)
56  {
57  const auto& localLayerName = localWeight.first;
58  const bool hasWeight = localWeight.second.has_value();
59 
60  // Look for a matching layer in "local":
61  auto itLocal = pcLocal.layers.find(localLayerName);
62  if (itLocal == pcLocal.layers.end())
63  {
64  // Silently ignore it:
65  if (!hasWeight)
66  continue;
67  else
68  THROW_EXCEPTION_FMT(
69  "Local pointcloud layer '%s' not found matching global "
70  "layer '%s'",
71  localLayerName.c_str(), glLayerName.c_str());
72  }
73 
74  const mrpt::maps::CMetricMap::Ptr& glLayer = glLayerKV.second;
75  ASSERT_(glLayer);
76 
77  const mrpt::maps::CMetricMap::Ptr& lcLayerMap = itLocal->second;
78  ASSERT_(lcLayerMap);
79  const auto lcLayer =
80  std::dynamic_pointer_cast<mrpt::maps::CPointsMap>(lcLayerMap);
81  if (!lcLayer)
82  THROW_EXCEPTION_FMT(
83  "Local layer map must be a point cloud, but found type "
84  "'%s'",
85  lcLayerMap->GetRuntimeClass()->className);
86 
87  const size_t nBefore = out.paired_pt2pt.size();
88 
89  // Ensure we have the KD-tree parameters desired by the user:
90  if (kdtree_leaf_max_points_.has_value())
91  {
92  if (const auto glLayerPts =
93  std::dynamic_pointer_cast<mrpt::maps::CPointsMap>(
94  glLayer);
95  glLayerPts &&
96  glLayerPts->kdtree_search_params.leaf_max_size !=
98  {
99  glLayerPts->kdtree_search_params.leaf_max_size =
101  glLayerPts->mark_as_modified(); // rebuild kd-tree index
102  }
103  }
104 
105  // matcher implementation:
107  *glLayer, *lcLayer, localPose, ms, glLayerName, localLayerName,
108  out);
109 
110  const size_t nAfter = out.paired_pt2pt.size();
111 
112  if (hasWeight && nAfter != nBefore)
113  {
114  const double w = localWeight.second.value();
115  out.point_weights.emplace_back(nAfter - nBefore, w);
116  }
117  }
118  }
119  return true;
120  MRPT_END
121 }
122 
123 void Matcher_Points_Base::initialize(const mrpt::containers::yaml& params)
124 {
125  Matcher::initialize(params);
126 
127  if (params.has("pointLayerMatches"))
128  {
129  auto& p = params["pointLayerMatches"];
130 
131  weight_pt2pt_layers.clear();
132  ASSERT_(p.isSequence());
133 
134  // - {global: "raw", local: "decimated", weight: 1.0}
135  // - {global: "raw", local: "decimated", weight: 1.0}
136  // ...
137 
138  for (const auto& entry : p.asSequence())
139  {
140  ASSERT_(entry.isMap());
141  const auto& em = entry.asMap();
142 
143  ASSERT_(em.count("global"));
144  ASSERT_(em.count("local"));
145 
146  const std::string globalLayer = em.at("global").as<std::string>();
147  const std::string localLayer = em.at("local").as<std::string>();
148  const double w =
149  em.count("weight") != 0 ? em.at("weight").as<double>() : 1.0;
150 
151  weight_pt2pt_layers[globalLayer][localLayer] = w;
152  }
153  }
154 
156  params.getOrDefault("maxLocalPointsPerLayer", maxLocalPointsPerLayer_);
157 
159  params.getOrDefault("localPointsSampleSeed", localPointsSampleSeed_);
160 
161  allowMatchAlreadyMatchedPoints_ = params.getOrDefault(
162  "allowMatchAlreadyMatchedPoints", allowMatchAlreadyMatchedPoints_);
163 
164  allowMatchAlreadyMatchedGlobalPoints_ = params.getOrDefault(
165  "allowMatchAlreadyMatchedGlobalPoints",
167 
168  if (auto val = params.getOrDefault("kdtree_leaf_max_points", 0); val > 0)
170 }
171 
174  const mrpt::maps::CPointsMap& pcLocal,
175  const mrpt::poses::CPose3D& localPose, const std::size_t maxLocalPoints,
176  const uint64_t localPointsSampleSeed)
177 {
178  MRPT_START
180 
181  const auto lambdaKeepBBox = [&](float x, float y, float z) {
182  mrpt::keep_max(r.localMax.x, x);
183  mrpt::keep_max(r.localMax.y, y);
184  mrpt::keep_max(r.localMax.z, z);
185 
186  mrpt::keep_min(r.localMin.x, x);
187  mrpt::keep_min(r.localMin.y, y);
188  mrpt::keep_min(r.localMin.z, z);
189  };
190 
191  const auto& lxs = pcLocal.getPointsBufferRef_x();
192  const auto& lys = pcLocal.getPointsBufferRef_y();
193  const auto& lzs = pcLocal.getPointsBufferRef_z();
194 
195  const size_t nLocalPoints = pcLocal.size();
196 
197  if (maxLocalPoints == 0 || nLocalPoints <= maxLocalPoints)
198  {
199  // All points:
200  r.x_locals.resize(nLocalPoints);
201  r.y_locals.resize(nLocalPoints);
202  r.z_locals.resize(nLocalPoints);
203 
204  for (size_t i = 0; i < nLocalPoints; i++)
205  {
206  localPose.composePoint(
207  lxs[i], lys[i], lzs[i], r.x_locals[i], r.y_locals[i],
208  r.z_locals[i]);
209  lambdaKeepBBox(r.x_locals[i], r.y_locals[i], r.z_locals[i]);
210  }
211  }
212  else
213  {
214  // random subset:
215  r.idxs.emplace(maxLocalPoints);
216  std::iota(r.idxs->begin(), r.idxs->end(), 0);
217 
218  const unsigned int seed =
219  localPointsSampleSeed != 0
220  ? localPointsSampleSeed
221  : std::chrono::system_clock::now().time_since_epoch().count();
222 
223  mrpt::random::partial_shuffle(
224  r.idxs->begin(), r.idxs->end(), std::default_random_engine(seed),
225  maxLocalPoints);
226 
227  r.x_locals.resize(maxLocalPoints);
228  r.y_locals.resize(maxLocalPoints);
229  r.z_locals.resize(maxLocalPoints);
230 
231  for (size_t ri = 0; ri < maxLocalPoints; ri++)
232  {
233  const auto i = (*r.idxs)[ri];
234  localPose.composePoint(
235  lxs[i], lys[i], lzs[i], r.x_locals[ri], r.y_locals[ri],
236  r.z_locals[ri]);
237  lambdaKeepBBox(r.x_locals[ri], r.y_locals[ri], r.z_locals[ri]);
238  }
239  }
240 
241  return r;
242  MRPT_END
243 }
mp2p_icp::Matcher_Points_Base::kdtree_leaf_max_points_
std::optional< std::size_t > kdtree_leaf_max_points_
Definition: Matcher_Points_Base.h:59
mp2p_icp
Definition: covariance.h:17
mp2p_icp::Matcher_Points_Base::TransformedLocalPointCloud
Definition: Matcher_Points_Base.h:82
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::weight_pt2pt_layers
std::map< std::string, std::map< std::string, double > > weight_pt2pt_layers
Definition: Matcher_Points_Base.h:45
mp2p_icp::Matcher_Points_Base::allowMatchAlreadyMatchedPoints_
bool allowMatchAlreadyMatchedPoints_
Definition: Matcher_Points_Base.h:52
test.x
x
Definition: test.py:4
testing::internal::string
::std::string string
Definition: gtest.h:1979
mp2p_icp::Matcher_Points_Base::implMatchOneLayer
virtual 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 =0
mp2p_icp::Matcher_Points_Base::initialize
void initialize(const mrpt::containers::yaml &params) override
Definition: Matcher_Points_Base.cpp:123
mp2p_icp::MatchState
Definition: Matcher.h:34
kitti-batch-convert.out
string out
Definition: kitti-batch-convert.py:7
mp2p_icp::MatchContext
Definition: Matcher.h:26
Matcher_Points_Base.h
Pointcloud matcher auxiliary class for iterating over point layers.
mp2p_icp::Matcher_Points_Base::localPointsSampleSeed_
uint64_t localPointsSampleSeed_
Definition: Matcher_Points_Base.h:48
mp2p_icp::Matcher_Points_Base::impl_match
bool impl_match(const metric_map_t &pcGlobal, const metric_map_t &pcLocal, const mrpt::poses::CPose3D &localPose, const MatchContext &mc, MatchState &ms, Pairings &out) const override final
Definition: Matcher_Points_Base.cpp:22
mp2p_icp::metric_map_t
Generic container of pointcloud(s), extracted features and other maps.
Definition: metricmap.h:47
mp2p_icp::Matcher_Points_Base::maxLocalPointsPerLayer_
uint64_t maxLocalPointsPerLayer_
Definition: Matcher_Points_Base.h:47
mp2p_icp::metric_map_t::layers
std::map< layer_name_t, mrpt::maps::CMetricMap::Ptr > layers
Definition: metricmap.h:74
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
mp2p_icp::Matcher::initialize
virtual void initialize(const mrpt::containers::yaml &params)
Definition: mp2p_icp/src/Matcher.cpp:20


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