SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NIImporter_OpenDrive.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // Importer for networks stored in openDrive format
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
13 // Copyright (C) 2001-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;
313  unsigned int noLanesRight = e->getMaxLaneNumber(OPENDRIVE_TAG_RIGHT);
314  unsigned int noLanesLeft = e->getMaxLaneNumber(OPENDRIVE_TAG_LEFT);
315  if (noLanesRight == 0 && noLanesLeft == 0) {
316  WRITE_WARNING("Edge '" + e->id + "' has no lanes.");
317  }
318 
319  // idea: go along the lane sections, build a node in between of each pair
320 
322 
325 
327  NBNode* sFrom = e->from;
328  NBNode* sTo = e->to;
329  int priorityR = e->getPriority(OPENDRIVE_TAG_RIGHT);
330  int priorityL = e->getPriority(OPENDRIVE_TAG_LEFT);
331  SUMOReal sB = 0;
332  SUMOReal sE = e->length;
333  SUMOReal cF = e->length / e->geom.length();
334  NBEdge* prevRight = 0;
335  NBEdge* prevLeft = 0;
336 
337  // starting at the same node as ending, and no lane sections?
338  if (sFrom == sTo && e->laneSections.size() == 1) {
339  // --> loop, split!
341  ls.s = e->length / 2.;
342  e->laneSections.push_back(ls);
343  WRITE_WARNING("Edge '" + e->id + "' has to be split as it connects same junctions.")
344  }
345 
346  // build along lane sections
347  for (std::vector<OpenDriveLaneSection>::iterator j = e->laneSections.begin(); j != e->laneSections.end(); ++j) {
348  // add internal node if needed
349  if (j == e->laneSections.end() - 1) {
350  sTo = e->to;
351  sE = e->length / cF;
352  } else {
353  SUMOReal nextS = (j + 1)->s;
354  sTo = new NBNode(e->id + "." + toString(nextS), e->geom.positionAtOffset(nextS));
355  if (!nb.getNodeCont().insert(sTo)) {
356  throw ProcessError("Could not add node '" + sTo->getID() + "'.");
357  }
358  sE = nextS / cF;
359  }
360  PositionVector geom = e->geom.getSubpart(sB, sE);
361  (*j).buildLaneMapping();
362  std::string id = e->id;
363  if (sFrom != e->from || sTo != e->to) {
364  id = id + "." + toString((*j).s);
365  }
366 
367  // build lanes to right
368  int rightLanesSection = (*j).getLaneNumber(OPENDRIVE_TAG_RIGHT);
369  NBEdge* currRight = 0;
370  if (rightLanesSection > 0) {
371  currRight = new NBEdge("-" + id, sFrom, sTo, "", defaultSpeed, rightLanesSection, priorityR,
373  if (!nb.getEdgeCont().insert(currRight)) {
374  throw ProcessError("Could not add edge '" + currRight->getID() + "'.");
375  }
376  const std::vector<OpenDriveLane>& lanes = (*j).lanesByDir[OPENDRIVE_TAG_RIGHT];
377  for (std::vector<OpenDriveLane>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
378  std::map<int, int>::const_iterator lp = (*j).laneMap.find((*k).id);
379  if (lp != (*j).laneMap.end()) {
380  int sumoLaneIndex = lp->second;
381  NBEdge::Lane& sumoLane = currRight->getLaneStruct(sumoLaneIndex);
382  const OpenDriveLane& odLane = *k;
383 
384  sumoLane.origID = e->id + " -" + toString((*k).id);
385  sumoLane.speed = odLane.speed != 0 ? odLane.speed : defaultSpeed;
386 
387  if (myImportWidths) {
388  SUMOReal width = odLane.width;
389  if (width != 0) {
390  sumoLane.width = width;
391  }
392  }
393  }
394  }
395  // connect lane sections
396  if (prevRight != 0) {
397  std::map<int, int> connections = (*j).getInnerConnections(OPENDRIVE_TAG_RIGHT, *(j - 1));
398  for (std::map<int, int>::const_iterator k = connections.begin(); k != connections.end(); ++k) {
399  prevRight->addLane2LaneConnection((*k).first, currRight, (*k).second, NBEdge::L2L_VALIDATED);
400  }
401  }
402  prevRight = currRight;
403  }
404 
405  // build lanes to left
406  int leftLanesSection = (*j).getLaneNumber(OPENDRIVE_TAG_LEFT);
407  NBEdge* currLeft = 0;
408  if (leftLanesSection > 0) {
409  currLeft = new NBEdge(id, sTo, sFrom, "", defaultSpeed, leftLanesSection, priorityL,
411  if (!nb.getEdgeCont().insert(currLeft)) {
412  throw ProcessError("Could not add edge '" + currLeft->getID() + "'.");
413  }
414  const std::vector<OpenDriveLane>& lanes = (*j).lanesByDir[OPENDRIVE_TAG_LEFT];
415  for (std::vector<OpenDriveLane>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
416  std::map<int, int>::const_iterator lp = (*j).laneMap.find((*k).id);
417  if (lp != (*j).laneMap.end()) {
418  int sumoLaneIndex = lp->second;
419  NBEdge::Lane& sumoLane = currLeft->getLaneStruct(sumoLaneIndex);
420  const OpenDriveLane& odLane = *k;
421 
422  sumoLane.origID = e->id + " " + toString((*k).id);
423  sumoLane.speed = odLane.speed != 0 ? odLane.speed : defaultSpeed;
424 
425  if (myImportWidths) {
426  SUMOReal width = odLane.width;
427  if (width != 0) {
428  sumoLane.width = width;
429  }
430  }
431  }
432  }
433  // connect lane sections
434  if (prevLeft != 0) {
435  std::map<int, int> connections = (*j).getInnerConnections(OPENDRIVE_TAG_LEFT, *(j - 1));
436  for (std::map<int, int>::const_iterator k = connections.begin(); k != connections.end(); ++k) {
437  currLeft->addLane2LaneConnection((*k).first, prevLeft, (*k).second, NBEdge::L2L_VALIDATED);
438  }
439  }
440  prevLeft = currLeft;
441  }
442  (*j).sumoID = id;
443 
444 
445  sB = sE;
446  sFrom = sTo;
447  }
448  }
449 
450 
451  // -------------------------
452  // connections building
453  // -------------------------
454  // generate explicit lane-to-lane connections
455  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
456  setEdgeLinks2(*(*i).second, edges);
457  }
458  // compute connections across intersections, if any
459  std::vector<Connection> connections2;
460  for (std::map<std::string, OpenDriveEdge*>::iterator j = edges.begin(); j != edges.end(); ++j) {
461  const std::set<Connection>& conns = (*j).second->connections;
462 
463  for (std::set<Connection>::const_iterator i = conns.begin(); i != conns.end(); ++i) {
464  if (innerEdges.find((*i).fromEdge) != innerEdges.end()) {
465  // connections starting at inner edges are processed by starting from outer edges
466  continue;
467  }
468  if (innerEdges.find((*i).toEdge) != innerEdges.end()) {
469  buildConnectionsToOuter(*i, innerEdges, connections2);
470  } else {
471  connections2.push_back(*i);
472  }
473  }
474  }
475  // set connections
476  for (std::vector<Connection>::const_iterator i = connections2.begin(); i != connections2.end(); ++i) {
477  std::string fromEdge = (*i).fromEdge;
478  if (edges.find(fromEdge) == edges.end()) {
479  WRITE_WARNING("While setting connections: from-edge '" + fromEdge + "' is not known.");
480  continue;
481  }
482  OpenDriveEdge* odFrom = edges[fromEdge];
483  int fromLane = (*i).fromLane;
484  bool fromLast = ((*i).fromCP == OPENDRIVE_CP_END) ^ ((*i).fromLane > 0 && !(*i).all);
485  fromEdge = fromLast ? odFrom->laneSections.back().sumoID : odFrom->laneSections[0].sumoID;
486 
487  std::string toEdge = (*i).toEdge;
488  if (edges.find(toEdge) == edges.end()) {
489  WRITE_WARNING("While setting connections: to-edge '" + toEdge + "' is not known.");
490  continue;
491  }
492 
493  OpenDriveEdge* odTo = edges[toEdge];
494  int toLane = (*i).toLane;
495  bool toLast = ((*i).toCP == OPENDRIVE_CP_END) || ((*i).toLane > 0);
496  toEdge = toLast ? odTo->laneSections.back().sumoID : odTo->laneSections[0].sumoID;
497 
498  if (fromLane == UNSET_CONNECTION) {
499  fromLane = toLast ? odTo->laneSections.back().laneMap.begin()->first : odTo->laneSections[0].laneMap.begin()->first;
500  }
501  if (fromLane < 0) {
502  fromEdge = revertID(fromEdge);
503  }
504  if (toLane == UNSET_CONNECTION) {
505  toLane = toLast ? odTo->laneSections.back().laneMap.begin()->first : odTo->laneSections[0].laneMap.begin()->first;
506  }
507  if (toLane < 0) {
508  toEdge = revertID(toEdge);
509  }
510  fromLane = fromLast ? odFrom->laneSections.back().laneMap[fromLane] : odFrom->laneSections[0].laneMap[fromLane];
511  toLane = toLast ? odTo->laneSections.back().laneMap[toLane] : odTo->laneSections[0].laneMap[toLane];
512  NBEdge* from = nb.getEdgeCont().retrieve(fromEdge);
513  NBEdge* to = nb.getEdgeCont().retrieve(toEdge);
514  if (from == 0) {
515  WRITE_WARNING("Could not find fromEdge representation of '' in connection ''.");
516  }
517  if (to == 0) {
518  WRITE_WARNING("Could not find fromEdge representation of '' in connection ''.");
519  }
520  if (from == 0 || to == 0) {
521  continue;
522  }
523 
524  from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER);
525 
526  if ((*i).origID != "") {
527  // @todo: this is the most silly way to determine the connection
528  std::vector<NBEdge::Connection>& cons = from->getConnections();
529  for (std::vector<NBEdge::Connection>::iterator k = cons.begin(); k != cons.end(); ++k) {
530  if ((*k).fromLane == fromLane && (*k).toEdge == to && (*k).toLane == toLane) {
531  (*k).origID = (*i).origID + " " + toString((*i).origLane);
532  break;
533  }
534  }
535  }
536  }
537  // clean up
538  if (oc.exists("geometry.min-dist") && oc.isSet("geometry.min-dist")) {
539  oc.unSet("geometry.min-dist");
540  }
541  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
542  delete(*i).second;
543  }
544 }
545 
546 
547 
548 void
549 NIImporter_OpenDrive::buildConnectionsToOuter(const Connection& c, const std::map<std::string, OpenDriveEdge*>& innerEdges, std::vector<Connection>& into) {
550 
551  OpenDriveEdge* dest = innerEdges.find(c.toEdge)->second;
552  if (dest == 0) {
554  return;
555  }
556  const std::set<Connection>& conts = dest->connections;
557  for (std::set<Connection>::const_iterator i = conts.begin(); i != conts.end(); ++i) {
558  if (innerEdges.find((*i).toEdge) != innerEdges.end()) {
559  std::vector<Connection> t;
560  buildConnectionsToOuter(*i, innerEdges, t);
561  for (std::vector<Connection>::const_iterator j = t.begin(); j != t.end(); ++j) {
562  // @todo this section is unverified
563  Connection cn = (*j);
564  cn.fromEdge = c.fromEdge;
565  cn.fromLane = c.fromLane;
566  cn.fromCP = c.fromCP;
567  cn.all = c.all; // @todo "all" is a hack trying to avoid the "from is zero" problem;
568  into.push_back(cn);
569  }
570  } else {
571  if ((*i).fromLane == c.toLane) {
572  Connection cn = (*i);
573  cn.fromEdge = c.fromEdge;
574  cn.fromLane = c.fromLane;
575  cn.fromCP = c.fromCP;
576  cn.all = c.all;
577  cn.origID = c.toEdge;
578  cn.origLane = c.toLane;
579  into.push_back(cn);
580  }
581  }
582  }
583 }
584 
585 
586 void
587 NIImporter_OpenDrive::setEdgeLinks2(OpenDriveEdge& e, const std::map<std::string, OpenDriveEdge*>& edges) {
588  for (std::vector<OpenDriveLink>::iterator i = e.links.begin(); i != e.links.end(); ++i) {
589  OpenDriveLink& l = *i;
590  if (l.elementType != OPENDRIVE_ET_ROAD) {
591  // we assume that links to nodes are later given as connections to edges
592  continue;
593  }
594  // get the right direction of the connected edge
595  std::string connectedEdge = l.elementID;
596  std::string edgeID = e.id;
597 
598  OpenDriveLaneSection& laneSection = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e.laneSections.back() : e.laneSections[0];
599  if (laneSection.lanesByDir.find(OPENDRIVE_TAG_RIGHT) != laneSection.lanesByDir.end()) {
600  const std::vector<OpenDriveLane>& lanes = laneSection.lanesByDir.find(OPENDRIVE_TAG_RIGHT)->second;
601  for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
602  if (!myImportAllTypes && myLaneTypes2Import.find((*j).type) == myLaneTypes2Import.end()) {
603  continue;
604  }
605  Connection c; // @todo: give Connection a new name and a constructor
606  c.fromEdge = e.id;
607  c.fromLane = (*j).id;
609  c.toLane = l.linkType == OPENDRIVE_LT_SUCCESSOR ? (*j).successor : (*j).predecessor;
610  c.toEdge = connectedEdge;
611  c.toCP = l.contactPoint;
612  c.all = false;
613  if (l.linkType != OPENDRIVE_LT_SUCCESSOR) {
614  std::swap(c.fromEdge, c.toEdge);
615  std::swap(c.fromLane, c.toLane);
616  std::swap(c.fromCP, c.toCP);
617  }
618  if (edges.find(c.fromEdge) == edges.end()) {
619  WRITE_ERROR("While setting connections: incoming road '" + c.fromEdge + "' is not known.");
620  } else {
621  OpenDriveEdge* src = edges.find(c.fromEdge)->second;
622  src->connections.insert(c);
623  }
624  }
625  }
626  if (laneSection.lanesByDir.find(OPENDRIVE_TAG_LEFT) != laneSection.lanesByDir.end()) {
627  const std::vector<OpenDriveLane>& lanes = laneSection.lanesByDir.find(OPENDRIVE_TAG_LEFT)->second;
628  for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
629  if (!myImportAllTypes && myLaneTypes2Import.find((*j).type) == myLaneTypes2Import.end()) {
630  continue;
631  }
632  Connection c;
633  c.toEdge = e.id;
634  c.toLane = (*j).id;
636  c.fromLane = l.linkType == OPENDRIVE_LT_SUCCESSOR ? (*j).successor : (*j).predecessor;
637  c.fromEdge = connectedEdge;
638  c.fromCP = l.contactPoint;
639  c.all = false;
640  if (l.linkType != OPENDRIVE_LT_SUCCESSOR) {
641  std::swap(c.fromEdge, c.toEdge);
642  std::swap(c.fromLane, c.toLane);
643  std::swap(c.fromCP, c.toCP);
644  }
645  if (edges.find(c.fromEdge) == edges.end()) {
646  WRITE_ERROR("While setting connections: incoming road '" + c.fromEdge + "' is not known.");
647  } else {
648  OpenDriveEdge* src = edges.find(c.fromEdge)->second;
649  src->connections.insert(c);
650  }
651  }
652  }
653  }
654 }
655 
656 
657 std::string NIImporter_OpenDrive::revertID(const std::string& id) {
658  if (id[0] == '-') {
659  return id.substr(1);
660  }
661  return "-" + id;
662 }
663 
664 NBNode*
665 NIImporter_OpenDrive::getOrBuildNode(const std::string& id, const Position& pos,
666  NBNodeCont& nc) {
667  if (nc.retrieve(id) == 0) {
668  // not yet built; build now
669  if (!nc.insert(id, pos)) {
670  // !!! clean up
671  throw ProcessError("Could not add node '" + id + "'.");
672  }
673  }
674  return nc.retrieve(id);
675 }
676 
677 
678 void
680  const std::string& nodeID, NIImporter_OpenDrive::LinkType lt) {
681  NBNode* n = nc.retrieve(nodeID);
682  if (n == 0) {
683  throw ProcessError("Could not find node '" + nodeID + "'.");
684  }
685  if (lt == OPENDRIVE_LT_SUCCESSOR) {
686  if (e.to != 0 && e.to != n) {
687  throw ProcessError("Edge '" + e.id + "' has two end nodes.");
688  }
689  e.to = n;
690  } else {
691  if (e.from != 0 && e.from != n) {
692  throw ProcessError("Edge '" + e.id + "' has two start nodes.");
693  }
694  e.from = n;
695  }
696 }
697 
698 
699 
700 
701 
702 
703 
704 void
705 NIImporter_OpenDrive::computeShapes(std::map<std::string, OpenDriveEdge*>& edges) {
707  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
708  OpenDriveEdge& e = *(*i).second;
709  for (std::vector<OpenDriveGeometry>::iterator j = e.geometries.begin(); j != e.geometries.end(); ++j) {
710  OpenDriveGeometry& g = *j;
711  std::vector<Position> geom;
712  switch (g.type) {
714  break;
715  case OPENDRIVE_GT_LINE:
716  geom = geomFromLine(e, g);
717  break;
718  case OPENDRIVE_GT_ARC:
719  geom = geomFromArc(e, g);
720  break;
721  case OPENDRIVE_GT_POLY3:
722  geom = geomFromPoly(e, g);
723  if (geom.size() == 1) {
724  geom = geomFromPoly(e, g);
725  }
726  break;
727  default:
728  break;
729  }
730  for (std::vector<Position>::iterator k = geom.begin(); k != geom.end(); ++k) {
732  }
733  }
734  if (oc.exists("geometry.min-dist") && oc.isSet("geometry.min-dist")) {
735  e.geom.removeDoublePoints(oc.getFloat("geometry.min-dist"), true);
736  }
737  for (unsigned int j = 0; j < e.geom.size(); ++j) {
739  WRITE_ERROR("Unable to project coordinates for.");
740  }
741  }
742  }
743 }
744 
745 
746 std::vector<Position>
748  UNUSED_PARAMETER(e);
749  std::vector<Position> ret;
750  ret.push_back(Position(g.x, g.y));
751  ret.push_back(calculateStraightEndPoint(g.hdg, g.length, Position(g.x, g.y)));
752  return ret;
753 }
754 
755 
756 std::vector<Position>
758  UNUSED_PARAMETER(e);
759  std::vector<Position> ret;
760  SUMOReal dist = 0.0;
761  SUMOReal centerX = g.x;
762  SUMOReal centerY = g.y;
763  // left: positive value
764  SUMOReal curvature = g.params[0];
765  SUMOReal radius = 1. / curvature;
766  // center point
767  calculateCurveCenter(&centerX, &centerY, radius, g.hdg);
768  SUMOReal endX = g.x;
769  SUMOReal endY = g.y;
770  SUMOReal startX = g.x;
771  SUMOReal startY = g.y;
772  SUMOReal geo_posS = g.s;
773  SUMOReal geo_posE = g.s;
774  bool end = false;
775  do {
776  geo_posE += C_LENGTH;
777  if (geo_posE - g.s > g.length) {
778  geo_posE = g.s + g.length;
779  }
780  if (geo_posE - g.s > g.length) {
781  geo_posE = g.s + g.length;
782  }
783  calcPointOnCurve(&endX, &endY, centerX, centerY, radius, geo_posE - geo_posS);
784 
785  dist += (geo_posE - geo_posS);
786  //
787  ret.push_back(Position(startX, startY));
788  //
789  startX = endX;
790  startY = endY;
791  geo_posS = geo_posE;
792 
793  if (geo_posE - (g.s + g.length) < 0.001 && geo_posE - (g.s + g.length) > -0.001) {
794  end = true;
795  }
796  } while (!end);
797  return ret;
798 }
799 
800 
801 std::vector<Position>
803  UNUSED_PARAMETER(e);
804  std::vector<Position> ret;
805  for (SUMOReal off = 0; off < g.length + 2.; off += 2.) {
806  //SUMOReal off = g.length;
807  SUMOReal x = off;
808  SUMOReal y = g.params[0] + g.params[1] * off + g.params[2] * pow(off, 2.) + g.params[3] * pow(off, 3.);
809  SUMOReal s = sin(g.hdg);
810  SUMOReal c = cos(g.hdg);
811  SUMOReal xnew = x * c - y * s;
812  SUMOReal ynew = x * s + y * c;
813  ret.push_back(Position(g.x + xnew, g.y + ynew));
814  }
815  return ret;
816 }
817 
818 
819 Position
820 NIImporter_OpenDrive::calculateStraightEndPoint(double hdg, double length, const Position& start) {
821  double normx = 1.0f;
822  double normy = 0.0f;
823  double x2 = normx * cos(hdg) - normy * sin(hdg);
824  double y2 = normx * sin(hdg) + normy * cos(hdg);
825  normx = x2 * length;
826  normy = y2 * length;
827  return Position(start.x() + normx, start.y() + normy);
828 }
829 
830 
831 void
833  SUMOReal normX = 1.0;
834  SUMOReal normY = 0.0;
835  SUMOReal tmpX;
836  SUMOReal turn;
837  if (ad_radius > 0) {
838  turn = -1.0;
839  } else {
840  turn = 1.0;
841  }
842 
843  tmpX = normX;
844  normX = normX * cos(ad_hdg) + normY * sin(ad_hdg);
845  normY = tmpX * sin(ad_hdg) + normY * cos(ad_hdg);
846 
847  tmpX = normX;
848  normX = turn * normY;
849  normY = -turn * tmpX;
850 
851  normX = fabs(ad_radius) * normX;
852  normY = fabs(ad_radius) * normY;
853 
854  *ad_x += normX;
855  *ad_y += normY;
856 }
857 
858 
859 void
861  SUMOReal ad_r, SUMOReal ad_length) {
862  double rotAngle = ad_length / fabs(ad_r);
863  double vx = *ad_x - ad_centerX;
864  double vy = *ad_y - ad_centerY;
865  double tmpx;
866 
867  double turn;
868  if (ad_r > 0) {
869  turn = -1; //left
870  } else {
871  turn = 1; //right
872  }
873  tmpx = vx;
874  vx = vx * cos(rotAngle) + turn * vy * sin(rotAngle);
875  vy = -1 * turn * tmpx * sin(rotAngle) + vy * cos(rotAngle);
876  *ad_x = vx + ad_centerX;
877  *ad_y = vy + ad_centerY;
878 }
879 
880 
881 // ---------------------------------------------------------------------------
882 // section
883 // ---------------------------------------------------------------------------
885  lanesByDir[OPENDRIVE_TAG_LEFT] = std::vector<OpenDriveLane>();
886  lanesByDir[OPENDRIVE_TAG_RIGHT] = std::vector<OpenDriveLane>();
887  lanesByDir[OPENDRIVE_TAG_CENTER] = std::vector<OpenDriveLane>();
888 }
889 
890 
891 unsigned int
893  unsigned int laneNum = 0;
894  const std::vector<OpenDriveLane>& dirLanes = lanesByDir.find(dir)->second;
895  for (std::vector<OpenDriveLane>::const_iterator i = dirLanes.begin(); i != dirLanes.end(); ++i) {
896  if (myImportAllTypes || myLaneTypes2Import.find((*i).type) != myLaneTypes2Import.end()) {
897  ++laneNum;
898  }
899  }
900  return laneNum;
901 }
902 
903 
904 void
906  unsigned int sumoLane = 0;
907  const std::vector<OpenDriveLane>& dirLanesR = lanesByDir.find(OPENDRIVE_TAG_RIGHT)->second;
908  for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanesR.rbegin(); i != dirLanesR.rend(); ++i) {
909  if (myImportAllTypes || myLaneTypes2Import.find((*i).type) != myLaneTypes2Import.end()) {
910  laneMap[(*i).id] = sumoLane++;
911  }
912  }
913  sumoLane = 0;
914  const std::vector<OpenDriveLane>& dirLanesL = lanesByDir.find(OPENDRIVE_TAG_LEFT)->second;
915  for (std::vector<OpenDriveLane>::const_iterator i = dirLanesL.begin(); i != dirLanesL.end(); ++i) {
916  if (myImportAllTypes || myLaneTypes2Import.find((*i).type) != myLaneTypes2Import.end()) {
917  laneMap[(*i).id] = sumoLane++;
918  }
919  }
920 }
921 
922 
923 std::map<int, int>
925  std::map<int, int> ret;
926  const std::vector<OpenDriveLane>& dirLanes = lanesByDir.find(dir)->second;
927  for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanes.rbegin(); i != dirLanes.rend(); ++i) {
928  std::map<int, int>::const_iterator toP = laneMap.find((*i).id);
929  if (toP == laneMap.end()) {
930  // the current lane is not available in SUMO
931  continue;
932  }
933  int to = (*toP).second;
934  int from = UNSET_CONNECTION;
935  if ((*i).predecessor != UNSET_CONNECTION) {
936  from = (*i).predecessor;
937  }
938  if (from != UNSET_CONNECTION) {
939  std::map<int, int>::const_iterator fromP = prev.laneMap.find(from);
940  if (fromP != prev.laneMap.end()) {
941  from = (*fromP).second;
942  } else {
943  from = UNSET_CONNECTION;
944  }
945  }
946  if (from != UNSET_CONNECTION && to != UNSET_CONNECTION) {
947  if (ret.find(from) != ret.end()) {
948 // WRITE_WARNING("double connection");
949  }
950  if (dir == OPENDRIVE_TAG_LEFT) {
951  std::swap(from, to);
952  }
953  ret[from] = to;
954  } else {
955 // WRITE_WARNING("missing connection");
956  }
957  }
958  return ret;
959 }
960 
961 
962 
963 // ---------------------------------------------------------------------------
964 // edge
965 // ---------------------------------------------------------------------------
966 unsigned int
968  unsigned int maxLaneNum = 0;
969  for (std::vector<OpenDriveLaneSection>::const_iterator i = laneSections.begin(); i != laneSections.end(); ++i) {
970  maxLaneNum = MAX2(maxLaneNum, (*i).getLaneNumber(dir));
971  }
972  return maxLaneNum;
973 }
974 
975 
976 int
978  int prio = 1;
979  for (std::vector<OpenDriveSignal>::const_iterator i = signals.begin(); i != signals.end(); ++i) {
980  int tmp = 1;
981  if ((*i).type == "301" || (*i).type == "306") {
982  tmp = 2;
983  }
984  if ((*i).type == "205") {
985  tmp = 0;
986  }
987  if (tmp != 1 && dir == OPENDRIVE_TAG_RIGHT && (*i).orientation < 0) {
988  prio = tmp;
989  }
990  if (tmp != 1 && dir == OPENDRIVE_TAG_LEFT && (*i).orientation > 0) {
991  prio = tmp;
992  }
993 
994  }
995  return prio;
996 }
997 
998 
999 
1000 // ---------------------------------------------------------------------------
1001 // loader methods
1002 // ---------------------------------------------------------------------------
1003 NIImporter_OpenDrive::NIImporter_OpenDrive(std::map<std::string, OpenDriveEdge*>& edges)
1005  myCurrentEdge("", "", -1), myEdges(edges) {
1006 }
1007 
1008 
1010 }
1011 
1012 
1013 void
1015  const SUMOSAXAttributes& attrs) {
1016  bool ok = true;
1017  switch (element) {
1018  case OPENDRIVE_TAG_HEADER: {
1019  int majorVersion = attrs.get<int>(OPENDRIVE_ATTR_REVMAJOR, 0, ok);
1020  int minorVersion = attrs.get<int>(OPENDRIVE_ATTR_REVMINOR, 0, ok);
1021  if (majorVersion != 1 || minorVersion != 2) {
1022  WRITE_WARNING("Given openDrive file '" + getFileName() + "' uses version " + toString(majorVersion) + "." + toString(minorVersion) + ";\n Version 1.2 is supported.");
1023  }
1024  }
1025  break;
1026  case OPENDRIVE_TAG_ROAD: {
1027  std::string id = attrs.get<std::string>(OPENDRIVE_ATTR_ID, 0, ok);
1028  std::string junction = attrs.get<std::string>(OPENDRIVE_ATTR_JUNCTION, id.c_str(), ok);
1029  SUMOReal length = attrs.get<SUMOReal>(OPENDRIVE_ATTR_LENGTH, id.c_str(), ok);
1030  myCurrentEdge = OpenDriveEdge(id, junction, length);
1031  }
1032  break;
1034  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
1035  std::string elementType = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
1036  std::string elementID = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
1037  std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
1038  ? attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok)
1039  : "end";
1040  addLink(OPENDRIVE_LT_PREDECESSOR, elementType, elementID, contactPoint);
1041  }
1042  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
1043  int no = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1044  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1045  l.predecessor = no;
1046  }
1047  }
1048  break;
1049  case OPENDRIVE_TAG_SUCCESSOR: {
1050  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
1051  std::string elementType = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
1052  std::string elementID = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
1053  std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
1054  ? attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok)
1055  : "start";
1056  addLink(OPENDRIVE_LT_SUCCESSOR, elementType, elementID, contactPoint);
1057  }
1058  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
1059  int no = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1060  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1061  l.successor = no;
1062  }
1063  }
1064  break;
1065  case OPENDRIVE_TAG_GEOMETRY: {
1066  SUMOReal length = attrs.get<SUMOReal>(OPENDRIVE_ATTR_LENGTH, myCurrentEdge.id.c_str(), ok);
1067  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1068  SUMOReal x = attrs.get<SUMOReal>(OPENDRIVE_ATTR_X, myCurrentEdge.id.c_str(), ok);
1069  SUMOReal y = attrs.get<SUMOReal>(OPENDRIVE_ATTR_Y, myCurrentEdge.id.c_str(), ok);
1070  SUMOReal hdg = attrs.get<SUMOReal>(OPENDRIVE_ATTR_HDG, myCurrentEdge.id.c_str(), ok);
1071  myCurrentEdge.geometries.push_back(OpenDriveGeometry(length, s, x, y, hdg));
1072  }
1073  break;
1074  case OPENDRIVE_TAG_LINE: {
1075  std::vector<SUMOReal> vals;
1077  }
1078  break;
1079  case OPENDRIVE_TAG_SPIRAL: {
1080  std::vector<SUMOReal> vals;
1081  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVSTART, myCurrentEdge.id.c_str(), ok));
1082  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVEND, myCurrentEdge.id.c_str(), ok));
1084  }
1085  break;
1086  case OPENDRIVE_TAG_ARC: {
1087  std::vector<SUMOReal> vals;
1088  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVATURE, myCurrentEdge.id.c_str(), ok));
1090  }
1091  break;
1092  case OPENDRIVE_TAG_POLY3: {
1093  std::vector<SUMOReal> vals;
1094  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok));
1095  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_B, myCurrentEdge.id.c_str(), ok));
1096  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_C, myCurrentEdge.id.c_str(), ok));
1097  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_D, myCurrentEdge.id.c_str(), ok));
1099  }
1100  break;
1102  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1104  }
1105  break;
1106  case OPENDRIVE_TAG_LEFT:
1108  break;
1109  case OPENDRIVE_TAG_CENTER:
1111  break;
1112  case OPENDRIVE_TAG_RIGHT:
1114  break;
1115  case OPENDRIVE_TAG_LANE: {
1116  std::string type = attrs.get<std::string>(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
1117  int id = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1118  std::string level = attrs.hasAttribute(OPENDRIVE_ATTR_LEVEL)
1119  ? attrs.get<std::string>(OPENDRIVE_ATTR_LEVEL, myCurrentEdge.id.c_str(), ok)
1120  : "";
1122  ls.lanesByDir[myCurrentLaneDirection].push_back(OpenDriveLane(id, level, type));
1123  }
1124  break;
1125  case OPENDRIVE_TAG_SIGNAL: {
1126  int id = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1127  std::string type = attrs.get<std::string>(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
1128  int orientation = attrs.get<std::string>(OPENDRIVE_ATTR_ORIENTATION, myCurrentEdge.id.c_str(), ok) == "-" ? -1 : 1;
1129  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1130  bool dynamic = attrs.get<std::string>(OPENDRIVE_ATTR_DYNAMIC, myCurrentEdge.id.c_str(), ok) == "no" ? false : true;
1131  myCurrentEdge.signals.push_back(OpenDriveSignal(id, type, orientation, dynamic, s));
1132  }
1133  break;
1135  myCurrentJunctionID = attrs.get<std::string>(OPENDRIVE_ATTR_ID, myCurrentJunctionID.c_str(), ok);
1136  break;
1137  case OPENDRIVE_TAG_CONNECTION: {
1138  std::string id = attrs.get<std::string>(OPENDRIVE_ATTR_ID, myCurrentJunctionID.c_str(), ok);
1139  myCurrentIncomingRoad = attrs.get<std::string>(OPENDRIVE_ATTR_INCOMINGROAD, myCurrentJunctionID.c_str(), ok);
1141  std::string cp = attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentJunctionID.c_str(), ok);
1143  myConnectionWasEmpty = true;
1144  }
1145  break;
1146  case OPENDRIVE_TAG_LANELINK: {
1147  int from = attrs.get<int>(OPENDRIVE_ATTR_FROM, myCurrentJunctionID.c_str(), ok);
1148  int to = attrs.get<int>(OPENDRIVE_ATTR_TO, myCurrentJunctionID.c_str(), ok);
1149  Connection c;
1151  c.toEdge = myCurrentConnectingRoad;
1152  c.fromLane = from;
1153  c.toLane = to;
1154  c.fromCP = OPENDRIVE_CP_END;
1155  c.toCP = myCurrentContactPoint;
1156  c.all = false;
1157  if (myEdges.find(c.fromEdge) == myEdges.end()) {
1158  WRITE_ERROR("In laneLink-element: incoming road '" + c.fromEdge + "' is not known.");
1159  } else {
1160  OpenDriveEdge* e = myEdges.find(c.fromEdge)->second;
1161  e->connections.insert(c);
1162  myConnectionWasEmpty = false;
1163  }
1164  }
1165  break;
1166  case OPENDRIVE_TAG_WIDTH: {
1167  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 1] == OPENDRIVE_TAG_LANE) {
1168  SUMOReal width = attrs.get<SUMOReal>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok);
1169  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1170  l.width = MAX2(l.width, width);
1171  }
1172  }
1173  break;
1174  case OPENDRIVE_TAG_SPEED: {
1175  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 1] == OPENDRIVE_TAG_LANE) {
1176  SUMOReal speed = attrs.get<SUMOReal>(OPENDRIVE_ATTR_MAX, myCurrentEdge.id.c_str(), ok);
1177  myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back().speed = speed;
1178  }
1179  }
1180  break;
1181  default:
1182  break;
1183  }
1184  myElementStack.push_back(element);
1185 }
1186 
1187 
1188 void
1190  myElementStack.pop_back();
1191  switch (element) {
1192  case OPENDRIVE_TAG_ROAD:
1194  break;
1196  if (myConnectionWasEmpty) {
1197  Connection c;
1200  c.fromLane = 0;
1201  c.toLane = 0;
1204  c.all = true;
1205  if (myEdges.find(c.fromEdge) == myEdges.end()) {
1206  WRITE_ERROR("In laneLink-element: incoming road '" + c.fromEdge + "' is not known.");
1207  } else {
1208  OpenDriveEdge* e = myEdges.find(c.fromEdge)->second;
1209  e->connections.insert(c);
1210  }
1211  }
1212  break;
1213  default:
1214  break;
1215  }
1216 }
1217 
1218 
1219 
1220 void
1221 NIImporter_OpenDrive::addLink(LinkType lt, const std::string& elementType,
1222  const std::string& elementID,
1223  const std::string& contactPoint) {
1224  OpenDriveLink l(lt, elementID);
1225  // elementType
1226  if (elementType == "road") {
1228  } else if (elementType == "junction") {
1230  }
1231  // contact point
1232  if (contactPoint == "start") {
1234  } else if (contactPoint == "end") {
1236  }
1237  // add
1238  myCurrentEdge.links.push_back(l);
1239 }
1240 
1241 
1242 void
1243 NIImporter_OpenDrive::addGeometryShape(GeometryType type, const std::vector<SUMOReal>& vals) {
1244  // checks
1245  if (myCurrentEdge.geometries.size() == 0) {
1246  throw ProcessError("Mismatching paranthesis in geometry definition for road '" + myCurrentEdge.id + "'");
1247  }
1249  if (last.type != OPENDRIVE_GT_UNKNOWN) {
1250  throw ProcessError("Double geometry information for road '" + myCurrentEdge.id + "'");
1251  }
1252  // set
1253  last.type = type;
1254  last.params = vals;
1255 }
1256 
1257 
1258 bool
1260  if (c1.fromEdge != c2.fromEdge) {
1261  return c1.fromEdge < c2.fromEdge;
1262  }
1263  if (c1.toEdge != c2.toEdge) {
1264  return c1.toEdge < c2.toEdge;
1265  }
1266  if (c1.fromLane != c2.fromLane) {
1267  return c1.fromLane < c2.fromLane;
1268  }
1269  return c1.toLane < c2.toLane;
1270 }
1271 
1272 
1273 
1274 /****************************************************************************/
1275