14 #include <mrpt/random/random_shuffle.h> 24 const mrpt::poses::CPose3D& localPose,
33 for (
const auto& glLayerKV : pcGlobal.
layers)
35 const auto& glLayerName = glLayerKV.first;
38 std::map<std::string, std::optional<double>> localLayers;
46 for (
const auto& kv : itGlob->second)
47 localLayers[kv.first] = kv.second;
52 localLayers[glLayerName] = {};
55 for (
const auto& localWeight : localLayers)
57 const auto& localLayerName = localWeight.first;
58 const bool hasWeight = localWeight.second.has_value();
61 auto itLocal = pcLocal.
layers.find(localLayerName);
62 if (itLocal == pcLocal.
layers.end())
69 "Local pointcloud layer '%s' not found matching global " 71 localLayerName.c_str(), glLayerName.c_str());
74 const mrpt::maps::CMetricMap::Ptr& glLayer = glLayerKV.second;
77 const mrpt::maps::CMetricMap::Ptr& lcLayerMap = itLocal->second;
80 std::dynamic_pointer_cast<mrpt::maps::CPointsMap>(lcLayerMap);
83 "Local layer map must be a point cloud, but found type " 85 lcLayerMap->GetRuntimeClass()->className);
87 const size_t nBefore = out.paired_pt2pt.size();
92 if (
const auto glLayerPts =
93 std::dynamic_pointer_cast<mrpt::maps::CPointsMap>(
96 glLayerPts->kdtree_search_params.leaf_max_size !=
99 glLayerPts->kdtree_search_params.leaf_max_size =
101 glLayerPts->mark_as_modified();
107 *glLayer, *lcLayer, localPose, ms, glLayerName, localLayerName,
110 const size_t nAfter = out.paired_pt2pt.size();
112 if (hasWeight && nAfter != nBefore)
114 const double w = localWeight.second.value();
115 out.point_weights.emplace_back(nAfter - nBefore, w);
127 if (params.has(
"pointLayerMatches"))
129 auto& p = params[
"pointLayerMatches"];
132 ASSERT_(p.isSequence());
138 for (
const auto& entry : p.asSequence())
140 ASSERT_(entry.isMap());
141 const auto& em = entry.asMap();
143 ASSERT_(em.count(
"global"));
144 ASSERT_(em.count(
"local"));
149 em.count(
"weight") != 0 ? em.at(
"weight").as<
double>() : 1.0;
165 "allowMatchAlreadyMatchedGlobalPoints",
168 if (
auto val = params.getOrDefault(
"kdtree_leaf_max_points", 0); val > 0)
174 const mrpt::maps::CPointsMap& pcLocal,
175 const mrpt::poses::CPose3D& localPose,
const std::size_t maxLocalPoints,
176 const uint64_t localPointsSampleSeed)
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);
186 mrpt::keep_min(r.localMin.x, x);
187 mrpt::keep_min(r.localMin.y, y);
188 mrpt::keep_min(r.localMin.z, z);
191 const auto& lxs = pcLocal.getPointsBufferRef_x();
192 const auto& lys = pcLocal.getPointsBufferRef_y();
193 const auto& lzs = pcLocal.getPointsBufferRef_z();
195 const size_t nLocalPoints = pcLocal.size();
197 if (maxLocalPoints == 0 || nLocalPoints <= maxLocalPoints)
200 r.x_locals.resize(nLocalPoints);
201 r.y_locals.resize(nLocalPoints);
202 r.z_locals.resize(nLocalPoints);
204 for (
size_t i = 0; i < nLocalPoints; i++)
206 localPose.composePoint(
207 lxs[i], lys[i], lzs[i], r.x_locals[i], r.y_locals[i],
209 lambdaKeepBBox(r.x_locals[i], r.y_locals[i], r.z_locals[i]);
215 r.idxs.emplace(maxLocalPoints);
216 std::iota(r.idxs->begin(), r.idxs->end(), 0);
218 const unsigned int seed =
219 localPointsSampleSeed != 0
220 ? localPointsSampleSeed
221 : std::chrono::system_clock::now().time_since_epoch().count();
223 mrpt::random::partial_shuffle(
224 r.idxs->begin(), r.idxs->end(), std::default_random_engine(seed),
227 r.x_locals.resize(maxLocalPoints);
228 r.y_locals.resize(maxLocalPoints);
229 r.z_locals.resize(maxLocalPoints);
231 for (
size_t ri = 0; ri < maxLocalPoints; ri++)
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],
237 lambdaKeepBBox(r.x_locals[ri], r.y_locals[ri], r.z_locals[ri]);
std::map< layer_name_t, mrpt::maps::CMetricMap::Ptr > layers
Pointcloud matcher auxiliary class for iterating over point layers.
bool allowMatchAlreadyMatchedPoints_
Generic container of pointcloud(s), extracted features and other maps.
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)
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
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
uint64_t maxLocalPointsPerLayer_
std::optional< std::size_t > kdtree_leaf_max_points_
uint64_t localPointsSampleSeed_
void initialize(const mrpt::containers::yaml ¶ms) override
bool allowMatchAlreadyMatchedGlobalPoints_
std::map< std::string, std::map< std::string, double > > weight_pt2pt_layers
virtual void initialize(const mrpt::containers::yaml ¶ms)