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());