SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NIImporter_OpenDrive.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // Importer for networks stored in openDrive format
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
13 // Copyright (C) 2001-2013 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>
38 #include <utils/common/ToString.h>
41 #include <netbuild/NBEdge.h>
42 #include <netbuild/NBEdgeCont.h>
43 #include <netbuild/NBNode.h>
44 #include <netbuild/NBNodeCont.h>
45 #include <netbuild/NBNetBuilder.h>
51 #include <utils/xml/XMLSubSys.h>
52 #include <utils/geom/Boundary.h>
53 #include "NILoader.h"
54 #include "NIImporter_OpenDrive.h"
55 
56 #ifdef CHECK_MEMORY_LEAKS
57 #include <foreign/nvwa/debug_new.h>
58 #endif // CHECK_MEMORY_LEAKS
59 
60 
61 // ===========================================================================
62 // definitions
63 // ===========================================================================
64 #define C_LENGTH 10.
65 
66 
67 // ===========================================================================
68 // static variables
69 // ===========================================================================
91 
93 };
94 
95 
125 
127 };
128 
129 
130 std::set<std::string> NIImporter_OpenDrive::myLaneTypes2Import;
133 
134 // ===========================================================================
135 // method definitions
136 // ===========================================================================
137 // ---------------------------------------------------------------------------
138 // static methods (interface in this case)
139 // ---------------------------------------------------------------------------
140 void
142  // check whether the option is set (properly)
143  if (!oc.isUsableFileList("opendrive-files")) {
144  return;
145  }
146  myImportAllTypes = oc.getBool("opendrive.import-all-lanes");
147  myImportWidths = oc.getBool("opendrive.import-widths");
148  myImportWidths = true;
149  myLaneTypes2Import.insert("driving");
150  myLaneTypes2Import.insert("stop");
151  myLaneTypes2Import.insert("mwyEntry");
152  myLaneTypes2Import.insert("mwyExit");
153  myLaneTypes2Import.insert("special1");
154  myLaneTypes2Import.insert("parking");
155  // build the handler
156  std::map<std::string, OpenDriveEdge*> edges;
157  NIImporter_OpenDrive handler(edges);
158  // parse file(s)
159  std::vector<std::string> files = oc.getStringVector("opendrive-files");
160  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
161  if (!FileHelpers::exists(*file)) {
162  WRITE_ERROR("Could not open opendrive file '" + *file + "'.");
163  return;
164  }
165  handler.setFileName(*file);
166  PROGRESS_BEGIN_MESSAGE("Parsing opendrive from '" + *file + "'");
167  XMLSubSys::runParser(handler, *file);
169  }
170  // split inner/outer edges
171  std::map<std::string, OpenDriveEdge*> innerEdges, outerEdges;
172  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
173  if ((*i).second->isInner) {
174  innerEdges[(*i).first] = (*i).second;
175  } else {
176  outerEdges[(*i).first] = (*i).second;
177  }
178  }
179 
180  // convert geometries into a discretised representation
181  computeShapes(edges);
182 
183  // -------------------------
184  // node building
185  // -------------------------
186  // build nodes#1
187  // look at all links which belong to a node, collect their bounding boxes
188  // and place the node in the middle of this bounding box
189  std::map<std::string, Boundary> posMap;
190  std::map<std::string, std::string> edge2junction;
191  // compute node positions
192  for (std::map<std::string, OpenDriveEdge*>::iterator i = innerEdges.begin(); i != innerEdges.end(); ++i) {
193  OpenDriveEdge* e = (*i).second;
194  assert(e->junction != "-1" && e->junction != "");
195  edge2junction[e->id] = e->junction;
196  if (posMap.find(e->junction) == posMap.end()) {
197  posMap[e->junction] = Boundary();
198  }
199  posMap[e->junction].add(e->geom.getBoxBoundary());
200  }
201  // build nodes
202  for (std::map<std::string, Boundary>::iterator i = posMap.begin(); i != posMap.end(); ++i) {
203  if (!nb.getNodeCont().insert((*i).first, (*i).second.getCenter())) {
204  throw ProcessError("Could not add node '" + (*i).first + "'.");
205  }
206  }
207  // assign built nodes
208  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
209  OpenDriveEdge* e = (*i).second;
210  for (std::vector<OpenDriveLink>::iterator j = e->links.begin(); j != e->links.end(); ++j) {
211  OpenDriveLink& l = *j;
212  if (l.elementType != OPENDRIVE_ET_ROAD) {
213  // set node information
215  continue;
216  }
217  if (edge2junction.find(l.elementID) != edge2junction.end()) {
218  // set node information of an internal road
219  setNodeSecure(nb.getNodeCont(), *e, edge2junction[l.elementID], l.linkType);
220  continue;
221  }
222  }
223  }
224  // we should now have all nodes set for links which are not outer edge-to-outer edge links
225 
226 
227  // build nodes#2
228  // build nodes for all outer edge-to-outer edge connections
229  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
230  OpenDriveEdge* e = (*i).second;
231  for (std::vector<OpenDriveLink>::iterator j = e->links.begin(); j != e->links.end(); ++j) {
232  OpenDriveLink& l = *j;
233  if (l.elementType != OPENDRIVE_ET_ROAD || edge2junction.find(l.elementID) != edge2junction.end()) {
234  // is a connection to an internal edge, or a node, skip
235  continue;
236  }
237  // we have a direct connection between to external edges
238  std::string id1 = e->id;
239  std::string id2 = l.elementID;
240  if (id1 < id2) {
241  std::swap(id1, id2);
242  }
243  std::string nid = id1 + "." + id2;
244  if (nb.getNodeCont().retrieve(nid) == 0) {
245  // not yet seen, build
246  Position pos = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e->geom[-1] : e->geom[0];
247  if (!nb.getNodeCont().insert(nid, pos)) {
248  throw ProcessError("Could not build node '" + nid + "'.");
249  }
250  }
251  /* debug-stuff
252  else {
253  Position pos = l.linkType==OPENDRIVE_LT_SUCCESSOR ? e.geom[e.geom.size()-1] : e.geom[0];
254  cout << nid << " " << pos << " " << nb.getNodeCont().retrieve(nid)->getPosition() << endl;
255  }
256  */
257  setNodeSecure(nb.getNodeCont(), *e, nid, l.linkType);
258  }
259  }
260  // we should now have start/end nodes for all outer edge-to-outer edge connections
261 
262 
263  // build nodes#3
264  // assign further nodes generated from inner-edges
265  // these nodes have not been assigned earlier, because the connectiosn are referenced in inner-edges
266  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
267  OpenDriveEdge* e = (*i).second;
268  if (e->to != 0 && e->from != 0) {
269  continue;
270  }
271  for (std::map<std::string, OpenDriveEdge*>::iterator j = innerEdges.begin(); j != innerEdges.end(); ++j) {
272  OpenDriveEdge* ie = (*j).second;
273  for (std::vector<OpenDriveLink>::iterator k = ie->links.begin(); k != ie->links.end(); ++k) {
274  OpenDriveLink& il = *k;
275  if (il.elementType != OPENDRIVE_ET_ROAD || il.elementID != e->id) {
276  // not conneted to the currently investigated outer edge
277  continue;
278  }
279  std::string nid = edge2junction[ie->id];
280  if (il.contactPoint == OPENDRIVE_CP_START) {
282  } else {
284  }
285  }
286  }
287 
288  }
289 
290 
291  // build start/end nodes which were not defined previously
292  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
293  OpenDriveEdge* e = (*i).second;
294  if (e->from == 0) {
295  const std::string nid = e->id + ".begin";
296  e->from = getOrBuildNode(nid, e->geom.front(), nb.getNodeCont());
297  }
298  if (e->to == 0) {
299  const std::string nid = e->id + ".end";
300  e->to = getOrBuildNode(nid, e->geom.back(), nb.getNodeCont());
301  }
302  }
303 
304 
305  // -------------------------
306  // edge building
307  // -------------------------
308  //bool useLoadedLengths = oc.getBool("opendrive.use-given-lengths");
309  SUMOReal defaultSpeed = nb.getTypeCont().getSpeed("");
310  // build edges
311  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
312  OpenDriveEdge* e = (*i).second;
314  unsigned int noLanesRight = e->getMaxLaneNumber(OPENDRIVE_TAG_RIGHT);
315  unsigned int noLanesLeft = e->getMaxLaneNumber(OPENDRIVE_TAG_LEFT);
316  if (noLanesRight == 0 && noLanesLeft == 0) {
317  WRITE_WARNING("Edge '" + e->id + "' has no lanes.");
318  }
319 
320  // idea: go along the lane sections, build a node in between of each pair
321 
323 
326 
328  NBNode* sFrom = e->from;
329  NBNode* sTo = e->to;
330  int priorityR = e->getPriority(OPENDRIVE_TAG_RIGHT);
331  int priorityL = e->getPriority(OPENDRIVE_TAG_LEFT);
332  SUMOReal sB = 0;
333  SUMOReal sE = e->length;
334  SUMOReal cF = e->length / e->geom.length();
335  NBEdge* prevRight = 0;
336  NBEdge* prevLeft = 0;
337 
338  // starting at the same node as ending, and no lane sections?
339  if (sFrom == sTo && e->laneSections.size() == 1) {
340  // --> loop, split!
342  ls.s = e->length / 2.;
343  e->laneSections.push_back(ls);
344  WRITE_WARNING("Edge '" + e->id + "' has to be split as it connects same junctions.")
345  }
346 
347  // build along lane sections
348  for (std::vector<OpenDriveLaneSection>::iterator j = e->laneSections.begin(); j != e->laneSections.end(); ++j) {
349  // add internal node if needed
350  if (j == e->laneSections.end() - 1) {
351  sTo = e->to;
352  sE = e->length / cF;
353  } else {
354  SUMOReal nextS = (j + 1)->s;
355  sTo = new NBNode(e->id + "." + toString(nextS), e->geom.positionAtOffset(nextS));
356  if (!nb.getNodeCont().insert(sTo)) {
357  throw ProcessError("Could not add node '" + sTo->getID() + "'.");
358  }
359  sE = nextS / cF;
360  }
361  PositionVector geom = e->geom.getSubpart(sB, sE);
362  (*j).buildLaneMapping();
363  std::string id = e->id;
364  if (sFrom != e->from || sTo != e->to) {
365  id = id + "." + toString((*j).s);
366  }
367 
368  // build lanes to right
369  int rightLanesSection = (*j).getLaneNumber(OPENDRIVE_TAG_RIGHT);
370  NBEdge* currRight = 0;
371  if (rightLanesSection > 0) {
372  currRight = new NBEdge("-" + id, sFrom, sTo, "", defaultSpeed, rightLanesSection, priorityR,
374  if (!nb.getEdgeCont().insert(currRight)) {
375  throw ProcessError("Could not add edge '" + currRight->getID() + "'.");
376  }
377  const std::vector<OpenDriveLane>& lanes = (*j).lanesByDir[OPENDRIVE_TAG_RIGHT];
378  for (std::vector<OpenDriveLane>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
379  std::map<int, int>::const_iterator lp = (*j).laneMap.find((*k).id);
380  if (lp != (*j).laneMap.end()) {
381  int sumoLaneIndex = lp->second;
382  NBEdge::Lane& sumoLane = currRight->getLaneStruct(sumoLaneIndex);
383  const OpenDriveLane& odLane = *k;
384 
385  sumoLane.origID = e->id + " -" + toString((*k).id);
386  sumoLane.speed = odLane.speed != 0 ? odLane.speed : defaultSpeed;
387 
388  if (myImportWidths) {
389  SUMOReal width = odLane.width;
390  if (width != 0) {
391  sumoLane.width = width;
392  }
393  }
394  }
395  }
396  // connect lane sections
397  if (prevRight != 0) {
398  std::map<int, int> connections = (*j).getInnerConnections(OPENDRIVE_TAG_RIGHT, *(j - 1));
399  for (std::map<int, int>::const_iterator k = connections.begin(); k != connections.end(); ++k) {
400  prevRight->addLane2LaneConnection((*k).first, currRight, (*k).second, NBEdge::L2L_VALIDATED);
401  }
402  }
403  prevRight = currRight;
404  }
405 
406  // build lanes to left
407  int leftLanesSection = (*j).getLaneNumber(OPENDRIVE_TAG_LEFT);
408  NBEdge* currLeft = 0;
409  if (leftLanesSection > 0) {
410  currLeft = new NBEdge(id, sTo, sFrom, "", defaultSpeed, leftLanesSection, priorityL,
412  if (!nb.getEdgeCont().insert(currLeft)) {
413  throw ProcessError("Could not add edge '" + currLeft->getID() + "'.");
414  }
415  const std::vector<OpenDriveLane>& lanes = (*j).lanesByDir[OPENDRIVE_TAG_LEFT];
416  for (std::vector<OpenDriveLane>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
417  std::map<int, int>::const_iterator lp = (*j).laneMap.find((*k).id);
418  if (lp != (*j).laneMap.end()) {
419  int sumoLaneIndex = lp->second;
420  NBEdge::Lane& sumoLane = currLeft->getLaneStruct(sumoLaneIndex);
421  const OpenDriveLane& odLane = *k;
422 
423  sumoLane.origID = e->id + " " + toString((*k).id);
424  sumoLane.speed = odLane.speed != 0 ? odLane.speed : defaultSpeed;
425 
426  if (myImportWidths) {
427  SUMOReal width = odLane.width;
428  if (width != 0) {
429  sumoLane.width = width;
430  }
431  }
432  }
433  }
434  // connect lane sections
435  if (prevLeft != 0) {
436  std::map<int, int> connections = (*j).getInnerConnections(OPENDRIVE_TAG_LEFT, *(j - 1));
437  for (std::map<int, int>::const_iterator k = connections.begin(); k != connections.end(); ++k) {
438  currLeft->addLane2LaneConnection((*k).first, prevLeft, (*k).second, NBEdge::L2L_VALIDATED);
439  }
440  }
441  prevLeft = currLeft;
442  }
443  (*j).sumoID = id;
444 
445 
446  sB = sE;
447  sFrom = sTo;
448  }
449  }
450 
451 
452  // -------------------------
453  // connections building
454  // -------------------------
455  // generate explicit lane-to-lane connections
456  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
457  setEdgeLinks2(*(*i).second, edges);
458  }
459  // compute connections across intersections, if any
460  std::vector<Connection> connections2;
461  for (std::map<std::string, OpenDriveEdge*>::iterator j = edges.begin(); j != edges.end(); ++j) {
462  const std::set<Connection>& conns = (*j).second->connections;
463 
464  for (std::set<Connection>::const_iterator i = conns.begin(); i != conns.end(); ++i) {
465  if (innerEdges.find((*i).fromEdge) != innerEdges.end()) {
466  // connections starting at inner edges are processed by starting from outer edges
467  continue;
468  }
469  if (innerEdges.find((*i).toEdge) != innerEdges.end()) {
470  buildConnectionsToOuter(*i, innerEdges, connections2);
471  } else {
472  connections2.push_back(*i);
473  }
474  }
475  }
476  // set connections
477  for (std::vector<Connection>::const_iterator i = connections2.begin(); i != connections2.end(); ++i) {
478  std::string fromEdge = (*i).fromEdge;
479  if (edges.find(fromEdge) == edges.end()) {
480  WRITE_WARNING("While setting connections: from-edge '" + fromEdge + "' is not known.");
481  continue;
482  }
483  OpenDriveEdge* odFrom = edges[fromEdge];
484  int fromLane = (*i).fromLane;
485  bool fromLast = ((*i).fromCP == OPENDRIVE_CP_END) ^ ((*i).fromLane > 0 && !(*i).all);
486  fromEdge = fromLast ? odFrom->laneSections.back().sumoID : odFrom->laneSections[0].sumoID;
487 
488  std::string toEdge = (*i).toEdge;
489  if (edges.find(toEdge) == edges.end()) {
490  WRITE_WARNING("While setting connections: to-edge '" + toEdge + "' is not known.");
491  continue;
492  }
493 
494  OpenDriveEdge* odTo = edges[toEdge];
495  int toLane = (*i).toLane;
496  bool toLast = ((*i).toCP == OPENDRIVE_CP_END) || ((*i).toLane > 0);
497  toEdge = toLast ? odTo->laneSections.back().sumoID : odTo->laneSections[0].sumoID;
498 
499  if (fromLane == UNSET_CONNECTION) {
500  fromLane = toLast ? odTo->laneSections.back().laneMap.begin()->first : odTo->laneSections[0].laneMap.begin()->first;
501  }
502  if (fromLane < 0) {
503  fromEdge = revertID(fromEdge);
504  }
505  if (toLane == UNSET_CONNECTION) {
506  toLane = toLast ? odTo->laneSections.back().laneMap.begin()->first : odTo->laneSections[0].laneMap.begin()->first;
507  }
508  if (toLane < 0) {
509  toEdge = revertID(toEdge);
510  }
511  fromLane = fromLast ? odFrom->laneSections.back().laneMap[fromLane] : odFrom->laneSections[0].laneMap[fromLane];
512  toLane = toLast ? odTo->laneSections.back().laneMap[toLane] : odTo->laneSections[0].laneMap[toLane];
513  NBEdge* from = nb.getEdgeCont().retrieve(fromEdge);
514  NBEdge* to = nb.getEdgeCont().retrieve(toEdge);
515  if (from == 0) {
516  WRITE_WARNING("Could not find fromEdge representation of '' in connection ''.");
517  }
518  if (to == 0) {
519  WRITE_WARNING("Could not find fromEdge representation of '' in connection ''.");
520  }
521  if (from == 0 || to == 0) {
522  continue;
523  }
524 
525  from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER);
526 
527  if ((*i).origID != "") {
528  // @todo: this is the most silly way to determine the connection
529  std::vector<NBEdge::Connection>& cons = from->getConnections();
530  for (std::vector<NBEdge::Connection>::iterator k = cons.begin(); k != cons.end(); ++k) {
531  if ((*k).fromLane == fromLane && (*k).toEdge == to && (*k).toLane == toLane) {
532  (*k).origID = (*i).origID + " " + toString((*i).origLane);
533  break;
534  }
535  }
536  }
537  }
538  // clean up
539  if (oc.exists("geometry.min-dist") && oc.isSet("geometry.min-dist")) {
540  oc.unSet("geometry.min-dist");
541  }
542  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
543  delete(*i).second;
544  }
545 }
546 
547 
548 
549 void
550 NIImporter_OpenDrive::buildConnectionsToOuter(const Connection& c, const std::map<std::string, OpenDriveEdge*>& innerEdges, std::vector<Connection>& into) {
551 
552  OpenDriveEdge* dest = innerEdges.find(c.toEdge)->second;
553  if (dest == 0) {
555  return;
556  }
557  const std::set<Connection>& conts = dest->connections;
558  for (std::set<Connection>::const_iterator i = conts.begin(); i != conts.end(); ++i) {
559  if (innerEdges.find((*i).toEdge) != innerEdges.end()) {
560  std::vector<Connection> t;
561  buildConnectionsToOuter(*i, innerEdges, t);
562  for (std::vector<Connection>::const_iterator j = t.begin(); j != t.end(); ++j) {
563  // @todo this section is unverified
564  Connection cn = (*j);
565  cn.fromEdge = c.fromEdge;
566  cn.fromLane = c.fromLane;
567  cn.fromCP = c.fromCP;
568  cn.all = c.all; // @todo "all" is a hack trying to avoid the "from is zero" problem;
569  into.push_back(cn);
570  }
571  } else {
572  unsigned int laneNo = c.toLane < 0 ? dest->laneSections[0].getLaneNumber(OPENDRIVE_TAG_RIGHT) : dest->laneSections[dest->laneSections.size() - 1].getLaneNumber(OPENDRIVE_TAG_LEFT);
573  if ((*i).fromLane == c.toLane) {
574  Connection cn = (*i);
575  cn.fromEdge = c.fromEdge;
576  cn.fromLane = c.fromLane;
577  cn.fromCP = c.fromCP;
578  cn.all = c.all;
579  cn.origID = c.toEdge;
580  cn.origLane = c.toLane;
581  into.push_back(cn);
582  }
583  }
584  }
585 }
586 
587 
588 void
589 NIImporter_OpenDrive::setEdgeLinks2(OpenDriveEdge& e, const std::map<std::string, OpenDriveEdge*>& edges) {
590  for (std::vector<OpenDriveLink>::iterator i = e.links.begin(); i != e.links.end(); ++i) {
591  OpenDriveLink& l = *i;
592  if (l.elementType != OPENDRIVE_ET_ROAD) {
593  // we assume that links to nodes are later given as connections to edges
594  continue;
595  }
596  // get the right direction of the connected edge
597  std::string connectedEdge = l.elementID;
598  std::string edgeID = e.id;
599 
600  OpenDriveLaneSection& laneSection = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e.laneSections.back() : e.laneSections[0];
601  if (laneSection.lanesByDir.find(OPENDRIVE_TAG_RIGHT) != laneSection.lanesByDir.end()) {
602  const std::vector<OpenDriveLane>& lanes = laneSection.lanesByDir.find(OPENDRIVE_TAG_RIGHT)->second;
603  for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
604  if (!myImportAllTypes && myLaneTypes2Import.find((*j).type) == myLaneTypes2Import.end()) {
605  continue;
606  }
607  Connection c; // @todo: give Connection a new name and a constructor
608  c.fromEdge = e.id;
609  c.fromLane = (*j).id;
611  c.toLane = l.linkType == OPENDRIVE_LT_SUCCESSOR ? (*j).successor : (*j).predecessor;
612  c.toEdge = connectedEdge;
613  c.toCP = l.contactPoint;
614  c.all = false;
615  if (l.linkType != OPENDRIVE_LT_SUCCESSOR) {
616  std::swap(c.fromEdge, c.toEdge);
617  std::swap(c.fromLane, c.toLane);
618  std::swap(c.fromCP, c.toCP);
619  }
620  if (edges.find(c.fromEdge) == edges.end()) {
621  WRITE_ERROR("While setting connections: incoming road '" + c.fromEdge + "' is not known.");
622  } else {
623  OpenDriveEdge* src = edges.find(c.fromEdge)->second;
624  src->connections.insert(c);
625  }
626  }
627  }
628  if (laneSection.lanesByDir.find(OPENDRIVE_TAG_LEFT) != laneSection.lanesByDir.end()) {
629  const std::vector<OpenDriveLane>& lanes = laneSection.lanesByDir.find(OPENDRIVE_TAG_LEFT)->second;
630  for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
631  if (!myImportAllTypes && myLaneTypes2Import.find((*j).type) == myLaneTypes2Import.end()) {
632  continue;
633  }
634  Connection c;
635  c.toEdge = e.id;
636  c.toLane = (*j).id;
638  c.fromLane = l.linkType == OPENDRIVE_LT_SUCCESSOR ? (*j).successor : (*j).predecessor;
639  c.fromEdge = connectedEdge;
640  c.fromCP = l.contactPoint;
641  c.all = false;
642  if (l.linkType != OPENDRIVE_LT_SUCCESSOR) {
643  std::swap(c.fromEdge, c.toEdge);
644  std::swap(c.fromLane, c.toLane);
645  std::swap(c.fromCP, c.toCP);
646  }
647  if (edges.find(c.fromEdge) == edges.end()) {
648  WRITE_ERROR("While setting connections: incoming road '" + c.fromEdge + "' is not known.");
649  } else {
650  OpenDriveEdge* src = edges.find(c.fromEdge)->second;
651  src->connections.insert(c);
652  }
653  }
654  }
655  }
656 }
657 
658 
659 std::string NIImporter_OpenDrive::revertID(const std::string& id) {
660  if (id[0] == '-') {
661  return id.substr(1);
662  }
663  return "-" + id;
664 }
665 
666 NBNode*
667 NIImporter_OpenDrive::getOrBuildNode(const std::string& id, const Position& pos,
668  NBNodeCont& nc) {
669  if (nc.retrieve(id) == 0) {
670  // not yet built; build now
671  if (!nc.insert(id, pos)) {
672  // !!! clean up
673  throw ProcessError("Could not add node '" + id + "'.");
674  }
675  }
676  return nc.retrieve(id);
677 }
678 
679 
680 void
682  const std::string& nodeID, NIImporter_OpenDrive::LinkType lt) {
683  NBNode* n = nc.retrieve(nodeID);
684  if (n == 0) {
685  throw ProcessError("Could not find node '" + nodeID + "'.");
686  }
687  if (lt == OPENDRIVE_LT_SUCCESSOR) {
688  if (e.to != 0 && e.to != n) {
689  throw ProcessError("Edge '" + e.id + "' has two end nodes.");
690  }
691  e.to = n;
692  } else {
693  if (e.from != 0 && e.from != n) {
694  throw ProcessError("Edge '" + e.id + "' has two start nodes.");
695  }
696  e.from = n;
697  }
698 }
699 
700 
701 
702 
703 
704 
705 
706 void
707 NIImporter_OpenDrive::computeShapes(std::map<std::string, OpenDriveEdge*>& edges) {
709  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
710  OpenDriveEdge& e = *(*i).second;
711  for (std::vector<OpenDriveGeometry>::iterator j = e.geometries.begin(); j != e.geometries.end(); ++j) {
712  OpenDriveGeometry& g = *j;
713  std::vector<Position> geom;
714  switch (g.type) {
716  break;
717  case OPENDRIVE_GT_LINE:
718  geom = geomFromLine(e, g);
719  break;
720  case OPENDRIVE_GT_ARC:
721  geom = geomFromArc(e, g);
722  break;
723  case OPENDRIVE_GT_POLY3:
724  geom = geomFromPoly(e, g);
725  if (geom.size() == 1) {
726  geom = geomFromPoly(e, g);
727  }
728  break;
729  default:
730  break;
731  }
732  for (std::vector<Position>::iterator k = geom.begin(); k != geom.end(); ++k) {
734  }
735  }
736  if (oc.exists("geometry.min-dist") && oc.isSet("geometry.min-dist")) {
737  e.geom.removeDoublePoints(oc.getFloat("geometry.min-dist"), true);
738  }
739  for (unsigned int j = 0; j < e.geom.size(); ++j) {
741  WRITE_ERROR("Unable to project coordinates for.");
742  }
743  }
744  }
745 }
746 
747 
748 std::vector<Position>
750  UNUSED_PARAMETER(e);
751  std::vector<Position> ret;
752  ret.push_back(Position(g.x, g.y));
753  ret.push_back(calculateStraightEndPoint(g.hdg, g.length, Position(g.x, g.y)));
754  return ret;
755 }
756 
757 
758 std::vector<Position>
760  UNUSED_PARAMETER(e);
761  std::vector<Position> ret;
762  SUMOReal dist = 0.0;
763  SUMOReal centerX = g.x;
764  SUMOReal centerY = g.y;
765  // left: positive value
766  SUMOReal curvature = g.params[0];
767  SUMOReal radius = 1. / curvature;
768  // center point
769  calculateCurveCenter(&centerX, &centerY, radius, g.hdg);
770  SUMOReal endX = g.x;
771  SUMOReal endY = g.y;
772  SUMOReal startX = g.x;
773  SUMOReal startY = g.y;
774  SUMOReal hdgS = g.hdg;
775  SUMOReal hdgE;
776  SUMOReal geo_posS = g.s;
777  SUMOReal geo_posE = g.s;
778  bool end = false;
779  do {
780  geo_posE += C_LENGTH;
781  if (geo_posE - g.s > g.length) {
782  geo_posE = g.s + g.length;
783  }
784  if (geo_posE - g.s > g.length) {
785  geo_posE = g.s + g.length;
786  }
787  calcPointOnCurve(&endX, &endY, centerX, centerY, radius, geo_posE - geo_posS);
788 
789  dist += (geo_posE - geo_posS);
790  if (curvature > 0.0) {
791  hdgE = g.hdg + dist / fabs(radius);
792  } else {
793  hdgE = g.hdg - dist / fabs(radius);
794  }
795  //
796  ret.push_back(Position(startX, startY));
797  //
798  startX = endX;
799  startY = endY;
800  geo_posS = geo_posE;
801  hdgS = hdgE;
802 
803  if (geo_posE - (g.s + g.length) < 0.001 && geo_posE - (g.s + g.length) > -0.001) {
804  end = true;
805  }
806  } while (!end);
807  return ret;
808 }
809 
810 
811 std::vector<Position>
813  UNUSED_PARAMETER(e);
814  std::vector<Position> ret;
815  for (SUMOReal off = 0; off < g.length + 2.; off += 2.) {
816  //SUMOReal off = g.length;
817  SUMOReal x = off;
818  SUMOReal y = g.params[0] + g.params[1] * off + g.params[2] * pow(off, 2.) + g.params[3] * pow(off, 3.);
819  SUMOReal s = sin(g.hdg);
820  SUMOReal c = cos(g.hdg);
821  SUMOReal xnew = x * c - y * s;
822  SUMOReal ynew = x * s + y * c;
823  ret.push_back(Position(g.x + xnew, g.y + ynew));
824  }
825  return ret;
826 }
827 
828 
829 Position
830 NIImporter_OpenDrive::calculateStraightEndPoint(double hdg, double length, const Position& start) {
831  double normx = 1.0f;
832  double normy = 0.0f;
833  double x2 = normx * cos(hdg) - normy * sin(hdg);
834  double y2 = normx * sin(hdg) + normy * cos(hdg);
835  normx = x2 * length;
836  normy = y2 * length;
837  return Position(start.x() + normx, start.y() + normy);
838 }
839 
840 
841 void
843  SUMOReal normX = 1.0;
844  SUMOReal normY = 0.0;
845  SUMOReal tmpX;
846  SUMOReal turn;
847  if (ad_radius > 0) {
848  turn = -1.0;
849  } else {
850  turn = 1.0;
851  }
852 
853  tmpX = normX;
854  normX = normX * cos(ad_hdg) + normY * sin(ad_hdg);
855  normY = tmpX * sin(ad_hdg) + normY * cos(ad_hdg);
856 
857  tmpX = normX;
858  normX = normX * cos(90 * PI / 180) + turn * normY * sin(90 * PI / 180);
859  normY = -1 * turn * tmpX * sin(90 * PI / 180) + normY * cos(90 * PI / 180);
860 
861  normX = fabs(ad_radius) * normX;
862  normY = fabs(ad_radius) * normY;
863 
864  *ad_x += normX;
865  *ad_y += normY;
866 }
867 
868 
869 void
871  SUMOReal ad_r, SUMOReal ad_length) {
872  double rotAngle = ad_length / fabs(ad_r);
873  double vx = *ad_x - ad_centerX;
874  double vy = *ad_y - ad_centerY;
875  double tmpx;
876 
877  double turn;
878  if (ad_r > 0) {
879  turn = -1; //left
880  } else {
881  turn = 1; //right
882  }
883  tmpx = vx;
884  vx = vx * cos(rotAngle) + turn * vy * sin(rotAngle);
885  vy = -1 * turn * tmpx * sin(rotAngle) + vy * cos(rotAngle);
886  *ad_x = vx + ad_centerX;
887  *ad_y = vy + ad_centerY;
888 }
889 
890 
891 // ---------------------------------------------------------------------------
892 // section
893 // ---------------------------------------------------------------------------
895  lanesByDir[OPENDRIVE_TAG_LEFT] = std::vector<OpenDriveLane>();
896  lanesByDir[OPENDRIVE_TAG_RIGHT] = std::vector<OpenDriveLane>();
897  lanesByDir[OPENDRIVE_TAG_CENTER] = std::vector<OpenDriveLane>();
898 }
899 
900 
901 unsigned int
903  unsigned int laneNum = 0;
904  const std::vector<OpenDriveLane>& dirLanes = lanesByDir.find(dir)->second;
905  for (std::vector<OpenDriveLane>::const_iterator i = dirLanes.begin(); i != dirLanes.end(); ++i) {
906  if (myImportAllTypes || myLaneTypes2Import.find((*i).type) != myLaneTypes2Import.end()) {
907  ++laneNum;
908  }
909  }
910  return laneNum;
911 }
912 
913 
914 void
916  unsigned int sumoLane = 0;
917  const std::vector<OpenDriveLane>& dirLanesR = lanesByDir.find(OPENDRIVE_TAG_RIGHT)->second;
918  for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanesR.rbegin(); i != dirLanesR.rend(); ++i) {
919  if (myImportAllTypes || myLaneTypes2Import.find((*i).type) != myLaneTypes2Import.end()) {
920  laneMap[(*i).id] = sumoLane++;
921  }
922  }
923  sumoLane = 0;
924  const std::vector<OpenDriveLane>& dirLanesL = lanesByDir.find(OPENDRIVE_TAG_LEFT)->second;
925  for (std::vector<OpenDriveLane>::const_iterator i = dirLanesL.begin(); i != dirLanesL.end(); ++i) {
926  if (myImportAllTypes || myLaneTypes2Import.find((*i).type) != myLaneTypes2Import.end()) {
927  laneMap[(*i).id] = sumoLane++;
928  }
929  }
930 }
931 
932 
933 std::map<int, int>
935  std::map<int, int> ret;
936  const std::vector<OpenDriveLane>& dirLanes = lanesByDir.find(dir)->second;
937  for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanes.rbegin(); i != dirLanes.rend(); ++i) {
938  std::map<int, int>::const_iterator toP = laneMap.find((*i).id);
939  if (toP == laneMap.end()) {
940  // the current lane is not available in SUMO
941  continue;
942  }
943  int to = (*toP).second;
944  int from = UNSET_CONNECTION;
945  if ((*i).predecessor != UNSET_CONNECTION) {
946  from = (*i).predecessor;
947  }
948  if (from != UNSET_CONNECTION) {
949  std::map<int, int>::const_iterator fromP = prev.laneMap.find(from);
950  if (fromP != prev.laneMap.end()) {
951  from = (*fromP).second;
952  } else {
953  from = UNSET_CONNECTION;
954  }
955  }
956  if (from != UNSET_CONNECTION && to != UNSET_CONNECTION) {
957  if (ret.find(from) != ret.end()) {
958 // WRITE_WARNING("double connection");
959  }
960  if (dir == OPENDRIVE_TAG_LEFT) {
961  std::swap(from, to);
962  }
963  ret[from] = to;
964  } else {
965 // WRITE_WARNING("missing connection");
966  }
967  }
968  return ret;
969 }
970 
971 
972 
973 // ---------------------------------------------------------------------------
974 // edge
975 // ---------------------------------------------------------------------------
976 unsigned int
978  unsigned int maxLaneNum = 0;
979  for (std::vector<OpenDriveLaneSection>::const_iterator i = laneSections.begin(); i != laneSections.end(); ++i) {
980  maxLaneNum = MAX2(maxLaneNum, (*i).getLaneNumber(dir));
981  }
982  return maxLaneNum;
983 }
984 
985 
986 int
988  int prio = 1;
989  for (std::vector<OpenDriveSignal>::const_iterator i = signals.begin(); i != signals.end(); ++i) {
990  int tmp = 1;
991  if ((*i).type == "301" || (*i).type == "306") {
992  tmp = 2;
993  }
994  if ((*i).type == "205") {
995  tmp = 0;
996  }
997  if (tmp != 1 && dir == OPENDRIVE_TAG_RIGHT && (*i).orientation < 0) {
998  prio = tmp;
999  }
1000  if (tmp != 1 && dir == OPENDRIVE_TAG_LEFT && (*i).orientation > 0) {
1001  prio = tmp;
1002  }
1003 
1004  }
1005  return prio;
1006 }
1007 
1008 
1009 
1010 // ---------------------------------------------------------------------------
1011 // loader methods
1012 // ---------------------------------------------------------------------------
1013 NIImporter_OpenDrive::NIImporter_OpenDrive(std::map<std::string, OpenDriveEdge*>& edges)
1015  myCurrentEdge("", "", -1), myEdges(edges) {
1016 }
1017 
1018 
1020 }
1021 
1022 
1023 void
1025  const SUMOSAXAttributes& attrs) {
1026  bool ok = true;
1027  switch (element) {
1028  case OPENDRIVE_TAG_HEADER: {
1029  int majorVersion = attrs.get<int>(OPENDRIVE_ATTR_REVMAJOR, 0, ok);
1030  int minorVersion = attrs.get<int>(OPENDRIVE_ATTR_REVMINOR, 0, ok);
1031  if (majorVersion != 1 || minorVersion != 2) {
1032  WRITE_WARNING("Given openDrive file '" + getFileName() + "' uses version " + toString(majorVersion) + "." + toString(minorVersion) + ";\n Version 1.2 is supported.");
1033  }
1034  }
1035  break;
1036  case OPENDRIVE_TAG_ROAD: {
1037  std::string id = attrs.get<std::string>(OPENDRIVE_ATTR_ID, 0, ok);
1038  std::string junction = attrs.get<std::string>(OPENDRIVE_ATTR_JUNCTION, id.c_str(), ok);
1039  SUMOReal length = attrs.get<SUMOReal>(OPENDRIVE_ATTR_LENGTH, id.c_str(), ok);
1040  myCurrentEdge = OpenDriveEdge(id, junction, length);
1041  }
1042  break;
1044  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
1045  std::string elementType = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
1046  std::string elementID = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
1047  std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
1048  ? attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok)
1049  : "end";
1050  addLink(OPENDRIVE_LT_PREDECESSOR, elementType, elementID, contactPoint);
1051  }
1052  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
1053  int no = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1054  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1055  l.predecessor = no;
1056  }
1057  }
1058  break;
1059  case OPENDRIVE_TAG_SUCCESSOR: {
1060  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
1061  std::string elementType = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
1062  std::string elementID = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
1063  std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
1064  ? attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok)
1065  : "start";
1066  addLink(OPENDRIVE_LT_SUCCESSOR, elementType, elementID, contactPoint);
1067  }
1068  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
1069  int no = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1070  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1071  l.successor = no;
1072  }
1073  }
1074  break;
1075  case OPENDRIVE_TAG_GEOMETRY: {
1076  SUMOReal length = attrs.get<SUMOReal>(OPENDRIVE_ATTR_LENGTH, myCurrentEdge.id.c_str(), ok);
1077  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1078  SUMOReal x = attrs.get<SUMOReal>(OPENDRIVE_ATTR_X, myCurrentEdge.id.c_str(), ok);
1079  SUMOReal y = attrs.get<SUMOReal>(OPENDRIVE_ATTR_Y, myCurrentEdge.id.c_str(), ok);
1080  SUMOReal hdg = attrs.get<SUMOReal>(OPENDRIVE_ATTR_HDG, myCurrentEdge.id.c_str(), ok);
1081  myCurrentEdge.geometries.push_back(OpenDriveGeometry(length, s, x, y, hdg));
1082  }
1083  break;
1084  case OPENDRIVE_TAG_LINE: {
1085  std::vector<SUMOReal> vals;
1087  }
1088  break;
1089  case OPENDRIVE_TAG_SPIRAL: {
1090  std::vector<SUMOReal> vals;
1091  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVSTART, myCurrentEdge.id.c_str(), ok));
1092  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVEND, myCurrentEdge.id.c_str(), ok));
1094  }
1095  break;
1096  case OPENDRIVE_TAG_ARC: {
1097  std::vector<SUMOReal> vals;
1098  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVATURE, myCurrentEdge.id.c_str(), ok));
1100  }
1101  break;
1102  case OPENDRIVE_TAG_POLY3: {
1103  std::vector<SUMOReal> vals;
1104  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok));
1105  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_B, myCurrentEdge.id.c_str(), ok));
1106  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_C, myCurrentEdge.id.c_str(), ok));
1107  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_D, myCurrentEdge.id.c_str(), ok));
1109  }
1110  break;
1112  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1114  }
1115  break;
1116  case OPENDRIVE_TAG_LEFT:
1118  break;
1119  case OPENDRIVE_TAG_CENTER:
1121  break;
1122  case OPENDRIVE_TAG_RIGHT:
1124  break;
1125  case OPENDRIVE_TAG_LANE: {
1126  std::string type = attrs.get<std::string>(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
1127  int id = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1128  std::string level = attrs.hasAttribute(OPENDRIVE_ATTR_LEVEL)
1129  ? attrs.get<std::string>(OPENDRIVE_ATTR_LEVEL, myCurrentEdge.id.c_str(), ok)
1130  : "";
1132  ls.lanesByDir[myCurrentLaneDirection].push_back(OpenDriveLane(id, level, type));
1133  }
1134  break;
1135  case OPENDRIVE_TAG_SIGNAL: {
1136  int id = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1137  std::string type = attrs.get<std::string>(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
1138  int orientation = attrs.get<std::string>(OPENDRIVE_ATTR_ORIENTATION, myCurrentEdge.id.c_str(), ok) == "-" ? -1 : 1;
1139  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1140  bool dynamic = attrs.get<std::string>(OPENDRIVE_ATTR_DYNAMIC, myCurrentEdge.id.c_str(), ok) == "no" ? false : true;
1141  myCurrentEdge.signals.push_back(OpenDriveSignal(id, type, orientation, dynamic, s));
1142  }
1143  break;
1145  myCurrentJunctionID = attrs.get<std::string>(OPENDRIVE_ATTR_ID, myCurrentJunctionID.c_str(), ok);
1146  break;
1147  case OPENDRIVE_TAG_CONNECTION: {
1148  std::string id = attrs.get<std::string>(OPENDRIVE_ATTR_ID, myCurrentJunctionID.c_str(), ok);
1149  myCurrentIncomingRoad = attrs.get<std::string>(OPENDRIVE_ATTR_INCOMINGROAD, myCurrentJunctionID.c_str(), ok);
1151  std::string cp = attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentJunctionID.c_str(), ok);
1153  myConnectionWasEmpty = true;
1154  }
1155  break;
1156  case OPENDRIVE_TAG_LANELINK: {
1157  int from = attrs.get<int>(OPENDRIVE_ATTR_FROM, myCurrentJunctionID.c_str(), ok);
1158  int to = attrs.get<int>(OPENDRIVE_ATTR_TO, myCurrentJunctionID.c_str(), ok);
1159  Connection c;
1161  c.toEdge = myCurrentConnectingRoad;
1162  c.fromLane = from;
1163  c.toLane = to;
1164  c.fromCP = OPENDRIVE_CP_END;
1165  c.toCP = myCurrentContactPoint;
1166  c.all = false;
1167  if (myEdges.find(c.fromEdge) == myEdges.end()) {
1168  WRITE_ERROR("In laneLink-element: incoming road '" + c.fromEdge + "' is not known.");
1169  } else {
1170  OpenDriveEdge* e = myEdges.find(c.fromEdge)->second;
1171  e->connections.insert(c);
1172  myConnectionWasEmpty = false;
1173  }
1174  }
1175  break;
1176  case OPENDRIVE_TAG_WIDTH: {
1177  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 1] == OPENDRIVE_TAG_LANE) {
1178  SUMOReal width = attrs.get<SUMOReal>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok);
1179  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1180  l.width = MAX2(l.width, width);
1181  }
1182  }
1183  break;
1184  case OPENDRIVE_TAG_SPEED: {
1185  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 1] == OPENDRIVE_TAG_LANE) {
1186  SUMOReal speed = attrs.get<SUMOReal>(OPENDRIVE_ATTR_MAX, myCurrentEdge.id.c_str(), ok);
1187  myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back().speed = speed;
1188  }
1189  }
1190  break;
1191  default:
1192  break;
1193  }
1194  myElementStack.push_back(element);
1195 }
1196 
1197 
1198 void
1200  myElementStack.pop_back();
1201  switch (element) {
1202  case OPENDRIVE_TAG_ROAD:
1204  break;
1206  if (myConnectionWasEmpty) {
1207  Connection c;
1210  c.fromLane = 0;
1211  c.toLane = 0;
1214  c.all = true;
1215  if (myEdges.find(c.fromEdge) == myEdges.end()) {
1216  WRITE_ERROR("In laneLink-element: incoming road '" + c.fromEdge + "' is not known.");
1217  } else {
1218  OpenDriveEdge* e = myEdges.find(c.fromEdge)->second;
1219  e->connections.insert(c);
1220  }
1221  }
1222  break;
1223  default:
1224  break;
1225  }
1226 }
1227 
1228 
1229 
1230 void
1231 NIImporter_OpenDrive::addLink(LinkType lt, const std::string& elementType,
1232  const std::string& elementID,
1233  const std::string& contactPoint) {
1234  OpenDriveLink l(lt, elementID);
1235  // elementType
1236  if (elementType == "road") {
1238  } else if (elementType == "junction") {
1240  }
1241  // contact point
1242  if (contactPoint == "start") {
1244  } else if (contactPoint == "end") {
1246  }
1247  // add
1248  myCurrentEdge.links.push_back(l);
1249 }
1250 
1251 
1252 void
1253 NIImporter_OpenDrive::addGeometryShape(GeometryType type, const std::vector<SUMOReal>& vals) {
1254  // checks
1255  if (myCurrentEdge.geometries.size() == 0) {
1256  throw ProcessError("Mismatching paranthesis in geometry definition for road '" + myCurrentEdge.id + "'");
1257  }
1259  if (last.type != OPENDRIVE_GT_UNKNOWN) {
1260  throw ProcessError("Double geometry information for road '" + myCurrentEdge.id + "'");
1261  }
1262  // set
1263  last.type = type;
1264  last.params = vals;
1265 }
1266 
1267 
1268 bool
1270  if (c1.fromEdge != c2.fromEdge) {
1271  return c1.fromEdge < c2.fromEdge;
1272  }
1273  if (c1.toEdge != c2.toEdge) {
1274  return c1.toEdge < c2.toEdge;
1275  }
1276  if (c1.fromLane != c2.fromLane) {
1277  return c1.fromLane < c2.fromLane;
1278  }
1279  return c1.toLane < c2.toLane;
1280 }
1281 
1282 
1283 
1284 /****************************************************************************/
1285