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