Generator.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-2024 Jose Luis Blanco, University of Almeria
4  * See LICENSE for license information.
5  * ------------------------------------------------------------------------- */
16 #include <mrpt/config/CConfigFile.h>
17 #include <mrpt/config/CConfigFileMemory.h>
18 #include <mrpt/containers/yaml.h>
19 #include <mrpt/core/get_env.h>
20 #include <mrpt/maps/CMultiMetricMap.h>
21 #include <mrpt/maps/CPointsMapXYZIRT.h>
22 #include <mrpt/maps/CSimplePointsMap.h>
23 #include <mrpt/obs/CObservation2DRangeScan.h>
24 #include <mrpt/obs/CObservation3DRangeScan.h>
25 #include <mrpt/obs/CObservationPointCloud.h>
26 #include <mrpt/obs/CObservationRotatingScan.h>
27 #include <mrpt/obs/CObservationVelodyneScan.h>
28 #include <mrpt/obs/CSensoryFrame.h>
29 #include <mrpt/system/filesystem.h>
30 
31 #include <filesystem>
32 namespace fs = std::filesystem;
33 
34 #if defined(__unix__)
35 #include <dlfcn.h>
36 #endif
37 
39 
40 using namespace mp2p_icp_filters;
41 
42 Generator::Generator() : mrpt::system::COutputLogger("Generator") {}
43 
44 void Generator::Parameters::load_from_yaml(const mrpt::containers::yaml& c, Generator& parent)
45 {
46  using namespace std::string_literals;
47 
48  MCP_LOAD_OPT(c, target_layer);
49  MCP_LOAD_OPT(c, metric_map_definition_ini_file);
50  MCP_LOAD_OPT(c, process_class_names_regex);
51  MCP_LOAD_OPT(c, process_sensor_labels_regex);
52  MCP_LOAD_OPT(c, throw_on_unhandled_observation_class);
53 
54  if (c.has("metric_map_definition"))
55  {
56  // Store values here:
57  auto& trg = metric_map_definition;
58 
59  const std::set<std::string> allowedTopKeys = {"class", "plugin"};
60 
61  ASSERT_(c["metric_map_definition"].isMap());
62  const auto mmd = c["metric_map_definition"].asMap();
63  for (const auto& [k, v] : mmd)
64  {
65  const auto key = k.as<std::string>();
66  if (v.isNullNode())
67  {
68  continue; // ignore
69  }
70  if (v.isScalar())
71  {
72  if (allowedTopKeys.count(key) != 0)
73  {
74  // simple key=value:
75  ASSERT_(v.isScalar());
76  trg[key] = v.as<std::string>();
77  continue;
78  }
79 
80  THROW_EXCEPTION_FMT("scalar key '%s' not allowed here.", key.c_str());
81  }
82  // if should then be a map
83  if (!v.isMap())
84  {
85  THROW_EXCEPTION_FMT("key '%s' must be either a scalar or a map", key.c_str());
86  }
87 
88  trg[key] = mrpt::containers::yaml::Map();
89  auto& newMap = trg.asMap().at(key).asMap();
90 
91  for (const auto& [kk, vv] : v.asMap())
92  {
93  const std::string val = vv.as<std::string>();
94  // Special case: handle parameterizable formulas:
95  if (val.substr(0, 3) == "$f{"s)
96  {
97  ASSERTMSG_(val.back() == '}', "Missing '}' in '$f{' formula");
98 
99  const auto ks = kk.as<std::string>();
100 
101  auto [it, exist] = newMap.insert({ks, .0});
102  double& placeholder = *std::any_cast<double>(&it->second.asScalar());
103 
104  parent.parseAndDeclareParameter(val.substr(3, val.size() - 4), placeholder);
105  }
106  else
107  {
108  // regular entry:
109  newMap[kk.as<std::string>()] = val;
110  }
111  }
112  }
113 
114  std::stringstream ss;
115  ss << "Using this metric_map_definition:\n"s << metric_map_definition;
116  parent.logStr(mrpt::system::LVL_DEBUG, ss.str());
117  }
118 }
119 
120 void Generator::initialize(const mrpt::containers::yaml& c)
121 {
122  MRPT_START
123 
124  MRPT_LOG_DEBUG_STREAM("Loading these params:\n" << c);
125  params_.load_from_yaml(c, *this);
126 
129 
130  initialized_ = true;
131  MRPT_END
132 }
133 
135  const mrpt::obs::CObservation& o, mp2p_icp::metric_map_t& out,
136  const std::optional<mrpt::poses::CPose3D>& robotPose) const
137 {
138  MRPT_START
139 
140  Parameterizable::checkAllParametersAreRealized();
141 
142  ASSERTMSG_(initialized_, "initialize() must be called once before using process().");
143 
144  const auto obsClassName = o.GetRuntimeClass()->className;
145 
146  MRPT_LOG_DEBUG_FMT(
147  "Processing observation type='%s' label='%s'", obsClassName, o.sensorLabel.c_str());
148 
149  // default: use point clouds:
151  {
152  return implProcessDefault(o, out, robotPose);
153  }
154  return implProcessCustomMap(o, out, robotPose);
155 
156  MRPT_END
157 }
158 
160  [[maybe_unused]] const mrpt::obs::CObservation2DRangeScan& pc,
161  [[maybe_unused]] mp2p_icp::metric_map_t& out,
162  [[maybe_unused]] const std::optional<mrpt::poses::CPose3D>& robotPose) const
163 {
164  return false; // Not implemented
165 }
166 
168  const mrpt::obs::CObservationVelodyneScan& pc, mp2p_icp::metric_map_t& out,
169  const std::optional<mrpt::poses::CPose3D>& robotPose) const
170 {
171  mrpt::maps::CPointsMap::Ptr outPc = GetOrCreatePointLayer(
172  out, params_.target_layer, false /*does not allow empty name*/,
173  "mrpt::maps::CPointsMapXYZIRT" /* creation class if not existing */);
174  ASSERT_(outPc);
175 
176  auto m = std::dynamic_pointer_cast<mrpt::maps::CPointsMapXYZIRT>(outPc);
177  ASSERTMSG_(
178  m,
179  "Output layer must be of type mrpt::maps::CPointsMapXYZIRT for the "
180  "specialized filterVelodyneScan() generator.");
181 
182  m->insertObservation(pc, robotPose);
183 
184  return true; // implemented
185 }
186 
188  [[maybe_unused]] const mrpt::obs::CObservation3DRangeScan& pc,
189  [[maybe_unused]] mp2p_icp::metric_map_t& out,
190  [[maybe_unused]] const std::optional<mrpt::poses::CPose3D>& robotPose) const
191 {
192  return false; // Not implemented
193 }
194 
196  const mrpt::maps::CPointsMap& pc, const mrpt::poses::CPose3D& sensorPose,
197  mp2p_icp::metric_map_t& out, const std::optional<mrpt::poses::CPose3D>& robotPose) const
198 {
199  // Create if new: Append to existing layer, if already existed.
200  mrpt::maps::CPointsMap::Ptr outPc;
201  if (auto itLy = out.layers.find(params_.target_layer); itLy != out.layers.end())
202  {
203  outPc = std::dynamic_pointer_cast<mrpt::maps::CPointsMap>(itLy->second);
204  if (!outPc)
205  {
206  THROW_EXCEPTION_FMT(
207  "Layer '%s' must be of point cloud type.", params_.target_layer.c_str());
208  }
209  }
210  else
211  {
212  // Make a new layer of the same type than the input cloud:
213  outPc = std::dynamic_pointer_cast<mrpt::maps::CPointsMap>(
214  pc.GetRuntimeClass()->ptrCreateObject());
215  ASSERT_(outPc);
216 
217  MRPT_LOG_DEBUG_FMT(
218  "[filterPointCloud] Created new layer '%s' of type '%s'", params_.target_layer.c_str(),
219  outPc->GetRuntimeClass()->className);
220 
221  out.layers[params_.target_layer] = outPc;
222  }
223 
224  const mrpt::poses::CPose3D p = robotPose ? robotPose.value() + sensorPose : sensorPose;
225 
226  outPc->insertAnotherMap(&pc, p);
227 
228  const bool sanityPassed = mp2p_icp::pointcloud_sanity_check(*outPc);
229  ASSERT_(sanityPassed);
230 
231  return true;
232 }
233 
235  [[maybe_unused]] const mrpt::obs::CObservationRotatingScan& pc,
236  [[maybe_unused]] mp2p_icp::metric_map_t& out,
237  [[maybe_unused]] const std::optional<mrpt::poses::CPose3D>& robotPose) const
238 {
239  return false; // Not implemented
240 }
241 
243  const GeneratorSet& generators, const mrpt::obs::CObservation& obs,
244  mp2p_icp::metric_map_t& output, const std::optional<mrpt::poses::CPose3D>& robotPose)
245 {
246  ASSERT_(!generators.empty());
247  bool anyHandled = false;
248  for (const auto& g : generators)
249  {
250  ASSERT_(g.get() != nullptr);
251  bool handled = g->process(obs, output, robotPose);
252  anyHandled = anyHandled || handled;
253  }
254  return anyHandled;
255 }
256 
258  const GeneratorSet& generators, const mrpt::obs::CObservation& obs,
259  const std::optional<mrpt::poses::CPose3D>& robotPose)
260 {
262  apply_generators(generators, obs, pc, robotPose);
263  return pc;
264 }
265 
267  const GeneratorSet& generators, const mrpt::obs::CSensoryFrame& sf,
268  const std::optional<mrpt::poses::CPose3D>& robotPose)
269 {
271  apply_generators(generators, sf, pc, robotPose);
272  return pc;
273 }
274 
276  const GeneratorSet& generators, const mrpt::obs::CSensoryFrame& sf,
277  mp2p_icp::metric_map_t& output, const std::optional<mrpt::poses::CPose3D>& robotPose)
278 {
279  ASSERT_(!generators.empty());
280  bool anyHandled = false;
281  for (const auto& g : generators)
282  {
283  ASSERT_(g.get() != nullptr);
284  for (const auto& obs : sf)
285  {
286  if (!obs)
287  {
288  continue;
289  }
290  const bool handled = g->process(*obs, output, robotPose);
291 
292  anyHandled = anyHandled || handled;
293  }
294  }
295  return anyHandled;
296 }
297 
299  const mrpt::containers::yaml& c, const mrpt::system::VerbosityLevel& vLevel)
300 {
301  if (c.isNullNode())
302  {
303  return {};
304  }
305 
306  ASSERT_(c.isSequence());
307 
309 
310  for (const auto& entry : c.asSequence())
311  {
312  const auto& e = entry.asMap();
313 
314  const auto sClass = e.at("class_name").as<std::string>();
315  auto o = mrpt::rtti::classFactory(sClass);
316  ASSERT_(o);
317 
318  auto f = std::dynamic_pointer_cast<Generator>(o);
319  ASSERTMSG_(
320  f, mrpt::format("`%s` class seems not to be derived from Generator", sClass.c_str()));
321 
322  f->setMinLoggingLevel(vLevel);
323 
324  f->initialize(e.at("params"));
325  generators.push_back(f);
326  }
327 
328  return generators;
329 }
330 
332  const std::string& filename, const mrpt::system::VerbosityLevel& vLevel)
333 {
334  const auto yamlContent = mrpt::containers::yaml::FromFile(filename);
335 
336  ASSERT_(yamlContent.has("generators") && yamlContent["generators"].isSequence());
337 
338  return generators_from_yaml(yamlContent["generators"], vLevel);
339 }
340 
342  const mrpt::obs::CObservation& o, mp2p_icp::metric_map_t& out,
343  const std::optional<mrpt::poses::CPose3D>& robotPose) const
344 {
345  using namespace mrpt::obs;
346  using namespace std::string_literals;
347 
348  bool processed = false;
349 
350  const auto obsClassName = o.GetRuntimeClass()->className;
351 
352  // user-given filters: Done *AFTER* creating the map, if needed.
353  if (obsClassName == "mrpt::obs::CObservationComment"s ||
354  obsClassName == "mrpt::obs::CObservationGPS"s ||
355  obsClassName == "mrpt::obs::CObservationRobotPose"s ||
356  !std::regex_match(obsClassName, process_class_names_regex_) ||
357  !std::regex_match(o.sensorLabel, process_sensor_labels_regex_))
358  {
359  MRPT_LOG_DEBUG_STREAM(
360  "Skipping observation of type '" << obsClassName << "' with label '" << o.sensorLabel
361  << "'.");
362  return false;
363  }
364 
365  // load lazy-load from disk:
366  o.load();
367 
368  if (auto oRS = dynamic_cast<const CObservationRotatingScan*>(&o); oRS)
369  {
370  processed = filterRotatingScan(*oRS, out, robotPose);
371  }
372  else if (auto o0 = dynamic_cast<const CObservationPointCloud*>(&o); o0)
373  {
374  ASSERT_(o0->pointcloud);
375  processed = filterPointCloud(*o0->pointcloud, o0->sensorPose, out, robotPose);
376  }
377  else if (auto o1 = dynamic_cast<const CObservation2DRangeScan*>(&o); o1)
378  {
379  processed = filterScan2D(*o1, out, robotPose);
380  }
381  else if (auto o2 = dynamic_cast<const CObservation3DRangeScan*>(&o); o2)
382  {
383  processed = filterScan3D(*o2, out, robotPose);
384  }
385  else if (auto o3 = dynamic_cast<const CObservationVelodyneScan*>(&o); o3)
386  {
387  processed = filterVelodyneScan(*o3, out, robotPose);
388  }
389 
390  // done?
391  if (processed)
392  {
393  // o.unload(); // DON'T! We don't know who else is using the data
394  return true; // we are done.
395  }
396 
397  // Create if new: Append to existing layer, if already existed.
398  mrpt::maps::CPointsMap::Ptr outPc = GetOrCreatePointLayer(
399  out, params_.target_layer, false /*does not allow empty name*/,
400  "mrpt::maps::CSimplePointsMap" /* creation class if not existing */);
401 
402  ASSERT_(outPc);
403 
404  MRPT_LOG_DEBUG_FMT(
405  "Using output layer '%s' of type '%s'", params_.target_layer.c_str(),
406  outPc->GetRuntimeClass()->className);
407 
408  // Observation format:
409 
410  // Special case:
411  // unproject 3D points, if needed:
412  if (auto obs3D = dynamic_cast<const mrpt::obs::CObservation3DRangeScan*>(&o);
413  obs3D && obs3D->points3D_x.empty())
414  {
415  mrpt::maps::CSimplePointsMap tmpMap;
416 
417  mrpt::obs::T3DPointsProjectionParams pp;
418  pp.takeIntoAccountSensorPoseOnRobot = true;
419  pp.robotPoseInTheWorld = robotPose;
420  const_cast<mrpt::obs::CObservation3DRangeScan*>(obs3D)->unprojectInto(tmpMap, pp);
421 
422  outPc->insertAnotherMap(&tmpMap, mrpt::poses::CPose3D::Identity());
423 
424  return true;
425  }
426 
427  // General case:
428  const bool insertDone = o.insertObservationInto(*outPc, robotPose);
429 
431  {
432  THROW_EXCEPTION_FMT(
433  "Observation of type '%s' could not be converted into a "
434  "point cloud, and none of the specializations handled it, "
435  "so I do not know what to do with this observation!",
436  obsClassName);
437  }
438  return insertDone;
439 
440  // o.unload(); // DON'T! We don't know who else is using the data
441 }
442 
444  const mrpt::obs::CObservation& o, mp2p_icp::metric_map_t& out,
445  const std::optional<mrpt::poses::CPose3D>& robotPose) const
446 {
447  using namespace std::string_literals;
448 
449  const auto obsClassName = o.GetRuntimeClass()->className;
450 
451  // Create if new: Append to existing layer, if already existed.
452  mrpt::maps::CMetricMap::Ptr outMap;
453 
454  if (auto itLy = out.layers.find(params_.target_layer); itLy != out.layers.end())
455  {
456  outMap = itLy->second;
457  }
458  else
459  {
460  // insert new layer:
461  mrpt::maps::TSetOfMetricMapInitializers mapInits;
462 
463  const std::string cfgPrefix = "map"s;
464 
465  // Create from either a INI file or the YAML version of it:
467  {
468  // Load from INI file
469  // ------------------------------
470  ASSERT_FILE_EXISTS_(params_.metric_map_definition_ini_file);
471  mrpt::config::CConfigFile cfg(params_.metric_map_definition_ini_file);
472  mapInits.loadFromConfigFile(cfg, cfgPrefix);
473  }
474  else
475  {
476  // Load from YAML file (with parameterizable values)
477  // ------------------------------------------------------
478  ASSERT_(!params_.metric_map_definition.empty());
479  const auto& c = params_.metric_map_definition;
480 
481  // Build an in-memory INI file with the structure expected by
482  // loadFromConfigFile():
483  mrpt::config::CConfigFileMemory cfg;
484 
485  ASSERT_(c.has("class"));
486  const std::string mapClass = c["class"].as<std::string>();
487  cfg.write(cfgPrefix, mapClass + "_count"s, "1");
488 
489  // optional plugin module?
490  if (c.has("plugin"))
491  {
492  const auto moduleToLoad = c["plugin"].as<std::string>();
493  MRPT_LOG_DEBUG_STREAM("About to load user-defined plugin: " << moduleToLoad);
494  internalLoadUserPlugin(moduleToLoad);
495  }
496 
497  // fill the rest sub-sections:
498  for (const auto& [k, v] : c.asMap())
499  {
500  if (!v.isMap())
501  {
502  continue;
503  }
504  const auto keyVal = k.as<std::string>();
505  const auto sectName = cfgPrefix + "_"s + mapClass + "_00_"s + keyVal;
506  for (const auto& [kk, vv] : v.asMap())
507  {
508  ASSERT_(kk.isScalar());
509  ASSERT_(vv.isScalar());
510 
511  cfg.write(sectName, kk.as<std::string>(), vv.as<std::string>());
512  }
513  }
514 
515  MRPT_LOG_DEBUG_STREAM(
516  "Built INI-like block for layer '" << params_.target_layer << "':\n"
517  << cfg.getContent());
518 
519  // parse it:
520  mapInits.loadFromConfigFile(cfg, cfgPrefix);
521  }
522 
523  // create the map:
524  mrpt::maps::CMultiMetricMap theMap;
525  theMap.setListOfMaps(mapInits);
526 
527  ASSERT_(theMap.maps.size() >= 1);
528  outMap = theMap.maps.at(0);
529 
530  out.layers[params_.target_layer] = outMap;
531  }
532 
533  ASSERT_(outMap);
534 
535  // user-given filters: Done *AFTER* creating the map, if needed.
536  if (obsClassName == "mrpt::obs::CObservationComment"s ||
537  !std::regex_match(obsClassName, process_class_names_regex_) ||
538  !std::regex_match(o.sensorLabel, process_sensor_labels_regex_))
539  {
540  MRPT_LOG_DEBUG_STREAM(
541  "Skipping observation of type '" << obsClassName << "' with label '" << o.sensorLabel
542  << "'.");
543  return false;
544  }
545 
546  // Observation format:
547  o.load();
548 
549  // Use virtual insert method:
550  const bool insertDone = o.insertObservationInto(*outMap, robotPose);
551 
553  {
554  THROW_EXCEPTION_FMT(
555  "Observation of type '%s' could not be converted inserted into "
556  "the map of type '%s', so I do not know what to do with this "
557  "observation!",
558  obsClassName, outMap->GetRuntimeClass()->className);
559  }
560 
561  // o.unload(); // DON'T! We don't know who else is using the data
562  return insertDone; // handled
563 }
564 
565 namespace
566 {
567 void safe_add_to_list(const std::string& path, std::vector<std::string>& lst)
568 {
569  if (mrpt::system::directoryExists(path))
570  {
571  lst.push_back(path);
572  }
573 }
574 
575 void from_env_var_to_list(
576  const std::string& env_var_name, std::vector<std::string>& lst,
577  const std::string& subStringPattern = {})
578 {
579 #if defined(_WIN32)
580  const auto delim = std::string(";");
581 #else
582  const auto delim = std::string(":");
583 #endif
584 
585  const auto additionalPaths = mrpt::get_env<std::string>(env_var_name);
586  std::vector<std::string> pathList;
587  mrpt::system::tokenize(additionalPaths, delim, pathList);
588 
589  // Append to list:
590  for (const auto& path : pathList)
591  {
592  if (!subStringPattern.empty() && path.find(subStringPattern) == std::string::npos)
593  {
594  continue;
595  }
596  safe_add_to_list(path, lst);
597  }
598 }
599 } // namespace
600 
601 void Generator::internalLoadUserPlugin(const std::string& moduleToLoad) const
602 {
603  std::string absPath;
604 
605  if (!fs::path(moduleToLoad).is_relative())
606  {
607  // already absolute:
608  ASSERT_FILE_EXISTS_(moduleToLoad);
609  absPath = moduleToLoad;
610  }
611  else
612  {
613  // search for it:
614  std::vector<std::string> lstPath;
615  from_env_var_to_list("LD_LIBRARY_PATH", lstPath);
616 
617  for (const auto& p : lstPath)
618  {
619  const auto fp = mrpt::system::pathJoin({p, moduleToLoad});
620  if (mrpt::system::fileExists(fp))
621  {
622  absPath = fp;
623  break;
624  }
625  }
626  if (absPath.empty())
627  {
628  THROW_EXCEPTION_FMT(
629  "Could not find '%s' anywhere under the LD_LIBRARY_PATH paths",
630  moduleToLoad.c_str());
631  }
632  }
633 
634 #if defined(__unix__)
635  // Check if already loaded?
636  {
637  void* handle = dlopen(absPath.c_str(), RTLD_NOLOAD);
638  if (handle != nullptr)
639  {
640  return; // skip. already loaded.
641  }
642  }
643  void* handle = dlopen(absPath.c_str(), RTLD_LAZY);
644 
645 #else
646  HMODULE handle = LoadLibrary(absPath.c_str());
647 #endif
648  if (handle == nullptr)
649  {
650  const char* err = dlerror();
651  if (!err)
652  {
653  err = "(error calling dlerror())";
654  }
655  THROW_EXCEPTION(
656  mrpt::format("Error loading module: `%s`\ndlerror(): `%s`", absPath.c_str(), err));
657  }
658 
659  MRPT_LOG_DEBUG_FMT("Successfully loaded: `%s`", absPath.c_str());
660 }
mp2p_icp_filters::Generator::Parameters::metric_map_definition_ini_file
std::string metric_map_definition_ini_file
Definition: Generator.h:123
mp2p_icp_filters::Generator::internalLoadUserPlugin
void internalLoadUserPlugin(const std::string &moduleToLoad) const
Definition: Generator.cpp:601
mp2p_icp_filters::Generator::filterPointCloud
virtual bool filterPointCloud(const mrpt::maps::CPointsMap &pc, const mrpt::poses::CPose3D &sensorPose, mp2p_icp::metric_map_t &out, const std::optional< mrpt::poses::CPose3D > &robotPose) const
Definition: Generator.cpp:195
generators
static mp2p_icp_filters::GeneratorSet generators
Definition: apps/icp-run/main.cpp:130
mp2p_icp_filters::Generator::initialize
virtual void initialize(const mrpt::containers::yaml &cfg_block)
Definition: Generator.cpp:120
s
XmlRpcServer s
kitti-run-seq.f
string f
Definition: kitti-run-seq.py:12
mp2p_icp_filters::Generator
Definition: Generator.h:71
mp2p_icp_filters::Generator::Parameters::metric_map_definition
mrpt::containers::yaml metric_map_definition
Definition: Generator.h:130
mp2p_icp_filters::Generator::filterScan2D
virtual bool filterScan2D(const mrpt::obs::CObservation2DRangeScan &pc, mp2p_icp::metric_map_t &out, const std::optional< mrpt::poses::CPose3D > &robotPose) const
Definition: Generator.cpp:159
mp2p_icp_filters::Generator::filterScan3D
virtual bool filterScan3D(const mrpt::obs::CObservation3DRangeScan &pc, mp2p_icp::metric_map_t &out, const std::optional< mrpt::poses::CPose3D > &robotPose) const
Definition: Generator.cpp:187
mp2p_icp_filters::Generator::initialized_
bool initialized_
Definition: Generator.h:173
mrpt
Definition: LogRecord.h:100
mp2p_icp_filters::Generator::implProcessCustomMap
bool implProcessCustomMap(const mrpt::obs::CObservation &o, mp2p_icp::metric_map_t &out, const std::optional< mrpt::poses::CPose3D > &robotPose=std::nullopt) const
Definition: Generator.cpp:443
mp2p_icp::pointcloud_sanity_check
bool pointcloud_sanity_check(const mrpt::maps::CPointsMap &pc, bool printWarnings=true)
Definition: pointcloud_sanity_check.cpp:19
pointcloud_sanity_check.h
Checks for consistent length of field vectors.
mp2p_icp_filters::Generator::process_class_names_regex_
std::regex process_class_names_regex_
Definition: Generator.h:174
mp2p_icp_filters::Generator::Parameters::process_class_names_regex
std::string process_class_names_regex
Definition: Generator.h:136
testing::internal::string
::std::string string
Definition: gtest.h:1979
mp2p_icp_filters::Generator::params_
Parameters params_
Definition: Generator.h:146
Generator.h
Base virtual class for point cloud filters.
IMPLEMENTS_MRPT_OBJECT
IMPLEMENTS_MRPT_OBJECT(FilterDecimateVoxelsQuadratic, mp2p_icp_filters::FilterBase, mp2p_icp_filters) using namespace mp2p_icp_filters
kitti-batch-convert.out
string out
Definition: kitti-batch-convert.py:7
mp2p_icp_filters::Generator::filterVelodyneScan
virtual bool filterVelodyneScan(const mrpt::obs::CObservationVelodyneScan &pc, mp2p_icp::metric_map_t &out, const std::optional< mrpt::poses::CPose3D > &robotPose) const
Definition: Generator.cpp:167
kitti-run-seq.cfg
cfg
Definition: kitti-run-seq.py:7
mp2p_icp_filters::Generator::Parameters::throw_on_unhandled_observation_class
bool throw_on_unhandled_observation_class
Definition: Generator.h:143
mp2p_icp_filters::Generator::Parameters::load_from_yaml
void load_from_yaml(const mrpt::containers::yaml &c, Generator &parent)
Definition: Generator.cpp:44
mp2p_icp_filters::Generator::Parameters::target_layer
std::string target_layer
Definition: Generator.h:104
mp2p_icp_filters::GeneratorSet
std::vector< Generator::Ptr > GeneratorSet
Definition: Generator.h:190
mp2p_icp_filters::GetOrCreatePointLayer
mrpt::maps::CPointsMap::Ptr GetOrCreatePointLayer(mp2p_icp::metric_map_t &m, const std::string &layerName, bool allowEmptyName=true, const std::string &classForLayerCreation="mrpt::maps::CSimplePointsMap")
Definition: GetOrCreatePointLayer.cpp:15
mp2p_icp_filters::Generator::implProcessDefault
bool implProcessDefault(const mrpt::obs::CObservation &o, mp2p_icp::metric_map_t &out, const std::optional< mrpt::poses::CPose3D > &robotPose=std::nullopt) const
Definition: Generator.cpp:341
mp2p_icp_filters::Generator::Parameters::process_sensor_labels_regex
std::string process_sensor_labels_regex
Definition: Generator.h:141
mp2p_icp_filters::generators_from_yaml_file
GeneratorSet generators_from_yaml_file(const std::string &filename, const mrpt::system::VerbosityLevel &vLevel=mrpt::system::LVL_INFO)
Definition: Generator.cpp:331
mp2p_icp_filters::Generator::filterRotatingScan
virtual bool filterRotatingScan(const mrpt::obs::CObservationRotatingScan &pc, mp2p_icp::metric_map_t &out, const std::optional< mrpt::poses::CPose3D > &robotPose) const
Definition: Generator.cpp:234
mp2p_icp_filters::Generator::Generator
Generator()
Definition: Generator.cpp:42
mp2p_icp::Parameterizable::parseAndDeclareParameter
void parseAndDeclareParameter(const std::string &value, double &target)
Definition: Parameterizable.cpp:120
GetOrCreatePointLayer.h
Auxiliary function GetOrCreatePointLayer.
mp2p_icp::metric_map_t
Generic container of pointcloud(s), extracted features and other maps.
Definition: metricmap.h:55
mp2p_icp_filters::Generator::process
virtual bool process(const mrpt::obs::CObservation &input_raw, mp2p_icp::metric_map_t &inOut, const std::optional< mrpt::poses::CPose3D > &robotPose=std::nullopt) const
Definition: Generator.cpp:134
mp2p_icp_filters::Generator::process_sensor_labels_regex_
std::regex process_sensor_labels_regex_
Definition: Generator.h:175
mp2p_icp_filters::apply_generators
bool apply_generators(const GeneratorSet &generators, const mrpt::obs::CObservation &obs, mp2p_icp::metric_map_t &output, const std::optional< mrpt::poses::CPose3D > &robotPose=std::nullopt)
Definition: Generator.cpp:242
mp2p_icp_filters
Definition: FilterAdjustTimestamps.h:19
kitti-batch-convert.filename
filename
Definition: kitti-batch-convert.py:6
mp2p_icp_filters::generators_from_yaml
GeneratorSet generators_from_yaml(const mrpt::containers::yaml &c, const mrpt::system::VerbosityLevel &vLevel=mrpt::system::LVL_INFO)
Definition: Generator.cpp:298


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