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>
32 namespace fs = std::filesystem;
45 const mrpt::containers::yaml& c,
Generator& parent)
47 using namespace std::string_literals;
55 if (c.has(
"metric_map_definition"))
60 const std::set<std::string> allowedTopKeys = {
"class",
"plugin"};
62 ASSERT_(c[
"metric_map_definition"].isMap());
63 const auto mmd = c[
"metric_map_definition"].asMap();
64 for (
const auto& [k, v] : mmd)
67 if (v.isNullNode())
continue;
70 if (allowedTopKeys.count(key) != 0)
73 ASSERT_(v.isScalar());
80 "scalar key '%s' not allowed here.", key.c_str());
86 "key '%s' must be either a scalar or a map", key.c_str());
88 trg[key] = mrpt::containers::yaml::Map();
89 auto& newMap = trg.asMap().at(key).asMap();
91 for (
const auto& [kk, vv] : v.asMap())
95 if (val.substr(0, 3) ==
"$f{"s)
98 val.back() ==
'}',
"Missing '}' in '$f{' formula");
102 auto [it, exist] = newMap.insert({ks, .0});
103 double& placeholder =
104 *std::any_cast<double>(&it->second.asScalar());
107 val.substr(3, val.size() - 4), placeholder);
117 std::stringstream ss;
119 parent.logStr(mrpt::system::LVL_DEBUG, ss.str());
127 MRPT_LOG_DEBUG_STREAM(
"Loading these params:\n" << c);
140 const std::optional<mrpt::poses::CPose3D>& robotPose)
const
144 Parameterizable::checkAllParametersAreRealized();
148 "initialize() must be called once before using process().");
150 const auto obsClassName = o.GetRuntimeClass()->className;
153 "Processing observation type='%s' label='%s'", obsClassName,
154 o.sensorLabel.c_str());
171 [[maybe_unused]]
const mrpt::obs::CObservation2DRangeScan& pc,
173 [[maybe_unused]]
const std::optional<mrpt::poses::CPose3D>& robotPose)
const
180 const std::optional<mrpt::poses::CPose3D>& robotPose)
const
184 "mrpt::maps::CPointsMapXYZIRT" );
187 auto m = std::dynamic_pointer_cast<mrpt::maps::CPointsMapXYZIRT>(outPc);
190 "Output layer must be of type mrpt::maps::CPointsMapXYZIRT for the "
191 "specialized filterVelodyneScan() generator.");
193 m->insertObservation(pc, robotPose);
199 [[maybe_unused]]
const mrpt::obs::CObservation3DRangeScan& pc,
201 [[maybe_unused]]
const std::optional<mrpt::poses::CPose3D>& robotPose)
const
207 const mrpt::maps::CPointsMap& pc,
const mrpt::poses::CPose3D& sensorPose,
209 const std::optional<mrpt::poses::CPose3D>& robotPose)
const
212 mrpt::maps::CPointsMap::Ptr outPc;
214 itLy !=
out.layers.end())
216 outPc = std::dynamic_pointer_cast<mrpt::maps::CPointsMap>(itLy->second);
219 "Layer '%s' must be of point cloud type.",
225 outPc = std::dynamic_pointer_cast<mrpt::maps::CPointsMap>(
226 pc.GetRuntimeClass()->ptrCreateObject());
230 "[filterPointCloud] Created new layer '%s' of type '%s'",
236 const mrpt::poses::CPose3D p =
237 robotPose ? robotPose.value() + sensorPose : sensorPose;
239 outPc->insertAnotherMap(&pc, p);
242 ASSERT_(sanityPassed);
248 [[maybe_unused]]
const mrpt::obs::CObservationRotatingScan& pc,
250 [[maybe_unused]]
const std::optional<mrpt::poses::CPose3D>& robotPose)
const
258 const std::optional<mrpt::poses::CPose3D>& robotPose)
261 bool anyHandled =
false;
264 ASSERT_(g.get() !=
nullptr);
265 bool handled = g->process(obs, output, robotPose);
266 anyHandled = anyHandled || handled;
273 const std::optional<mrpt::poses::CPose3D>& robotPose)
282 const std::optional<mrpt::poses::CPose3D>& robotPose)
292 const std::optional<mrpt::poses::CPose3D>& robotPose)
295 bool anyHandled =
false;
298 ASSERT_(g.get() !=
nullptr);
299 for (
const auto& obs : sf)
302 const bool handled = g->process(*obs, output, robotPose);
304 anyHandled = anyHandled || handled;
311 const mrpt::containers::yaml& c,
const mrpt::system::VerbosityLevel& vLevel)
313 if (c.isNullNode())
return {};
315 ASSERT_(c.isSequence());
319 for (
const auto& entry : c.asSequence())
321 const auto& e = entry.asMap();
323 const auto sClass = e.at(
"class_name").as<
std::string>();
324 auto o = mrpt::rtti::classFactory(sClass);
327 auto f = std::dynamic_pointer_cast<Generator>(o);
330 "`%s` class seems not to be derived from Generator",
333 f->setMinLoggingLevel(vLevel);
335 f->initialize(e.at(
"params"));
345 const auto yamlContent = mrpt::containers::yaml::FromFile(
filename);
348 yamlContent.has(
"generators") &&
349 yamlContent[
"generators"].isSequence());
356 const std::optional<mrpt::poses::CPose3D>& robotPose)
const
358 using namespace mrpt::obs;
359 using namespace std::string_literals;
361 bool processed =
false;
363 const auto obsClassName = o.GetRuntimeClass()->className;
366 if (obsClassName ==
"mrpt::obs::CObservationComment"s ||
367 obsClassName ==
"mrpt::obs::CObservationGPS"s ||
368 obsClassName ==
"mrpt::obs::CObservationRobotPose"s ||
372 MRPT_LOG_DEBUG_STREAM(
"Skipping this observation");
379 if (
auto oRS =
dynamic_cast<const CObservationRotatingScan*
>(&o); oRS)
381 else if (
auto o0 =
dynamic_cast<const CObservationPointCloud*
>(&o); o0)
383 ASSERT_(o0->pointcloud);
387 else if (
auto o1 =
dynamic_cast<const CObservation2DRangeScan*
>(&o); o1)
389 else if (
auto o2 =
dynamic_cast<const CObservation3DRangeScan*
>(&o); o2)
391 else if (
auto o3 =
dynamic_cast<const CObservationVelodyneScan*
>(&o); o3)
404 "mrpt::maps::CSimplePointsMap" );
410 outPc->GetRuntimeClass()->className);
417 dynamic_cast<const mrpt::obs::CObservation3DRangeScan*
>(&o);
418 obs3D && obs3D->points3D_x.empty())
420 mrpt::maps::CSimplePointsMap tmpMap;
422 mrpt::obs::T3DPointsProjectionParams pp;
423 pp.takeIntoAccountSensorPoseOnRobot =
true;
424 pp.robotPoseInTheWorld = robotPose;
425 const_cast<mrpt::obs::CObservation3DRangeScan*
>(obs3D)->unprojectInto(
428 outPc->insertAnotherMap(&tmpMap, mrpt::poses::CPose3D::Identity());
435 const bool insertDone = o.insertObservationInto(*outPc, robotPose);
440 "Observation of type '%s' could not be converted into a "
441 "point cloud, and none of the specializations handled it, "
442 "so I do not know what to do with this observation!",
453 const std::optional<mrpt::poses::CPose3D>& robotPose)
const
455 using namespace std::string_literals;
457 const auto obsClassName = o.GetRuntimeClass()->className;
460 mrpt::maps::CMetricMap::Ptr outMap;
463 itLy !=
out.layers.end())
465 outMap = itLy->second;
470 mrpt::maps::TSetOfMetricMapInitializers mapInits;
480 mrpt::config::CConfigFile
cfg(
482 mapInits.loadFromConfigFile(
cfg, cfgPrefix);
493 mrpt::config::CConfigFileMemory
cfg;
495 ASSERT_(c.has(
"class"));
497 cfg.write(cfgPrefix, mapClass +
"_count"s,
"1");
502 const auto moduleToLoad = c[
"plugin"].as<
std::string>();
503 MRPT_LOG_DEBUG_STREAM(
504 "About to load user-defined plugin: " << moduleToLoad);
509 for (
const auto& [k, v] : c.asMap())
511 if (!v.isMap())
continue;
513 const auto sectName =
514 cfgPrefix +
"_"s + mapClass +
"_00_"s + keyVal;
515 for (
const auto& [kk, vv] : v.asMap())
517 ASSERT_(kk.isScalar());
518 ASSERT_(vv.isScalar());
525 MRPT_LOG_DEBUG_STREAM(
528 <<
cfg.getContent());
531 mapInits.loadFromConfigFile(
cfg, cfgPrefix);
535 mrpt::maps::CMultiMetricMap theMap;
536 theMap.setListOfMaps(mapInits);
538 ASSERT_(theMap.maps.size() >= 1);
539 outMap = theMap.maps.at(0);
547 if (obsClassName ==
"mrpt::obs::CObservationComment"s ||
551 MRPT_LOG_DEBUG_STREAM(
"Skipping this observation");
559 const bool insertDone = o.insertObservationInto(*outMap, robotPose);
564 "Observation of type '%s' could not be converted inserted into "
565 "the map of type '%s', so I do not know what to do with this "
567 obsClassName, outMap->GetRuntimeClass()->className);
576 void safe_add_to_list(
const std::string& path, std::vector<std::string>& lst)
578 if (mrpt::system::directoryExists(path)) lst.push_back(path);
581 void from_env_var_to_list(
582 const std::string& env_var_name, std::vector<std::string>& lst,
591 const auto additionalPaths = mrpt::get_env<std::string>(env_var_name);
592 std::vector<std::string> pathList;
593 mrpt::system::tokenize(additionalPaths, delim, pathList);
596 for (
const auto& path : pathList)
598 if (!subStringPattern.empty() &&
599 path.find(subStringPattern) == std::string::npos)
601 safe_add_to_list(path, lst);
610 if (!fs::path(moduleToLoad).is_relative())
613 ASSERT_FILE_EXISTS_(moduleToLoad);
614 absPath = moduleToLoad;
619 std::vector<std::string> lstPath;
620 from_env_var_to_list(
"LD_LIBRARY_PATH", lstPath);
622 for (
const auto& p : lstPath)
624 const auto fp = mrpt::system::pathJoin({p, moduleToLoad});
625 if (mrpt::system::fileExists(fp))
634 "Could not find '%s' anywhere under the LD_LIBRARY_PATH paths",
635 moduleToLoad.c_str());
639 #if defined(__unix__)
642 void* handle = dlopen(absPath.c_str(), RTLD_NOLOAD);
643 if (handle !=
nullptr)
648 void* handle = dlopen(absPath.c_str(), RTLD_LAZY);
651 HMODULE handle = LoadLibrary(absPath.c_str());
653 if (handle ==
nullptr)
655 const char* err = dlerror();
656 if (!err) err =
"(error calling dlerror())";
657 THROW_EXCEPTION(mrpt::format(
658 "Error loading module: `%s`\ndlerror(): `%s`", absPath.c_str(),
662 MRPT_LOG_DEBUG_FMT(
"Successfully loaded: `%s`", absPath.c_str());