SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules 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.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, myImportAllTypes)) {
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, myImportAllTypes)) {
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  if (!toNode->isTLControlled()) {
619  NBOwnTLDef* tlDef = new NBOwnTLDef(toNode->getID(), toNode, 0, type);
620  if (!nb.getTLLogicCont().insert(tlDef)) {
621  // actually, nothing should fail here
622  delete tlDef;
623  throw ProcessError();
624  }
625  toNode->addTrafficLight(tlDef);
626  //tlDef->setSinglePhase();
627  }
628  NBTrafficLightDefinition* tlDef = *toNode->getControllingTLS().begin();
629  tlDef->addParameter("connection:" + id, (*i).second);
630  }
631 
632  // -------------------------
633  // clean up
634  // -------------------------
635  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
636  delete(*i).second;
637  }
638 }
639 
640 
641 void
642 NIImporter_OpenDrive::buildConnectionsToOuter(const Connection& c, const std::map<std::string, OpenDriveEdge*>& innerEdges, std::vector<Connection>& into) {
643 
644  OpenDriveEdge* dest = innerEdges.find(c.toEdge)->second;
645  if (dest == 0) {
647  return;
648  }
649  const std::set<Connection>& conts = dest->connections;
650  for (std::set<Connection>::const_iterator i = conts.begin(); i != conts.end(); ++i) {
651  if (innerEdges.find((*i).toEdge) != innerEdges.end()) {
652  std::vector<Connection> t;
653  buildConnectionsToOuter(*i, innerEdges, t);
654  for (std::vector<Connection>::const_iterator j = t.begin(); j != t.end(); ++j) {
655  // @todo this section is unverified
656  Connection cn = (*j);
657  cn.fromEdge = c.fromEdge;
658  cn.fromLane = c.fromLane;
659  cn.fromCP = c.fromCP;
660  cn.all = c.all; // @todo "all" is a hack trying to avoid the "from is zero" problem;
661  into.push_back(cn);
662  }
663  } else {
664  if ((*i).fromLane == c.toLane) {
665  Connection cn = (*i);
666  cn.fromEdge = c.fromEdge;
667  cn.fromLane = c.fromLane;
668  cn.fromCP = c.fromCP;
669  cn.all = c.all;
670  cn.origID = c.toEdge;
671  cn.origLane = c.toLane;
672  into.push_back(cn);
673  }
674  }
675  }
676 }
677 
678 
679 void
680 NIImporter_OpenDrive::setEdgeLinks2(OpenDriveEdge& e, const std::map<std::string, OpenDriveEdge*>& edges) {
681  for (std::vector<OpenDriveLink>::iterator i = e.links.begin(); i != e.links.end(); ++i) {
682  OpenDriveLink& l = *i;
683  if (l.elementType != OPENDRIVE_ET_ROAD) {
684  // we assume that links to nodes are later given as connections to edges
685  continue;
686  }
687  // get the right direction of the connected edge
688  std::string connectedEdge = l.elementID;
689  std::string edgeID = e.id;
690 
691  OpenDriveLaneSection& laneSection = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e.laneSections.back() : e.laneSections[0];
692  const std::map<int, int>& laneMap = laneSection.laneMap;
693  if (laneSection.lanesByDir.find(OPENDRIVE_TAG_RIGHT) != laneSection.lanesByDir.end()) {
694  const std::vector<OpenDriveLane>& lanes = laneSection.lanesByDir.find(OPENDRIVE_TAG_RIGHT)->second;
695  for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
696  if (!myImportAllTypes && laneMap.find((*j).id) == laneMap.end()) {
697  continue;
698  }
699  Connection c; // @todo: give Connection a new name and a constructor
700  c.fromEdge = e.id;
701  c.fromLane = (*j).id;
703  c.toLane = l.linkType == OPENDRIVE_LT_SUCCESSOR ? (*j).successor : (*j).predecessor;
704  c.toEdge = connectedEdge;
705  c.toCP = l.contactPoint;
706  c.all = false;
707  if (l.linkType != OPENDRIVE_LT_SUCCESSOR) {
708  std::swap(c.fromEdge, c.toEdge);
709  std::swap(c.fromLane, c.toLane);
710  std::swap(c.fromCP, c.toCP);
711  }
712  if (edges.find(c.fromEdge) == edges.end()) {
713  WRITE_ERROR("While setting connections: incoming road '" + c.fromEdge + "' is not known.");
714  } else {
715  OpenDriveEdge* src = edges.find(c.fromEdge)->second;
716  src->connections.insert(c);
717  }
718  }
719  }
720  if (laneSection.lanesByDir.find(OPENDRIVE_TAG_LEFT) != laneSection.lanesByDir.end()) {
721  const std::vector<OpenDriveLane>& lanes = laneSection.lanesByDir.find(OPENDRIVE_TAG_LEFT)->second;
722  for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
723  if (!myImportAllTypes && laneMap.find((*j).id) == laneMap.end()) {
724  continue;
725  }
726  Connection c;
727  c.toEdge = e.id;
728  c.toLane = (*j).id;
730  c.fromLane = l.linkType == OPENDRIVE_LT_SUCCESSOR ? (*j).successor : (*j).predecessor;
731  c.fromEdge = connectedEdge;
732  c.fromCP = l.contactPoint;
733  c.all = false;
734  if (l.linkType != OPENDRIVE_LT_SUCCESSOR) {
735  std::swap(c.fromEdge, c.toEdge);
736  std::swap(c.fromLane, c.toLane);
737  std::swap(c.fromCP, c.toCP);
738  }
739  if (edges.find(c.fromEdge) == edges.end()) {
740  WRITE_ERROR("While setting connections: incoming road '" + c.fromEdge + "' is not known.");
741  } else {
742  OpenDriveEdge* src = edges.find(c.fromEdge)->second;
743  src->connections.insert(c);
744  }
745  }
746  }
747  }
748 }
749 
750 
751 std::string NIImporter_OpenDrive::revertID(const std::string& id) {
752  if (id[0] == '-') {
753  return id.substr(1);
754  }
755  return "-" + id;
756 }
757 
758 
759 NBNode*
760 NIImporter_OpenDrive::getOrBuildNode(const std::string& id, const Position& pos,
761  NBNodeCont& nc) {
762  if (nc.retrieve(id) == 0) {
763  // not yet built; build now
764  if (!nc.insert(id, pos)) {
765  // !!! clean up
766  throw ProcessError("Could not add node '" + id + "'.");
767  }
768  }
769  return nc.retrieve(id);
770 }
771 
772 
773 void
775  const std::string& nodeID, NIImporter_OpenDrive::LinkType lt) {
776  NBNode* n = nc.retrieve(nodeID);
777  if (n == 0) {
778  throw ProcessError("Could not find node '" + nodeID + "'.");
779  }
780  if (lt == OPENDRIVE_LT_SUCCESSOR) {
781  if (e.to != 0 && e.to != n) {
782  throw ProcessError("Edge '" + e.id + "' has two end nodes.");
783  }
784  e.to = n;
785  } else {
786  if (e.from != 0 && e.from != n) {
787  throw ProcessError("Edge '" + e.id + "' has two start nodes.");
788  }
789  e.from = n;
790  }
791 }
792 
793 
794 void
795 NIImporter_OpenDrive::computeShapes(std::map<std::string, OpenDriveEdge*>& edges) {
797  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
798  OpenDriveEdge& e = *(*i).second;
800  for (std::vector<OpenDriveGeometry>::iterator j = e.geometries.begin(); j != e.geometries.end(); ++j) {
801  OpenDriveGeometry& g = *j;
802  PositionVector geom;
803  switch (g.type) {
805  break;
806  case OPENDRIVE_GT_LINE:
807  geom = geomFromLine(e, g);
808  break;
809  case OPENDRIVE_GT_SPIRAL:
810  geom = geomFromSpiral(e, g);
811  break;
812  case OPENDRIVE_GT_ARC:
813  geom = geomFromArc(e, g);
814  break;
815  case OPENDRIVE_GT_POLY3:
816  geom = geomFromPoly(e, g);
817  break;
819  geom = geomFromParamPoly(e, g);
820  break;
821  default:
822  break;
823  }
824  if (e.geom.size() > 0 && prevType == OPENDRIVE_GT_LINE) {
825  // remove redundant end point of the previous geometry segment
826  // (the start point of the current segment should have the same value)
827  // this avoids geometry errors due to imprecision
828  if (!e.geom.back().almostSame(geom.front())) {
829  const int index = (int)(j - e.geometries.begin());
830  WRITE_WARNING("Mismatched geometry for edge '" + e.id + "' between geometry segments " + toString(index - 1) + " and " + toString(index) + ".");
831  }
832  e.geom.pop_back();
833  }
834  for (PositionVector::iterator k = geom.begin(); k != geom.end(); ++k) {
836  }
837  prevType = g.type;
838  }
839  if (oc.exists("geometry.min-dist") && !oc.isDefault("geometry.min-dist")) {
840  e.geom.removeDoublePoints(oc.getFloat("geometry.min-dist"), true);
841  }
842  for (int j = 0; j < (int)e.geom.size(); ++j) {
844  WRITE_ERROR("Unable to project coordinates for.");
845  }
846  }
847  // add z-data
848  int k = 0;
849  SUMOReal pos = 0;
850  for (std::vector<OpenDriveElevation>::iterator j = e.elevations.begin(); j != e.elevations.end(); ++j) {
851  const OpenDriveElevation& el = *j;
852  const SUMOReal sNext = (j + 1) == e.elevations.end() ? std::numeric_limits<SUMOReal>::max() : (*(j + 1)).s;
853  while (k < (int)e.geom.size() && pos < sNext) {
854  const SUMOReal ds = pos - el.s;
855  const SUMOReal z = el.a + el.b * ds + el.c * ds * ds + el.d * ds * ds * ds;
856  //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";
857  e.geom[k].add(0, 0, z);
858  k++;
859  if (k < (int)e.geom.size()) {
860  // XXX pos understimates the actual position since the
861  // actual geometry between k-1 and k could be curved
862  pos += e.geom[k - 1].distanceTo2D(e.geom[k]);
863  }
864  }
865  }
866  }
867 }
868 
869 
870 void
871 NIImporter_OpenDrive::revisitLaneSections(const NBTypeCont& tc, std::map<std::string, OpenDriveEdge*>& edges) {
872  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
873  OpenDriveEdge& e = *(*i).second;
874  std::vector<OpenDriveLaneSection>& laneSections = e.laneSections;
875  // split by speed limits
876  std::vector<OpenDriveLaneSection> newSections;
877  for (std::vector<OpenDriveLaneSection>::iterator j = laneSections.begin(); j != laneSections.end(); ++j) {
878  std::vector<OpenDriveLaneSection> splitSections;
879  bool splitBySpeed = (*j).buildSpeedChanges(tc, splitSections);
880  if (!splitBySpeed) {
881  newSections.push_back(*j);
882  } else {
883  std::copy(splitSections.begin(), splitSections.end(), back_inserter(newSections));
884  }
885  }
886 
887  e.laneSections = newSections;
888  laneSections = e.laneSections;
889  SUMOReal lastS = -1;
890  // check whether the lane sections are in the right order
891  bool sorted = true;
892  for (std::vector<OpenDriveLaneSection>::const_iterator j = laneSections.begin(); j != laneSections.end() && sorted; ++j) {
893  if ((*j).s <= lastS) {
894  sorted = false;
895  }
896  lastS = (*j).s;
897  }
898  if (!sorted) {
899  WRITE_WARNING("The sections of edge '" + e.id + "' are not sorted properly.");
900  sort(e.laneSections.begin(), e.laneSections.end(), sections_by_s_sorter());
901  }
902  // check whether no duplicates of s-value occure
903  lastS = -1;
904  laneSections = e.laneSections;
905  for (std::vector<OpenDriveLaneSection>::iterator j = laneSections.begin(); j != laneSections.end();) {
906  bool simlarToLast = fabs((*j).s - lastS) < POSITION_EPS;
907  lastS = (*j).s;
908  if (simlarToLast) {
909  WRITE_WARNING("Almost duplicate s-value '" + toString(lastS) + "' for lane sections occured at edge '" + e.id + "'; second entry was removed.");
910  j = laneSections.erase(j);
911  } else {
912  ++j;
913  }
914  }
915  }
916 }
917 
918 
921  UNUSED_PARAMETER(e);
922  PositionVector ret;
923  ret.push_back(Position(g.x, g.y));
924  ret.push_back(calculateStraightEndPoint(g.hdg, g.length, Position(g.x, g.y)));
925  return ret;
926 }
927 
928 
931  UNUSED_PARAMETER(e);
932  PositionVector ret;
933  SUMOReal curveStart = g.params[0];
934  SUMOReal curveEnd = g.params[1];
935  Point2D<double> end;
936  try {
937  EulerSpiral s(Point2D<double>(g.x, g.y), g.hdg, curveStart, (curveEnd - curveStart) / g.length, g.length);
938  std::vector<Point2D<double> > into;
939  s.computeSpiral(into, 1.);
940  for (std::vector<Point2D<double> >::iterator i = into.begin(); i != into.end(); ++i) {
941  ret.push_back(Position((*i).getX(), (*i).getY()));
942  }
943  } catch (const std::runtime_error& error) {
944  WRITE_WARNING("Could not compute spiral geometry for edge '" + e.id + "' (" + error.what() + ").");
945  ret.push_back(Position(g.x, g.y));
946  }
947  return ret.getSubpart2D(0, g.length);
948 }
949 
950 
953  UNUSED_PARAMETER(e);
954  PositionVector ret;
955  SUMOReal dist = 0.0;
956  SUMOReal centerX = g.x;
957  SUMOReal centerY = g.y;
958  // left: positive value
959  SUMOReal curvature = g.params[0];
960  SUMOReal radius = 1. / curvature;
961  // center point
962  calculateCurveCenter(&centerX, &centerY, radius, g.hdg);
963  SUMOReal endX = g.x;
964  SUMOReal endY = g.y;
965  SUMOReal startX = g.x;
966  SUMOReal startY = g.y;
967  SUMOReal geo_posS = g.s;
968  SUMOReal geo_posE = g.s;
969  bool end = false;
970  do {
971  geo_posE += C_LENGTH;
972  if (geo_posE - g.s > g.length) {
973  geo_posE = g.s + g.length;
974  }
975  if (geo_posE - g.s > g.length) {
976  geo_posE = g.s + g.length;
977  }
978  calcPointOnCurve(&endX, &endY, centerX, centerY, radius, geo_posE - geo_posS);
979 
980  dist += (geo_posE - geo_posS);
981  //
982  ret.push_back(Position(startX, startY));
983  //
984  startX = endX;
985  startY = endY;
986  geo_posS = geo_posE;
987 
988  if (geo_posE - (g.s + g.length) < 0.001 && geo_posE - (g.s + g.length) > -0.001) {
989  end = true;
990  }
991  } while (!end);
992  return ret.getSubpart2D(0, g.length);
993 }
994 
995 
998  UNUSED_PARAMETER(e);
999  const SUMOReal s = sin(g.hdg);
1000  const SUMOReal c = cos(g.hdg);
1001  PositionVector ret;
1002  for (SUMOReal off = 0; off < g.length + 2.; off += 2.) {
1003  SUMOReal x = off;
1004  SUMOReal y = g.params[0] + g.params[1] * off + g.params[2] * pow(off, 2.) + g.params[3] * pow(off, 3.);
1005  SUMOReal xnew = x * c - y * s;
1006  SUMOReal ynew = x * s + y * c;
1007  ret.push_back(Position(g.x + xnew, g.y + ynew));
1008  }
1009  return ret.getSubpart2D(0, g.length);
1010 }
1011 
1012 
1015  UNUSED_PARAMETER(e);
1016  const SUMOReal s = sin(g.hdg);
1017  const SUMOReal c = cos(g.hdg);
1018  const SUMOReal pMax = g.params[8];
1019  // import with 2m resolution
1020  const SUMOReal pStep = pMax / ceil(g.length / 2.0);
1021  PositionVector ret;
1022  for (SUMOReal p = 0; p < pMax + pStep; p += pStep) {
1023  SUMOReal x = g.params[0] + g.params[1] * p + g.params[2] * pow(p, 2.) + g.params[3] * pow(p, 3.);
1024  SUMOReal y = g.params[4] + g.params[5] * p + g.params[6] * pow(p, 2.) + g.params[7] * pow(p, 3.);
1025  SUMOReal xnew = x * c - y * s;
1026  SUMOReal ynew = x * s + y * c;
1027  ret.push_back(Position(g.x + xnew, g.y + ynew));
1028  }
1029  return ret.getSubpart2D(0, g.length);
1030 }
1031 
1032 
1033 Position
1034 NIImporter_OpenDrive::calculateStraightEndPoint(double hdg, double length, const Position& start) {
1035  double normx = 1.0f;
1036  double normy = 0.0f;
1037  double x2 = normx * cos(hdg) - normy * sin(hdg);
1038  double y2 = normx * sin(hdg) + normy * cos(hdg);
1039  normx = x2 * length;
1040  normy = y2 * length;
1041  return Position(start.x() + normx, start.y() + normy);
1042 }
1043 
1044 
1045 void
1047  SUMOReal normX = 1.0;
1048  SUMOReal normY = 0.0;
1049  SUMOReal tmpX;
1050  SUMOReal turn;
1051  if (ad_radius > 0) {
1052  turn = -1.0;
1053  } else {
1054  turn = 1.0;
1055  }
1056 
1057  tmpX = normX;
1058  normX = normX * cos(ad_hdg) + normY * sin(ad_hdg);
1059  normY = tmpX * sin(ad_hdg) + normY * cos(ad_hdg);
1060 
1061  tmpX = normX;
1062  normX = turn * normY;
1063  normY = -turn * tmpX;
1064 
1065  normX = fabs(ad_radius) * normX;
1066  normY = fabs(ad_radius) * normY;
1067 
1068  *ad_x += normX;
1069  *ad_y += normY;
1070 }
1071 
1072 
1073 void
1075  SUMOReal ad_r, SUMOReal ad_length) {
1076  double rotAngle = ad_length / fabs(ad_r);
1077  double vx = *ad_x - ad_centerX;
1078  double vy = *ad_y - ad_centerY;
1079  double tmpx;
1080 
1081  double turn;
1082  if (ad_r > 0) {
1083  turn = -1; //left
1084  } else {
1085  turn = 1; //right
1086  }
1087  tmpx = vx;
1088  vx = vx * cos(rotAngle) + turn * vy * sin(rotAngle);
1089  vy = -1 * turn * tmpx * sin(rotAngle) + vy * cos(rotAngle);
1090  *ad_x = vx + ad_centerX;
1091  *ad_y = vy + ad_centerY;
1092 }
1093 
1094 
1095 // ---------------------------------------------------------------------------
1096 // section
1097 // ---------------------------------------------------------------------------
1099  lanesByDir[OPENDRIVE_TAG_LEFT] = std::vector<OpenDriveLane>();
1100  lanesByDir[OPENDRIVE_TAG_RIGHT] = std::vector<OpenDriveLane>();
1101  lanesByDir[OPENDRIVE_TAG_CENTER] = std::vector<OpenDriveLane>();
1102 }
1103 
1104 
1105 void
1107  int sumoLane = 0;
1108  bool singleType = true;
1109  std::vector<std::string> types;
1110  const std::vector<OpenDriveLane>& dirLanesR = lanesByDir.find(OPENDRIVE_TAG_RIGHT)->second;
1111  for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanesR.rbegin(); i != dirLanesR.rend(); ++i) {
1112  if (myImportAllTypes || (tc.knows((*i).type) && !tc.getShallBeDiscarded((*i).type))) {
1113  laneMap[(*i).id] = sumoLane++;
1114  types.push_back((*i).type);
1115  if (types.front() != types.back()) {
1116  singleType = false;
1117  }
1118  }
1119  }
1120  rightLaneNumber = sumoLane;
1121  rightType = sumoLane > 0 ? (singleType ? types.front() : joinToString(types, "|")) : "";
1122  sumoLane = 0;
1123  singleType = true;
1124  types.clear();
1125  const std::vector<OpenDriveLane>& dirLanesL = lanesByDir.find(OPENDRIVE_TAG_LEFT)->second;
1126  for (std::vector<OpenDriveLane>::const_iterator i = dirLanesL.begin(); i != dirLanesL.end(); ++i) {
1127  if (myImportAllTypes || (tc.knows((*i).type) && !tc.getShallBeDiscarded((*i).type))) {
1128  laneMap[(*i).id] = sumoLane++;
1129  types.push_back((*i).type);
1130  if (types.front() != types.back()) {
1131  singleType = false;
1132  }
1133  }
1134  }
1135  leftLaneNumber = sumoLane;
1136  leftType = sumoLane > 0 ? (singleType ? types.front() : joinToString(types, "|")) : "";
1137 }
1138 
1139 
1140 std::map<int, int>
1142  std::map<int, int> ret;
1143  const std::vector<OpenDriveLane>& dirLanes = lanesByDir.find(dir)->second;
1144  for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanes.rbegin(); i != dirLanes.rend(); ++i) {
1145  std::map<int, int>::const_iterator toP = laneMap.find((*i).id);
1146  if (toP == laneMap.end()) {
1147  // the current lane is not available in SUMO
1148  continue;
1149  }
1150  int to = (*toP).second;
1151  int from = UNSET_CONNECTION;
1152  if ((*i).predecessor != UNSET_CONNECTION) {
1153  from = (*i).predecessor;
1154  }
1155  if (from != UNSET_CONNECTION) {
1156  std::map<int, int>::const_iterator fromP = prev.laneMap.find(from);
1157  if (fromP != prev.laneMap.end()) {
1158  from = (*fromP).second;
1159  } else {
1160  from = UNSET_CONNECTION;
1161  }
1162  }
1163  if (from != UNSET_CONNECTION && to != UNSET_CONNECTION) {
1164  if (ret.find(from) != ret.end()) {
1165 // WRITE_WARNING("double connection");
1166  }
1167  if (dir == OPENDRIVE_TAG_LEFT) {
1168  std::swap(from, to);
1169  }
1170  ret[from] = to;
1171  } else {
1172 // WRITE_WARNING("missing connection");
1173  }
1174  }
1175  return ret;
1176 }
1177 
1178 
1181  OpenDriveLaneSection ret(*this);
1182  ret.s += startPos;
1183  for (int k = 0; k < (int)ret.lanesByDir[OPENDRIVE_TAG_RIGHT].size(); ++k) {
1185  l.speed = 0;
1186  std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator i = std::find_if(l.speeds.begin(), l.speeds.end(), same_position_finder(startPos));
1187  if (i != l.speeds.end()) {
1188  l.speed = (*i).second;
1189  }
1190  }
1191  for (int k = 0; k < (int)ret.lanesByDir[OPENDRIVE_TAG_LEFT].size(); ++k) {
1193  std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator i = std::find_if(l.speeds.begin(), l.speeds.end(), same_position_finder(startPos));
1194  l.speed = 0;
1195  if (i != l.speeds.end()) {
1196  l.speed = (*i).second;
1197  }
1198  }
1199  return ret;
1200 }
1201 
1202 
1203 bool
1204 NIImporter_OpenDrive::OpenDriveLaneSection::buildSpeedChanges(const NBTypeCont& tc, std::vector<OpenDriveLaneSection>& newSections) {
1205  std::set<SUMOReal> speedChangePositions;
1206  // collect speed change positions and apply initial speed to the begin
1207  for (std::vector<OpenDriveLane>::iterator k = lanesByDir[OPENDRIVE_TAG_RIGHT].begin(); k != lanesByDir[OPENDRIVE_TAG_RIGHT].end(); ++k) {
1208  for (std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator l = (*k).speeds.begin(); l != (*k).speeds.end(); ++l) {
1209  speedChangePositions.insert((*l).first);
1210  if ((*l).first == 0) {
1211  (*k).speed = (*l).second;
1212  }
1213  }
1214  }
1215  for (std::vector<OpenDriveLane>::iterator k = lanesByDir[OPENDRIVE_TAG_LEFT].begin(); k != lanesByDir[OPENDRIVE_TAG_LEFT].end(); ++k) {
1216  for (std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator l = (*k).speeds.begin(); l != (*k).speeds.end(); ++l) {
1217  speedChangePositions.insert((*l).first);
1218  if ((*l).first == 0) {
1219  (*k).speed = (*l).second;
1220  }
1221  }
1222  }
1223  // do nothing if there is none
1224  if (speedChangePositions.size() == 0) {
1225  return false;
1226  }
1227  if (*speedChangePositions.begin() > 0) {
1228  speedChangePositions.insert(0);
1229  }
1230  //
1231  for (std::set<SUMOReal>::iterator i = speedChangePositions.begin(); i != speedChangePositions.end(); ++i) {
1232  if (i == speedChangePositions.begin()) {
1233  newSections.push_back(*this);
1234  } else {
1235  newSections.push_back(buildLaneSection(*i));
1236  }
1237  }
1238  // propagate speeds
1239  for (int i = 0; i != (int)newSections.size(); ++i) {
1240  OpenDriveLaneSection& ls = newSections[i];
1241  std::map<OpenDriveXMLTag, std::vector<OpenDriveLane> >& lanesByDir = ls.lanesByDir;
1242  for (std::map<OpenDriveXMLTag, std::vector<OpenDriveLane> >::iterator k = lanesByDir.begin(); k != lanesByDir.end(); ++k) {
1243  std::vector<OpenDriveLane>& lanes = (*k).second;
1244  for (int j = 0; j != (int)lanes.size(); ++j) {
1245  OpenDriveLane& l = lanes[j];
1246  if (l.speed != 0) {
1247  continue;
1248  }
1249  if (i > 0) {
1250  l.speed = newSections[i - 1].lanesByDir[(*k).first][j].speed;
1251  } else {
1252  tc.getSpeed(l.type);
1253  }
1254  }
1255  }
1256  }
1257  return true;
1258 }
1259 
1260 
1261 
1262 // ---------------------------------------------------------------------------
1263 // edge
1264 // ---------------------------------------------------------------------------
1265 int
1267  int prio = 1;
1268  for (std::vector<OpenDriveSignal>::const_iterator i = signals.begin(); i != signals.end(); ++i) {
1269  int tmp = 1;
1270  if ((*i).type == "301" || (*i).type == "306") {
1271  tmp = 2;
1272  }
1273  if ((*i).type == "205") {
1274  tmp = 0;
1275  }
1276  if (tmp != 1 && dir == OPENDRIVE_TAG_RIGHT && (*i).orientation > 0) {
1277  prio = tmp;
1278  }
1279  if (tmp != 1 && dir == OPENDRIVE_TAG_LEFT && (*i).orientation < 0) {
1280  prio = tmp;
1281  }
1282 
1283  }
1284  return prio;
1285 }
1286 
1287 
1288 
1289 // ---------------------------------------------------------------------------
1290 // loader methods
1291 // ---------------------------------------------------------------------------
1292 NIImporter_OpenDrive::NIImporter_OpenDrive(const NBTypeCont& tc, std::map<std::string, OpenDriveEdge*>& edges)
1294  myTypeContainer(tc), myCurrentEdge("", "", "", -1), myEdges(edges) {
1295 }
1296 
1297 
1299 }
1300 
1301 
1302 void
1304  const SUMOSAXAttributes& attrs) {
1305  bool ok = true;
1306  switch (element) {
1307  case OPENDRIVE_TAG_HEADER: {
1308  int majorVersion = attrs.get<int>(OPENDRIVE_ATTR_REVMAJOR, 0, ok);
1309  int minorVersion = attrs.get<int>(OPENDRIVE_ATTR_REVMINOR, 0, ok);
1310  if (majorVersion != 1 || minorVersion != 2) {
1311  WRITE_WARNING("Given openDrive file '" + getFileName() + "' uses version " + toString(majorVersion) + "." + toString(minorVersion) + ";\n Version 1.2 is supported.");
1312  }
1313  }
1314  break;
1315  case OPENDRIVE_TAG_ROAD: {
1316  std::string id = attrs.get<std::string>(OPENDRIVE_ATTR_ID, 0, ok);
1317  std::string streetName = attrs.getOpt<std::string>(OPENDRIVE_ATTR_NAME, 0, ok, "", false);
1318  std::string junction = attrs.get<std::string>(OPENDRIVE_ATTR_JUNCTION, id.c_str(), ok);
1319  SUMOReal length = attrs.get<SUMOReal>(OPENDRIVE_ATTR_LENGTH, id.c_str(), ok);
1320  myCurrentEdge = OpenDriveEdge(id, streetName, junction, length);
1321  }
1322  break;
1324  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
1325  std::string elementType = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
1326  std::string elementID = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
1327  std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
1328  ? attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok)
1329  : "end";
1330  addLink(OPENDRIVE_LT_PREDECESSOR, elementType, elementID, contactPoint);
1331  }
1332  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
1333  int no = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1334  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1335  l.predecessor = no;
1336  }
1337  }
1338  break;
1339  case OPENDRIVE_TAG_SUCCESSOR: {
1340  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
1341  std::string elementType = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
1342  std::string elementID = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
1343  std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
1344  ? attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok)
1345  : "start";
1346  addLink(OPENDRIVE_LT_SUCCESSOR, elementType, elementID, contactPoint);
1347  }
1348  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
1349  int no = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1350  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1351  l.successor = no;
1352  }
1353  }
1354  break;
1355  case OPENDRIVE_TAG_GEOMETRY: {
1356  SUMOReal length = attrs.get<SUMOReal>(OPENDRIVE_ATTR_LENGTH, myCurrentEdge.id.c_str(), ok);
1357  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1358  SUMOReal x = attrs.get<SUMOReal>(OPENDRIVE_ATTR_X, myCurrentEdge.id.c_str(), ok);
1359  SUMOReal y = attrs.get<SUMOReal>(OPENDRIVE_ATTR_Y, myCurrentEdge.id.c_str(), ok);
1360  SUMOReal hdg = attrs.get<SUMOReal>(OPENDRIVE_ATTR_HDG, myCurrentEdge.id.c_str(), ok);
1361  myCurrentEdge.geometries.push_back(OpenDriveGeometry(length, s, x, y, hdg));
1362  }
1363  break;
1364  case OPENDRIVE_TAG_ELEVATION: {
1365  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1366  SUMOReal a = attrs.get<SUMOReal>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok);
1367  SUMOReal b = attrs.get<SUMOReal>(OPENDRIVE_ATTR_B, myCurrentEdge.id.c_str(), ok);
1368  SUMOReal c = attrs.get<SUMOReal>(OPENDRIVE_ATTR_C, myCurrentEdge.id.c_str(), ok);
1369  SUMOReal d = attrs.get<SUMOReal>(OPENDRIVE_ATTR_D, myCurrentEdge.id.c_str(), ok);
1370  myCurrentEdge.elevations.push_back(OpenDriveElevation(s, a, b, c, d));
1371  }
1372  break;
1373  case OPENDRIVE_TAG_LINE: {
1374  std::vector<SUMOReal> vals;
1376  }
1377  break;
1378  case OPENDRIVE_TAG_SPIRAL: {
1379  std::vector<SUMOReal> vals;
1380  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVSTART, myCurrentEdge.id.c_str(), ok));
1381  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVEND, myCurrentEdge.id.c_str(), ok));
1383  }
1384  break;
1385  case OPENDRIVE_TAG_ARC: {
1386  std::vector<SUMOReal> vals;
1387  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVATURE, myCurrentEdge.id.c_str(), ok));
1389  }
1390  break;
1391  case OPENDRIVE_TAG_POLY3: {
1392  std::vector<SUMOReal> vals;
1393  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok));
1394  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_B, myCurrentEdge.id.c_str(), ok));
1395  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_C, myCurrentEdge.id.c_str(), ok));
1396  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_D, myCurrentEdge.id.c_str(), ok));
1398  }
1399  break;
1400  case OPENDRIVE_TAG_PARAMPOLY3: {
1401  std::vector<SUMOReal> vals;
1402  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_AU, myCurrentEdge.id.c_str(), ok));
1403  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_BU, myCurrentEdge.id.c_str(), ok));
1404  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CU, myCurrentEdge.id.c_str(), ok));
1405  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_DU, myCurrentEdge.id.c_str(), ok));
1406  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_AV, myCurrentEdge.id.c_str(), ok));
1407  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_BV, myCurrentEdge.id.c_str(), ok));
1408  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CV, myCurrentEdge.id.c_str(), ok));
1409  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_DV, myCurrentEdge.id.c_str(), ok));
1410  vals.push_back(attrs.getOpt<SUMOReal>(OPENDRIVE_ATTR_PRANGE, myCurrentEdge.id.c_str(), ok, 1.0, false));
1412  }
1413  break;
1415  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1417  }
1418  break;
1419  case OPENDRIVE_TAG_LEFT:
1421  break;
1422  case OPENDRIVE_TAG_CENTER:
1424  break;
1425  case OPENDRIVE_TAG_RIGHT:
1427  break;
1428  case OPENDRIVE_TAG_LANE: {
1429  std::string type = attrs.get<std::string>(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
1430  int id = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1431  std::string level = attrs.hasAttribute(OPENDRIVE_ATTR_LEVEL)
1432  ? attrs.get<std::string>(OPENDRIVE_ATTR_LEVEL, myCurrentEdge.id.c_str(), ok)
1433  : "";
1435  ls.lanesByDir[myCurrentLaneDirection].push_back(OpenDriveLane(id, level, type));
1436  }
1437  break;
1438  case OPENDRIVE_TAG_SIGNAL: {
1439  int id = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1440  std::string type = attrs.get<std::string>(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
1441  std::string name = attrs.getOpt<std::string>(OPENDRIVE_ATTR_NAME, myCurrentEdge.id.c_str(), ok, "", false);
1442  int orientation = attrs.get<std::string>(OPENDRIVE_ATTR_ORIENTATION, myCurrentEdge.id.c_str(), ok) == "-" ? -1 : 1;
1443  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1444  bool dynamic = attrs.get<std::string>(OPENDRIVE_ATTR_DYNAMIC, myCurrentEdge.id.c_str(), ok) == "no" ? false : true;
1445  myCurrentEdge.signals.push_back(OpenDriveSignal(id, type, name, orientation, dynamic, s));
1446  }
1447  break;
1449  myCurrentJunctionID = attrs.get<std::string>(OPENDRIVE_ATTR_ID, myCurrentJunctionID.c_str(), ok);
1450  break;
1451  case OPENDRIVE_TAG_CONNECTION: {
1452  std::string id = attrs.get<std::string>(OPENDRIVE_ATTR_ID, myCurrentJunctionID.c_str(), ok);
1453  myCurrentIncomingRoad = attrs.get<std::string>(OPENDRIVE_ATTR_INCOMINGROAD, myCurrentJunctionID.c_str(), ok);
1455  std::string cp = attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentJunctionID.c_str(), ok);
1457  myConnectionWasEmpty = true;
1458  }
1459  break;
1460  case OPENDRIVE_TAG_LANELINK: {
1461  int from = attrs.get<int>(OPENDRIVE_ATTR_FROM, myCurrentJunctionID.c_str(), ok);
1462  int to = attrs.get<int>(OPENDRIVE_ATTR_TO, myCurrentJunctionID.c_str(), ok);
1463  Connection c;
1465  c.toEdge = myCurrentConnectingRoad;
1466  c.fromLane = from;
1467  c.toLane = to;
1468  c.fromCP = OPENDRIVE_CP_END;
1469  c.toCP = myCurrentContactPoint;
1470  c.all = false;
1471  if (myEdges.find(c.fromEdge) == myEdges.end()) {
1472  WRITE_ERROR("In laneLink-element: incoming road '" + c.fromEdge + "' is not known.");
1473  } else {
1474  OpenDriveEdge* e = myEdges.find(c.fromEdge)->second;
1475  e->connections.insert(c);
1476  myConnectionWasEmpty = false;
1477  }
1478  }
1479  break;
1480  case OPENDRIVE_TAG_WIDTH: {
1481  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 1] == OPENDRIVE_TAG_LANE) {
1482  SUMOReal width = attrs.get<SUMOReal>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok);
1483  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1484  l.width = MAX2(l.width, width);
1485  }
1486  }
1487  break;
1488  case OPENDRIVE_TAG_SPEED: {
1489  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 1] == OPENDRIVE_TAG_LANE) {
1490  SUMOReal speed = attrs.get<SUMOReal>(OPENDRIVE_ATTR_MAX, myCurrentEdge.id.c_str(), ok);
1491  SUMOReal pos = attrs.get<SUMOReal>(OPENDRIVE_ATTR_SOFFSET, myCurrentEdge.id.c_str(), ok);
1492  myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back().speeds.push_back(std::make_pair(pos, speed));
1493  }
1494  }
1495  break;
1496  default:
1497  break;
1498  }
1499  myElementStack.push_back(element);
1500 }
1501 
1502 
1503 void
1505  myElementStack.pop_back();
1506  switch (element) {
1507  case OPENDRIVE_TAG_ROAD:
1509  break;
1511  if (myConnectionWasEmpty) {
1512  Connection c;
1515  c.fromLane = 0;
1516  c.toLane = 0;
1519  c.all = true;
1520  if (myEdges.find(c.fromEdge) == myEdges.end()) {
1521  WRITE_ERROR("In laneLink-element: incoming road '" + c.fromEdge + "' is not known.");
1522  } else {
1523  OpenDriveEdge* e = myEdges.find(c.fromEdge)->second;
1524  e->connections.insert(c);
1525  }
1526  }
1527  break;
1529  myCurrentEdge.laneSections.back().buildLaneMapping(myTypeContainer);
1530  }
1531  break;
1532  default:
1533  break;
1534  }
1535 }
1536 
1537 
1538 
1539 void
1540 NIImporter_OpenDrive::addLink(LinkType lt, const std::string& elementType,
1541  const std::string& elementID,
1542  const std::string& contactPoint) {
1543  OpenDriveLink l(lt, elementID);
1544  // elementType
1545  if (elementType == "road") {
1547  } else if (elementType == "junction") {
1549  }
1550  // contact point
1551  if (contactPoint == "start") {
1553  } else if (contactPoint == "end") {
1555  }
1556  // add
1557  myCurrentEdge.links.push_back(l);
1558 }
1559 
1560 
1561 void
1562 NIImporter_OpenDrive::addGeometryShape(GeometryType type, const std::vector<SUMOReal>& vals) {
1563  // checks
1564  if (myCurrentEdge.geometries.size() == 0) {
1565  throw ProcessError("Mismatching paranthesis in geometry definition for road '" + myCurrentEdge.id + "'");
1566  }
1568  if (last.type != OPENDRIVE_GT_UNKNOWN) {
1569  throw ProcessError("Double geometry information for road '" + myCurrentEdge.id + "'");
1570  }
1571  // set
1572  last.type = type;
1573  last.params = vals;
1574 }
1575 
1576 
1577 bool
1579  if (c1.fromEdge != c2.fromEdge) {
1580  return c1.fromEdge < c2.fromEdge;
1581  }
1582  if (c1.toEdge != c2.toEdge) {
1583  return c1.toEdge < c2.toEdge;
1584  }
1585  if (c1.fromLane != c2.fromLane) {
1586  return c1.fromLane < c2.fromLane;
1587  }
1588  return c1.toLane < c2.toLane;
1589 }
1590 
1591 
1592 
1593 /****************************************************************************/
1594 
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:237
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.
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)
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
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:1117
static const SUMOReal UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:240
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:221
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:117
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:132
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:124
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:135
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:185
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'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: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
bool addLane2LaneConnection(int fromLane, NBEdge *dest, int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, SUMOReal contPos=UNSPECIFIED_CONTPOS, SUMOReal visibility=UNSPECIFIED_VISIBILITY_DISTANCE)
Adds a connection between the specified this edge's lane and an approached one.
Definition: NBEdge.cpp:802
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:188
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
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:79
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:115
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:147
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's geometry.
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:416
void addTrafficLight(NBTrafficLightDefinition *tlDef)
Adds a traffic light to the list of traffic lights that control this node.
Definition: NBNode.cpp:314
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'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:203
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:214
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:215
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:803
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's width.
Definition: NBEdge.h:144
#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.
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)