SUMO - Simulation of Urban MObility
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.dlr.de/
13 // Copyright (C) 2001-2016 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 // static variables
72 // ===========================================================================
96 
98 };
99 
100 
141 
143 };
144 
145 
148 
149 // ===========================================================================
150 // method definitions
151 // ===========================================================================
152 // ---------------------------------------------------------------------------
153 // static methods (interface in this case)
154 // ---------------------------------------------------------------------------
155 void
157  // check whether the option is set (properly)
158  if (!oc.isUsableFileList("opendrive-files")) {
159  return;
160  }
161  // prepare types
162  myImportAllTypes = oc.getBool("opendrive.import-all-lanes");
163  myImportWidths = !oc.getBool("opendrive.ignore-widths");
164  NBTypeCont& tc = nb.getTypeCont();
165  // build the handler
166  std::map<std::string, OpenDriveEdge*> edges;
167  NIImporter_OpenDrive handler(nb.getTypeCont(), edges);
168  // parse file(s)
169  std::vector<std::string> files = oc.getStringVector("opendrive-files");
170  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
171  if (!FileHelpers::isReadable(*file)) {
172  WRITE_ERROR("Could not open opendrive file '" + *file + "'.");
173  return;
174  }
175  handler.setFileName(*file);
176  PROGRESS_BEGIN_MESSAGE("Parsing opendrive from '" + *file + "'");
177  XMLSubSys::runParser(handler, *file);
179  }
180  // split inner/outer edges
181  std::map<std::string, OpenDriveEdge*> innerEdges, outerEdges;
182  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
183  if ((*i).second->isInner) {
184  innerEdges[(*i).first] = (*i).second;
185  } else {
186  outerEdges[(*i).first] = (*i).second;
187  }
188  }
189 
190  // convert geometries into a discretised representation
191  computeShapes(edges);
192  // check whether lane sections are valid and whether further must be introduced
193  revisitLaneSections(tc, edges);
194 
195  // -------------------------
196  // node building
197  // -------------------------
198  // build nodes#1
199  // look at all links which belong to a node, collect their bounding boxes
200  // and place the node in the middle of this bounding box
201  std::map<std::string, Boundary> posMap;
202  std::map<std::string, std::string> edge2junction;
203  // compute node positions
204  for (std::map<std::string, OpenDriveEdge*>::iterator i = innerEdges.begin(); i != innerEdges.end(); ++i) {
205  OpenDriveEdge* e = (*i).second;
206  assert(e->junction != "-1" && e->junction != "");
207  edge2junction[e->id] = e->junction;
208  if (posMap.find(e->junction) == posMap.end()) {
209  posMap[e->junction] = Boundary();
210  }
211  posMap[e->junction].add(e->geom.getBoxBoundary());
212  }
213  // build nodes
214  for (std::map<std::string, Boundary>::iterator i = posMap.begin(); i != posMap.end(); ++i) {
215  if (!nb.getNodeCont().insert((*i).first, (*i).second.getCenter())) {
216  throw ProcessError("Could not add node '" + (*i).first + "'.");
217  }
218  }
219  // assign built nodes
220  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
221  OpenDriveEdge* e = (*i).second;
222  for (std::vector<OpenDriveLink>::iterator j = e->links.begin(); j != e->links.end(); ++j) {
223  OpenDriveLink& l = *j;
224  const std::string& nid = l.elementID;
225  if (l.elementType != OPENDRIVE_ET_ROAD) {
226  if (nb.getNodeCont().retrieve(nid) == 0) {
227  // not yet seen, build (possibly a junction without connections)
228  Position pos = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e->geom[-1] : e->geom[0];
229  if (!nb.getNodeCont().insert(nid, pos)) {
230  throw ProcessError("Could not build node '" + nid + "'.");
231  }
232  }
233  // set node information
235  continue;
236  }
237  if (edge2junction.find(l.elementID) != edge2junction.end()) {
238  // set node information of an internal road
239  setNodeSecure(nb.getNodeCont(), *e, edge2junction[l.elementID], l.linkType);
240  continue;
241  }
242  }
243  }
244  // we should now have all nodes set for links which are not outer edge-to-outer edge links
245 
246 
247  // build nodes#2
248  // build nodes for all outer edge-to-outer edge connections
249  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
250  OpenDriveEdge* e = (*i).second;
251  for (std::vector<OpenDriveLink>::iterator j = e->links.begin(); j != e->links.end(); ++j) {
252  OpenDriveLink& l = *j;
253  if (l.elementType != OPENDRIVE_ET_ROAD || edge2junction.find(l.elementID) != edge2junction.end()) {
254  // is a connection to an internal edge, or a node, skip
255  continue;
256  }
257  // we have a direct connection between to external edges
258  std::string id1 = e->id;
259  std::string id2 = l.elementID;
260  if (id1 < id2) {
261  std::swap(id1, id2);
262  }
263  std::string nid = id1 + "." + id2;
264  if (nb.getNodeCont().retrieve(nid) == 0) {
265  // not yet seen, build
266  Position pos = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e->geom[-1] : e->geom[0];
267  if (!nb.getNodeCont().insert(nid, pos)) {
268  throw ProcessError("Could not build node '" + nid + "'.");
269  }
270  }
271  /* debug-stuff
272  else {
273  Position pos = l.linkType==OPENDRIVE_LT_SUCCESSOR ? e.geom[e.geom.size()-1] : e.geom[0];
274  cout << nid << " " << pos << " " << nb.getNodeCont().retrieve(nid)->getPosition() << endl;
275  }
276  */
277  setNodeSecure(nb.getNodeCont(), *e, nid, l.linkType);
278  }
279  }
280  // we should now have start/end nodes for all outer edge-to-outer edge connections
281 
282 
283  // build nodes#3
284  // assign further nodes generated from inner-edges
285  // these nodes have not been assigned earlier, because the connections are referenced in inner-edges
286  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
287  OpenDriveEdge* e = (*i).second;
288  if (e->to != 0 && e->from != 0) {
289  continue;
290  }
291  for (std::map<std::string, OpenDriveEdge*>::iterator j = innerEdges.begin(); j != innerEdges.end(); ++j) {
292  OpenDriveEdge* ie = (*j).second;
293  for (std::vector<OpenDriveLink>::iterator k = ie->links.begin(); k != ie->links.end(); ++k) {
294  OpenDriveLink& il = *k;
295  if (il.elementType != OPENDRIVE_ET_ROAD || il.elementID != e->id) {
296  // not conneted to the currently investigated outer edge
297  continue;
298  }
299  std::string nid = edge2junction[ie->id];
300  if (il.contactPoint == OPENDRIVE_CP_START) {
302  } else {
304  }
305  }
306  }
307 
308  }
309 
310  // build start/end nodes which were not defined previously
311  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
312  OpenDriveEdge* e = (*i).second;
313  if (e->from == 0) {
314  const std::string nid = e->id + ".begin";
315  e->from = getOrBuildNode(nid, e->geom.front(), nb.getNodeCont());
316  }
317  if (e->to == 0) {
318  const std::string nid = e->id + ".end";
319  e->to = getOrBuildNode(nid, e->geom.back(), nb.getNodeCont());
320  }
321  }
322 
323 
324  // -------------------------
325  // edge building
326  // -------------------------
327  SUMOReal defaultSpeed = tc.getSpeed("");
328  // build edges
329  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
330  OpenDriveEdge* e = (*i).second;
331  bool lanesBuilt = false;
332 
333  // go along the lane sections, build a node in between of each pair
334 
337 
339  NBNode* sFrom = e->from;
340  NBNode* sTo = e->to;
341  int priorityR = e->getPriority(OPENDRIVE_TAG_RIGHT);
342  int priorityL = e->getPriority(OPENDRIVE_TAG_LEFT);
343  SUMOReal sB = 0;
344  SUMOReal sE = e->length;
345  // 0-length geometries are possible if only the inner points are represented
346  const SUMOReal length2D = e->geom.length2D();
347  SUMOReal cF = length2D == 0 ? 1 : e->length / length2D;
348  NBEdge* prevRight = 0;
349  NBEdge* prevLeft = 0;
350 
351  // starting at the same node as ending, and no lane sections?
352  if (sFrom == sTo && e->laneSections.size() == 1) {
353  // --> loop, split!
355  ls.s = e->length / 2.;
356  e->laneSections.push_back(ls);
357  WRITE_WARNING("Edge '" + e->id + "' has to be split as it connects same junctions.")
358  }
359 
360  // build along lane sections
361  for (std::vector<OpenDriveLaneSection>::iterator j = e->laneSections.begin(); j != e->laneSections.end(); ++j) {
362  // add internal node if needed
363  if (j == e->laneSections.end() - 1) {
364  sTo = e->to;
365  sE = e->length / cF;
366  } else {
367  SUMOReal nextS = (j + 1)->s;
368  sTo = new NBNode(e->id + "." + toString(nextS), e->geom.positionAtOffset(nextS));
369  if (!nb.getNodeCont().insert(sTo)) {
370  throw ProcessError("Could not add node '" + sTo->getID() + "'.");
371  }
372  sE = nextS / cF;
373  }
374  PositionVector geom = e->geom.getSubpart2D(sB, sE);
375  std::string id = e->id;
376  if (sFrom != e->from || sTo != e->to) {
377  id = id + "." + toString((*j).s);
378  } else if (e->laneSections.size() == 1) {
379  id = id + ".0.00";
380  }
381 
382  // build lanes to right
383  NBEdge* currRight = 0;
384  if ((*j).rightLaneNumber > 0) {
385  currRight = new NBEdge("-" + id, sFrom, sTo, (*j).rightType, defaultSpeed, (*j).rightLaneNumber, priorityR,
387  if (!nb.getEdgeCont().insert(currRight)) {
388  throw ProcessError("Could not add edge '" + currRight->getID() + "'.");
389  }
390  lanesBuilt = true;
391  const std::vector<OpenDriveLane>& lanes = (*j).lanesByDir[OPENDRIVE_TAG_RIGHT];
392  for (std::vector<OpenDriveLane>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
393  std::map<int, int>::const_iterator lp = (*j).laneMap.find((*k).id);
394  if (lp != (*j).laneMap.end()) {
395  int sumoLaneIndex = lp->second;
396  NBEdge::Lane& sumoLane = currRight->getLaneStruct(sumoLaneIndex);
397  const OpenDriveLane& odLane = *k;
398 
399  sumoLane.origID = e->id + " -" + toString((*k).id);
400  sumoLane.speed = odLane.speed != 0 ? odLane.speed : tc.getSpeed(odLane.type);
401  sumoLane.permissions = tc.getPermissions(odLane.type);
402  sumoLane.width = myImportWidths && odLane.width != 0 ? odLane.width : tc.getWidth(odLane.type);
403  }
404  }
405  // connect lane sections
406  if (prevRight != 0) {
407  std::map<int, int> connections = (*j).getInnerConnections(OPENDRIVE_TAG_RIGHT, *(j - 1));
408  for (std::map<int, int>::const_iterator k = connections.begin(); k != connections.end(); ++k) {
409  prevRight->addLane2LaneConnection((*k).first, currRight, (*k).second, NBEdge::L2L_VALIDATED);
410  }
411  }
412  prevRight = currRight;
413  }
414 
415  // build lanes to left
416  NBEdge* currLeft = 0;
417  if ((*j).leftLaneNumber > 0) {
418  currLeft = new NBEdge(id, sTo, sFrom, (*j).leftType, defaultSpeed, (*j).leftLaneNumber, priorityL,
420  if (!nb.getEdgeCont().insert(currLeft)) {
421  throw ProcessError("Could not add edge '" + currLeft->getID() + "'.");
422  }
423  lanesBuilt = true;
424  const std::vector<OpenDriveLane>& lanes = (*j).lanesByDir[OPENDRIVE_TAG_LEFT];
425  for (std::vector<OpenDriveLane>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
426  std::map<int, int>::const_iterator lp = (*j).laneMap.find((*k).id);
427  if (lp != (*j).laneMap.end()) {
428  int sumoLaneIndex = lp->second;
429  NBEdge::Lane& sumoLane = currLeft->getLaneStruct(sumoLaneIndex);
430  const OpenDriveLane& odLane = *k;
431 
432  sumoLane.origID = e->id + " " + toString((*k).id);
433  sumoLane.speed = odLane.speed != 0 ? odLane.speed : tc.getSpeed(odLane.type);
434  sumoLane.permissions = tc.getPermissions(odLane.type);
435  sumoLane.width = myImportWidths && odLane.width != 0 ? odLane.width : tc.getWidth(odLane.type);
436  }
437  }
438  // connect lane sections
439  if (prevLeft != 0) {
440  std::map<int, int> connections = (*j).getInnerConnections(OPENDRIVE_TAG_LEFT, *(j - 1));
441  for (std::map<int, int>::const_iterator k = connections.begin(); k != connections.end(); ++k) {
442  currLeft->addLane2LaneConnection((*k).first, prevLeft, (*k).second, NBEdge::L2L_VALIDATED);
443  }
444  }
445  prevLeft = currLeft;
446  }
447  (*j).sumoID = id;
448 
449 
450  sB = sE;
451  sFrom = sTo;
452  }
453  if (!lanesBuilt) {
454  WRITE_WARNING("Edge '" + e->id + "' has no lanes.");
455  }
456  }
457 
458  // -------------------------
459  // connections building
460  // -------------------------
461  // generate explicit lane-to-lane connections
462  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
463  setEdgeLinks2(*(*i).second, edges);
464  }
465  // compute connections across intersections, if any
466  std::vector<Connection> connections2;
467  for (std::map<std::string, OpenDriveEdge*>::iterator j = edges.begin(); j != edges.end(); ++j) {
468  const std::set<Connection>& conns = (*j).second->connections;
469 
470  for (std::set<Connection>::const_iterator i = conns.begin(); i != conns.end(); ++i) {
471  if (innerEdges.find((*i).fromEdge) != innerEdges.end()) {
472  // connections starting at inner edges are processed by starting from outer edges
473  continue;
474  }
475  if (innerEdges.find((*i).toEdge) != innerEdges.end()) {
476  buildConnectionsToOuter(*i, innerEdges, connections2);
477  } else {
478  connections2.push_back(*i);
479  }
480  }
481  }
482  // set connections
483  for (std::vector<Connection>::const_iterator i = connections2.begin(); i != connections2.end(); ++i) {
484  std::string fromEdge = (*i).fromEdge;
485  if (edges.find(fromEdge) == edges.end()) {
486  WRITE_WARNING("While setting connections: from-edge '" + fromEdge + "' is not known.");
487  continue;
488  }
489  OpenDriveEdge* odFrom = edges[fromEdge];
490  int fromLane = (*i).fromLane;
491  bool fromLast = ((*i).fromCP == OPENDRIVE_CP_END) ^ ((*i).fromLane > 0 && !(*i).all);
492  fromEdge = fromLast ? odFrom->laneSections.back().sumoID : odFrom->laneSections[0].sumoID;
493 
494  std::string toEdge = (*i).toEdge;
495  if (edges.find(toEdge) == edges.end()) {
496  WRITE_WARNING("While setting connections: to-edge '" + toEdge + "' is not known.");
497  continue;
498  }
499 
500  OpenDriveEdge* odTo = edges[toEdge];
501  int toLane = (*i).toLane;
502  bool toLast = ((*i).toCP == OPENDRIVE_CP_END) || ((*i).toLane > 0);
503  toEdge = toLast ? odTo->laneSections.back().sumoID : odTo->laneSections[0].sumoID;
504 
505  if (fromLane == UNSET_CONNECTION) {
506  fromLane = toLast ? odTo->laneSections.back().laneMap.begin()->first : odTo->laneSections[0].laneMap.begin()->first;
507  }
508  if (fromLane < 0) {
509  fromEdge = revertID(fromEdge);
510  }
511  if (toLane == UNSET_CONNECTION) {
512  toLane = toLast ? odTo->laneSections.back().laneMap.begin()->first : odTo->laneSections[0].laneMap.begin()->first;
513  }
514  if (toLane < 0) {
515  toEdge = revertID(toEdge);
516  }
517  fromLane = fromLast ? odFrom->laneSections.back().laneMap[fromLane] : odFrom->laneSections[0].laneMap[fromLane];
518  toLane = toLast ? odTo->laneSections.back().laneMap[toLane] : odTo->laneSections[0].laneMap[toLane];
519  NBEdge* from = nb.getEdgeCont().retrieve(fromEdge);
520  NBEdge* to = nb.getEdgeCont().retrieve(toEdge);
521  if (from == 0) {
522  WRITE_WARNING("Could not find fromEdge representation of '" + fromEdge + "' in connection '" + (*i).origID + "'.");
523  }
524  if (to == 0) {
525  WRITE_WARNING("Could not find fromEdge representation of '" + toEdge + "' in connection '" + (*i).origID + "'.");
526  }
527  if (from == 0 || to == 0) {
528  continue;
529  }
530 
531  from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER);
532 
533  if ((*i).origID != "") {
534  // @todo: this is the most silly way to determine the connection
535  std::vector<NBEdge::Connection>& cons = from->getConnections();
536  for (std::vector<NBEdge::Connection>::iterator k = cons.begin(); k != cons.end(); ++k) {
537  if ((*k).fromLane == fromLane && (*k).toEdge == to && (*k).toLane == toLane) {
538  (*k).origID = (*i).origID + " " + toString((*i).origLane);
539  break;
540  }
541  }
542  }
543  }
544 
545 
546  // -------------------------
547  // traffic lights
548  // -------------------------
549  std::map<std::string, std::string> tlsControlled;
550  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
551  OpenDriveEdge* e = (*i).second;
552  for (std::vector<OpenDriveSignal>::const_iterator j = e->signals.begin(); j != e->signals.end(); ++j) {
553  if ((*j).type != "1000001") { // traffic_light (Section 6.11)
554  continue;
555  }
556  std::vector<OpenDriveLaneSection>::iterator k = e->laneSections.begin();
557  bool found = false;
558  for (; k != e->laneSections.end() - 1 && !found;) {
559  if ((*j).s > (*k).s && (*j).s <= (*(k + 1)).s) {
560  found = true;
561  } else {
562  ++k;
563  }
564  }
565 
566  // @todo: major problem, currently, still not completely solved:
567  // inner edges may have traffic lights, too. Nice on one hand, as directions can be recognized
568  // but hard to follow backwards
569  std::string id = (*k).sumoID;
570  if (id == "") {
571  if (e->junction != "") {
572  //WRITE_WARNING("Found a traffic light signal on an internal edge; will not build it (original edge id='" + e->id + "').");
573  std::string fromID, toID;
574  for (std::vector<OpenDriveLink>::const_iterator l = e->links.begin(); l != e->links.end(); ++l) {
575  if ((*l).linkType == OPENDRIVE_LT_PREDECESSOR && (*l).elementType == OPENDRIVE_ET_ROAD) {
576  if (fromID != "") {
577  WRITE_WARNING("Ambigous start of connection.");
578  }
579  fromID = (*l).elementID;
580  OpenDriveEdge* e = edges[fromID];
581  fromID = (*l).contactPoint == OPENDRIVE_CP_START ? e->laneSections[0].sumoID : e->laneSections.back().sumoID;
582  }
583  if ((*l).linkType == OPENDRIVE_LT_SUCCESSOR && (*l).elementType == OPENDRIVE_ET_ROAD) {
584  if (toID != "") {
585  WRITE_WARNING("Ambigous end of connection.");
586  }
587  toID = (*l).elementID;
588  OpenDriveEdge* e = edges[toID];
589  toID = (*l).contactPoint == OPENDRIVE_CP_START ? e->laneSections[0].sumoID : e->laneSections.back().sumoID;
590  }
591  }
592  id = fromID + "->" + toID;
593  } else {
594  WRITE_WARNING("Found a traffic light signal on an unknown edge (original edge id='" + e->id + "').");
595  continue;
596  }
597  }
598 
599  if ((*j).orientation > 0) {
600  id = "-" + id;
601  }
602  tlsControlled[id] = (*j).name;
603  }
604  }
605 
606  for (std::map<std::string, std::string>::iterator i = tlsControlled.begin(); i != tlsControlled.end(); ++i) {
607  std::string id = (*i).first;
608  if (id.find("->") != std::string::npos) {
609  id = id.substr(0, id.find("->"));
610  }
611  NBEdge* e = nb.getEdgeCont().retrieve(id);
612  if (e == 0) {
613  WRITE_WARNING("Could not find edge '" + id + "' while building its traffic light.");
614  continue;
615  }
616  NBNode* toNode = e->getToNode();
617  NBTrafficLightDefinition* tlDef = 0;
618  if (!toNode->isTLControlled()) {
620  tlDef = new NBOwnTLDef(toNode->getID(), toNode, 0, type);
621  if (!nb.getTLLogicCont().insert(tlDef)) {
622  // actually, nothing should fail here
623  delete tlDef;
624  throw ProcessError();
625  }
626  toNode->addTrafficLight(tlDef);
627  static_cast<NBOwnTLDef*>(tlDef)->setSinglePhase();
628  }
629  tlDef = *toNode->getControllingTLS().begin();
630  tlDef->addParameter("connection:" + id, (*i).second);
631  }
632 
633  // -------------------------
634  // clean up
635  // -------------------------
636  if (oc.exists("geometry.min-dist") && oc.isSet("geometry.min-dist")) {
637  oc.unSet("geometry.min-dist");
638  }
639  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
640  delete(*i).second;
641  }
642 }
643 
644 
645 
646 void
647 NIImporter_OpenDrive::buildConnectionsToOuter(const Connection& c, const std::map<std::string, OpenDriveEdge*>& innerEdges, std::vector<Connection>& into) {
648 
649  OpenDriveEdge* dest = innerEdges.find(c.toEdge)->second;
650  if (dest == 0) {
652  return;
653  }
654  const std::set<Connection>& conts = dest->connections;
655  for (std::set<Connection>::const_iterator i = conts.begin(); i != conts.end(); ++i) {
656  if (innerEdges.find((*i).toEdge) != innerEdges.end()) {
657  std::vector<Connection> t;
658  buildConnectionsToOuter(*i, innerEdges, t);
659  for (std::vector<Connection>::const_iterator j = t.begin(); j != t.end(); ++j) {
660  // @todo this section is unverified
661  Connection cn = (*j);
662  cn.fromEdge = c.fromEdge;
663  cn.fromLane = c.fromLane;
664  cn.fromCP = c.fromCP;
665  cn.all = c.all; // @todo "all" is a hack trying to avoid the "from is zero" problem;
666  into.push_back(cn);
667  }
668  } else {
669  if ((*i).fromLane == c.toLane) {
670  Connection cn = (*i);
671  cn.fromEdge = c.fromEdge;
672  cn.fromLane = c.fromLane;
673  cn.fromCP = c.fromCP;
674  cn.all = c.all;
675  cn.origID = c.toEdge;
676  cn.origLane = c.toLane;
677  into.push_back(cn);
678  }
679  }
680  }
681 }
682 
683 
684 void
685 NIImporter_OpenDrive::setEdgeLinks2(OpenDriveEdge& e, const std::map<std::string, OpenDriveEdge*>& edges) {
686  for (std::vector<OpenDriveLink>::iterator i = e.links.begin(); i != e.links.end(); ++i) {
687  OpenDriveLink& l = *i;
688  if (l.elementType != OPENDRIVE_ET_ROAD) {
689  // we assume that links to nodes are later given as connections to edges
690  continue;
691  }
692  // get the right direction of the connected edge
693  std::string connectedEdge = l.elementID;
694  std::string edgeID = e.id;
695 
696  OpenDriveLaneSection& laneSection = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e.laneSections.back() : e.laneSections[0];
697  const std::map<int, int>& laneMap = laneSection.laneMap;
698  if (laneSection.lanesByDir.find(OPENDRIVE_TAG_RIGHT) != laneSection.lanesByDir.end()) {
699  const std::vector<OpenDriveLane>& lanes = laneSection.lanesByDir.find(OPENDRIVE_TAG_RIGHT)->second;
700  for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
701  if (!myImportAllTypes && laneMap.find((*j).id) == laneMap.end()) {
702  continue;
703  }
704  Connection c; // @todo: give Connection a new name and a constructor
705  c.fromEdge = e.id;
706  c.fromLane = (*j).id;
708  c.toLane = l.linkType == OPENDRIVE_LT_SUCCESSOR ? (*j).successor : (*j).predecessor;
709  c.toEdge = connectedEdge;
710  c.toCP = l.contactPoint;
711  c.all = false;
712  if (l.linkType != OPENDRIVE_LT_SUCCESSOR) {
713  std::swap(c.fromEdge, c.toEdge);
714  std::swap(c.fromLane, c.toLane);
715  std::swap(c.fromCP, c.toCP);
716  }
717  if (edges.find(c.fromEdge) == edges.end()) {
718  WRITE_ERROR("While setting connections: incoming road '" + c.fromEdge + "' is not known.");
719  } else {
720  OpenDriveEdge* src = edges.find(c.fromEdge)->second;
721  src->connections.insert(c);
722  }
723  }
724  }
725  if (laneSection.lanesByDir.find(OPENDRIVE_TAG_LEFT) != laneSection.lanesByDir.end()) {
726  const std::vector<OpenDriveLane>& lanes = laneSection.lanesByDir.find(OPENDRIVE_TAG_LEFT)->second;
727  for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
728  if (!myImportAllTypes && laneMap.find((*j).id) == laneMap.end()) {
729  continue;
730  }
731  Connection c;
732  c.toEdge = e.id;
733  c.toLane = (*j).id;
735  c.fromLane = l.linkType == OPENDRIVE_LT_SUCCESSOR ? (*j).successor : (*j).predecessor;
736  c.fromEdge = connectedEdge;
737  c.fromCP = l.contactPoint;
738  c.all = false;
739  if (l.linkType != OPENDRIVE_LT_SUCCESSOR) {
740  std::swap(c.fromEdge, c.toEdge);
741  std::swap(c.fromLane, c.toLane);
742  std::swap(c.fromCP, c.toCP);
743  }
744  if (edges.find(c.fromEdge) == edges.end()) {
745  WRITE_ERROR("While setting connections: incoming road '" + c.fromEdge + "' is not known.");
746  } else {
747  OpenDriveEdge* src = edges.find(c.fromEdge)->second;
748  src->connections.insert(c);
749  }
750  }
751  }
752  }
753 }
754 
755 
756 std::string NIImporter_OpenDrive::revertID(const std::string& id) {
757  if (id[0] == '-') {
758  return id.substr(1);
759  }
760  return "-" + id;
761 }
762 
763 NBNode*
764 NIImporter_OpenDrive::getOrBuildNode(const std::string& id, const Position& pos,
765  NBNodeCont& nc) {
766  if (nc.retrieve(id) == 0) {
767  // not yet built; build now
768  if (!nc.insert(id, pos)) {
769  // !!! clean up
770  throw ProcessError("Could not add node '" + id + "'.");
771  }
772  }
773  return nc.retrieve(id);
774 }
775 
776 
777 void
779  const std::string& nodeID, NIImporter_OpenDrive::LinkType lt) {
780  NBNode* n = nc.retrieve(nodeID);
781  if (n == 0) {
782  throw ProcessError("Could not find node '" + nodeID + "'.");
783  }
784  if (lt == OPENDRIVE_LT_SUCCESSOR) {
785  if (e.to != 0 && e.to != n) {
786  throw ProcessError("Edge '" + e.id + "' has two end nodes.");
787  }
788  e.to = n;
789  } else {
790  if (e.from != 0 && e.from != n) {
791  throw ProcessError("Edge '" + e.id + "' has two start nodes.");
792  }
793  e.from = n;
794  }
795 }
796 
797 
798 
799 
800 
801 
802 
803 void
804 NIImporter_OpenDrive::computeShapes(std::map<std::string, OpenDriveEdge*>& edges) {
806  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
807  OpenDriveEdge& e = *(*i).second;
809  for (std::vector<OpenDriveGeometry>::iterator j = e.geometries.begin(); j != e.geometries.end(); ++j) {
810  OpenDriveGeometry& g = *j;
811  PositionVector geom;
812  switch (g.type) {
814  break;
815  case OPENDRIVE_GT_LINE:
816  geom = geomFromLine(e, g);
817  break;
818  case OPENDRIVE_GT_SPIRAL:
819  geom = geomFromSpiral(e, g);
820  break;
821  case OPENDRIVE_GT_ARC:
822  geom = geomFromArc(e, g);
823  break;
824  case OPENDRIVE_GT_POLY3:
825  geom = geomFromPoly(e, g);
826  break;
828  geom = geomFromParamPoly(e, g);
829  break;
830  default:
831  break;
832  }
833  if (e.geom.size() > 0 && prevType == OPENDRIVE_GT_LINE) {
834  // remove redundant end point of the previous geometry segment
835  // (the start point of the current segment should have the same value)
836  // this avoids geometry errors due to imprecision
837  if (!e.geom.back().almostSame(geom.front())) {
838  const int index = (int)(j - e.geometries.begin());
839  WRITE_WARNING("Mismatched geometry for edge '" + e.id + "' between geometry segments " + toString(index - 1) + " and " + toString(index) + ".");
840  }
841  e.geom.pop_back();
842  }
843  for (PositionVector::iterator k = geom.begin(); k != geom.end(); ++k) {
845  }
846  prevType = g.type;
847  }
848  if (oc.exists("geometry.min-dist") && oc.isSet("geometry.min-dist")) {
849  e.geom.removeDoublePoints(oc.getFloat("geometry.min-dist"), true);
850  }
851  for (int j = 0; j < (int)e.geom.size(); ++j) {
853  WRITE_ERROR("Unable to project coordinates for.");
854  }
855  }
856  // add z-data
857  int k = 0;
858  SUMOReal pos = 0;
859  for (std::vector<OpenDriveElevation>::iterator j = e.elevations.begin(); j != e.elevations.end(); ++j) {
860  const OpenDriveElevation& el = *j;
861  const SUMOReal sNext = (j + 1) == e.elevations.end() ? std::numeric_limits<SUMOReal>::max() : (*(j + 1)).s;
862  while (k < (int)e.geom.size() && pos < sNext) {
863  const SUMOReal ds = pos - el.s;
864  const SUMOReal z = el.a + el.b * ds + el.c * ds * ds + el.d * ds * ds * ds;
865  //std::cout << " edge=" << e.id << " k=" << k << " sNext=" << sNext << " pos=" << pos << " z=" << z << " pos=" << pos << " ds=" << ds << " el.s=" << el.s << "el.a=" << el.a << " el.b=" << el.b << " el.c=" << el.c << " el.d=" << el.d << "\n";
866  e.geom[k].add(0, 0, z);
867  k++;
868  if (k < (int)e.geom.size()) {
869  // XXX pos understimates the actual position since the
870  // actual geometry between k-1 and k could be curved
871  pos += e.geom[k - 1].distanceTo2D(e.geom[k]);
872  }
873  }
874  }
875  }
876 }
877 
878 
879 void
880 NIImporter_OpenDrive::revisitLaneSections(const NBTypeCont& tc, std::map<std::string, OpenDriveEdge*>& edges) {
881  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
882  OpenDriveEdge& e = *(*i).second;
883  std::vector<OpenDriveLaneSection>& laneSections = e.laneSections;
884  // split by speed limits
885  std::vector<OpenDriveLaneSection> newSections;
886  for (std::vector<OpenDriveLaneSection>::iterator j = laneSections.begin(); j != laneSections.end(); ++j) {
887  std::vector<OpenDriveLaneSection> splitSections;
888  bool splitBySpeed = (*j).buildSpeedChanges(tc, splitSections);
889  if (!splitBySpeed) {
890  newSections.push_back(*j);
891  } else {
892  std::copy(splitSections.begin(), splitSections.end(), back_inserter(newSections));
893  }
894  }
895 
896  e.laneSections = newSections;
897  laneSections = e.laneSections;
898  SUMOReal lastS = -1;
899  // check whether the lane sections are in the right order
900  bool sorted = true;
901  for (std::vector<OpenDriveLaneSection>::const_iterator j = laneSections.begin(); j != laneSections.end() && sorted; ++j) {
902  if ((*j).s <= lastS) {
903  sorted = false;
904  }
905  lastS = (*j).s;
906  }
907  if (!sorted) {
908  WRITE_WARNING("The sections of edge '" + e.id + "' are not sorted properly.");
909  sort(e.laneSections.begin(), e.laneSections.end(), sections_by_s_sorter());
910  }
911  // check whether no duplicates of s-value occure
912  lastS = -1;
913  laneSections = e.laneSections;
914  for (std::vector<OpenDriveLaneSection>::iterator j = laneSections.begin(); j != laneSections.end();) {
915  bool simlarToLast = fabs((*j).s - lastS) < POSITION_EPS;
916  lastS = (*j).s;
917  if (simlarToLast) {
918  WRITE_WARNING("Almost duplicate s-value '" + toString(lastS) + "' for lane sections occured at edge '" + e.id + "'; second entry was removed.");
919  j = laneSections.erase(j);
920  } else {
921  ++j;
922  }
923  }
924  }
925 }
926 
927 
930  UNUSED_PARAMETER(e);
931  PositionVector ret;
932  ret.push_back(Position(g.x, g.y));
933  ret.push_back(calculateStraightEndPoint(g.hdg, g.length, Position(g.x, g.y)));
934  return ret;
935 }
936 
937 
940  UNUSED_PARAMETER(e);
941  PositionVector ret;
942  SUMOReal curveStart = g.params[0];
943  SUMOReal curveEnd = g.params[1];
944  Point2D<double> end;
945  try {
946  EulerSpiral s(Point2D<double>(g.x, g.y), g.hdg, curveStart, (curveEnd - curveStart) / g.length, g.length);
947  std::vector<Point2D<double> > into;
948  s.computeSpiral(into, 1.);
949  for (std::vector<Point2D<double> >::iterator i = into.begin(); i != into.end(); ++i) {
950  ret.push_back(Position((*i).getX(), (*i).getY()));
951  }
952  } catch (const std::runtime_error& error) {
953  WRITE_WARNING("Could not compute spiral geometry for edge '" + e.id + "' (" + error.what() + ").");
954  ret.push_back(Position(g.x, g.y));
955  }
956  return ret.getSubpart2D(0, g.length);
957 }
958 
959 
962  UNUSED_PARAMETER(e);
963  PositionVector ret;
964  SUMOReal dist = 0.0;
965  SUMOReal centerX = g.x;
966  SUMOReal centerY = g.y;
967  // left: positive value
968  SUMOReal curvature = g.params[0];
969  SUMOReal radius = 1. / curvature;
970  // center point
971  calculateCurveCenter(&centerX, &centerY, radius, g.hdg);
972  SUMOReal endX = g.x;
973  SUMOReal endY = g.y;
974  SUMOReal startX = g.x;
975  SUMOReal startY = g.y;
976  SUMOReal geo_posS = g.s;
977  SUMOReal geo_posE = g.s;
978  bool end = false;
979  do {
980  geo_posE += C_LENGTH;
981  if (geo_posE - g.s > g.length) {
982  geo_posE = g.s + g.length;
983  }
984  if (geo_posE - g.s > g.length) {
985  geo_posE = g.s + g.length;
986  }
987  calcPointOnCurve(&endX, &endY, centerX, centerY, radius, geo_posE - geo_posS);
988 
989  dist += (geo_posE - geo_posS);
990  //
991  ret.push_back(Position(startX, startY));
992  //
993  startX = endX;
994  startY = endY;
995  geo_posS = geo_posE;
996 
997  if (geo_posE - (g.s + g.length) < 0.001 && geo_posE - (g.s + g.length) > -0.001) {
998  end = true;
999  }
1000  } while (!end);
1001  return ret.getSubpart2D(0, g.length);
1002 }
1003 
1004 
1007  UNUSED_PARAMETER(e);
1008  const SUMOReal s = sin(g.hdg);
1009  const SUMOReal c = cos(g.hdg);
1010  PositionVector ret;
1011  for (SUMOReal off = 0; off < g.length + 2.; off += 2.) {
1012  SUMOReal x = off;
1013  SUMOReal y = g.params[0] + g.params[1] * off + g.params[2] * pow(off, 2.) + g.params[3] * pow(off, 3.);
1014  SUMOReal xnew = x * c - y * s;
1015  SUMOReal ynew = x * s + y * c;
1016  ret.push_back(Position(g.x + xnew, g.y + ynew));
1017  }
1018  return ret.getSubpart2D(0, g.length);
1019 }
1020 
1021 
1024  UNUSED_PARAMETER(e);
1025  const SUMOReal s = sin(g.hdg);
1026  const SUMOReal c = cos(g.hdg);
1027  const SUMOReal pMax = g.params[8];
1028  // import with 2m resolution
1029  const SUMOReal pStep = pMax / ceil(g.length / 2.0);
1030  PositionVector ret;
1031  for (SUMOReal p = 0; p < pMax + pStep; p += pStep) {
1032  SUMOReal x = g.params[0] + g.params[1] * p + g.params[2] * pow(p, 2.) + g.params[3] * pow(p, 3.);
1033  SUMOReal y = g.params[4] + g.params[5] * p + g.params[6] * pow(p, 2.) + g.params[7] * pow(p, 3.);
1034  SUMOReal xnew = x * c - y * s;
1035  SUMOReal ynew = x * s + y * c;
1036  ret.push_back(Position(g.x + xnew, g.y + ynew));
1037  }
1038  return ret.getSubpart2D(0, g.length);
1039 }
1040 
1041 
1042 Position
1043 NIImporter_OpenDrive::calculateStraightEndPoint(double hdg, double length, const Position& start) {
1044  double normx = 1.0f;
1045  double normy = 0.0f;
1046  double x2 = normx * cos(hdg) - normy * sin(hdg);
1047  double y2 = normx * sin(hdg) + normy * cos(hdg);
1048  normx = x2 * length;
1049  normy = y2 * length;
1050  return Position(start.x() + normx, start.y() + normy);
1051 }
1052 
1053 
1054 void
1056  SUMOReal normX = 1.0;
1057  SUMOReal normY = 0.0;
1058  SUMOReal tmpX;
1059  SUMOReal turn;
1060  if (ad_radius > 0) {
1061  turn = -1.0;
1062  } else {
1063  turn = 1.0;
1064  }
1065 
1066  tmpX = normX;
1067  normX = normX * cos(ad_hdg) + normY * sin(ad_hdg);
1068  normY = tmpX * sin(ad_hdg) + normY * cos(ad_hdg);
1069 
1070  tmpX = normX;
1071  normX = turn * normY;
1072  normY = -turn * tmpX;
1073 
1074  normX = fabs(ad_radius) * normX;
1075  normY = fabs(ad_radius) * normY;
1076 
1077  *ad_x += normX;
1078  *ad_y += normY;
1079 }
1080 
1081 
1082 void
1084  SUMOReal ad_r, SUMOReal ad_length) {
1085  double rotAngle = ad_length / fabs(ad_r);
1086  double vx = *ad_x - ad_centerX;
1087  double vy = *ad_y - ad_centerY;
1088  double tmpx;
1089 
1090  double turn;
1091  if (ad_r > 0) {
1092  turn = -1; //left
1093  } else {
1094  turn = 1; //right
1095  }
1096  tmpx = vx;
1097  vx = vx * cos(rotAngle) + turn * vy * sin(rotAngle);
1098  vy = -1 * turn * tmpx * sin(rotAngle) + vy * cos(rotAngle);
1099  *ad_x = vx + ad_centerX;
1100  *ad_y = vy + ad_centerY;
1101 }
1102 
1103 
1104 // ---------------------------------------------------------------------------
1105 // section
1106 // ---------------------------------------------------------------------------
1108  lanesByDir[OPENDRIVE_TAG_LEFT] = std::vector<OpenDriveLane>();
1109  lanesByDir[OPENDRIVE_TAG_RIGHT] = std::vector<OpenDriveLane>();
1110  lanesByDir[OPENDRIVE_TAG_CENTER] = std::vector<OpenDriveLane>();
1111 }
1112 
1113 
1114 void
1116  int sumoLane = 0;
1117  bool singleType = true;
1118  std::vector<std::string> types;
1119  const std::vector<OpenDriveLane>& dirLanesR = lanesByDir.find(OPENDRIVE_TAG_RIGHT)->second;
1120  for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanesR.rbegin(); i != dirLanesR.rend(); ++i) {
1121  if (myImportAllTypes || (tc.knows((*i).type) && !tc.getShallBeDiscarded((*i).type))) {
1122  laneMap[(*i).id] = sumoLane++;
1123  types.push_back((*i).type);
1124  if (types.front() != types.back()) {
1125  singleType = false;
1126  }
1127  }
1128  }
1129  rightLaneNumber = sumoLane;
1130  rightType = sumoLane > 0 ? (singleType ? types.front() : joinToString(types, "|")) : "";
1131  sumoLane = 0;
1132  singleType = true;
1133  types.clear();
1134  const std::vector<OpenDriveLane>& dirLanesL = lanesByDir.find(OPENDRIVE_TAG_LEFT)->second;
1135  for (std::vector<OpenDriveLane>::const_iterator i = dirLanesL.begin(); i != dirLanesL.end(); ++i) {
1136  if (myImportAllTypes || (tc.knows((*i).type) && !tc.getShallBeDiscarded((*i).type))) {
1137  laneMap[(*i).id] = sumoLane++;
1138  types.push_back((*i).type);
1139  if (types.front() != types.back()) {
1140  singleType = false;
1141  }
1142  }
1143  }
1144  leftLaneNumber = sumoLane;
1145  leftType = sumoLane > 0 ? (singleType ? types.front() : joinToString(types, "|")) : "";
1146 }
1147 
1148 
1149 std::map<int, int>
1151  std::map<int, int> ret;
1152  const std::vector<OpenDriveLane>& dirLanes = lanesByDir.find(dir)->second;
1153  for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanes.rbegin(); i != dirLanes.rend(); ++i) {
1154  std::map<int, int>::const_iterator toP = laneMap.find((*i).id);
1155  if (toP == laneMap.end()) {
1156  // the current lane is not available in SUMO
1157  continue;
1158  }
1159  int to = (*toP).second;
1160  int from = UNSET_CONNECTION;
1161  if ((*i).predecessor != UNSET_CONNECTION) {
1162  from = (*i).predecessor;
1163  }
1164  if (from != UNSET_CONNECTION) {
1165  std::map<int, int>::const_iterator fromP = prev.laneMap.find(from);
1166  if (fromP != prev.laneMap.end()) {
1167  from = (*fromP).second;
1168  } else {
1169  from = UNSET_CONNECTION;
1170  }
1171  }
1172  if (from != UNSET_CONNECTION && to != UNSET_CONNECTION) {
1173  if (ret.find(from) != ret.end()) {
1174 // WRITE_WARNING("double connection");
1175  }
1176  if (dir == OPENDRIVE_TAG_LEFT) {
1177  std::swap(from, to);
1178  }
1179  ret[from] = to;
1180  } else {
1181 // WRITE_WARNING("missing connection");
1182  }
1183  }
1184  return ret;
1185 }
1186 
1187 
1190  OpenDriveLaneSection ret(*this);
1191  ret.s += startPos;
1192  for (int k = 0; k < (int)ret.lanesByDir[OPENDRIVE_TAG_RIGHT].size(); ++k) {
1194  l.speed = 0;
1195  std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator i = std::find_if(l.speeds.begin(), l.speeds.end(), same_position_finder(startPos));
1196  if (i != l.speeds.end()) {
1197  l.speed = (*i).second;
1198  }
1199  }
1200  for (int k = 0; k < (int)ret.lanesByDir[OPENDRIVE_TAG_LEFT].size(); ++k) {
1202  std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator i = std::find_if(l.speeds.begin(), l.speeds.end(), same_position_finder(startPos));
1203  l.speed = 0;
1204  if (i != l.speeds.end()) {
1205  l.speed = (*i).second;
1206  }
1207  }
1208  return ret;
1209 }
1210 
1211 
1212 bool
1213 NIImporter_OpenDrive::OpenDriveLaneSection::buildSpeedChanges(const NBTypeCont& tc, std::vector<OpenDriveLaneSection>& newSections) {
1214  std::set<SUMOReal> speedChangePositions;
1215  // collect speed change positions and apply initial speed to the begin
1216  for (std::vector<OpenDriveLane>::iterator k = lanesByDir[OPENDRIVE_TAG_RIGHT].begin(); k != lanesByDir[OPENDRIVE_TAG_RIGHT].end(); ++k) {
1217  for (std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator l = (*k).speeds.begin(); l != (*k).speeds.end(); ++l) {
1218  speedChangePositions.insert((*l).first);
1219  if ((*l).first == 0) {
1220  (*k).speed = (*l).second;
1221  }
1222  }
1223  }
1224  for (std::vector<OpenDriveLane>::iterator k = lanesByDir[OPENDRIVE_TAG_LEFT].begin(); k != lanesByDir[OPENDRIVE_TAG_LEFT].end(); ++k) {
1225  for (std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator l = (*k).speeds.begin(); l != (*k).speeds.end(); ++l) {
1226  speedChangePositions.insert((*l).first);
1227  if ((*l).first == 0) {
1228  (*k).speed = (*l).second;
1229  }
1230  }
1231  }
1232  // do nothing if there is none
1233  if (speedChangePositions.size() == 0) {
1234  return false;
1235  }
1236  if (*speedChangePositions.begin() > 0) {
1237  speedChangePositions.insert(0);
1238  }
1239  //
1240  for (std::set<SUMOReal>::iterator i = speedChangePositions.begin(); i != speedChangePositions.end(); ++i) {
1241  if (i == speedChangePositions.begin()) {
1242  newSections.push_back(*this);
1243  } else {
1244  newSections.push_back(buildLaneSection(*i));
1245  }
1246  }
1247  // propagate speeds
1248  for (int i = 0; i != (int)newSections.size(); ++i) {
1249  OpenDriveLaneSection& ls = newSections[i];
1250  std::map<OpenDriveXMLTag, std::vector<OpenDriveLane> >& lanesByDir = ls.lanesByDir;
1251  for (std::map<OpenDriveXMLTag, std::vector<OpenDriveLane> >::iterator k = lanesByDir.begin(); k != lanesByDir.end(); ++k) {
1252  std::vector<OpenDriveLane>& lanes = (*k).second;
1253  for (int j = 0; j != (int)lanes.size(); ++j) {
1254  OpenDriveLane& l = lanes[j];
1255  if (l.speed != 0) {
1256  continue;
1257  }
1258  if (i > 0) {
1259  l.speed = newSections[i - 1].lanesByDir[(*k).first][j].speed;
1260  } else {
1261  tc.getSpeed(l.type);
1262  }
1263  }
1264  }
1265  }
1266  return true;
1267 }
1268 
1269 
1270 
1271 // ---------------------------------------------------------------------------
1272 // edge
1273 // ---------------------------------------------------------------------------
1274 int
1276  int prio = 1;
1277  for (std::vector<OpenDriveSignal>::const_iterator i = signals.begin(); i != signals.end(); ++i) {
1278  int tmp = 1;
1279  if ((*i).type == "301" || (*i).type == "306") {
1280  tmp = 2;
1281  }
1282  if ((*i).type == "205") {
1283  tmp = 0;
1284  }
1285  if (tmp != 1 && dir == OPENDRIVE_TAG_RIGHT && (*i).orientation > 0) {
1286  prio = tmp;
1287  }
1288  if (tmp != 1 && dir == OPENDRIVE_TAG_LEFT && (*i).orientation < 0) {
1289  prio = tmp;
1290  }
1291 
1292  }
1293  return prio;
1294 }
1295 
1296 
1297 
1298 // ---------------------------------------------------------------------------
1299 // loader methods
1300 // ---------------------------------------------------------------------------
1301 NIImporter_OpenDrive::NIImporter_OpenDrive(const NBTypeCont& tc, std::map<std::string, OpenDriveEdge*>& edges)
1303  myTypeContainer(tc), myCurrentEdge("", "", "", -1), myEdges(edges) {
1304 }
1305 
1306 
1308 }
1309 
1310 
1311 void
1313  const SUMOSAXAttributes& attrs) {
1314  bool ok = true;
1315  switch (element) {
1316  case OPENDRIVE_TAG_HEADER: {
1317  int majorVersion = attrs.get<int>(OPENDRIVE_ATTR_REVMAJOR, 0, ok);
1318  int minorVersion = attrs.get<int>(OPENDRIVE_ATTR_REVMINOR, 0, ok);
1319  if (majorVersion != 1 || minorVersion != 2) {
1320  WRITE_WARNING("Given openDrive file '" + getFileName() + "' uses version " + toString(majorVersion) + "." + toString(minorVersion) + ";\n Version 1.2 is supported.");
1321  }
1322  }
1323  break;
1324  case OPENDRIVE_TAG_ROAD: {
1325  std::string id = attrs.get<std::string>(OPENDRIVE_ATTR_ID, 0, ok);
1326  std::string streetName = attrs.getOpt<std::string>(OPENDRIVE_ATTR_NAME, 0, ok, "", false);
1327  std::string junction = attrs.get<std::string>(OPENDRIVE_ATTR_JUNCTION, id.c_str(), ok);
1328  SUMOReal length = attrs.get<SUMOReal>(OPENDRIVE_ATTR_LENGTH, id.c_str(), ok);
1329  myCurrentEdge = OpenDriveEdge(id, streetName, junction, length);
1330  }
1331  break;
1333  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
1334  std::string elementType = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
1335  std::string elementID = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
1336  std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
1337  ? attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok)
1338  : "end";
1339  addLink(OPENDRIVE_LT_PREDECESSOR, elementType, elementID, contactPoint);
1340  }
1341  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
1342  int no = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1343  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1344  l.predecessor = no;
1345  }
1346  }
1347  break;
1348  case OPENDRIVE_TAG_SUCCESSOR: {
1349  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
1350  std::string elementType = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
1351  std::string elementID = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
1352  std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
1353  ? attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok)
1354  : "start";
1355  addLink(OPENDRIVE_LT_SUCCESSOR, elementType, elementID, contactPoint);
1356  }
1357  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
1358  int no = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1359  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1360  l.successor = no;
1361  }
1362  }
1363  break;
1364  case OPENDRIVE_TAG_GEOMETRY: {
1365  SUMOReal length = attrs.get<SUMOReal>(OPENDRIVE_ATTR_LENGTH, myCurrentEdge.id.c_str(), ok);
1366  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1367  SUMOReal x = attrs.get<SUMOReal>(OPENDRIVE_ATTR_X, myCurrentEdge.id.c_str(), ok);
1368  SUMOReal y = attrs.get<SUMOReal>(OPENDRIVE_ATTR_Y, myCurrentEdge.id.c_str(), ok);
1369  SUMOReal hdg = attrs.get<SUMOReal>(OPENDRIVE_ATTR_HDG, myCurrentEdge.id.c_str(), ok);
1370  myCurrentEdge.geometries.push_back(OpenDriveGeometry(length, s, x, y, hdg));
1371  }
1372  break;
1373  case OPENDRIVE_TAG_ELEVATION: {
1374  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1375  SUMOReal a = attrs.get<SUMOReal>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok);
1376  SUMOReal b = attrs.get<SUMOReal>(OPENDRIVE_ATTR_B, myCurrentEdge.id.c_str(), ok);
1377  SUMOReal c = attrs.get<SUMOReal>(OPENDRIVE_ATTR_C, myCurrentEdge.id.c_str(), ok);
1378  SUMOReal d = attrs.get<SUMOReal>(OPENDRIVE_ATTR_D, myCurrentEdge.id.c_str(), ok);
1379  myCurrentEdge.elevations.push_back(OpenDriveElevation(s, a, b, c, d));
1380  }
1381  break;
1382  case OPENDRIVE_TAG_LINE: {
1383  std::vector<SUMOReal> vals;
1385  }
1386  break;
1387  case OPENDRIVE_TAG_SPIRAL: {
1388  std::vector<SUMOReal> vals;
1389  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVSTART, myCurrentEdge.id.c_str(), ok));
1390  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVEND, myCurrentEdge.id.c_str(), ok));
1392  }
1393  break;
1394  case OPENDRIVE_TAG_ARC: {
1395  std::vector<SUMOReal> vals;
1396  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVATURE, myCurrentEdge.id.c_str(), ok));
1398  }
1399  break;
1400  case OPENDRIVE_TAG_POLY3: {
1401  std::vector<SUMOReal> vals;
1402  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok));
1403  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_B, myCurrentEdge.id.c_str(), ok));
1404  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_C, myCurrentEdge.id.c_str(), ok));
1405  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_D, myCurrentEdge.id.c_str(), ok));
1407  }
1408  break;
1409  case OPENDRIVE_TAG_PARAMPOLY3: {
1410  std::vector<SUMOReal> vals;
1411  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_AU, myCurrentEdge.id.c_str(), ok));
1412  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_BU, myCurrentEdge.id.c_str(), ok));
1413  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CU, myCurrentEdge.id.c_str(), ok));
1414  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_DU, myCurrentEdge.id.c_str(), ok));
1415  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_AV, myCurrentEdge.id.c_str(), ok));
1416  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_BV, myCurrentEdge.id.c_str(), ok));
1417  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CV, myCurrentEdge.id.c_str(), ok));
1418  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_DV, myCurrentEdge.id.c_str(), ok));
1419  vals.push_back(attrs.getOpt<SUMOReal>(OPENDRIVE_ATTR_PRANGE, myCurrentEdge.id.c_str(), ok, 1.0, false));
1421  }
1422  break;
1424  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1426  }
1427  break;
1428  case OPENDRIVE_TAG_LEFT:
1430  break;
1431  case OPENDRIVE_TAG_CENTER:
1433  break;
1434  case OPENDRIVE_TAG_RIGHT:
1436  break;
1437  case OPENDRIVE_TAG_LANE: {
1438  std::string type = attrs.get<std::string>(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
1439  int id = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1440  std::string level = attrs.hasAttribute(OPENDRIVE_ATTR_LEVEL)
1441  ? attrs.get<std::string>(OPENDRIVE_ATTR_LEVEL, myCurrentEdge.id.c_str(), ok)
1442  : "";
1444  ls.lanesByDir[myCurrentLaneDirection].push_back(OpenDriveLane(id, level, type));
1445  }
1446  break;
1447  case OPENDRIVE_TAG_SIGNAL: {
1448  int id = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1449  std::string type = attrs.get<std::string>(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
1450  std::string name = attrs.getOpt<std::string>(OPENDRIVE_ATTR_NAME, myCurrentEdge.id.c_str(), ok, "", false);
1451  int orientation = attrs.get<std::string>(OPENDRIVE_ATTR_ORIENTATION, myCurrentEdge.id.c_str(), ok) == "-" ? -1 : 1;
1452  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1453  bool dynamic = attrs.get<std::string>(OPENDRIVE_ATTR_DYNAMIC, myCurrentEdge.id.c_str(), ok) == "no" ? false : true;
1454  myCurrentEdge.signals.push_back(OpenDriveSignal(id, type, name, orientation, dynamic, s));
1455  }
1456  break;
1458  myCurrentJunctionID = attrs.get<std::string>(OPENDRIVE_ATTR_ID, myCurrentJunctionID.c_str(), ok);
1459  break;
1460  case OPENDRIVE_TAG_CONNECTION: {
1461  std::string id = attrs.get<std::string>(OPENDRIVE_ATTR_ID, myCurrentJunctionID.c_str(), ok);
1462  myCurrentIncomingRoad = attrs.get<std::string>(OPENDRIVE_ATTR_INCOMINGROAD, myCurrentJunctionID.c_str(), ok);
1464  std::string cp = attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentJunctionID.c_str(), ok);
1466  myConnectionWasEmpty = true;
1467  }
1468  break;
1469  case OPENDRIVE_TAG_LANELINK: {
1470  int from = attrs.get<int>(OPENDRIVE_ATTR_FROM, myCurrentJunctionID.c_str(), ok);
1471  int to = attrs.get<int>(OPENDRIVE_ATTR_TO, myCurrentJunctionID.c_str(), ok);
1472  Connection c;
1474  c.toEdge = myCurrentConnectingRoad;
1475  c.fromLane = from;
1476  c.toLane = to;
1477  c.fromCP = OPENDRIVE_CP_END;
1478  c.toCP = myCurrentContactPoint;
1479  c.all = false;
1480  if (myEdges.find(c.fromEdge) == myEdges.end()) {
1481  WRITE_ERROR("In laneLink-element: incoming road '" + c.fromEdge + "' is not known.");
1482  } else {
1483  OpenDriveEdge* e = myEdges.find(c.fromEdge)->second;
1484  e->connections.insert(c);
1485  myConnectionWasEmpty = false;
1486  }
1487  }
1488  break;
1489  case OPENDRIVE_TAG_WIDTH: {
1490  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 1] == OPENDRIVE_TAG_LANE) {
1491  SUMOReal width = attrs.get<SUMOReal>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok);
1492  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1493  l.width = MAX2(l.width, width);
1494  }
1495  }
1496  break;
1497  case OPENDRIVE_TAG_SPEED: {
1498  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 1] == OPENDRIVE_TAG_LANE) {
1499  SUMOReal speed = attrs.get<SUMOReal>(OPENDRIVE_ATTR_MAX, myCurrentEdge.id.c_str(), ok);
1500  SUMOReal pos = attrs.get<SUMOReal>(OPENDRIVE_ATTR_SOFFSET, myCurrentEdge.id.c_str(), ok);
1501  myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back().speeds.push_back(std::make_pair(pos, speed));
1502  }
1503  }
1504  break;
1505  default:
1506  break;
1507  }
1508  myElementStack.push_back(element);
1509 }
1510 
1511 
1512 void
1514  myElementStack.pop_back();
1515  switch (element) {
1516  case OPENDRIVE_TAG_ROAD:
1518  break;
1520  if (myConnectionWasEmpty) {
1521  Connection c;
1524  c.fromLane = 0;
1525  c.toLane = 0;
1528  c.all = true;
1529  if (myEdges.find(c.fromEdge) == myEdges.end()) {
1530  WRITE_ERROR("In laneLink-element: incoming road '" + c.fromEdge + "' is not known.");
1531  } else {
1532  OpenDriveEdge* e = myEdges.find(c.fromEdge)->second;
1533  e->connections.insert(c);
1534  }
1535  }
1536  break;
1538  myCurrentEdge.laneSections.back().buildLaneMapping(myTypeContainer);
1539  }
1540  break;
1541  default:
1542  break;
1543  }
1544 }
1545 
1546 
1547 
1548 void
1549 NIImporter_OpenDrive::addLink(LinkType lt, const std::string& elementType,
1550  const std::string& elementID,
1551  const std::string& contactPoint) {
1552  OpenDriveLink l(lt, elementID);
1553  // elementType
1554  if (elementType == "road") {
1556  } else if (elementType == "junction") {
1558  }
1559  // contact point
1560  if (contactPoint == "start") {
1562  } else if (contactPoint == "end") {
1564  }
1565  // add
1566  myCurrentEdge.links.push_back(l);
1567 }
1568 
1569 
1570 void
1571 NIImporter_OpenDrive::addGeometryShape(GeometryType type, const std::vector<SUMOReal>& vals) {
1572  // checks
1573  if (myCurrentEdge.geometries.size() == 0) {
1574  throw ProcessError("Mismatching paranthesis in geometry definition for road '" + myCurrentEdge.id + "'");
1575  }
1577  if (last.type != OPENDRIVE_GT_UNKNOWN) {
1578  throw ProcessError("Double geometry information for road '" + myCurrentEdge.id + "'");
1579  }
1580  // set
1581  last.type = type;
1582  last.params = vals;
1583 }
1584 
1585 
1586 bool
1588  if (c1.fromEdge != c2.fromEdge) {
1589  return c1.fromEdge < c2.fromEdge;
1590  }
1591  if (c1.toEdge != c2.toEdge) {
1592  return c1.toEdge < c2.toEdge;
1593  }
1594  if (c1.fromLane != c2.fromLane) {
1595  return c1.fromLane < c2.fromLane;
1596  }
1597  return c1.toLane < c2.toLane;
1598 }
1599 
1600 
1601 
1602 /****************************************************************************/
1603 
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) ...
std::string rightType
the composite type built from all used lane types
static const SUMOReal UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:203
static PositionVector geomFromLine(const OpenDriveEdge &e, const OpenDriveGeometry &g)
static StringBijection< int >::Entry openDriveAttrs[]
The names of openDrive-XML attributes (for passing to GenericSAXHandler)
NBTypeCont & getTypeCont()
Returns the type container.
Definition: NBNetBuilder.h:169
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
get subpart of a position vector in two dimensions (Z is ignored)
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.
std::vector< OpenDriveElevation > elevations
GeometryType
OpenDrive geometry type enumeration.
int rightLaneNumber
The number of lanes on the right and on the left side, respectively.
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:304
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:70
Representation of an openDrive "link".
The base class for traffic light logic definitions.
ContactPoint myCurrentContactPoint
SUMOReal s
The starting offset of this lane section.
T MAX2(T a, T b)
Definition: StdDefs.h:75
static PositionVector geomFromArc(const OpenDriveEdge &e, const OpenDriveGeometry &g)
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)
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1090
static const SUMOReal UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:205
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false)
Runs the given handler on the given file; returns if everything&#39;s ok.
Definition: XMLSubSys.cpp:114
SUMOReal x() const
Returns the x-position.
Definition: Position.h:63
friend bool operator<(const Connection &c1, const Connection &c2)
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
bool addLane2LaneConnection(int fromLane, NBEdge *dest, int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, SUMOReal contPos=UNSPECIFIED_CONTPOS)
Adds a connection between the specified this edge&#39;s lane and an approached one.
Definition: NBEdge.cpp:697
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:219
static NBNode * getOrBuildNode(const std::string &id, const Position &pos, NBNodeCont &nc)
Builds a node or returns the already built.
void error(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Handler for XML-errors.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
The connection was computed and validated.
Definition: NBEdge.h:115
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:69
static std::string revertID(const std::string &id)
PositionVector reverse() const
reverse position vector
#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:122
const std::string & getID() const
Returns the id.
Definition: Named.h:66
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)
#define max(a, b)
Definition: polyfonts.c:65
SUMOReal getSpeed(const std::string &type) const
Returns the maximal velocity for the given type [m/s].
Definition: NBTypeCont.cpp:183
const std::string & getFileName() const
returns the current file name
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node.
Definition: NBNode.h:318
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:162
std::string type
The lane&#39;s type.
int getPriority(OpenDriveXMLTag dir) const
Returns the edge&#39;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:153
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.
void add(SUMOReal xoff, SUMOReal yoff, SUMOReal zoff)
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
SUMOReal width
The lane&#39;s width;.
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:187
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:77
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
The connection was given by the user.
Definition: NBEdge.h:113
static PositionVector geomFromSpiral(const OpenDriveEdge &e, const OpenDriveGeometry &g)
static PositionVector geomFromPoly(const OpenDriveEdge &e, const OpenDriveGeometry &g)
static StringBijection< int >::Entry openDriveTags[]
The names of openDrive-XML elements (for passing to GenericSAXHandler)
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:206
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&#39;s geometry.
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:371
void addTrafficLight(NBTrafficLightDefinition *tlDef)
Adds a traffic light to the list of traffic lights that control this node.
Definition: NBNode.cpp:312
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:247
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:161
SUMOReal speed
The lane&#39;s speed (set in post-processing)
Instance responsible for building networks.
Definition: NBNetBuilder.h:112
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:201
SUMOReal y() const
Returns the y-position.
Definition: Position.h:68
A storage for options typed value containers)
Definition: OptionsCont.h:99
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:81
NBTrafficLightLogicCont & getTLLogicCont()
Returns the traffic light logics container.
Definition: NBNetBuilder.h:177
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:74
T get(const std::string &str) const
A class for sorting lane sections by their s-value.
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:188
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
static PositionVector geomFromParamPoly(const OpenDriveEdge &e, const OpenDriveGeometry &g)
#define SUMOReal
Definition: config.h:213
static void setNodeSecure(NBNodeCont &nc, OpenDriveEdge &e, const std::string &nodeID, NIImporter_OpenDrive::LinkType lt)
void push_back_noDoublePos(const Position &p)
insert in back a non double position
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:110
SVCPermissions getPermissions(const std::string &type) const
Returns allowed vehicle classes for the given type.
Definition: NBTypeCont.cpp:213
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:63
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
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:786
Importer for networks stored in openDrive format.
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&#39;s width.
Definition: NBEdge.h:138
#define UNSET_CONNECTION
TrafficLightType
A storage for available types of edges.
Definition: NBTypeCont.h:62
std::string streetName
The road name of the edge.
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.
Coefficients of an elevation profile (3rd degree polynomial)