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;
46 using namespace std::string_literals;
54 if (c.has(
"metric_map_definition"))
59 const std::set<std::string> allowedTopKeys = {
"class",
"plugin"};
61 ASSERT_(c[
"metric_map_definition"].isMap());
62 const auto mmd = c[
"metric_map_definition"].asMap();
63 for (
const auto& [k, v] : mmd)
72 if (allowedTopKeys.count(key) != 0)
75 ASSERT_(v.isScalar());
80 THROW_EXCEPTION_FMT(
"scalar key '%s' not allowed here.", key.c_str());
85 THROW_EXCEPTION_FMT(
"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)
97 ASSERTMSG_(val.back() ==
'}',
"Missing '}' in '$f{' formula");
101 auto [it, exist] = newMap.insert({ks, .0});
102 double& placeholder = *std::any_cast<double>(&it->second.asScalar());
114 std::stringstream ss;
116 parent.logStr(mrpt::system::LVL_DEBUG, ss.str());
124 MRPT_LOG_DEBUG_STREAM(
"Loading these params:\n" << c);
136 const std::optional<mrpt::poses::CPose3D>& robotPose)
const
140 Parameterizable::checkAllParametersAreRealized();
142 ASSERTMSG_(
initialized_,
"initialize() must be called once before using process().");
144 const auto obsClassName = o.GetRuntimeClass()->className;
147 "Processing observation type='%s' label='%s'", obsClassName, o.sensorLabel.c_str());
160 [[maybe_unused]]
const mrpt::obs::CObservation2DRangeScan& pc,
162 [[maybe_unused]]
const std::optional<mrpt::poses::CPose3D>& robotPose)
const
169 const std::optional<mrpt::poses::CPose3D>& robotPose)
const
173 "mrpt::maps::CPointsMapXYZIRT" );
176 auto m = std::dynamic_pointer_cast<mrpt::maps::CPointsMapXYZIRT>(outPc);
179 "Output layer must be of type mrpt::maps::CPointsMapXYZIRT for the "
180 "specialized filterVelodyneScan() generator.");
182 m->insertObservation(pc, robotPose);
188 [[maybe_unused]]
const mrpt::obs::CObservation3DRangeScan& pc,
190 [[maybe_unused]]
const std::optional<mrpt::poses::CPose3D>& robotPose)
const
196 const mrpt::maps::CPointsMap& pc,
const mrpt::poses::CPose3D& sensorPose,
200 mrpt::maps::CPointsMap::Ptr outPc;
203 outPc = std::dynamic_pointer_cast<mrpt::maps::CPointsMap>(itLy->second);
213 outPc = std::dynamic_pointer_cast<mrpt::maps::CPointsMap>(
214 pc.GetRuntimeClass()->ptrCreateObject());
219 outPc->GetRuntimeClass()->className);
224 const mrpt::poses::CPose3D p = robotPose ? robotPose.value() + sensorPose : sensorPose;
226 outPc->insertAnotherMap(&pc, p);
229 ASSERT_(sanityPassed);
235 [[maybe_unused]]
const mrpt::obs::CObservationRotatingScan& pc,
237 [[maybe_unused]]
const std::optional<mrpt::poses::CPose3D>& robotPose)
const
247 bool anyHandled =
false;
250 ASSERT_(g.get() !=
nullptr);
251 bool handled = g->process(obs, output, robotPose);
252 anyHandled = anyHandled || handled;
259 const std::optional<mrpt::poses::CPose3D>& robotPose)
268 const std::optional<mrpt::poses::CPose3D>& robotPose)
280 bool anyHandled =
false;
283 ASSERT_(g.get() !=
nullptr);
284 for (
const auto& obs : sf)
290 const bool handled = g->process(*obs, output, robotPose);
292 anyHandled = anyHandled || handled;
299 const mrpt::containers::yaml& c,
const mrpt::system::VerbosityLevel& vLevel)
306 ASSERT_(c.isSequence());
310 for (
const auto& entry : c.asSequence())
312 const auto& e = entry.asMap();
314 const auto sClass = e.at(
"class_name").as<
std::string>();
315 auto o = mrpt::rtti::classFactory(sClass);
318 auto f = std::dynamic_pointer_cast<Generator>(o);
320 f, mrpt::format(
"`%s` class seems not to be derived from Generator", sClass.c_str()));
322 f->setMinLoggingLevel(vLevel);
324 f->initialize(e.at(
"params"));
334 const auto yamlContent = mrpt::containers::yaml::FromFile(
filename);
336 ASSERT_(yamlContent.has(
"generators") && yamlContent[
"generators"].isSequence());
343 const std::optional<mrpt::poses::CPose3D>& robotPose)
const
345 using namespace mrpt::obs;
346 using namespace std::string_literals;
348 bool processed =
false;
350 const auto obsClassName = o.GetRuntimeClass()->className;
353 if (obsClassName ==
"mrpt::obs::CObservationComment"s ||
354 obsClassName ==
"mrpt::obs::CObservationGPS"s ||
355 obsClassName ==
"mrpt::obs::CObservationRobotPose"s ||
359 MRPT_LOG_DEBUG_STREAM(
360 "Skipping observation of type '" << obsClassName <<
"' with label '" << o.sensorLabel
368 if (
auto oRS =
dynamic_cast<const CObservationRotatingScan*
>(&o); oRS)
372 else if (
auto o0 =
dynamic_cast<const CObservationPointCloud*
>(&o); o0)
374 ASSERT_(o0->pointcloud);
377 else if (
auto o1 =
dynamic_cast<const CObservation2DRangeScan*
>(&o); o1)
381 else if (
auto o2 =
dynamic_cast<const CObservation3DRangeScan*
>(&o); o2)
385 else if (
auto o3 =
dynamic_cast<const CObservationVelodyneScan*
>(&o); o3)
400 "mrpt::maps::CSimplePointsMap" );
406 outPc->GetRuntimeClass()->className);
412 if (
auto obs3D =
dynamic_cast<const mrpt::obs::CObservation3DRangeScan*
>(&o);
413 obs3D && obs3D->points3D_x.empty())
415 mrpt::maps::CSimplePointsMap tmpMap;
417 mrpt::obs::T3DPointsProjectionParams pp;
418 pp.takeIntoAccountSensorPoseOnRobot =
true;
419 pp.robotPoseInTheWorld = robotPose;
420 const_cast<mrpt::obs::CObservation3DRangeScan*
>(obs3D)->unprojectInto(tmpMap, pp);
422 outPc->insertAnotherMap(&tmpMap, mrpt::poses::CPose3D::Identity());
428 const bool insertDone = o.insertObservationInto(*outPc, robotPose);
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!",
445 const std::optional<mrpt::poses::CPose3D>& robotPose)
const
447 using namespace std::string_literals;
449 const auto obsClassName = o.GetRuntimeClass()->className;
452 mrpt::maps::CMetricMap::Ptr outMap;
456 outMap = itLy->second;
461 mrpt::maps::TSetOfMetricMapInitializers mapInits;
472 mapInits.loadFromConfigFile(
cfg, cfgPrefix);
483 mrpt::config::CConfigFileMemory
cfg;
485 ASSERT_(c.has(
"class"));
487 cfg.write(cfgPrefix, mapClass +
"_count"s,
"1");
492 const auto moduleToLoad = c[
"plugin"].as<
std::string>();
493 MRPT_LOG_DEBUG_STREAM(
"About to load user-defined plugin: " << moduleToLoad);
498 for (
const auto& [k, v] : c.asMap())
505 const auto sectName = cfgPrefix +
"_"s + mapClass +
"_00_"s + keyVal;
506 for (
const auto& [kk, vv] : v.asMap())
508 ASSERT_(kk.isScalar());
509 ASSERT_(vv.isScalar());
515 MRPT_LOG_DEBUG_STREAM(
517 <<
cfg.getContent());
520 mapInits.loadFromConfigFile(
cfg, cfgPrefix);
524 mrpt::maps::CMultiMetricMap theMap;
525 theMap.setListOfMaps(mapInits);
527 ASSERT_(theMap.maps.size() >= 1);
528 outMap = theMap.maps.at(0);
536 if (obsClassName ==
"mrpt::obs::CObservationComment"s ||
540 MRPT_LOG_DEBUG_STREAM(
541 "Skipping observation of type '" << obsClassName <<
"' with label '" << o.sensorLabel
550 const bool insertDone = o.insertObservationInto(*outMap, robotPose);
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 "
558 obsClassName, outMap->GetRuntimeClass()->className);
567 void safe_add_to_list(
const std::string& path, std::vector<std::string>& lst)
569 if (mrpt::system::directoryExists(path))
575 void from_env_var_to_list(
576 const std::string& env_var_name, std::vector<std::string>& lst,
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);
590 for (
const auto& path : pathList)
592 if (!subStringPattern.empty() && path.find(subStringPattern) == std::string::npos)
596 safe_add_to_list(path, lst);
605 if (!fs::path(moduleToLoad).is_relative())
608 ASSERT_FILE_EXISTS_(moduleToLoad);
609 absPath = moduleToLoad;
614 std::vector<std::string> lstPath;
615 from_env_var_to_list(
"LD_LIBRARY_PATH", lstPath);
617 for (
const auto& p : lstPath)
619 const auto fp = mrpt::system::pathJoin({p, moduleToLoad});
620 if (mrpt::system::fileExists(fp))
629 "Could not find '%s' anywhere under the LD_LIBRARY_PATH paths",
630 moduleToLoad.c_str());
634 #if defined(__unix__)
637 void* handle = dlopen(absPath.c_str(), RTLD_NOLOAD);
638 if (handle !=
nullptr)
643 void* handle = dlopen(absPath.c_str(), RTLD_LAZY);
646 HMODULE handle = LoadLibrary(absPath.c_str());
648 if (handle ==
nullptr)
650 const char* err = dlerror();
653 err =
"(error calling dlerror())";
656 mrpt::format(
"Error loading module: `%s`\ndlerror(): `%s`", absPath.c_str(), err));
659 MRPT_LOG_DEBUG_FMT(
"Successfully loaded: `%s`", absPath.c_str());