CARLA
RoadParser.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
2 // de Barcelona (UAB).
3 //
4 // This work is licensed under the terms of the MIT license.
5 // For a copy, see <https://opensource.org/licenses/MIT>.
6 
8 
9 #include "carla/Logging.h"
10 #include "carla/StringUtil.h"
11 #include "carla/road/MapBuilder.h"
12 #include "carla/road/RoadTypes.h"
13 
14 #include <pugixml/pugixml.hpp>
15 
16 namespace carla {
17 namespace opendrive {
18 namespace parser {
19 
20  using RoadId = road::RoadId;
23 
24  struct Polynomial {
25  double s;
26  double a, b, c, d;
27  };
28 
29  struct Lane {
32  bool level;
35  };
36 
37  struct LaneOffset {
38  double s;
39  double a, b, c, d;
40  };
41 
42  struct LaneSection {
43  double s;
44  std::vector<Lane> lanes;
45  };
46 
47  struct RoadTypeSpeed {
48  double s;
49  std::string type;
50  double max;
51  std::string unit;
52  };
53 
54  struct Road {
56  std::string name;
57  double length;
61  std::vector<RoadTypeSpeed> speed;
62  std::vector<LaneOffset> section_offsets;
63  std::vector<LaneSection> sections;
64  };
65 
66  static road::Lane::LaneType StringToLaneType(std::string &&str) {
68  if (str == "driving") {
70  } else if (str == "stop") {
72  } else if (str == "shoulder") {
74  } else if (str == "biking") {
76  } else if (str == "sidewalk") {
78  } else if (str == "border") {
80  } else if (str == "restricted") {
82  } else if (str == "parking") {
84  } else if (str == "bidirectional") {
86  } else if (str == "median") {
88  } else if (str == "special1") {
90  } else if (str == "special2") {
92  } else if (str == "special3") {
94  } else if (str == "roadworks") {
96  } else if (str == "tram") {
98  } else if (str == "rail") {
100  } else if (str == "entry") {
102  } else if (str == "exit") {
104  } else if (str == "offramp") {
106  } else if (str == "onramp") {
108  } else {
110  }
111  }
112 
114  const pugi::xml_document &xml,
115  carla::road::MapBuilder &map_builder) {
116 
117  std::vector<Road> roads;
118 
119  for (pugi::xml_node node_road : xml.child("OpenDRIVE").children("road")) {
120  Road road { 0, "", 0.0, -1, 0, 0, {}, {}, {} };
121 
122  // attributes
123  road.id = node_road.attribute("id").as_uint();
124  road.name = node_road.attribute("name").value();
125  road.length = node_road.attribute("length").as_double();
126  road.junction_id = node_road.attribute("junction").as_int();
127 
128  // link
129  pugi::xml_node link = node_road.child("link");
130  if (link) {
131  if (link.child("predecessor")) {
132  road.predecessor = link.child("predecessor").attribute("elementId").as_uint();
133  }
134  if (link.child("successor")) {
135  road.successor = link.child("successor").attribute("elementId").as_uint();
136  }
137  }
138 
139  // types
140  for (pugi::xml_node node_type : node_road.children("type")) {
141  RoadTypeSpeed type { 0.0, "", 0.0, "" };
142 
143  type.s = node_type.attribute("s").as_double();
144  type.type = node_type.attribute("type").value();
145 
146  // speed type
147  pugi::xml_node speed = node_type.child("speed");
148  if (speed) {
149  type.max = speed.attribute("max").as_double();
150  type.unit = speed.attribute("unit").value();
151  }
152 
153  // add it
154  road.speed.emplace_back(type);
155  }
156 
157  // section offsets
158  for (pugi::xml_node node_offset : node_road.child("lanes").children("laneOffset")) {
159  LaneOffset offset { 0.0, 0.0, 0.0, 0.0, 0.0 };
160  offset.s = node_offset.attribute("s").as_double();
161  offset.a = node_offset.attribute("a").as_double();
162  offset.b = node_offset.attribute("b").as_double();
163  offset.c = node_offset.attribute("c").as_double();
164  offset.d = node_offset.attribute("d").as_double();
165  road.section_offsets.emplace_back(offset);
166  }
167  // Add default lane offset if none is found
168  if(road.section_offsets.size() == 0) {
169  LaneOffset offset { 0.0, 0.0, 0.0, 0.0, 0.0 };
170  road.section_offsets.emplace_back(offset);
171  }
172 
173  // lane sections
174  for (pugi::xml_node node_section : node_road.child("lanes").children("laneSection")) {
175  LaneSection section { 0.0, {} };
176 
177  section.s = node_section.attribute("s").as_double();
178 
179  // left lanes
180  for (pugi::xml_node node_lane : node_section.child("left").children("lane")) {
181  Lane lane { 0, road::Lane::LaneType::None, false, 0, 0 };
182 
183  lane.id = node_lane.attribute("id").as_int();
184  lane.type = StringToLaneType(node_lane.attribute("type").value());
185  lane.level = node_lane.attribute("level").as_bool();
186 
187  // link
188  pugi::xml_node link2 = node_lane.child("link");
189  if (link2) {
190  if (link2.child("predecessor")) {
191  lane.predecessor = link2.child("predecessor").attribute("id").as_int();
192  }
193  if (link2.child("successor")) {
194  lane.successor = link2.child("successor").attribute("id").as_int();
195  }
196  }
197 
198  // add it
199  section.lanes.emplace_back(lane);
200  }
201 
202  // center lane
203  for (pugi::xml_node node_lane : node_section.child("center").children("lane")) {
204  Lane lane { 0, road::Lane::LaneType::None, false, 0, 0 };
205 
206  lane.id = node_lane.attribute("id").as_int();
207  lane.type = StringToLaneType(node_lane.attribute("type").value());
208  lane.level = node_lane.attribute("level").as_bool();
209 
210  // link (probably it never exists)
211  pugi::xml_node link2 = node_lane.child("link");
212  if (link2) {
213  if (link2.child("predecessor")) {
214  lane.predecessor = link2.child("predecessor").attribute("id").as_int();
215  }
216  if (link2.child("successor")) {
217  lane.successor = link2.child("successor").attribute("id").as_int();
218  }
219  }
220 
221  // add it
222  section.lanes.emplace_back(lane);
223  }
224 
225  // right lane
226  for (pugi::xml_node node_lane : node_section.child("right").children("lane")) {
227  Lane lane { 0, road::Lane::LaneType::None, false, 0, 0 };
228 
229  lane.id = node_lane.attribute("id").as_int();
230  lane.type = StringToLaneType(node_lane.attribute("type").value());
231  lane.level = node_lane.attribute("level").as_bool();
232 
233  // link
234  pugi::xml_node link2 = node_lane.child("link");
235  if (link2) {
236  if (link2.child("predecessor")) {
237  lane.predecessor = link2.child("predecessor").attribute("id").as_int();
238  }
239  if (link2.child("successor")) {
240  lane.successor = link2.child("successor").attribute("id").as_int();
241  }
242  }
243 
244  // add it
245  section.lanes.emplace_back(lane);
246  }
247 
248  // add section
249  road.sections.emplace_back(section);
250  }
251 
252  // add road
253  roads.emplace_back(road);
254  }
255 
256  // test print
257  /*
258  printf("Roads: %d\n", roads.size());
259  for (auto const r : roads) {
260  printf("Road: %d\n", r.id);
261  printf(" Name: %s\n", r.name.c_str());
262  printf(" Length: %e\n", r.length);
263  printf(" JunctionId: %d\n", r.junction_id);
264  printf(" Predecessor: %d\n", r.predecessor);
265  printf(" Successor: %d\n", r.successor);
266  printf(" Speed: %d\n", r.speed.size());
267  for (auto const s : r.speed) {
268  printf(" S offset: %e\n", s.s);
269  printf(" Type: %s\n", s.type.c_str());
270  printf(" Max: %e\n", s.max);
271  printf(" Unit: %s\n", s.unit.c_str());
272  }
273  printf("LaneSections: %d\n", r.sections.size());
274  for (auto const s : r.sections) {
275  printf(" S offset: %e\n", s.s);
276  printf(" a,b,c,d: %e,%e,%e,%e\n", s.a, s.b, s.c, s.d);
277  printf(" Lanes: %d\n", s.lanes.size());
278  for (auto const l : s.lanes) {
279  printf(" Id: %d\n", l.id);
280  printf(" Type: %s\n", l.type.c_str());
281  printf(" Level: %d\n", l.level);
282  printf(" Predecessor: %d\n", l.predecessor);
283  printf(" Successor: %d\n", l.successor);
284  }
285  }
286  }
287  */
288 
289  // map_builder calls
290  for (auto const r : roads) {
291  carla::road::Road *road = map_builder.AddRoad(r.id,
292  r.name,
293  r.length,
294  r.junction_id,
295  r.predecessor,
296  r.successor);
297 
298  // type speed
299  for (auto const s : r.speed) {
300  map_builder.CreateRoadSpeed(road, s.s, s.type, s.max, s.unit);
301  }
302 
303  // section offsets
304  for (auto const s : r.section_offsets) {
305  map_builder.CreateSectionOffset(road, s.s, s.a, s.b, s.c, s.d);
306  }
307 
308  // lane sections
309  road::SectionId i = 0;
310  for (auto const s : r.sections) {
311  carla::road::LaneSection *section = map_builder.AddRoadSection(road, i++, s.s);
312 
313  // lanes
314  for (auto const l : s.lanes) {
315  /*carla::road::Lane *lane = */ map_builder.AddRoadSectionLane(section, l.id,
316  static_cast<uint32_t>(l.type), l.level, l.predecessor, l.successor);
317  }
318  }
319  }
320  }
321 
322 } // namespace parser
323 } // namespace opendrive
324 } // namespace carla
const char_t * value() const
Definition: pugixml.cpp:5215
double as_double(double def=0) const
Definition: pugixml.cpp:5178
uint32_t RoadId
Definition: RoadTypes.h:15
unsigned int as_uint(unsigned int def=0) const
Definition: pugixml.cpp:5173
This file contains definitions of common data structures used in traffic manager. ...
Definition: Carla.cpp:133
void CreateSectionOffset(Road *road, const double s, const double a, const double b, const double c, const double d)
Definition: MapBuilder.cpp:440
uint32_t SectionId
Definition: RoadTypes.h:21
xml_attribute attribute(const char_t *name) const
Definition: pugixml.cpp:5500
int32_t JuncId
Definition: RoadTypes.h:17
static void Parse(const pugi::xml_document &xml, carla::road::MapBuilder &map_builder)
Definition: RoadParser.cpp:113
road::Lane::LaneType type
Definition: RoadParser.cpp:31
int as_int(int def=0) const
Definition: pugixml.cpp:5168
xml_node child(const char_t *name) const
Definition: pugixml.cpp:5490
carla::road::LaneSection * AddRoadSection(carla::road::Road *road, const SectionId id, const double s)
Definition: MapBuilder.cpp:378
carla::road::Lane * AddRoadSectionLane(carla::road::LaneSection *section, const LaneId lane_id, const uint32_t lane_type, const bool lane_level, const LaneId predecessor, const LaneId successor)
Definition: MapBuilder.cpp:388
static road::Lane::LaneType StringToLaneType(std::string &&str)
Definition: RoadParser.cpp:66
LaneType
Can be used as flags.
Definition: Lane.h:29
int32_t LaneId
Definition: RoadTypes.h:19
std::vector< LaneOffset > section_offsets
Definition: RoadParser.cpp:62
static void ToLower(WritableRangeT &str)
Definition: StringUtil.h:36
std::vector< RoadTypeSpeed > speed
Definition: RoadParser.cpp:61
void CreateRoadSpeed(Road *road, const double s, const std::string type, const double max, const std::string unit)
Definition: MapBuilder.cpp:430
std::vector< LaneSection > sections
Definition: RoadParser.cpp:63
xml_object_range< xml_node_iterator > children() const
Definition: pugixml.cpp:5425
carla::road::Road * AddRoad(const RoadId road_id, const std::string name, const double length, const JuncId junction_id, const RoadId predecessor, const RoadId successor)
Definition: MapBuilder.cpp:353