9 #include <mrpt/core/format.h>
10 #include <mrpt/core/get_env.h>
11 #include <mrpt/core/lock_helper.h>
12 #include <mrpt/maps/CSimplePointsMap.h>
13 #include <mrpt/system/filesystem.h>
14 #include <mrpt/topography/conversions.h>
28 using namespace mvsim;
34 load_from_XML(fil_xml.
data(), xmlFileNamePath.c_str());
42 std::string fileDir = mrpt::system::extractFileDirectory(fileNameForPath);
43 if (fileDir.empty()) fileDir =
".";
46 basePath_ = mrpt::system::toAbsolutePath(fileDir,
false );
50 userDefinedVariables_[
"MVSIM_CURRENT_FILE_DIRECTORY"] = basePath_;
52 auto lck = mrpt::lockHelper(world_cs_);
60 simulableObjectsMtx_.lock();
61 simulableObjects_.emplace(
"__standaloneSensorHost", standaloneSensorHost);
62 simulableObjectsMtx_.unlock();
68 if (0 != strcmp(
root->name(),
"mvsim_world"))
70 mrpt::format(
"XML root element is '%s' ('mvsim_world' expected)",
root->name()));
74 int version_major = 1, version_min = 0;
77 int ret = sscanf(attrb_version->value(),
"%i.%i", &version_major, &version_min);
79 throw runtime_error(mrpt::format(
80 "Error parsing version attribute: '%s' ('%%i.%%i' "
82 attrb_version->value()));
86 register_standard_xml_tag_parsers();
94 internal_recursive_parse_XML({node, basePath_});
100 internal_initialize();
105 if (!xmlParsers_.empty())
return;
129 using namespace std::string_literals;
135 const auto savedBasePath = basePath_;
138 userDefinedVariables_[
"MVSIM_CURRENT_FILE_DIRECTORY"] = basePath_;
141 if (
auto itParser = xmlParsers_.find(node->name()); itParser != xmlParsers_.end())
143 itParser->second(ctx);
150 MRPT_LOG_WARN_STREAM(
151 "[World::load_from_XML] *Warning* Ignoring unknown XML node type '" << node->name()
157 basePath_ = savedBasePath;
159 userDefinedVariables_[
"MVSIM_CURRENT_FILE_DIRECTORY"] = basePath_;
166 worldElements_.emplace_back(e);
168 auto lckListObjs = mrpt::lockHelper(getListOfSimulableObjectsMtx());
169 simulableObjects_.emplace(e->getName(), std::dynamic_pointer_cast<Simulable>(e));
177 veh->setVehicleIndex(vehicles_.size());
180 vehicles_.count(veh->getName()) == 0,
181 mrpt::format(
"Duplicated vehicle name: '%s'", veh->getName().c_str()));
183 vehicles_.insert(VehicleList::value_type(veh->getName(), veh));
185 auto lckListObjs = mrpt::lockHelper(getListOfSimulableObjectsMtx());
186 simulableObjects_.emplace(veh->getName(), std::dynamic_pointer_cast<Simulable>(veh));
198 auto lckListObjs = mrpt::lockHelper(getListOfSimulableObjectsMtx());
201 simulableObjects_.find(
"__standaloneSensorHost")->second);
202 ASSERT_(standaloneSensorHost);
205 standaloneSensorHost->add_sensor(sensor);
213 lut2d_objects_is_up_to_date_ =
false;
225 guiOptions_.parse_from(*ctx.
node, *
this);
230 lightOptions_.parse_from(*ctx.
node, *
this);
235 georeferenceOptions_.parse_from(*ctx.
node, *
this);
238 auto& g = georeferenceOptions_;
243 g.world_to_enu_rotation == 0,
244 "Cannot define both, <world_to_enu_rotation> and <world_is_utm>");
247 !g.georefCoord.isClear(),
248 "<world_is_utm> requires defining a valid reference geodetic coordinates too.");
250 mrpt::topography::GeodeticToUTM(g.georefCoord, g.utmRef, g.utm_zone, g.utm_band);
252 MRPT_LOG_INFO_STREAM(
253 "Using UTM georeference: utm_zone=" << g.utm_zone <<
" geoRef: utmRef=" << g.utmRef);
262 ASSERTMSG_(fileAttrb,
"XML tag '<include />' must have a 'file=\"xxx\"' attribute)");
264 const std::string relFile =
mvsim::parse(fileAttrb->value(), user_defined_variables());
266 const auto absFile = this->local_to_abs_path(relFile);
267 MRPT_LOG_DEBUG_STREAM(
"XML parser: including file: '" << absFile <<
"'");
269 std::map<std::string, std::string> vars;
271 vars = user_defined_variables();
275 if (strcmp(attr->name(),
"file") == 0)
continue;
276 vars[attr->name()] = attr->value();
283 const auto newBasePath = mrpt::system::extractFileDirectory(absFile);
284 internal_recursive_parse_XML({
root, newBasePath});
290 ASSERTMSG_(nameAttr,
"XML tag '<variable />' must have a 'name=\"xxx\"' attribute)");
291 const auto name = nameAttr->value();
294 ASSERTMSG_(valueAttr,
"XML tag '<variable />' must have a 'value=\"xxx\"' attribute)");
296 const std::string finalValue =
mvsim::parse(valueAttr->value(), userDefinedVariables_);
298 thread_local
const bool MVSIM_VERBOSE_PARSE = mrpt::get_env<bool>(
"MVSIM_VERBOSE_PARSE",
false);
303 "[mvsim] Parsed <variable>: name='%s' value='%s' (original "
304 "expression='%s')\n",
305 name, finalValue.c_str(), valueAttr->value());
308 userDefinedVariables_[name] = finalValue;
314 ASSERTMSG_(varAttr,
"XML tag '<for />' must have a 'var=\"xxx\"' attribute)");
315 const auto varName = varAttr->value();
318 ASSERTMSG_(varFrom,
"XML tag '<for />' must have a 'from=\"xxx\"' attribute)");
319 const auto fromStr =
mvsim::parse(varFrom->value(), userDefinedVariables_);
322 ASSERTMSG_(varTo,
"XML tag '<for />' must have a 'to=\"xxx\"' attribute)");
323 const auto toStr =
mvsim::parse(varTo->value(), userDefinedVariables_);
325 bool forBodyEmpty =
true;
329 forBodyEmpty =
false;
330 for (
int curVal = std::stoi(fromStr); curVal <= std::stoi(toStr); curVal++)
332 userDefinedVariables_[varName] = std::to_string(curVal);
333 internal_recursive_parse_XML({childNode, basePath_});
339 MRPT_LOG_WARN_STREAM(
340 "[World::load_from_XML] *Warning* <for ...> </for> loop has no "
342 << ctx.
node->value() <<
"'");
348 bool isTrue = evaluate_tag_if(*ctx.
node);
353 internal_recursive_parse_XML({childNode, basePath_});
360 ASSERTMSG_(varCond,
"XML tag '<if />' must have a 'condition=\"xxx\"' attribute)");
361 const auto str =
mvsim::parse(varCond->value(), userDefinedVariables_);
364 std::optional<int> intVal;
365 char* retStr =
nullptr;
366 const long long ret = std::strtoll(str.c_str(), &retStr, 0 );
367 if (retStr != 0 && retStr != str.c_str()) intVal = ret;
369 bool isTrue = str ==
"y" || str ==
"Y" || str ==
"yes" || str ==
"Yes" || str ==
"YES" ||
370 str ==
"true" || str ==
"True" || str ==
"TRUE" || str ==
"on" || str ==
"ON" ||
371 str ==
"On" || (intVal.has_value() && intVal.value() != 0);
379 ASSERTMSG_(typeAttr,
"XML tag '<marker />' must have a 'type=\"xxx\"' attribute)");
380 const std::string
type = typeAttr->value();
382 mrpt::img::TColor color{0xff, 0xff, 0xff, 0xff};
385 mrpt::math::TPoint3D translation = {0, 0, 0};
387 params[
"translation"] =
TParamEntry(
"%point3d", &translation);
392 if (
type ==
"line_strip")
398 ASSERTMSG_(xmlPts,
"<marker type='line_strip'> requires tag <points>x y z...</points>");
400 mrpt::maps::CSimplePointsMap pts;
401 std::string parseError;
402 std::stringstream ss(
mvsim::trim(xmlPts->value()));
403 bool parsedOk = pts.load3D_from_text_stream(ss, parseError);
405 parsedOk,
"Error parsing XYZ data within <marker type='line_strip'>: "s + parseError);
407 auto glObj = mrpt::opengl::CSetOfLines::Create();
408 glObj->setColor_u8(color);
409 glObj->setLocation(translation);
411 for (
size_t i = 0; i < pts.size(); i++)
413 mrpt::math::TPoint3D pt;
415 pt += worldRenderOffset();
418 glObj->appendLine(pt, pt);
420 glObj->appendLineStrip(pt);
423 auto lckPhys = mrpt::lockHelper(physical_objects_mtx());
424 worldVisual_->insert(glObj);
428 THROW_EXCEPTION_FMT(
"Unknown <marker> of type='%s'>",
type.c_str());