World_load_xml.cpp
Go to the documentation of this file.
00001 /*+-------------------------------------------------------------------------+
00002   |                       MultiVehicle simulator (libmvsim)                 |
00003   |                                                                         |
00004   | Copyright (C) 2014  Jose Luis Blanco Claraco (University of Almeria)    |
00005   | Copyright (C) 2017  Borys Tymchenko (Odessa Polytechnic University)     |
00006   | Distributed under GNU General Public License version 3                  |
00007   |   See <http://www.gnu.org/licenses/>                                    |
00008   +-------------------------------------------------------------------------+ */
00009 #include <mvsim/World.h>
00010 
00011 #if MRPT_VERSION<0x199
00012 #include <mrpt/utils/utils_defs.h>  // mrpt::format()
00013 #else
00014 #include <mrpt/core/format.h>
00015 #endif
00016 
00017 #include <mrpt/system/filesystem.h>  // extractFileDirectory()
00018 
00019 #include <iostream>  // for debugging
00020 #include <algorithm>  // count()
00021 #include <stdexcept>
00022 #include <map>
00023 
00024 // XML parsing:
00025 #include <rapidxml.hpp>
00026 #include <rapidxml_print.hpp>
00027 
00028 #include "xml_utils.h"
00029 
00030 using namespace mvsim;
00031 using namespace std;
00032 
00038 void World::load_from_XML(
00039         const std::string& xml_text, const std::string& fileNameForPath)
00040 {
00041         using namespace std;
00042         using namespace rapidxml;
00043 
00044         // Extract base path of file:
00045         m_base_path =
00046                 mrpt::system::trim(mrpt::system::extractFileDirectory(fileNameForPath));
00047         // printf("[World] INFO: Using base path='%s'\n",m_base_path.c_str());
00048 
00049         std::lock_guard<std::mutex> csl(m_world_cs);  // Protect multithread access
00050 
00051         // Clear the existing world.
00052         this->clear_all(false /* critical section is already acquired */);
00053 
00054         // Parse the XML input:
00055         rapidxml::xml_document<> xml;
00056         char* input_str = const_cast<char*>(xml_text.c_str());
00057         try
00058         {
00059                 xml.parse<0>(input_str);
00060         }
00061         catch (rapidxml::parse_error& e)
00062         {
00063                 unsigned int line =
00064                         static_cast<long>(std::count(input_str, e.where<char>(), '\n') + 1);
00065                 throw std::runtime_error(
00066                         mrpt::format(
00067                                 "XML parse error (Line %u): %s", static_cast<unsigned>(line),
00068                                 e.what()));
00069         }
00070 
00071         // Sanity checks:
00072         const xml_node<>* root = xml.first_node();
00073         if (!root)
00074                 throw runtime_error(
00075                         "XML parse error: No root node found (empty file?)");
00076         if (0 != strcmp(root->name(), "mvsim_world"))
00077                 throw runtime_error(
00078                         mrpt::format(
00079                                 "XML root element is '%s' ('mvsim_world' expected)",
00080                                 root->name()));
00081 
00082         // Optional: format version attrib:
00083         const xml_attribute<>* attrb_version = root->first_attribute("version");
00084         int version_major = 1, version_min = 0;
00085         if (attrb_version)
00086         {
00087                 int ret = sscanf(
00088                         attrb_version->value(), "%i.%i", &version_major, &version_min);
00089                 if (ret != 2)
00090                         throw runtime_error(
00091                                 mrpt::format(
00092                                         "Error parsing version attribute: '%s' ('%%i.%%i' "
00093                                         "expected)",
00094                                         attrb_version->value()));
00095         }
00096 
00097         // load general parameters:
00098         // ------------------------------------------------
00099         std::map<std::string, TParamEntry> other_world_params;
00100         other_world_params["gravity"] = TParamEntry("%lf", &this->m_gravity);
00101         other_world_params["simul_timestep"] =
00102                 TParamEntry("%lf", &this->m_simul_timestep);
00103         other_world_params["b2d_vel_iters"] =
00104                 TParamEntry("%i", &this->m_b2d_vel_iters);
00105         other_world_params["b2d_pos_iters"] =
00106                 TParamEntry("%i", &this->m_b2d_pos_iters);
00107 
00108         // Process all nodes:
00109         // ------------------------------------------------
00110         xml_node<>* node = root->first_node();
00111         while (node)
00112         {
00113                 // <element class='*'> entries:
00114                 if (!strcmp(node->name(), "element"))
00115                 {
00116                         WorldElementBase* we = WorldElementBase::factory(this, node);
00117                         this->m_world_elements.push_back(we);
00118                 }
00119                 // <vehicle> entries:
00120                 else if (!strcmp(node->name(), "vehicle"))
00121                 {
00122                         VehicleBase* veh = VehicleBase::factory(this, node);
00123                         veh->setVehicleIndex(
00124                                 m_vehicles.size());  // Assign each vehicle an "index" number
00125 
00126                         MRPT_TODO("Check for duplicated names")
00127                         m_vehicles.insert(TListVehicles::value_type(veh->getName(), veh));
00128                 }
00129                 // <vehicle:class> entries:
00130                 else if (!strcmp(node->name(), "vehicle:class"))
00131                 {
00132                         VehicleBase::register_vehicle_class(node);
00133                 }
00134                 // <block> entries:
00135                 else if (!strcmp(node->name(), "block"))
00136                 {
00137                         Block* block = Block::factory(this, node);
00138                         block->setBlockIndex(
00139                                 m_blocks.size());  // Assign each block an "index" number
00140 
00141                         // make sure the name is not duplicated:
00142                         m_blocks.insert(TListBlocks::value_type(block->getName(), block));
00143                 }
00144                 // <block:class> entries:
00145                 else if (!strcmp(node->name(), "block:class"))
00146                 {
00147                         Block::register_block_class(node);
00148                 }
00149                 // <gui> </gui> params:
00150                 else if (!strcmp(node->name(), "gui"))
00151                 {
00152                         m_gui_options.parse_from(*node);
00153                 }
00154                 else
00155                 {
00156                         // Default: Check if it's a parameter:
00157                         if (!parse_xmlnode_as_param(*node, other_world_params))
00158                         {
00159                                 // Unknown element!!
00160                                 std::cerr << "[World::load_from_XML] *Warning* Ignoring "
00161                                                          "unknown XML node type '"
00162                                                   << node->name() << "'\n";
00163                         }
00164                 }
00165 
00166                 // Move on to next node:
00167                 node = node->next_sibling(NULL);
00168         }
00169 }


mvsim
Author(s):
autogenerated on Thu Jun 6 2019 22:08:35