World_load_xml.cpp
Go to the documentation of this file.
1 /*+-------------------------------------------------------------------------+
2  | MultiVehicle simulator (libmvsim) |
3  | |
4  | Copyright (C) 2014-2020 Jose Luis Blanco Claraco |
5  | Copyright (C) 2017 Borys Tymchenko (Odessa Polytechnic University) |
6  | Distributed under 3-clause BSD License |
7  | See COPYING |
8  +-------------------------------------------------------------------------+ */
9 #include <mrpt/core/format.h>
10 #include <mrpt/core/lock_helper.h>
11 #include <mrpt/system/filesystem.h> // extractFileDirectory()
12 #include <mvsim/World.h>
13 
14 #include <algorithm> // count()
15 #include <iostream> // for debugging
16 #include <map>
17 #include <rapidxml.hpp>
18 #include <rapidxml_print.hpp>
19 #include <stdexcept>
20 
21 #include "xml_utils.h"
22 
23 using namespace mvsim;
24 using namespace std;
25 
26 MRPT_TODO("Replace if-else chain with a node load registry")
27 
28 void World::load_from_XML(
29  const std::string& xml_text, const std::string& fileNameForPath)
30 {
31  using namespace std;
32  using namespace rapidxml;
33 
34  // Extract base path of file:
35  m_base_path =
37  // printf("[World] INFO: Using base path='%s'\n",m_base_path.c_str());
38 
39  auto lck = mrpt::lockHelper(m_world_cs); // Protect multithread access
40 
41  // Clear the existing world.
42  this->clear_all();
43 
44  // Parse the XML input:
46  char* input_str = const_cast<char*>(xml_text.c_str());
47  try
48  {
49  xml.parse<0>(input_str);
50  }
51  catch (rapidxml::parse_error& e)
52  {
53  unsigned int line =
54  static_cast<long>(std::count(input_str, e.where<char>(), '\n') + 1);
55  throw std::runtime_error(mrpt::format(
56  "XML parse error (Line %u): %s", static_cast<unsigned>(line),
57  e.what()));
58  }
59 
60  // Sanity checks:
61  const xml_node<>* root = xml.first_node();
62  if (!root)
63  throw runtime_error(
64  "XML parse error: No root node found (empty file?)");
65  if (0 != strcmp(root->name(), "mvsim_world"))
66  throw runtime_error(mrpt::format(
67  "XML root element is '%s' ('mvsim_world' expected)", root->name()));
68 
69  // Optional: format version attrib:
70  const xml_attribute<>* attrb_version = root->first_attribute("version");
71  int version_major = 1, version_min = 0;
72  if (attrb_version)
73  {
74  int ret = sscanf(
75  attrb_version->value(), "%i.%i", &version_major, &version_min);
76  if (ret != 2)
77  throw runtime_error(mrpt::format(
78  "Error parsing version attribute: '%s' ('%%i.%%i' "
79  "expected)",
80  attrb_version->value()));
81  }
82 
83  // Process all nodes:
84  // ------------------------------------------------
85  xml_node<>* node = root->first_node();
86  while (node)
87  {
88  // <element class='*'> entries:
89  if (!strcmp(node->name(), "element"))
90  {
92  m_world_elements.emplace_back(e);
93  m_simulableObjects.insert(
94  m_simulableObjects.end(),
95  std::make_pair(
96  e->getName(), std::dynamic_pointer_cast<Simulable>(e)));
97  }
98  // <vehicle> entries:
99  else if (!strcmp(node->name(), "vehicle"))
100  {
101  VehicleBase::Ptr veh = VehicleBase::factory(this, node);
102  // Assign each vehicle a unique "index" number
103  veh->setVehicleIndex(m_vehicles.size());
104 
105  MRPT_TODO("Check for duplicated names")
106  m_vehicles.insert(VehicleList::value_type(veh->getName(), veh));
107  m_simulableObjects.insert(
108  m_simulableObjects.end(),
109  std::make_pair(
110  veh->getName(), std::dynamic_pointer_cast<Simulable>(veh)));
111  }
112  // <vehicle:class> entries:
113  else if (!strcmp(node->name(), "vehicle:class"))
114  {
116  }
117  // <block> entries:
118  else if (!strcmp(node->name(), "block"))
119  {
120  Block::Ptr block = Block::factory(this, node);
121  insertBlock(block);
122  }
123  // <block:class> entries:
124  else if (!strcmp(node->name(), "block:class"))
125  {
127  }
128  // <gui> </gui> params:
129  else if (!strcmp(node->name(), "gui"))
130  {
131  m_gui_options.parse_from(*node);
132  }
133  // <walls> </walls> params:
134  else if (!strcmp(node->name(), "walls"))
135  {
136  process_load_walls(*node);
137  }
138  else
139  {
140  // Default: Check if it's a parameter:
141  if (!parse_xmlnode_as_param(*node, m_other_world_params))
142  {
143  // Unknown element!!
145  "[World::load_from_XML] *Warning* Ignoring "
146  "unknown XML node type '"
147  << node->name());
148  }
149  }
150 
151  // Move on to next node:
152  node = node->next_sibling(nullptr);
153  }
154 }
This file contains rapidxml parser and DOM implementation.
Ch * where() const
Definition: rapidxml.hpp:94
static Ptr factory(World *parent, const rapidxml::xml_node< char > *xml_node, const char *class_name=nullptr)
Ch * value() const
Definition: rapidxml.hpp:692
static Ptr factory(World *parent, const rapidxml::xml_node< char > *xml_node)
bool parse_xmlnode_as_param(const rapidxml::xml_node< char > &xml_node, const TParameterDefinitions &params, const std::map< std::string, std::string > &variableNamesValues={}, const char *functionNameContext="")
Definition: xml_utils.cpp:157
static Ptr factory(World *parent, const rapidxml::xml_node< char > *xml_node)
Definition: Block.cpp:68
#define MRPT_LOG_WARN_STREAM(__CONTENTS)
static void register_block_class(const rapidxml::xml_node< char > *xml_node)
Definition: Block.cpp:48
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
std::shared_ptr< Block > Ptr
Definition: Block.h:36
MRPT_TODO("Modify ping to run on Windows + Test this")
std::shared_ptr< WorldElementBase > Ptr
Ch * name() const
Definition: rapidxml.hpp:673
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
std::shared_ptr< VehicleBase > Ptr
Definition: VehicleBase.h:44
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)
T root(const T v0, const T v1)
xml_node< Ch > * next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Definition: rapidxml.hpp:1004
std::string BASE_IMPEXP trim(const std::string &str)
This file contains rapidxml printer implementation.
std::string BASE_IMPEXP extractFileDirectory(const std::string &filePath)


mvsim
Author(s):
autogenerated on Fri May 7 2021 03:05:51