xml_utils.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 
10 #include <mvsim/basic_types.h>
11 #include "xml_utils.h"
12 
13 #include <cstdio>
14 #include <mrpt/poses/CPose2D.h>
15 #include <mrpt/poses/CPose3D.h>
16 #include <mrpt/math/lightweight_geom_data.h>
17 #include <mrpt/system/string_utils.h>
18 
19 #include <mrpt/version.h>
20 #if MRPT_VERSION<0x199
21 #include <mrpt/utils/utils_defs.h> // mrpt::format()
22 #include <mrpt/utils/TColor.h>
23 using mrpt::utils::TColor;
24 using mrpt::utils::DEG2RAD;
25 using mrpt::utils::RAD2DEG;
26 #else
27 #include <mrpt/core/format.h>
28 #include <mrpt/core/bits_math.h>
29 #include <mrpt/img/TColor.h>
30 using mrpt::img::TColor;
31 using mrpt::DEG2RAD;
32 using mrpt::RAD2DEG;
33 #endif
34 
35 using namespace rapidxml;
36 using namespace mvsim;
37 
42 void TParamEntry::parse(
43  const std::string& str, const std::string& varName,
44  const char* function_name_context) const
45 {
46  // Special cases:
47  // "%s" ==> std::strings
48  if (std::string(frmt) == std::string("%s"))
49  {
50  char auxStr[512];
51  if (1 != ::sscanf(str.c_str(), frmt, auxStr))
52  throw std::runtime_error(
53  mrpt::format(
54  "%s Error parsing '%s'='%s' (Expected format:'%s')",
55  function_name_context, varName.c_str(), str.c_str(), frmt));
56  std::string& str = *reinterpret_cast<std::string*>(val);
57  str = mrpt::system::trim(auxStr);
58  }
59  // "%lf_deg" ==> DEG2RAD()
60  else if (std::string(frmt) == std::string("%lf_deg"))
61  {
62  if (1 != ::sscanf(str.c_str(), frmt, val))
63  throw std::runtime_error(
64  mrpt::format(
65  "%s Error parsing attribute '%s'='%s' (Expected "
66  "format:'%s')",
67  function_name_context, varName.c_str(), str.c_str(), frmt));
68  double& ang = *reinterpret_cast<double*>(val);
69  ang = DEG2RAD(ang);
70  }
71  // "%bool" ==> bool*
72  else if (std::string(frmt) == std::string("%bool"))
73  {
74  bool& bool_val = *reinterpret_cast<bool*>(val);
75 
76  const std::string sStr =
77  mrpt::system::lowerCase(mrpt::system::trim(std::string(str)));
78  if (sStr == "1" || sStr == "true")
79  bool_val = true;
80  else if (sStr == "0" || sStr == "false")
81  bool_val = false;
82  else
83  throw std::runtime_error(
84  mrpt::format(
85  "%s Error parsing 'bool' attribute '%s'='%s' (Expected "
86  "'true' or 'false')",
87  function_name_context, varName.c_str(), str.c_str()));
88  }
89  // "%color" ==> TColor
90  else if (std::string(frmt) == std::string("%color"))
91  {
92  // HTML-like format:
93  if (!(str.size() > 1 && str[0] == '#'))
94  throw std::runtime_error(
95  mrpt::format(
96  "%s Error parsing '%s'='%s' (Expected "
97  "format:'#RRGGBB[AA]')",
98  function_name_context, varName.c_str(), str.c_str()));
99 
100  unsigned int r, g, b, a = 0xff;
101  int ret = ::sscanf(str.c_str() + 1, "%2x%2x%2x%2x", &r, &g, &b, &a);
102  if (ret != 3 && ret != 4)
103  throw std::runtime_error(
104  mrpt::format(
105  "%s Error parsing '%s'='%s' (Expected "
106  "format:'#RRGGBB[AA]')",
107  function_name_context, varName.c_str(), str.c_str()));
108  TColor& col = *reinterpret_cast<TColor*>(val);
109  col = TColor(r, g, b, a);
110  }
111  // "%pose2d"
112  // "%pose2d_ptr3d"
113  else if (!strncmp(frmt, "%pose2d", strlen("%pose2d")))
114  {
115  double x, y, yaw;
116  int ret = ::sscanf(str.c_str(), "%lf %lf %lf", &x, &y, &yaw);
117  if (ret != 3)
118  throw std::runtime_error(
119  mrpt::format(
120  "%s Error parsing '%s'='%s' (Expected format:'X Y "
121  "YAW_DEG')",
122  function_name_context, varName.c_str(), str.c_str()));
123 
124  // User provides angles in deg:
125  yaw = DEG2RAD(yaw);
126 
127  const mrpt::poses::CPose2D p(x, y, yaw);
128 
129  // Sub-cases:
130  if (!strcmp(frmt, "%pose2d"))
131  {
132  mrpt::poses::CPose2D& pp =
133  *reinterpret_cast<mrpt::poses::CPose2D*>(val);
134  pp = p;
135  }
136  else if (!strcmp(frmt, "%pose2d_ptr3d"))
137  {
138  mrpt::poses::CPose3D& pp =
139  *reinterpret_cast<mrpt::poses::CPose3D*>(val);
140  pp = mrpt::poses::CPose3D(p);
141  }
142  else
143  throw std::runtime_error(
144  mrpt::format(
145  "%s Error: Unknown format specifier '%s'",
146  function_name_context, frmt));
147  }
148  else
149  {
150  // Generic parse:
151  if (1 != ::sscanf(str.c_str(), frmt, val))
152  throw std::runtime_error(
153  mrpt::format(
154  "%s Error parsing attribute '%s'='%s' (Expected "
155  "format:'%s')",
156  function_name_context, varName.c_str(), str.c_str(), frmt));
157  }
158 }
159 
162  const std::map<std::string, TParamEntry>& params,
163  const char* function_name_context)
164 {
165  for (std::map<std::string, TParamEntry>::const_iterator it = params.begin();
166  it != params.end(); ++it)
167  {
168  const rapidxml::xml_attribute<char>* attr =
169  xml_node.first_attribute(it->first.c_str());
170  if (attr && attr->value())
171  it->second.parse(
172  attr->value(), attr->name(), function_name_context);
173  }
174 }
175 
178  const std::map<std::string, TParamEntry>& params,
179  const char* function_name_context)
180 {
181  std::map<std::string, TParamEntry>::const_iterator it_param =
182  params.find(xml_node.name());
183 
184  if (it_param != params.end())
185  {
186  // parse parameter:
187  it_param->second.parse(
188  xml_node.value(), xml_node.name(), function_name_context);
189  return true;
190  }
191  return false;
192 }
193 
197  const rapidxml::xml_node<char>& root,
198  const std::map<std::string, TParamEntry>& params,
199  const char* function_name_context)
200 {
201  rapidxml::xml_node<>* node = root.first_node();
202  while (node)
203  {
204  parse_xmlnode_as_param(*node, params, function_name_context);
205  node = node->next_sibling(NULL); // Move on to next node
206  }
207 }
208 
215  const std::string& s, bool allow_missing_angle,
216  double default_angle_radians)
217 {
218  vec3 v;
219  v.vals[2] = RAD2DEG(default_angle_radians); // Default ang.
220 
221  int na =
222  ::sscanf(s.c_str(), "%lf %lf %lf", &v.vals[0], &v.vals[1], &v.vals[2]);
223 
224  // User provides numbers as degrees:
225  v.vals[2] = DEG2RAD(v.vals[2]);
226 
227  if ((na != 3 && !allow_missing_angle) ||
228  (na != 2 && na != 3 && allow_missing_angle))
229  throw std::runtime_error(
230  mrpt::format("Malformed pose string: '%s'", s.c_str()));
231 
232  return v;
233 }
234 
240  const rapidxml::xml_node<char>& xml_node, mrpt::math::TPolygon2D& out_poly,
241  const char* function_name_context)
242 {
243  out_poly.clear();
244 
245  for (rapidxml::xml_node<char>* pt_node = xml_node.first_node("pt"); pt_node;
246  pt_node = pt_node->next_sibling("pt"))
247  {
248  if (!pt_node->value())
249  throw std::runtime_error(
250  mrpt::format(
251  "%s Error: <pt> node seems empty.", function_name_context));
252 
253  mrpt::math::TPoint2D pt;
254  const char* str_val = pt_node->value();
255  if (2 != ::sscanf(str_val, "%lf %lf", &pt.x, &pt.y))
256  throw std::runtime_error(
257  mrpt::format(
258  "%s Error parsing <pt> node: '%s' (Expected format:'<pt>X "
259  "Y</pt>')",
260  function_name_context, str_val));
261 
262  out_poly.push_back(pt);
263  }
264 
265  if (out_poly.size() < 3)
266  throw std::runtime_error(
267  mrpt::format(
268  "%s Error: <shape> node requires 3 or more <pt>X Y</pt> "
269  "entries.",
270  function_name_context));
271 }
void parse_xmlnode_shape(const rapidxml::xml_node< char > &xml_node, mrpt::math::TPolygon2D &out_poly, const char *function_name_context="")
Definition: xml_utils.cpp:239
Ch * value() const
Definition: rapidxml.hpp:692
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
double vals[3]
Definition: basic_types.h:64
TFSIMD_FORCE_INLINE const tfScalar & y() const
xml_node< Ch > * first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Definition: rapidxml.hpp:936
void parse_xmlnode_attribs(const rapidxml::xml_node< char > &xml_node, const std::map< std::string, TParamEntry > &params, const char *function_name_context="")
Definition: xml_utils.cpp:160
void parse_xmlnode_children_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:196
Ch * name() const
Definition: rapidxml.hpp:673
xml_attribute< Ch > * first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Definition: rapidxml.hpp:1025
TFSIMD_FORCE_INLINE const tfScalar & x() const
vec3 parseXYPHI(const std::string &s, bool allow_missing_angle=false, double default_angle_radians=0.0)
Definition: xml_utils.cpp:214
xml_node< Ch > * next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Definition: rapidxml.hpp:1004


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