World_load_xml.cpp
Go to the documentation of this file.
1 /*+-------------------------------------------------------------------------+
2  | MultiVehicle simulator (libmvsim) |
3  | |
4  | Copyright (C) 2014 Jose Luis Blanco Claraco (University of Almeria) |
5  | Copyright (C) 2017 Borys Tymchenko (Odessa Polytechnic University) |
6  | Distributed under GNU General Public License version 3 |
7  | See <http://www.gnu.org/licenses/> |
8  +-------------------------------------------------------------------------+ */
9 #include <mvsim/World.h>
10 
11 #if MRPT_VERSION<0x199
12 #include <mrpt/utils/utils_defs.h> // mrpt::format()
13 #else
14 #include <mrpt/core/format.h>
15 #endif
16 
17 #include <mrpt/system/filesystem.h> // extractFileDirectory()
18 
19 #include <iostream> // for debugging
20 #include <algorithm> // count()
21 #include <stdexcept>
22 #include <map>
23 
24 // XML parsing:
25 #include <rapidxml.hpp>
26 #include <rapidxml_print.hpp>
27 
28 #include "xml_utils.h"
29 
30 using namespace mvsim;
31 using namespace std;
32 
39  const std::string& xml_text, const std::string& fileNameForPath)
40 {
41  using namespace std;
42  using namespace rapidxml;
43 
44  // Extract base path of file:
45  m_base_path =
46  mrpt::system::trim(mrpt::system::extractFileDirectory(fileNameForPath));
47  // printf("[World] INFO: Using base path='%s'\n",m_base_path.c_str());
48 
49  std::lock_guard<std::mutex> csl(m_world_cs); // Protect multithread access
50 
51  // Clear the existing world.
52  this->clear_all(false /* critical section is already acquired */);
53 
54  // Parse the XML input:
56  char* input_str = const_cast<char*>(xml_text.c_str());
57  try
58  {
59  xml.parse<0>(input_str);
60  }
61  catch (rapidxml::parse_error& e)
62  {
63  unsigned int line =
64  static_cast<long>(std::count(input_str, e.where<char>(), '\n') + 1);
65  throw std::runtime_error(
66  mrpt::format(
67  "XML parse error (Line %u): %s", static_cast<unsigned>(line),
68  e.what()));
69  }
70 
71  // Sanity checks:
72  const xml_node<>* root = xml.first_node();
73  if (!root)
74  throw runtime_error(
75  "XML parse error: No root node found (empty file?)");
76  if (0 != strcmp(root->name(), "mvsim_world"))
77  throw runtime_error(
78  mrpt::format(
79  "XML root element is '%s' ('mvsim_world' expected)",
80  root->name()));
81 
82  // Optional: format version attrib:
83  const xml_attribute<>* attrb_version = root->first_attribute("version");
84  int version_major = 1, version_min = 0;
85  if (attrb_version)
86  {
87  int ret = sscanf(
88  attrb_version->value(), "%i.%i", &version_major, &version_min);
89  if (ret != 2)
90  throw runtime_error(
91  mrpt::format(
92  "Error parsing version attribute: '%s' ('%%i.%%i' "
93  "expected)",
94  attrb_version->value()));
95  }
96 
97  // load general parameters:
98  // ------------------------------------------------
99  std::map<std::string, TParamEntry> other_world_params;
100  other_world_params["gravity"] = TParamEntry("%lf", &this->m_gravity);
101  other_world_params["simul_timestep"] =
102  TParamEntry("%lf", &this->m_simul_timestep);
103  other_world_params["b2d_vel_iters"] =
104  TParamEntry("%i", &this->m_b2d_vel_iters);
105  other_world_params["b2d_pos_iters"] =
106  TParamEntry("%i", &this->m_b2d_pos_iters);
107 
108  // Process all nodes:
109  // ------------------------------------------------
110  xml_node<>* node = root->first_node();
111  while (node)
112  {
113  // <element class='*'> entries:
114  if (!strcmp(node->name(), "element"))
115  {
117  this->m_world_elements.push_back(we);
118  }
119  // <vehicle> entries:
120  else if (!strcmp(node->name(), "vehicle"))
121  {
122  VehicleBase* veh = VehicleBase::factory(this, node);
123  veh->setVehicleIndex(
124  m_vehicles.size()); // Assign each vehicle an "index" number
125 
126  MRPT_TODO("Check for duplicated names")
127  m_vehicles.insert(TListVehicles::value_type(veh->getName(), veh));
128  }
129  // <vehicle:class> entries:
130  else if (!strcmp(node->name(), "vehicle:class"))
131  {
133  }
134  // <block> entries:
135  else if (!strcmp(node->name(), "block"))
136  {
137  Block* block = Block::factory(this, node);
138  block->setBlockIndex(
139  m_blocks.size()); // Assign each block an "index" number
140 
141  // make sure the name is not duplicated:
142  m_blocks.insert(TListBlocks::value_type(block->getName(), block));
143  }
144  // <block:class> entries:
145  else if (!strcmp(node->name(), "block:class"))
146  {
148  }
149  // <gui> </gui> params:
150  else if (!strcmp(node->name(), "gui"))
151  {
152  m_gui_options.parse_from(*node);
153  }
154  else
155  {
156  // Default: Check if it's a parameter:
157  if (!parse_xmlnode_as_param(*node, other_world_params))
158  {
159  // Unknown element!!
160  std::cerr << "[World::load_from_XML] *Warning* Ignoring "
161  "unknown XML node type '"
162  << node->name() << "'\n";
163  }
164  }
165 
166  // Move on to next node:
167  node = node->next_sibling(NULL);
168  }
169 }
This file contains rapidxml parser and DOM implementation.
Ch * where() const
Definition: rapidxml.hpp:94
static WorldElementBase * factory(World *parent, const rapidxml::xml_node< char > *xml_node, const char *class_name=NULL)
Ch * value() const
Definition: rapidxml.hpp:692
const std::string & getName() const
Definition: Block.h:96
bool parse_xmlnode_as_param(const rapidxml::xml_node< char > &xml_node, const std::map< std::string, TParamEntry > &params, const char *function_name_context="")
Definition: xml_utils.cpp:176
const std::string & getName() const
Definition: VehicleBase.h:139
static void register_block_class(const rapidxml::xml_node< char > *xml_node)
Definition: Block.cpp:93
void parse(Ch *text)
Definition: rapidxml.hpp:1381
xml_node< Ch > * first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Definition: rapidxml.hpp:936
Ch * name() const
Definition: rapidxml.hpp:673
virtual const char * what() const
Definition: rapidxml.hpp:85
xml_attribute< Ch > * first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Definition: rapidxml.hpp:1025
static void register_vehicle_class(const rapidxml::xml_node< char > *xml_node)
void load_from_XML(const std::string &xml_text, const std::string &fileNameForPath=std::string("."))
xml_node< Ch > * next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Definition: rapidxml.hpp:1004
static Block * factory(World *parent, const rapidxml::xml_node< char > *xml_node)
Definition: Block.cpp:114
void setBlockIndex(size_t idx)
Definition: Block.h:101
void setVehicleIndex(size_t idx)
Definition: VehicleBase.h:148
This file contains rapidxml printer implementation.
static VehicleBase * factory(World *parent, const rapidxml::xml_node< char > *xml_node)


mvsim
Author(s):
autogenerated on Thu Jun 6 2019 19:36:40