SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NIImporter_OpenDrive.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // Importer for networks stored in openDrive format
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
13 // Copyright (C) 2001-2014 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 #include <string>
34 #include <cmath>
35 #include <iterator>
39 #include <utils/common/ToString.h>
42 #include <netbuild/NBEdge.h>
43 #include <netbuild/NBEdgeCont.h>
44 #include <netbuild/NBNode.h>
45 #include <netbuild/NBNodeCont.h>
46 #include <netbuild/NBNetBuilder.h>
47 #include <netbuild/NBOwnTLDef.h>
55 #include <utils/xml/XMLSubSys.h>
56 #include <utils/geom/Boundary.h>
57 #include "NILoader.h"
58 #include "NIImporter_OpenDrive.h"
59 
60 #ifdef CHECK_MEMORY_LEAKS
61 #include <foreign/nvwa/debug_new.h>
62 #endif // CHECK_MEMORY_LEAKS
63 
64 
65 // ===========================================================================
66 // definitions
67 // ===========================================================================
68 #define C_LENGTH 10.
69 
70 
71 // ===========================================================================
72 // static variables
73 // ===========================================================================
95 
97 };
98 
99 
131 
133 };
134 
135 
138 
139 // ===========================================================================
140 // method definitions
141 // ===========================================================================
142 // ---------------------------------------------------------------------------
143 // static methods (interface in this case)
144 // ---------------------------------------------------------------------------
145 void
147  // check whether the option is set (properly)
148  if (!oc.isUsableFileList("opendrive-files")) {
149  return;
150  }
151  // prepare types
152  myImportAllTypes = oc.getBool("opendrive.import-all-lanes");
153  myImportWidths = !oc.getBool("opendrive.ignore-widths");
154  NBTypeCont& tc = nb.getTypeCont();
155  const SUMOReal WIDTH(3.65); // as wanted
156  const SVCPermissions defaultPermissions = SVCAll & ~SVC_PEDESTRIAN;
157  tc.insert("driving", 1, (SUMOReal)(80. / 3.6), 1, defaultPermissions, WIDTH, true, NBEdge::UNSPECIFIED_WIDTH);
158  tc.insert("mwyEntry", 1, (SUMOReal)(80. / 3.6), 1, defaultPermissions, WIDTH, true, NBEdge::UNSPECIFIED_WIDTH);
159  tc.insert("mwyExit", 1, (SUMOReal)(80. / 3.6), 1, defaultPermissions, WIDTH, true, NBEdge::UNSPECIFIED_WIDTH);
160  tc.insert("stop", 1, (SUMOReal)(80. / 3.6), 1, defaultPermissions, WIDTH, true, NBEdge::UNSPECIFIED_WIDTH);
161  tc.insert("special1", 1, (SUMOReal)(80. / 3.6), 1, defaultPermissions, WIDTH, true, NBEdge::UNSPECIFIED_WIDTH);
162  tc.insert("parking", 1, (SUMOReal)(5. / 3.6), 1, defaultPermissions, WIDTH, true, NBEdge::UNSPECIFIED_WIDTH);
163  // build the handler
164  std::map<std::string, OpenDriveEdge*> edges;
165  NIImporter_OpenDrive handler(tc, edges);
166  // parse file(s)
167  std::vector<std::string> files = oc.getStringVector("opendrive-files");
168  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
169  if (!FileHelpers::isReadable(*file)) {
170  WRITE_ERROR("Could not open opendrive file '" + *file + "'.");
171  return;
172  }
173  handler.setFileName(*file);
174  PROGRESS_BEGIN_MESSAGE("Parsing opendrive from '" + *file + "'");
175  XMLSubSys::runParser(handler, *file);
177  }
178  // split inner/outer edges
179  std::map<std::string, OpenDriveEdge*> innerEdges, outerEdges;
180  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
181  if ((*i).second->isInner) {
182  innerEdges[(*i).first] = (*i).second;
183  } else {
184  outerEdges[(*i).first] = (*i).second;
185  }
186  }
187 
188  // convert geometries into a discretised representation
189  computeShapes(edges);
190  // check whether lane sections are valid and whether further must be introduced
191  revisitLaneSections(tc, edges);
192 
193  // -------------------------
194  // node building
195  // -------------------------
196  // build nodes#1
197  // look at all links which belong to a node, collect their bounding boxes
198  // and place the node in the middle of this bounding box
199  std::map<std::string, Boundary> posMap;
200  std::map<std::string, std::string> edge2junction;
201  // compute node positions
202  for (std::map<std::string, OpenDriveEdge*>::iterator i = innerEdges.begin(); i != innerEdges.end(); ++i) {
203  OpenDriveEdge* e = (*i).second;
204  assert(e->junction != "-1" && e->junction != "");
205  edge2junction[e->id] = e->junction;
206  if (posMap.find(e->junction) == posMap.end()) {
207  posMap[e->junction] = Boundary();
208  }
209  posMap[e->junction].add(e->geom.getBoxBoundary());
210  }
211  // build nodes
212  for (std::map<std::string, Boundary>::iterator i = posMap.begin(); i != posMap.end(); ++i) {
213  if (!nb.getNodeCont().insert((*i).first, (*i).second.getCenter())) {
214  throw ProcessError("Could not add node '" + (*i).first + "'.");
215  }
216  }
217  // assign built nodes
218  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
219  OpenDriveEdge* e = (*i).second;
220  for (std::vector<OpenDriveLink>::iterator j = e->links.begin(); j != e->links.end(); ++j) {
221  OpenDriveLink& l = *j;
222  if (l.elementType != OPENDRIVE_ET_ROAD) {
223  // set node information
225  continue;
226  }
227  if (edge2junction.find(l.elementID) != edge2junction.end()) {
228  // set node information of an internal road
229  setNodeSecure(nb.getNodeCont(), *e, edge2junction[l.elementID], l.linkType);
230  continue;
231  }
232  }
233  }
234  // we should now have all nodes set for links which are not outer edge-to-outer edge links
235 
236 
237  // build nodes#2
238  // build nodes for all outer edge-to-outer edge connections
239  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
240  OpenDriveEdge* e = (*i).second;
241  for (std::vector<OpenDriveLink>::iterator j = e->links.begin(); j != e->links.end(); ++j) {
242  OpenDriveLink& l = *j;
243  if (l.elementType != OPENDRIVE_ET_ROAD || edge2junction.find(l.elementID) != edge2junction.end()) {
244  // is a connection to an internal edge, or a node, skip
245  continue;
246  }
247  // we have a direct connection between to external edges
248  std::string id1 = e->id;
249  std::string id2 = l.elementID;
250  if (id1 < id2) {
251  std::swap(id1, id2);
252  }
253  std::string nid = id1 + "." + id2;
254  if (nb.getNodeCont().retrieve(nid) == 0) {
255  // not yet seen, build
256  Position pos = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e->geom[-1] : e->geom[0];
257  if (!nb.getNodeCont().insert(nid, pos)) {
258  throw ProcessError("Could not build node '" + nid + "'.");
259  }
260  }
261  /* debug-stuff
262  else {
263  Position pos = l.linkType==OPENDRIVE_LT_SUCCESSOR ? e.geom[e.geom.size()-1] : e.geom[0];
264  cout << nid << " " << pos << " " << nb.getNodeCont().retrieve(nid)->getPosition() << endl;
265  }
266  */
267  setNodeSecure(nb.getNodeCont(), *e, nid, l.linkType);
268  }
269  }
270  // we should now have start/end nodes for all outer edge-to-outer edge connections
271 
272 
273  // build nodes#3
274  // assign further nodes generated from inner-edges
275  // these nodes have not been assigned earlier, because the connectiosn are referenced in inner-edges
276  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
277  OpenDriveEdge* e = (*i).second;
278  if (e->to != 0 && e->from != 0) {
279  continue;
280  }
281  for (std::map<std::string, OpenDriveEdge*>::iterator j = innerEdges.begin(); j != innerEdges.end(); ++j) {
282  OpenDriveEdge* ie = (*j).second;
283  for (std::vector<OpenDriveLink>::iterator k = ie->links.begin(); k != ie->links.end(); ++k) {
284  OpenDriveLink& il = *k;
285  if (il.elementType != OPENDRIVE_ET_ROAD || il.elementID != e->id) {
286  // not conneted to the currently investigated outer edge
287  continue;
288  }
289  std::string nid = edge2junction[ie->id];
290  if (il.contactPoint == OPENDRIVE_CP_START) {
292  } else {
294  }
295  }
296  }
297 
298  }
299 
300  // build start/end nodes which were not defined previously
301  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
302  OpenDriveEdge* e = (*i).second;
303  if (e->from == 0) {
304  const std::string nid = e->id + ".begin";
305  e->from = getOrBuildNode(nid, e->geom.front(), nb.getNodeCont());
306  }
307  if (e->to == 0) {
308  const std::string nid = e->id + ".end";
309  e->to = getOrBuildNode(nid, e->geom.back(), nb.getNodeCont());
310  }
311  }
312 
313 
314  // -------------------------
315  // edge building
316  // -------------------------
317  SUMOReal defaultSpeed = tc.getSpeed("");
318  // build edges
319  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
320  OpenDriveEdge* e = (*i).second;
321  bool lanesBuilt = false;
322 
323  // go along the lane sections, build a node in between of each pair
324 
327 
329  NBNode* sFrom = e->from;
330  NBNode* sTo = e->to;
331  int priorityR = e->getPriority(OPENDRIVE_TAG_RIGHT);
332  int priorityL = e->getPriority(OPENDRIVE_TAG_LEFT);
333  SUMOReal sB = 0;
334  SUMOReal sE = e->length;
335  SUMOReal cF = e->length / e->geom.length2D();
336  NBEdge* prevRight = 0;
337  NBEdge* prevLeft = 0;
338 
339  // starting at the same node as ending, and no lane sections?
340  if (sFrom == sTo && e->laneSections.size() == 1) {
341  // --> loop, split!
343  ls.s = e->length / 2.;
344  e->laneSections.push_back(ls);
345  WRITE_WARNING("Edge '" + e->id + "' has to be split as it connects same junctions.")
346  }
347 
348  // build along lane sections
349  for (std::vector<OpenDriveLaneSection>::iterator j = e->laneSections.begin(); j != e->laneSections.end(); ++j) {
350  // add internal node if needed
351  if (j == e->laneSections.end() - 1) {
352  sTo = e->to;
353  sE = e->length / cF;
354  } else {
355  SUMOReal nextS = (j + 1)->s;
356  sTo = new NBNode(e->id + "." + toString(nextS), e->geom.positionAtOffset(nextS));
357  if (!nb.getNodeCont().insert(sTo)) {
358  throw ProcessError("Could not add node '" + sTo->getID() + "'.");
359  }
360  sE = nextS / cF;
361  }
362  PositionVector geom = e->geom.getSubpart2D(sB, sE);
363  std::string id = e->id;
364  if (sFrom != e->from || sTo != e->to) {
365  id = id + "." + toString((*j).s);
366  } else if (e->laneSections.size() == 1) {
367  id = id + ".0.00";
368  }
369 
370  // build lanes to right
371  NBEdge* currRight = 0;
372  if ((*j).rightLaneNumber > 0) {
373  currRight = new NBEdge("-" + id, sFrom, sTo, "", defaultSpeed, (*j).rightLaneNumber, priorityR,
375  if (!nb.getEdgeCont().insert(currRight)) {
376  throw ProcessError("Could not add edge '" + currRight->getID() + "'.");
377  }
378  lanesBuilt = true;
379  const std::vector<OpenDriveLane>& lanes = (*j).lanesByDir[OPENDRIVE_TAG_RIGHT];
380  for (std::vector<OpenDriveLane>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
381  std::map<int, int>::const_iterator lp = (*j).laneMap.find((*k).id);
382  if (lp != (*j).laneMap.end()) {
383  int sumoLaneIndex = lp->second;
384  NBEdge::Lane& sumoLane = currRight->getLaneStruct(sumoLaneIndex);
385  const OpenDriveLane& odLane = *k;
386 
387  sumoLane.origID = e->id + " -" + toString((*k).id);
388  sumoLane.speed = odLane.speed != 0 ? odLane.speed : tc.getSpeed(odLane.type);
389  sumoLane.permissions = tc.getPermissions(odLane.type);
390  sumoLane.width = myImportWidths && odLane.width != 0 ? odLane.width : tc.getWidth(odLane.type);
391  }
392  }
393  // connect lane sections
394  if (prevRight != 0) {
395  std::map<int, int> connections = (*j).getInnerConnections(OPENDRIVE_TAG_RIGHT, *(j - 1));
396  for (std::map<int, int>::const_iterator k = connections.begin(); k != connections.end(); ++k) {
397  prevRight->addLane2LaneConnection((*k).first, currRight, (*k).second, NBEdge::L2L_VALIDATED);
398  }
399  }
400  prevRight = currRight;
401  }
402 
403  // build lanes to left
404  NBEdge* currLeft = 0;
405  if ((*j).leftLaneNumber > 0) {
406  currLeft = new NBEdge(id, sTo, sFrom, "", defaultSpeed, (*j).leftLaneNumber, priorityL,
408  if (!nb.getEdgeCont().insert(currLeft)) {
409  throw ProcessError("Could not add edge '" + currLeft->getID() + "'.");
410  }
411  lanesBuilt = true;
412  const std::vector<OpenDriveLane>& lanes = (*j).lanesByDir[OPENDRIVE_TAG_LEFT];
413  for (std::vector<OpenDriveLane>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
414  std::map<int, int>::const_iterator lp = (*j).laneMap.find((*k).id);
415  if (lp != (*j).laneMap.end()) {
416  int sumoLaneIndex = lp->second;
417  NBEdge::Lane& sumoLane = currLeft->getLaneStruct(sumoLaneIndex);
418  const OpenDriveLane& odLane = *k;
419 
420  sumoLane.origID = e->id + " " + toString((*k).id);
421  sumoLane.speed = odLane.speed != 0 ? odLane.speed : tc.getSpeed(odLane.type);
422  sumoLane.permissions = tc.getPermissions(odLane.type);
423  sumoLane.width = myImportWidths && odLane.width != 0 ? odLane.width : tc.getWidth(odLane.type);
424  }
425  }
426  // connect lane sections
427  if (prevLeft != 0) {
428  std::map<int, int> connections = (*j).getInnerConnections(OPENDRIVE_TAG_LEFT, *(j - 1));
429  for (std::map<int, int>::const_iterator k = connections.begin(); k != connections.end(); ++k) {
430  currLeft->addLane2LaneConnection((*k).first, prevLeft, (*k).second, NBEdge::L2L_VALIDATED);
431  }
432  }
433  prevLeft = currLeft;
434  }
435  (*j).sumoID = id;
436 
437 
438  sB = sE;
439  sFrom = sTo;
440  }
441  if (!lanesBuilt) {
442  WRITE_WARNING("Edge '" + e->id + "' has no lanes.");
443  }
444  }
445 
446  // -------------------------
447  // connections building
448  // -------------------------
449  // generate explicit lane-to-lane connections
450  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
451  setEdgeLinks2(*(*i).second, edges);
452  }
453  // compute connections across intersections, if any
454  std::vector<Connection> connections2;
455  for (std::map<std::string, OpenDriveEdge*>::iterator j = edges.begin(); j != edges.end(); ++j) {
456  const std::set<Connection>& conns = (*j).second->connections;
457 
458  for (std::set<Connection>::const_iterator i = conns.begin(); i != conns.end(); ++i) {
459  if (innerEdges.find((*i).fromEdge) != innerEdges.end()) {
460  // connections starting at inner edges are processed by starting from outer edges
461  continue;
462  }
463  if (innerEdges.find((*i).toEdge) != innerEdges.end()) {
464  buildConnectionsToOuter(*i, innerEdges, connections2);
465  } else {
466  connections2.push_back(*i);
467  }
468  }
469  }
470  // set connections
471  for (std::vector<Connection>::const_iterator i = connections2.begin(); i != connections2.end(); ++i) {
472  std::string fromEdge = (*i).fromEdge;
473  if (edges.find(fromEdge) == edges.end()) {
474  WRITE_WARNING("While setting connections: from-edge '" + fromEdge + "' is not known.");
475  continue;
476  }
477  OpenDriveEdge* odFrom = edges[fromEdge];
478  int fromLane = (*i).fromLane;
479  bool fromLast = ((*i).fromCP == OPENDRIVE_CP_END) ^ ((*i).fromLane > 0 && !(*i).all);
480  fromEdge = fromLast ? odFrom->laneSections.back().sumoID : odFrom->laneSections[0].sumoID;
481 
482  std::string toEdge = (*i).toEdge;
483  if (edges.find(toEdge) == edges.end()) {
484  WRITE_WARNING("While setting connections: to-edge '" + toEdge + "' is not known.");
485  continue;
486  }
487 
488  OpenDriveEdge* odTo = edges[toEdge];
489  int toLane = (*i).toLane;
490  bool toLast = ((*i).toCP == OPENDRIVE_CP_END) || ((*i).toLane > 0);
491  toEdge = toLast ? odTo->laneSections.back().sumoID : odTo->laneSections[0].sumoID;
492 
493  if (fromLane == UNSET_CONNECTION) {
494  fromLane = toLast ? odTo->laneSections.back().laneMap.begin()->first : odTo->laneSections[0].laneMap.begin()->first;
495  }
496  if (fromLane < 0) {
497  fromEdge = revertID(fromEdge);
498  }
499  if (toLane == UNSET_CONNECTION) {
500  toLane = toLast ? odTo->laneSections.back().laneMap.begin()->first : odTo->laneSections[0].laneMap.begin()->first;
501  }
502  if (toLane < 0) {
503  toEdge = revertID(toEdge);
504  }
505  fromLane = fromLast ? odFrom->laneSections.back().laneMap[fromLane] : odFrom->laneSections[0].laneMap[fromLane];
506  toLane = toLast ? odTo->laneSections.back().laneMap[toLane] : odTo->laneSections[0].laneMap[toLane];
507  NBEdge* from = nb.getEdgeCont().retrieve(fromEdge);
508  NBEdge* to = nb.getEdgeCont().retrieve(toEdge);
509  if (from == 0) {
510  WRITE_WARNING("Could not find fromEdge representation of '" + fromEdge + "' in connection '" + (*i).origID + "'.");
511  }
512  if (to == 0) {
513  WRITE_WARNING("Could not find fromEdge representation of '" + toEdge + "' in connection '" + (*i).origID + "'.");
514  }
515  if (from == 0 || to == 0) {
516  continue;
517  }
518 
519  from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER);
520 
521  if ((*i).origID != "") {
522  // @todo: this is the most silly way to determine the connection
523  std::vector<NBEdge::Connection>& cons = from->getConnections();
524  for (std::vector<NBEdge::Connection>::iterator k = cons.begin(); k != cons.end(); ++k) {
525  if ((*k).fromLane == fromLane && (*k).toEdge == to && (*k).toLane == toLane) {
526  (*k).origID = (*i).origID + " " + toString((*i).origLane);
527  break;
528  }
529  }
530  }
531  }
532 
533 
534  // -------------------------
535  // traffic lights
536  // -------------------------
537  std::map<std::string, std::string> tlsControlled;
538  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
539  OpenDriveEdge* e = (*i).second;
540  for (std::vector<OpenDriveSignal>::const_iterator j = e->signals.begin(); j != e->signals.end(); ++j) {
541  if ((*j).type != "1000001") {
542  continue;
543  }
544  std::vector<OpenDriveLaneSection>::iterator k = e->laneSections.begin();
545  bool found = false;
546  for (; k != e->laneSections.end() - 1 && !found;) {
547  if ((*j).s > (*k).s && (*j).s <= (*(k + 1)).s) {
548  found = true;
549  } else {
550  ++k;
551  }
552  }
553 
554  // @todo: major problem, currently, still not completely solved:
555  // inner edges may have traffic lights, too. Nice on one hand, as directions can be recognized
556  // but hard to follow backwards
557  std::string id = (*k).sumoID;
558  if (id == "") {
559  if (e->junction != "") {
560  //WRITE_WARNING("Found a traffic light signal on an internal edge; will not build it (original edge id='" + e->id + "').");
561  std::string fromID, toID;
562  for (std::vector<OpenDriveLink>::const_iterator l = e->links.begin(); l != e->links.end(); ++l) {
563  if ((*l).linkType == OPENDRIVE_LT_PREDECESSOR && (*l).elementType == OPENDRIVE_ET_ROAD) {
564  if (fromID != "") {
565  WRITE_WARNING("Ambigous start of connection.");
566  }
567  fromID = (*l).elementID;
568  OpenDriveEdge* e = edges[fromID];
569  fromID = (*l).contactPoint == OPENDRIVE_CP_START ? e->laneSections[0].sumoID : e->laneSections.back().sumoID;
570  }
571  if ((*l).linkType == OPENDRIVE_LT_SUCCESSOR && (*l).elementType == OPENDRIVE_ET_ROAD) {
572  if (toID != "") {
573  WRITE_WARNING("Ambigous end of connection.");
574  }
575  toID = (*l).elementID;
576  OpenDriveEdge* e = edges[toID];
577  toID = (*l).contactPoint == OPENDRIVE_CP_START ? e->laneSections[0].sumoID : e->laneSections.back().sumoID;
578  }
579  }
580  id = fromID + "->" + toID;
581  } else {
582  WRITE_WARNING("Found a traffic light signal on an unknown edge (original edge id='" + e->id + "').");
583  continue;
584  }
585  }
586 
587  if ((*j).orientation > 0) {
588  id = "-" + id;
589  }
590  tlsControlled[id] = (*j).name;
591  }
592  }
593 
594  for (std::map<std::string, std::string>::iterator i = tlsControlled.begin(); i != tlsControlled.end(); ++i) {
595  std::string id = (*i).first;
596  if (id.find("->") != std::string::npos) {
597  id = id.substr(0, id.find("->"));
598  }
599  NBEdge* e = nb.getEdgeCont().retrieve(id);
600  if (e == 0) {
601  WRITE_WARNING("Could not find edge '" + id + "' while building its traffic light.");
602  continue;
603  }
604  NBNode* toNode = e->getToNode();
605  NBTrafficLightDefinition* tlDef = 0;
606  if (!toNode->isTLControlled()) {
608  tlDef = new NBOwnTLDef(toNode->getID(), toNode, 0, type);
609  if (!nb.getTLLogicCont().insert(tlDef)) {
610  // actually, nothing should fail here
611  delete tlDef;
612  throw ProcessError();
613  }
614  toNode->addTrafficLight(tlDef);
615  static_cast<NBOwnTLDef*>(tlDef)->setSinglePhase();
616  }
617  tlDef = *toNode->getControllingTLS().begin();
618  tlDef->addParameter("connection:" + id, (*i).second);
619  }
620 
621  // -------------------------
622  // clean up
623  // -------------------------
624  if (oc.exists("geometry.min-dist") && oc.isSet("geometry.min-dist")) {
625  oc.unSet("geometry.min-dist");
626  }
627  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
628  delete(*i).second;
629  }
630 }
631 
632 
633 
634 void
635 NIImporter_OpenDrive::buildConnectionsToOuter(const Connection& c, const std::map<std::string, OpenDriveEdge*>& innerEdges, std::vector<Connection>& into) {
636 
637  OpenDriveEdge* dest = innerEdges.find(c.toEdge)->second;
638  if (dest == 0) {
640  return;
641  }
642  const std::set<Connection>& conts = dest->connections;
643  for (std::set<Connection>::const_iterator i = conts.begin(); i != conts.end(); ++i) {
644  if (innerEdges.find((*i).toEdge) != innerEdges.end()) {
645  std::vector<Connection> t;
646  buildConnectionsToOuter(*i, innerEdges, t);
647  for (std::vector<Connection>::const_iterator j = t.begin(); j != t.end(); ++j) {
648  // @todo this section is unverified
649  Connection cn = (*j);
650  cn.fromEdge = c.fromEdge;
651  cn.fromLane = c.fromLane;
652  cn.fromCP = c.fromCP;
653  cn.all = c.all; // @todo "all" is a hack trying to avoid the "from is zero" problem;
654  into.push_back(cn);
655  }
656  } else {
657  if ((*i).fromLane == c.toLane) {
658  Connection cn = (*i);
659  cn.fromEdge = c.fromEdge;
660  cn.fromLane = c.fromLane;
661  cn.fromCP = c.fromCP;
662  cn.all = c.all;
663  cn.origID = c.toEdge;
664  cn.origLane = c.toLane;
665  into.push_back(cn);
666  }
667  }
668  }
669 }
670 
671 
672 void
673 NIImporter_OpenDrive::setEdgeLinks2(OpenDriveEdge& e, const std::map<std::string, OpenDriveEdge*>& edges) {
674  for (std::vector<OpenDriveLink>::iterator i = e.links.begin(); i != e.links.end(); ++i) {
675  OpenDriveLink& l = *i;
676  if (l.elementType != OPENDRIVE_ET_ROAD) {
677  // we assume that links to nodes are later given as connections to edges
678  continue;
679  }
680  // get the right direction of the connected edge
681  std::string connectedEdge = l.elementID;
682  std::string edgeID = e.id;
683 
684  OpenDriveLaneSection& laneSection = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e.laneSections.back() : e.laneSections[0];
685  const std::map<int, int>& laneMap = laneSection.laneMap;
686  if (laneSection.lanesByDir.find(OPENDRIVE_TAG_RIGHT) != laneSection.lanesByDir.end()) {
687  const std::vector<OpenDriveLane>& lanes = laneSection.lanesByDir.find(OPENDRIVE_TAG_RIGHT)->second;
688  for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
689  if (!myImportAllTypes && laneMap.find((*j).id) == laneMap.end()) {
690  continue;
691  }
692  Connection c; // @todo: give Connection a new name and a constructor
693  c.fromEdge = e.id;
694  c.fromLane = (*j).id;
696  c.toLane = l.linkType == OPENDRIVE_LT_SUCCESSOR ? (*j).successor : (*j).predecessor;
697  c.toEdge = connectedEdge;
698  c.toCP = l.contactPoint;
699  c.all = false;
700  if (l.linkType != OPENDRIVE_LT_SUCCESSOR) {
701  std::swap(c.fromEdge, c.toEdge);
702  std::swap(c.fromLane, c.toLane);
703  std::swap(c.fromCP, c.toCP);
704  }
705  if (edges.find(c.fromEdge) == edges.end()) {
706  WRITE_ERROR("While setting connections: incoming road '" + c.fromEdge + "' is not known.");
707  } else {
708  OpenDriveEdge* src = edges.find(c.fromEdge)->second;
709  src->connections.insert(c);
710  }
711  }
712  }
713  if (laneSection.lanesByDir.find(OPENDRIVE_TAG_LEFT) != laneSection.lanesByDir.end()) {
714  const std::vector<OpenDriveLane>& lanes = laneSection.lanesByDir.find(OPENDRIVE_TAG_LEFT)->second;
715  for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
716  if (!myImportAllTypes && laneMap.find((*j).id) == laneMap.end()) {
717  continue;
718  }
719  Connection c;
720  c.toEdge = e.id;
721  c.toLane = (*j).id;
723  c.fromLane = l.linkType == OPENDRIVE_LT_SUCCESSOR ? (*j).successor : (*j).predecessor;
724  c.fromEdge = connectedEdge;
725  c.fromCP = l.contactPoint;
726  c.all = false;
727  if (l.linkType != OPENDRIVE_LT_SUCCESSOR) {
728  std::swap(c.fromEdge, c.toEdge);
729  std::swap(c.fromLane, c.toLane);
730  std::swap(c.fromCP, c.toCP);
731  }
732  if (edges.find(c.fromEdge) == edges.end()) {
733  WRITE_ERROR("While setting connections: incoming road '" + c.fromEdge + "' is not known.");
734  } else {
735  OpenDriveEdge* src = edges.find(c.fromEdge)->second;
736  src->connections.insert(c);
737  }
738  }
739  }
740  }
741 }
742 
743 
744 std::string NIImporter_OpenDrive::revertID(const std::string& id) {
745  if (id[0] == '-') {
746  return id.substr(1);
747  }
748  return "-" + id;
749 }
750 
751 NBNode*
752 NIImporter_OpenDrive::getOrBuildNode(const std::string& id, const Position& pos,
753  NBNodeCont& nc) {
754  if (nc.retrieve(id) == 0) {
755  // not yet built; build now
756  if (!nc.insert(id, pos)) {
757  // !!! clean up
758  throw ProcessError("Could not add node '" + id + "'.");
759  }
760  }
761  return nc.retrieve(id);
762 }
763 
764 
765 void
767  const std::string& nodeID, NIImporter_OpenDrive::LinkType lt) {
768  NBNode* n = nc.retrieve(nodeID);
769  if (n == 0) {
770  throw ProcessError("Could not find node '" + nodeID + "'.");
771  }
772  if (lt == OPENDRIVE_LT_SUCCESSOR) {
773  if (e.to != 0 && e.to != n) {
774  throw ProcessError("Edge '" + e.id + "' has two end nodes.");
775  }
776  e.to = n;
777  } else {
778  if (e.from != 0 && e.from != n) {
779  throw ProcessError("Edge '" + e.id + "' has two start nodes.");
780  }
781  e.from = n;
782  }
783 }
784 
785 
786 
787 
788 
789 
790 
791 void
792 NIImporter_OpenDrive::computeShapes(std::map<std::string, OpenDriveEdge*>& edges) {
794  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
795  OpenDriveEdge& e = *(*i).second;
796  for (std::vector<OpenDriveGeometry>::iterator j = e.geometries.begin(); j != e.geometries.end(); ++j) {
797  OpenDriveGeometry& g = *j;
798  std::vector<Position> geom;
799  switch (g.type) {
801  break;
802  case OPENDRIVE_GT_LINE:
803  geom = geomFromLine(e, g);
804  break;
805  case OPENDRIVE_GT_SPIRAL:
806  geom = geomFromSpiral(e, g);
807  break;
808  case OPENDRIVE_GT_ARC:
809  geom = geomFromArc(e, g);
810  break;
811  case OPENDRIVE_GT_POLY3:
812  geom = geomFromPoly(e, g);
813  break;
814  default:
815  break;
816  }
817  for (std::vector<Position>::iterator k = geom.begin(); k != geom.end(); ++k) {
819  }
820  }
821  if (oc.exists("geometry.min-dist") && oc.isSet("geometry.min-dist")) {
822  e.geom.removeDoublePoints(oc.getFloat("geometry.min-dist"), true);
823  }
824  for (unsigned int j = 0; j < e.geom.size(); ++j) {
826  WRITE_ERROR("Unable to project coordinates for.");
827  }
828  }
829  }
830 }
831 
832 
833 void
834 NIImporter_OpenDrive::revisitLaneSections(const NBTypeCont& tc, std::map<std::string, OpenDriveEdge*>& edges) {
835  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
836  OpenDriveEdge& e = *(*i).second;
837  std::vector<OpenDriveLaneSection>& laneSections = e.laneSections;
838  // split by speed limits
839  std::vector<OpenDriveLaneSection> newSections;
840  for (std::vector<OpenDriveLaneSection>::iterator j = laneSections.begin(); j != laneSections.end(); ++j) {
841  std::vector<OpenDriveLaneSection> splitSections;
842  bool splitBySpeed = (*j).buildSpeedChanges(tc, splitSections);
843  if (!splitBySpeed) {
844  newSections.push_back(*j);
845  } else {
846  std::copy(splitSections.begin(), splitSections.end(), back_inserter(newSections));
847  }
848  }
849 
850  e.laneSections = newSections;
851  laneSections = e.laneSections;
852  SUMOReal lastS = -1;
853  // check whether the lane sections are in the right order
854  bool sorted = true;
855  for (std::vector<OpenDriveLaneSection>::const_iterator j = laneSections.begin(); j != laneSections.end() && sorted; ++j) {
856  if ((*j).s <= lastS) {
857  sorted = false;
858  }
859  lastS = (*j).s;
860  }
861  if (!sorted) {
862  WRITE_WARNING("The sections of edge '" + e.id + "' are not sorted properly.");
863  sort(e.laneSections.begin(), e.laneSections.end(), sections_by_s_sorter());
864  }
865  // check whether no duplicates of s-value occure
866  lastS = -1;
867  laneSections = e.laneSections;
868  for (std::vector<OpenDriveLaneSection>::iterator j = laneSections.begin(); j != laneSections.end();) {
869  bool simlarToLast = fabs((*j).s - lastS) < POSITION_EPS;
870  lastS = (*j).s;
871  if (simlarToLast) {
872  WRITE_WARNING("Almost duplicate s-value '" + toString(lastS) + "' for lane sections occured at edge '" + e.id + "'; second entry was removed.");
873  j = laneSections.erase(j);
874  } else {
875  ++j;
876  }
877  }
878  }
879 }
880 
881 
882 std::vector<Position>
884  UNUSED_PARAMETER(e);
885  std::vector<Position> ret;
886  ret.push_back(Position(g.x, g.y));
887  ret.push_back(calculateStraightEndPoint(g.hdg, g.length, Position(g.x, g.y)));
888  return ret;
889 }
890 
891 
892 std::vector<Position>
894  UNUSED_PARAMETER(e);
895  std::vector<Position> ret;
896  SUMOReal curveStart = g.params[0];
897  SUMOReal curveEnd = g.params[1];
898  Point2D<double> end;
899  EulerSpiral s(Point2D<double>(g.x, g.y), g.hdg, curveStart, (curveEnd - curveStart) / g.length, g.length);
900  std::vector<Point2D<double> > into;
901  s.computeSpiral(into, 1.);
902  for (std::vector<Point2D<double> >::iterator i = into.begin(); i != into.end(); ++i) {
903  ret.push_back(Position((*i).getX(), (*i).getY()));
904  }
905  return ret;
906 }
907 
908 
909 std::vector<Position>
911  UNUSED_PARAMETER(e);
912  std::vector<Position> ret;
913  SUMOReal dist = 0.0;
914  SUMOReal centerX = g.x;
915  SUMOReal centerY = g.y;
916  // left: positive value
917  SUMOReal curvature = g.params[0];
918  SUMOReal radius = 1. / curvature;
919  // center point
920  calculateCurveCenter(&centerX, &centerY, radius, g.hdg);
921  SUMOReal endX = g.x;
922  SUMOReal endY = g.y;
923  SUMOReal startX = g.x;
924  SUMOReal startY = g.y;
925  SUMOReal geo_posS = g.s;
926  SUMOReal geo_posE = g.s;
927  bool end = false;
928  do {
929  geo_posE += C_LENGTH;
930  if (geo_posE - g.s > g.length) {
931  geo_posE = g.s + g.length;
932  }
933  if (geo_posE - g.s > g.length) {
934  geo_posE = g.s + g.length;
935  }
936  calcPointOnCurve(&endX, &endY, centerX, centerY, radius, geo_posE - geo_posS);
937 
938  dist += (geo_posE - geo_posS);
939  //
940  ret.push_back(Position(startX, startY));
941  //
942  startX = endX;
943  startY = endY;
944  geo_posS = geo_posE;
945 
946  if (geo_posE - (g.s + g.length) < 0.001 && geo_posE - (g.s + g.length) > -0.001) {
947  end = true;
948  }
949  } while (!end);
950  return ret;
951 }
952 
953 
954 std::vector<Position>
956  UNUSED_PARAMETER(e);
957  std::vector<Position> ret;
958  for (SUMOReal off = 0; off < g.length + 2.; off += 2.) {
959  SUMOReal x = off;
960  SUMOReal y = g.params[0] + g.params[1] * off + g.params[2] * pow(off, 2.) + g.params[3] * pow(off, 3.);
961  SUMOReal s = sin(g.hdg);
962  SUMOReal c = cos(g.hdg);
963  SUMOReal xnew = x * c - y * s;
964  SUMOReal ynew = x * s + y * c;
965  ret.push_back(Position(g.x + xnew, g.y + ynew));
966  }
967  return ret;
968 }
969 
970 
971 Position
972 NIImporter_OpenDrive::calculateStraightEndPoint(double hdg, double length, const Position& start) {
973  double normx = 1.0f;
974  double normy = 0.0f;
975  double x2 = normx * cos(hdg) - normy * sin(hdg);
976  double y2 = normx * sin(hdg) + normy * cos(hdg);
977  normx = x2 * length;
978  normy = y2 * length;
979  return Position(start.x() + normx, start.y() + normy);
980 }
981 
982 
983 void
985  SUMOReal normX = 1.0;
986  SUMOReal normY = 0.0;
987  SUMOReal tmpX;
988  SUMOReal turn;
989  if (ad_radius > 0) {
990  turn = -1.0;
991  } else {
992  turn = 1.0;
993  }
994 
995  tmpX = normX;
996  normX = normX * cos(ad_hdg) + normY * sin(ad_hdg);
997  normY = tmpX * sin(ad_hdg) + normY * cos(ad_hdg);
998 
999  tmpX = normX;
1000  normX = turn * normY;
1001  normY = -turn * tmpX;
1002 
1003  normX = fabs(ad_radius) * normX;
1004  normY = fabs(ad_radius) * normY;
1005 
1006  *ad_x += normX;
1007  *ad_y += normY;
1008 }
1009 
1010 
1011 void
1013  SUMOReal ad_r, SUMOReal ad_length) {
1014  double rotAngle = ad_length / fabs(ad_r);
1015  double vx = *ad_x - ad_centerX;
1016  double vy = *ad_y - ad_centerY;
1017  double tmpx;
1018 
1019  double turn;
1020  if (ad_r > 0) {
1021  turn = -1; //left
1022  } else {
1023  turn = 1; //right
1024  }
1025  tmpx = vx;
1026  vx = vx * cos(rotAngle) + turn * vy * sin(rotAngle);
1027  vy = -1 * turn * tmpx * sin(rotAngle) + vy * cos(rotAngle);
1028  *ad_x = vx + ad_centerX;
1029  *ad_y = vy + ad_centerY;
1030 }
1031 
1032 
1033 // ---------------------------------------------------------------------------
1034 // section
1035 // ---------------------------------------------------------------------------
1037  lanesByDir[OPENDRIVE_TAG_LEFT] = std::vector<OpenDriveLane>();
1038  lanesByDir[OPENDRIVE_TAG_RIGHT] = std::vector<OpenDriveLane>();
1039  lanesByDir[OPENDRIVE_TAG_CENTER] = std::vector<OpenDriveLane>();
1040 }
1041 
1042 
1043 void
1045  unsigned int sumoLane = 0;
1046  const std::vector<OpenDriveLane>& dirLanesR = lanesByDir.find(OPENDRIVE_TAG_RIGHT)->second;
1047  for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanesR.rbegin(); i != dirLanesR.rend(); ++i) {
1048  if (myImportAllTypes || (tc.knows((*i).type) && !tc.getShallBeDiscarded((*i).type))) {
1049  laneMap[(*i).id] = sumoLane++;
1050  }
1051  }
1052  rightLaneNumber = sumoLane;
1053  sumoLane = 0;
1054  const std::vector<OpenDriveLane>& dirLanesL = lanesByDir.find(OPENDRIVE_TAG_LEFT)->second;
1055  for (std::vector<OpenDriveLane>::const_iterator i = dirLanesL.begin(); i != dirLanesL.end(); ++i) {
1056  if (myImportAllTypes || (tc.knows((*i).type) && !tc.getShallBeDiscarded((*i).type))) {
1057  laneMap[(*i).id] = sumoLane++;
1058  }
1059  }
1060  leftLaneNumber = sumoLane;
1061 }
1062 
1063 
1064 std::map<int, int>
1066  std::map<int, int> ret;
1067  const std::vector<OpenDriveLane>& dirLanes = lanesByDir.find(dir)->second;
1068  for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanes.rbegin(); i != dirLanes.rend(); ++i) {
1069  std::map<int, int>::const_iterator toP = laneMap.find((*i).id);
1070  if (toP == laneMap.end()) {
1071  // the current lane is not available in SUMO
1072  continue;
1073  }
1074  int to = (*toP).second;
1075  int from = UNSET_CONNECTION;
1076  if ((*i).predecessor != UNSET_CONNECTION) {
1077  from = (*i).predecessor;
1078  }
1079  if (from != UNSET_CONNECTION) {
1080  std::map<int, int>::const_iterator fromP = prev.laneMap.find(from);
1081  if (fromP != prev.laneMap.end()) {
1082  from = (*fromP).second;
1083  } else {
1084  from = UNSET_CONNECTION;
1085  }
1086  }
1087  if (from != UNSET_CONNECTION && to != UNSET_CONNECTION) {
1088  if (ret.find(from) != ret.end()) {
1089 // WRITE_WARNING("double connection");
1090  }
1091  if (dir == OPENDRIVE_TAG_LEFT) {
1092  std::swap(from, to);
1093  }
1094  ret[from] = to;
1095  } else {
1096 // WRITE_WARNING("missing connection");
1097  }
1098  }
1099  return ret;
1100 }
1101 
1102 
1105  OpenDriveLaneSection ret(*this);
1106  ret.s += startPos;
1107  for (unsigned int k = 0; k != ret.lanesByDir[OPENDRIVE_TAG_RIGHT].size(); ++k) {
1109  l.speed = 0;
1110  std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator i = std::find_if(l.speeds.begin(), l.speeds.end(), same_position_finder(startPos));
1111  if (i != l.speeds.end()) {
1112  l.speed = (*i).second;
1113  }
1114  }
1115  for (unsigned int k = 0; k != ret.lanesByDir[OPENDRIVE_TAG_LEFT].size(); ++k) {
1117  std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator i = std::find_if(l.speeds.begin(), l.speeds.end(), same_position_finder(startPos));
1118  l.speed = 0;
1119  if (i != l.speeds.end()) {
1120  l.speed = (*i).second;
1121  }
1122  }
1123  return ret;
1124 }
1125 
1126 
1127 bool
1128 NIImporter_OpenDrive::OpenDriveLaneSection::buildSpeedChanges(const NBTypeCont& tc, std::vector<OpenDriveLaneSection>& newSections) {
1129  std::set<SUMOReal> speedChangePositions;
1130  // collect speed change positions and apply initial speed to the begin
1131  for (std::vector<OpenDriveLane>::iterator k = lanesByDir[OPENDRIVE_TAG_RIGHT].begin(); k != lanesByDir[OPENDRIVE_TAG_RIGHT].end(); ++k) {
1132  for (std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator l = (*k).speeds.begin(); l != (*k).speeds.end(); ++l) {
1133  speedChangePositions.insert((*l).first);
1134  if ((*l).first == 0) {
1135  (*k).speed = (*l).second;
1136  }
1137  }
1138  }
1139  for (std::vector<OpenDriveLane>::iterator k = lanesByDir[OPENDRIVE_TAG_LEFT].begin(); k != lanesByDir[OPENDRIVE_TAG_LEFT].end(); ++k) {
1140  for (std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator l = (*k).speeds.begin(); l != (*k).speeds.end(); ++l) {
1141  speedChangePositions.insert((*l).first);
1142  if ((*l).first == 0) {
1143  (*k).speed = (*l).second;
1144  }
1145  }
1146  }
1147  // do nothing if there is none
1148  if (speedChangePositions.size() == 0) {
1149  return false;
1150  }
1151  if (*speedChangePositions.begin() > 0) {
1152  speedChangePositions.insert(0);
1153  }
1154  //
1155  for (std::set<SUMOReal>::iterator i = speedChangePositions.begin(); i != speedChangePositions.end(); ++i) {
1156  if (i == speedChangePositions.begin()) {
1157  newSections.push_back(*this);
1158  } else {
1159  newSections.push_back(buildLaneSection(*i));
1160  }
1161  }
1162  // propagate speeds
1163  for (int i = 0; i != (int)newSections.size(); ++i) {
1164  OpenDriveLaneSection& ls = newSections[i];
1165  std::map<OpenDriveXMLTag, std::vector<OpenDriveLane> >& lanesByDir = ls.lanesByDir;
1166  for (std::map<OpenDriveXMLTag, std::vector<OpenDriveLane> >::iterator k = lanesByDir.begin(); k != lanesByDir.end(); ++k) {
1167  std::vector<OpenDriveLane>& lanes = (*k).second;
1168  for (int j = 0; j != (int)lanes.size(); ++j) {
1169  OpenDriveLane& l = lanes[j];
1170  if (l.speed != 0) {
1171  continue;
1172  }
1173  if (i > 0) {
1174  l.speed = newSections[i - 1].lanesByDir[(*k).first][j].speed;
1175  } else {
1176  tc.getSpeed(l.type);
1177  }
1178  }
1179  }
1180  }
1181  return true;
1182 }
1183 
1184 
1185 
1186 // ---------------------------------------------------------------------------
1187 // edge
1188 // ---------------------------------------------------------------------------
1189 int
1191  int prio = 1;
1192  for (std::vector<OpenDriveSignal>::const_iterator i = signals.begin(); i != signals.end(); ++i) {
1193  int tmp = 1;
1194  if ((*i).type == "301" || (*i).type == "306") {
1195  tmp = 2;
1196  }
1197  if ((*i).type == "205") {
1198  tmp = 0;
1199  }
1200  if (tmp != 1 && dir == OPENDRIVE_TAG_RIGHT && (*i).orientation > 0) {
1201  prio = tmp;
1202  }
1203  if (tmp != 1 && dir == OPENDRIVE_TAG_LEFT && (*i).orientation < 0) {
1204  prio = tmp;
1205  }
1206 
1207  }
1208  return prio;
1209 }
1210 
1211 
1212 
1213 // ---------------------------------------------------------------------------
1214 // loader methods
1215 // ---------------------------------------------------------------------------
1216 NIImporter_OpenDrive::NIImporter_OpenDrive(const NBTypeCont& tc, std::map<std::string, OpenDriveEdge*>& edges)
1218  myTypeContainer(tc), myCurrentEdge("", "", -1), myEdges(edges) {
1219 }
1220 
1221 
1223 }
1224 
1225 
1226 void
1228  const SUMOSAXAttributes& attrs) {
1229  bool ok = true;
1230  switch (element) {
1231  case OPENDRIVE_TAG_HEADER: {
1232  int majorVersion = attrs.get<int>(OPENDRIVE_ATTR_REVMAJOR, 0, ok);
1233  int minorVersion = attrs.get<int>(OPENDRIVE_ATTR_REVMINOR, 0, ok);
1234  if (majorVersion != 1 || minorVersion != 2) {
1235  WRITE_WARNING("Given openDrive file '" + getFileName() + "' uses version " + toString(majorVersion) + "." + toString(minorVersion) + ";\n Version 1.2 is supported.");
1236  }
1237  }
1238  break;
1239  case OPENDRIVE_TAG_ROAD: {
1240  std::string id = attrs.get<std::string>(OPENDRIVE_ATTR_ID, 0, ok);
1241  std::string junction = attrs.get<std::string>(OPENDRIVE_ATTR_JUNCTION, id.c_str(), ok);
1242  SUMOReal length = attrs.get<SUMOReal>(OPENDRIVE_ATTR_LENGTH, id.c_str(), ok);
1243  myCurrentEdge = OpenDriveEdge(id, junction, length);
1244  }
1245  break;
1247  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
1248  std::string elementType = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
1249  std::string elementID = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
1250  std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
1251  ? attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok)
1252  : "end";
1253  addLink(OPENDRIVE_LT_PREDECESSOR, elementType, elementID, contactPoint);
1254  }
1255  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
1256  int no = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1257  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1258  l.predecessor = no;
1259  }
1260  }
1261  break;
1262  case OPENDRIVE_TAG_SUCCESSOR: {
1263  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
1264  std::string elementType = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
1265  std::string elementID = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
1266  std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
1267  ? attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok)
1268  : "start";
1269  addLink(OPENDRIVE_LT_SUCCESSOR, elementType, elementID, contactPoint);
1270  }
1271  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
1272  int no = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1273  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1274  l.successor = no;
1275  }
1276  }
1277  break;
1278  case OPENDRIVE_TAG_GEOMETRY: {
1279  SUMOReal length = attrs.get<SUMOReal>(OPENDRIVE_ATTR_LENGTH, myCurrentEdge.id.c_str(), ok);
1280  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1281  SUMOReal x = attrs.get<SUMOReal>(OPENDRIVE_ATTR_X, myCurrentEdge.id.c_str(), ok);
1282  SUMOReal y = attrs.get<SUMOReal>(OPENDRIVE_ATTR_Y, myCurrentEdge.id.c_str(), ok);
1283  SUMOReal hdg = attrs.get<SUMOReal>(OPENDRIVE_ATTR_HDG, myCurrentEdge.id.c_str(), ok);
1284  myCurrentEdge.geometries.push_back(OpenDriveGeometry(length, s, x, y, hdg));
1285  }
1286  break;
1287  case OPENDRIVE_TAG_LINE: {
1288  std::vector<SUMOReal> vals;
1290  }
1291  break;
1292  case OPENDRIVE_TAG_SPIRAL: {
1293  std::vector<SUMOReal> vals;
1294  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVSTART, myCurrentEdge.id.c_str(), ok));
1295  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVEND, myCurrentEdge.id.c_str(), ok));
1297  }
1298  break;
1299  case OPENDRIVE_TAG_ARC: {
1300  std::vector<SUMOReal> vals;
1301  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVATURE, myCurrentEdge.id.c_str(), ok));
1303  }
1304  break;
1305  case OPENDRIVE_TAG_POLY3: {
1306  std::vector<SUMOReal> vals;
1307  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok));
1308  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_B, myCurrentEdge.id.c_str(), ok));
1309  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_C, myCurrentEdge.id.c_str(), ok));
1310  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_D, myCurrentEdge.id.c_str(), ok));
1312  }
1313  break;
1315  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1317  }
1318  break;
1319  case OPENDRIVE_TAG_LEFT:
1321  break;
1322  case OPENDRIVE_TAG_CENTER:
1324  break;
1325  case OPENDRIVE_TAG_RIGHT:
1327  break;
1328  case OPENDRIVE_TAG_LANE: {
1329  std::string type = attrs.get<std::string>(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
1330  int id = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1331  std::string level = attrs.hasAttribute(OPENDRIVE_ATTR_LEVEL)
1332  ? attrs.get<std::string>(OPENDRIVE_ATTR_LEVEL, myCurrentEdge.id.c_str(), ok)
1333  : "";
1335  ls.lanesByDir[myCurrentLaneDirection].push_back(OpenDriveLane(id, level, type));
1336  }
1337  break;
1338  case OPENDRIVE_TAG_SIGNAL: {
1339  int id = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1340  std::string type = attrs.get<std::string>(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
1341  std::string name = attrs.getOpt<std::string>(OPENDRIVE_ATTR_NAME, myCurrentEdge.id.c_str(), ok, "", false);
1342  int orientation = attrs.get<std::string>(OPENDRIVE_ATTR_ORIENTATION, myCurrentEdge.id.c_str(), ok) == "-" ? -1 : 1;
1343  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1344  bool dynamic = attrs.get<std::string>(OPENDRIVE_ATTR_DYNAMIC, myCurrentEdge.id.c_str(), ok) == "no" ? false : true;
1345  myCurrentEdge.signals.push_back(OpenDriveSignal(id, type, name, orientation, dynamic, s));
1346  }
1347  break;
1349  myCurrentJunctionID = attrs.get<std::string>(OPENDRIVE_ATTR_ID, myCurrentJunctionID.c_str(), ok);
1350  break;
1351  case OPENDRIVE_TAG_CONNECTION: {
1352  std::string id = attrs.get<std::string>(OPENDRIVE_ATTR_ID, myCurrentJunctionID.c_str(), ok);
1353  myCurrentIncomingRoad = attrs.get<std::string>(OPENDRIVE_ATTR_INCOMINGROAD, myCurrentJunctionID.c_str(), ok);
1355  std::string cp = attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentJunctionID.c_str(), ok);
1357  myConnectionWasEmpty = true;
1358  }
1359  break;
1360  case OPENDRIVE_TAG_LANELINK: {
1361  int from = attrs.get<int>(OPENDRIVE_ATTR_FROM, myCurrentJunctionID.c_str(), ok);
1362  int to = attrs.get<int>(OPENDRIVE_ATTR_TO, myCurrentJunctionID.c_str(), ok);
1363  Connection c;
1365  c.toEdge = myCurrentConnectingRoad;
1366  c.fromLane = from;
1367  c.toLane = to;
1368  c.fromCP = OPENDRIVE_CP_END;
1369  c.toCP = myCurrentContactPoint;
1370  c.all = false;
1371  if (myEdges.find(c.fromEdge) == myEdges.end()) {
1372  WRITE_ERROR("In laneLink-element: incoming road '" + c.fromEdge + "' is not known.");
1373  } else {
1374  OpenDriveEdge* e = myEdges.find(c.fromEdge)->second;
1375  e->connections.insert(c);
1376  myConnectionWasEmpty = false;
1377  }
1378  }
1379  break;
1380  case OPENDRIVE_TAG_WIDTH: {
1381  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 1] == OPENDRIVE_TAG_LANE) {
1382  SUMOReal width = attrs.get<SUMOReal>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok);
1383  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1384  l.width = MAX2(l.width, width);
1385  }
1386  }
1387  break;
1388  case OPENDRIVE_TAG_SPEED: {
1389  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 1] == OPENDRIVE_TAG_LANE) {
1390  SUMOReal speed = attrs.get<SUMOReal>(OPENDRIVE_ATTR_MAX, myCurrentEdge.id.c_str(), ok);
1391  SUMOReal pos = attrs.get<SUMOReal>(OPENDRIVE_ATTR_SOFFSET, myCurrentEdge.id.c_str(), ok);
1392  myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back().speeds.push_back(std::make_pair(pos, speed));
1393  }
1394  }
1395  break;
1396  default:
1397  break;
1398  }
1399  myElementStack.push_back(element);
1400 }
1401 
1402 
1403 void
1405  myElementStack.pop_back();
1406  switch (element) {
1407  case OPENDRIVE_TAG_ROAD:
1409  break;
1411  if (myConnectionWasEmpty) {
1412  Connection c;
1415  c.fromLane = 0;
1416  c.toLane = 0;
1419  c.all = true;
1420  if (myEdges.find(c.fromEdge) == myEdges.end()) {
1421  WRITE_ERROR("In laneLink-element: incoming road '" + c.fromEdge + "' is not known.");
1422  } else {
1423  OpenDriveEdge* e = myEdges.find(c.fromEdge)->second;
1424  e->connections.insert(c);
1425  }
1426  }
1427  break;
1429  myCurrentEdge.laneSections.back().buildLaneMapping(myTypeContainer);
1430  }
1431  break;
1432  default:
1433  break;
1434  }
1435 }
1436 
1437 
1438 
1439 void
1440 NIImporter_OpenDrive::addLink(LinkType lt, const std::string& elementType,
1441  const std::string& elementID,
1442  const std::string& contactPoint) {
1443  OpenDriveLink l(lt, elementID);
1444  // elementType
1445  if (elementType == "road") {
1447  } else if (elementType == "junction") {
1449  }
1450  // contact point
1451  if (contactPoint == "start") {
1453  } else if (contactPoint == "end") {
1455  }
1456  // add
1457  myCurrentEdge.links.push_back(l);
1458 }
1459 
1460 
1461 void
1462 NIImporter_OpenDrive::addGeometryShape(GeometryType type, const std::vector<SUMOReal>& vals) {
1463  // checks
1464  if (myCurrentEdge.geometries.size() == 0) {
1465  throw ProcessError("Mismatching paranthesis in geometry definition for road '" + myCurrentEdge.id + "'");
1466  }
1468  if (last.type != OPENDRIVE_GT_UNKNOWN) {
1469  throw ProcessError("Double geometry information for road '" + myCurrentEdge.id + "'");
1470  }
1471  // set
1472  last.type = type;
1473  last.params = vals;
1474 }
1475 
1476 
1477 bool
1479  if (c1.fromEdge != c2.fromEdge) {
1480  return c1.fromEdge < c2.fromEdge;
1481  }
1482  if (c1.toEdge != c2.toEdge) {
1483  return c1.toEdge < c2.toEdge;
1484  }
1485  if (c1.fromLane != c2.fromLane) {
1486  return c1.fromLane < c2.fromLane;
1487  }
1488  return c1.toLane < c2.toLane;
1489 }
1490 
1491 
1492 
1493 /****************************************************************************/
1494 
std::map< std::string, OpenDriveEdge * > & myEdges
static void calculateCurveCenter(SUMOReal *ad_x, SUMOReal *ad_y, SUMOReal ad_radius, SUMOReal ad_hdg)
std::vector< int > myElementStack
std::vector< std::string > getStringVector(const std::string &name) const
Returns the list of string-vector-value of the named option (only for Option_String) ...
static const SUMOReal UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:201
static StringBijection< int >::Entry openDriveAttrs[]
The names of openDrive-XML attributes (for passing to GenericSAXHandler)
NBTypeCont & getTypeCont()
Returns the type container.
Definition: NBNetBuilder.h:170
is a pedestrian
static bool transformCoordinates(Position &from, bool includeInBoundary=true, GeoConvHelper *from_srs=0)
transforms loaded coordinates handles projections, offsets (using GeoConvHelper) and import of height...
PositionVector getSubpart2D(SUMOReal beginOffset, SUMOReal endOffset) const
void addLink(LinkType lt, const std::string &elementType, const std::string &elementID, const std::string &contactPoint)
static bool isReadable(std::string path)
Checks whether the given file is readable.
Definition: FileHelpers.cpp:58
std::string junction
The id of the junction the edge belongs to.
GeometryType
OpenDrive geometry type enumeration.
static std::vector< Position > geomFromPoly(const OpenDriveEdge &e, const OpenDriveGeometry &g)
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:295
static void buildConnectionsToOuter(const Connection &c, const std::map< std::string, OpenDriveEdge * > &innerEdges, std::vector< Connection > &into)
void unSet(const std::string &name, bool failOnNonExistant=true) const
Marks the option as unset.
Representation of a lane section.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
The representation of a single edge during network building.
Definition: NBEdge.h:71
Representation of an openDrive "link".
The base class for traffic light logic definitions.
ContactPoint myCurrentContactPoint
bool addLane2LaneConnection(unsigned int fromLane, NBEdge *dest, unsigned int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false)
Adds a connection between the specified this edge's lane and an approached one.
Definition: NBEdge.cpp:628
SUMOReal s
The starting offset of this lane section.
T MAX2(T a, T b)
Definition: StdDefs.h:72
std::map< OpenDriveXMLTag, std::vector< OpenDriveLane > > lanesByDir
The lanes, sorted by their direction.
SUMOReal getFloat(const std::string &name) const
Returns the SUMOReal-value of the named option (only for Option_Float)
const SVCPermissions SVCAll
static const SUMOReal UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:203
bool operator<(const NIImporter_OpenDrive::Connection &c1, const NIImporter_OpenDrive::Connection &c2)
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false)
Runs the given handler on the given file; returns if everything's ok.
Definition: XMLSubSys.cpp:114
SUMOReal x() const
Returns the x-position.
Definition: Position.h:63
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list...
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:39
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:48
SUMOReal getWidth(const std::string &type) const
Returns the lane width for the given type [m].
Definition: NBTypeCont.cpp:134
static NBNode * getOrBuildNode(const std::string &id, const Position &pos, NBNodeCont &nc)
Builds a node or returns the already built.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
The connection was computed and validated.
Definition: NBEdge.h:116
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:67
static std::string revertID(const std::string &id)
PositionVector reverse() const
#define C_LENGTH
SUMOReal speed
The speed allowed on this lane.
Definition: NBEdge.h:130
OpenDriveXMLTag myCurrentLaneDirection
static void calcPointOnCurve(SUMOReal *ad_x, SUMOReal *ad_y, SUMOReal ad_centerX, SUMOReal ad_centerY, SUMOReal ad_r, SUMOReal ad_length)
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:123
const std::string & getID() const
Returns the id.
Definition: Named.h:60
SUMOReal length2D() const
Returns the length.
SVCPermissions permissions
List of vehicle types that are allowed on this lane.
Definition: NBEdge.h:132
std::vector< OpenDriveLink > links
A handler which converts occuring elements and attributes into enums.
OpenDriveLaneSection buildLaneSection(SUMOReal startPos)
SUMOReal getSpeed(const std::string &type) const
Returns the maximal velocity for the given type [m/s].
Definition: NBTypeCont.cpp:104
const std::string & getFileName() const
returns the current file name
void setFileName(const std::string &name)
Sets the current file name.
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node.
Definition: NBNode.h:309
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:158
std::string type
The lane's type.
int getPriority(OpenDriveXMLTag dir) const
Returns the edge's priority, regarding the direction.
Encapsulated SAX-Attributes.
static StringBijection< TrafficLightType > TrafficLightTypes
static Position calculateStraightEndPoint(double hdg, double length, const Position &start)
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
NBEdgeCont & getEdgeCont()
Returns the edge container.
Definition: NBNetBuilder.h:154
void computeSpiral(std::vector< Point2D< double > > &spiral, double ds=0, int NPts=0)
Definition: euler.cpp:262
std::string id
The id of the edge.
A list of positions.
static void loadNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Loads content of the optionally given SUMO file.
NIImporter_OpenDrive(const NBTypeCont &tc, std::map< std::string, OpenDriveEdge * > &edges)
Constructor.
bool isUsableFileList(const std::string &name) const
Checks whether the named option is usable as a file list (with at least a single file) ...
bool buildSpeedChanges(const NBTypeCont &tc, std::vector< OpenDriveLaneSection > &newSections)
const NBTypeCont & myTypeContainer
Position positionAtOffset(SUMOReal pos, SUMOReal lateralOffset=0) const
Returns the position at the given length.
std::vector< OpenDriveLaneSection > laneSections
std::map< int, int > laneMap
A mapping from OpenDrive to SUMO-index (the first is signed, the second unsigned) ...
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:202
#define POSITION_EPS
Definition: config.h:186
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
OpenDriveXMLTag
Numbers representing openDrive-XML - element names.
bool knows(const std::string &type) const
Returns whether the named type is in the container.
Definition: NBTypeCont.cpp:80
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:53
The connection was given by the user.
Definition: NBEdge.h:114
bool insert(const std::string &id, int noLanes, SUMOReal maxSpeed, int prio, SUMOReal width, SUMOVehicleClass vClasses=SVC_IGNORING, bool oneWayIsDefault=false, SUMOReal sidewalkWidth=NBEdge::UNSPECIFIED_WIDTH)
Adds a type into the list. This is a simplified convenience form of insert, if only one allowed vehic...
Definition: NBTypeCont.cpp:60
static StringBijection< int >::Entry openDriveTags[]
The names of openDrive-XML elements (for passing to GenericSAXHandler)
static std::vector< Position > geomFromLine(const OpenDriveEdge &e, const OpenDriveGeometry &g)
std::string origID
An original ID, if given (.
Definition: NBEdge.h:140
void buildLaneMapping(const NBTypeCont &tc)
Build the mapping from OpenDrive to SUMO lanes.
std::vector< OpenDriveSignal > signals
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:205
LinkType
OpenDrive link type enumeration.
void addParameter(const std::string &key, const std::string &value)
Adds a parameter.
static void computeShapes(std::map< std::string, OpenDriveEdge * > &edges)
Computes a polygon representation of each edge's geometry.
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:368
void addTrafficLight(NBTrafficLightDefinition *tlDef)
Adds a traffic light to the list of traffic lights that control this node.
Definition: NBNode.cpp:289
void removeDoublePoints(SUMOReal minDist=POSITION_EPS, bool assertLength=false)
Removes positions if too near.
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:245
std::map< int, int > getInnerConnections(OpenDriveXMLTag dir, const OpenDriveLaneSection &prev)
Returns the links from the previous to this lane section.
NBNodeCont & getNodeCont()
Returns the node container.
Definition: NBNetBuilder.h:162
SUMOReal speed
The lane's speed (set in post-processing)
Instance responsible for building networks.
Definition: NBNetBuilder.h:113
Representation of an OpenDrive geometry part.
bool getShallBeDiscarded(const std::string &type) const
Returns the information whether edges of this type shall be discarded.
Definition: NBTypeCont.cpp:122
SUMOReal y() const
Returns the y-position.
Definition: Position.h:68
A storage for options typed value containers)
Definition: OptionsCont.h:108
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:79
NBTrafficLightLogicCont & getTLLogicCont()
Returns the traffic light logics container.
Definition: NBNetBuilder.h:178
static void setEdgeLinks2(OpenDriveEdge &e, const std::map< std::string, OpenDriveEdge * > &edges)
std::vector< OpenDriveGeometry > geometries
Represents a single node (junction) during network building.
Definition: NBNode.h:75
T get(const std::string &str) const
Lane & getLaneStruct(unsigned int lane)
Definition: NBEdge.h:1022
A class for sorting lane sections by their s-value.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
#define SUMOReal
Definition: config.h:215
static void setNodeSecure(NBNodeCont &nc, OpenDriveEdge &e, const std::string &nodeID, NIImporter_OpenDrive::LinkType lt)
void push_back_noDoublePos(const Position &p)
A connection between two roads.
void addGeometryShape(GeometryType type, const std::vector< SUMOReal > &vals)
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue, bool report=true) const
Tries to read given attribute assuming it is an int.
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:124
SVCPermissions getPermissions(const std::string &type) const
Returns allowed vehicle classes for the given type.
Definition: NBTypeCont.cpp:128
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:64
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
SUMOReal length
The length of the edge.
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:203
A traffic light logics which must be computed (only nodes/edges are given)
Definition: NBOwnTLDef.h:54
static std::vector< Position > geomFromArc(const OpenDriveEdge &e, const OpenDriveGeometry &g)
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:747
Importer for networks stored in openDrive format.
static std::vector< Position > geomFromSpiral(const OpenDriveEdge &e, const OpenDriveGeometry &g)
std::vector< std::pair< SUMOReal, SUMOReal > > speeds
List of positions/speeds of speed changes.
bool exists(const std::string &name) const
Returns the information whether the named option is known.
SUMOReal width
This lane's width.
Definition: NBEdge.h:138
#define UNSET_CONNECTION
TrafficLightType
A storage for available types of edges.
Definition: NBTypeCont.h:56
void myEndElement(int element)
Called when a closing tag occurs.
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
static void revisitLaneSections(const NBTypeCont &tc, std::map< std::string, OpenDriveEdge * > &edges)
Rechecks lane sections of the given edges.