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>
35 #include <iterator>
39 #include <utils/common/ToString.h>
42 #include <netbuild/NBEdge.h>
43 #include <netbuild/NBEdgeCont.h>
44 #include <netbuild/NBNode.h>
45 #include <netbuild/NBNodeCont.h>
46 #include <netbuild/NBNetBuilder.h>
47 #include <netbuild/NBOwnTLDef.h>
55 #include <utils/xml/XMLSubSys.h>
56 #include <utils/geom/Boundary.h>
57 #include "NILoader.h"
58 #include "NIImporter_OpenDrive.h"
59 
60 #ifdef CHECK_MEMORY_LEAKS
61 #include <foreign/nvwa/debug_new.h>
62 #endif // CHECK_MEMORY_LEAKS
63 
64 
65 // ===========================================================================
66 // definitions
67 // ===========================================================================
68 #define C_LENGTH 10.
69 
70 
71 // ===========================================================================
72 // static variables
73 // ===========================================================================
95 
97 };
98 
99 
131 
133 };
134 
135 
138 
139 // ===========================================================================
140 // method definitions
141 // ===========================================================================
142 // ---------------------------------------------------------------------------
143 // static methods (interface in this case)
144 // ---------------------------------------------------------------------------
145 void
147  // check whether the option is set (properly)
148  if (!oc.isUsableFileList("opendrive-files")) {
149  return;
150  }
151  // prepare types
152  myImportAllTypes = oc.getBool("opendrive.import-all-lanes");
153  myImportWidths = !oc.getBool("opendrive.ignore-widths");
154  NBTypeCont& tc = nb.getTypeCont();
155  const SUMOReal WIDTH(3.65); // as wanted
156  tc.insert("driving", 1, (SUMOReal)(80. / 3.6), 1, ~SVC_PEDESTRIAN, WIDTH, true);
157  tc.insert("mwyEntry", 1, (SUMOReal)(80. / 3.6), 1, ~SVC_PEDESTRIAN, WIDTH, true);
158  tc.insert("mwyExit", 1, (SUMOReal)(80. / 3.6), 1, ~SVC_PEDESTRIAN, WIDTH, true);
159  tc.insert("stop", 1, (SUMOReal)(80. / 3.6), 1, ~SVC_PEDESTRIAN, WIDTH, true);
160  tc.insert("special1", 1, (SUMOReal)(80. / 3.6), 1, ~SVC_PEDESTRIAN, WIDTH, true);
161  tc.insert("parking", 1, (SUMOReal)(5. / 3.6), 1, ~SVC_PEDESTRIAN, WIDTH, true);
162  // build the handler
163  std::map<std::string, OpenDriveEdge*> edges;
164  NIImporter_OpenDrive handler(tc, edges);
165  // parse file(s)
166  std::vector<std::string> files = oc.getStringVector("opendrive-files");
167  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
168  if (!FileHelpers::exists(*file)) {
169  WRITE_ERROR("Could not open opendrive file '" + *file + "'.");
170  return;
171  }
172  handler.setFileName(*file);
173  PROGRESS_BEGIN_MESSAGE("Parsing opendrive from '" + *file + "'");
174  XMLSubSys::runParser(handler, *file);
176  }
177  // split inner/outer edges
178  std::map<std::string, OpenDriveEdge*> innerEdges, outerEdges;
179  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
180  if ((*i).second->isInner) {
181  innerEdges[(*i).first] = (*i).second;
182  } else {
183  outerEdges[(*i).first] = (*i).second;
184  }
185  }
186 
187  // convert geometries into a discretised representation
188  computeShapes(edges);
189  // check whether lane sections are valid and whether further must be introduced
190  revisitLaneSections(tc, edges);
191 
192  // -------------------------
193  // node building
194  // -------------------------
195  // build nodes#1
196  // look at all links which belong to a node, collect their bounding boxes
197  // and place the node in the middle of this bounding box
198  std::map<std::string, Boundary> posMap;
199  std::map<std::string, std::string> edge2junction;
200  // compute node positions
201  for (std::map<std::string, OpenDriveEdge*>::iterator i = innerEdges.begin(); i != innerEdges.end(); ++i) {
202  OpenDriveEdge* e = (*i).second;
203  assert(e->junction != "-1" && e->junction != "");
204  edge2junction[e->id] = e->junction;
205  if (posMap.find(e->junction) == posMap.end()) {
206  posMap[e->junction] = Boundary();
207  }
208  posMap[e->junction].add(e->geom.getBoxBoundary());
209  }
210  // build nodes
211  for (std::map<std::string, Boundary>::iterator i = posMap.begin(); i != posMap.end(); ++i) {
212  if (!nb.getNodeCont().insert((*i).first, (*i).second.getCenter())) {
213  throw ProcessError("Could not add node '" + (*i).first + "'.");
214  }
215  }
216  // assign built nodes
217  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
218  OpenDriveEdge* e = (*i).second;
219  for (std::vector<OpenDriveLink>::iterator j = e->links.begin(); j != e->links.end(); ++j) {
220  OpenDriveLink& l = *j;
221  if (l.elementType != OPENDRIVE_ET_ROAD) {
222  // set node information
224  continue;
225  }
226  if (edge2junction.find(l.elementID) != edge2junction.end()) {
227  // set node information of an internal road
228  setNodeSecure(nb.getNodeCont(), *e, edge2junction[l.elementID], l.linkType);
229  continue;
230  }
231  }
232  }
233  // we should now have all nodes set for links which are not outer edge-to-outer edge links
234 
235 
236  // build nodes#2
237  // build nodes for all outer edge-to-outer edge connections
238  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
239  OpenDriveEdge* e = (*i).second;
240  for (std::vector<OpenDriveLink>::iterator j = e->links.begin(); j != e->links.end(); ++j) {
241  OpenDriveLink& l = *j;
242  if (l.elementType != OPENDRIVE_ET_ROAD || edge2junction.find(l.elementID) != edge2junction.end()) {
243  // is a connection to an internal edge, or a node, skip
244  continue;
245  }
246  // we have a direct connection between to external edges
247  std::string id1 = e->id;
248  std::string id2 = l.elementID;
249  if (id1 < id2) {
250  std::swap(id1, id2);
251  }
252  std::string nid = id1 + "." + id2;
253  if (nb.getNodeCont().retrieve(nid) == 0) {
254  // not yet seen, build
255  Position pos = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e->geom[-1] : e->geom[0];
256  if (!nb.getNodeCont().insert(nid, pos)) {
257  throw ProcessError("Could not build node '" + nid + "'.");
258  }
259  }
260  /* debug-stuff
261  else {
262  Position pos = l.linkType==OPENDRIVE_LT_SUCCESSOR ? e.geom[e.geom.size()-1] : e.geom[0];
263  cout << nid << " " << pos << " " << nb.getNodeCont().retrieve(nid)->getPosition() << endl;
264  }
265  */
266  setNodeSecure(nb.getNodeCont(), *e, nid, l.linkType);
267  }
268  }
269  // we should now have start/end nodes for all outer edge-to-outer edge connections
270 
271 
272  // build nodes#3
273  // assign further nodes generated from inner-edges
274  // these nodes have not been assigned earlier, because the connectiosn are referenced in inner-edges
275  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
276  OpenDriveEdge* e = (*i).second;
277  if (e->to != 0 && e->from != 0) {
278  continue;
279  }
280  for (std::map<std::string, OpenDriveEdge*>::iterator j = innerEdges.begin(); j != innerEdges.end(); ++j) {
281  OpenDriveEdge* ie = (*j).second;
282  for (std::vector<OpenDriveLink>::iterator k = ie->links.begin(); k != ie->links.end(); ++k) {
283  OpenDriveLink& il = *k;
284  if (il.elementType != OPENDRIVE_ET_ROAD || il.elementID != e->id) {
285  // not conneted to the currently investigated outer edge
286  continue;
287  }
288  std::string nid = edge2junction[ie->id];
289  if (il.contactPoint == OPENDRIVE_CP_START) {
291  } else {
293  }
294  }
295  }
296 
297  }
298 
299  // build start/end nodes which were not defined previously
300  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
301  OpenDriveEdge* e = (*i).second;
302  if (e->from == 0) {
303  const std::string nid = e->id + ".begin";
304  e->from = getOrBuildNode(nid, e->geom.front(), nb.getNodeCont());
305  }
306  if (e->to == 0) {
307  const std::string nid = e->id + ".end";
308  e->to = getOrBuildNode(nid, e->geom.back(), nb.getNodeCont());
309  }
310  }
311 
312 
313  // -------------------------
314  // edge building
315  // -------------------------
316  SUMOReal defaultSpeed = tc.getSpeed("");
317  // build edges
318  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
319  OpenDriveEdge* e = (*i).second;
320  bool lanesBuilt = false;
321 
322  // go along the lane sections, build a node in between of each pair
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.length2D();
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.getSubpart2D(sB, sE);
362  std::string id = e->id;
363  if (sFrom != e->from || sTo != e->to) {
364  id = id + "." + toString((*j).s);
365  } else if (e->laneSections.size() == 1) {
366  id = id + ".0.00";
367  }
368 
369  // build lanes to right
370  NBEdge* currRight = 0;
371  if ((*j).rightLaneNumber > 0) {
372  currRight = new NBEdge("-" + id, sFrom, sTo, "", defaultSpeed, (*j).rightLaneNumber, priorityR,
374  if (!nb.getEdgeCont().insert(currRight)) {
375  throw ProcessError("Could not add edge '" + currRight->getID() + "'.");
376  }
377  lanesBuilt = true;
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 : tc.getSpeed(odLane.type);
388  sumoLane.permissions = tc.getPermissions(odLane.type);
389  sumoLane.width = myImportWidths && odLane.width != 0 ? odLane.width : tc.getWidth(odLane.type);
390  }
391  }
392  // connect lane sections
393  if (prevRight != 0) {
394  std::map<int, int> connections = (*j).getInnerConnections(OPENDRIVE_TAG_RIGHT, *(j - 1));
395  for (std::map<int, int>::const_iterator k = connections.begin(); k != connections.end(); ++k) {
396  prevRight->addLane2LaneConnection((*k).first, currRight, (*k).second, NBEdge::L2L_VALIDATED);
397  }
398  }
399  prevRight = currRight;
400  }
401 
402  // build lanes to left
403  NBEdge* currLeft = 0;
404  if ((*j).leftLaneNumber > 0) {
405  currLeft = new NBEdge(id, sTo, sFrom, "", defaultSpeed, (*j).leftLaneNumber, priorityL,
407  if (!nb.getEdgeCont().insert(currLeft)) {
408  throw ProcessError("Could not add edge '" + currLeft->getID() + "'.");
409  }
410  lanesBuilt = true;
411  const std::vector<OpenDriveLane>& lanes = (*j).lanesByDir[OPENDRIVE_TAG_LEFT];
412  for (std::vector<OpenDriveLane>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
413  std::map<int, int>::const_iterator lp = (*j).laneMap.find((*k).id);
414  if (lp != (*j).laneMap.end()) {
415  int sumoLaneIndex = lp->second;
416  NBEdge::Lane& sumoLane = currLeft->getLaneStruct(sumoLaneIndex);
417  const OpenDriveLane& odLane = *k;
418 
419  sumoLane.origID = e->id + " " + toString((*k).id);
420  sumoLane.speed = odLane.speed != 0 ? odLane.speed : tc.getSpeed(odLane.type);
421  sumoLane.permissions = tc.getPermissions(odLane.type);
422  sumoLane.width = myImportWidths && odLane.width != 0 ? odLane.width : tc.getWidth(odLane.type);
423  }
424  }
425  // connect lane sections
426  if (prevLeft != 0) {
427  std::map<int, int> connections = (*j).getInnerConnections(OPENDRIVE_TAG_LEFT, *(j - 1));
428  for (std::map<int, int>::const_iterator k = connections.begin(); k != connections.end(); ++k) {
429  currLeft->addLane2LaneConnection((*k).first, prevLeft, (*k).second, NBEdge::L2L_VALIDATED);
430  }
431  }
432  prevLeft = currLeft;
433  }
434  (*j).sumoID = id;
435 
436 
437  sB = sE;
438  sFrom = sTo;
439  }
440  if (!lanesBuilt) {
441  WRITE_WARNING("Edge '" + e->id + "' has no lanes.");
442  }
443  }
444 
445  // -------------------------
446  // connections building
447  // -------------------------
448  // generate explicit lane-to-lane connections
449  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
450  setEdgeLinks2(*(*i).second, edges);
451  }
452  // compute connections across intersections, if any
453  std::vector<Connection> connections2;
454  for (std::map<std::string, OpenDriveEdge*>::iterator j = edges.begin(); j != edges.end(); ++j) {
455  const std::set<Connection>& conns = (*j).second->connections;
456 
457  for (std::set<Connection>::const_iterator i = conns.begin(); i != conns.end(); ++i) {
458  if (innerEdges.find((*i).fromEdge) != innerEdges.end()) {
459  // connections starting at inner edges are processed by starting from outer edges
460  continue;
461  }
462  if (innerEdges.find((*i).toEdge) != innerEdges.end()) {
463  buildConnectionsToOuter(*i, innerEdges, connections2);
464  } else {
465  connections2.push_back(*i);
466  }
467  }
468  }
469  // set connections
470  for (std::vector<Connection>::const_iterator i = connections2.begin(); i != connections2.end(); ++i) {
471  std::string fromEdge = (*i).fromEdge;
472  if (edges.find(fromEdge) == edges.end()) {
473  WRITE_WARNING("While setting connections: from-edge '" + fromEdge + "' is not known.");
474  continue;
475  }
476  OpenDriveEdge* odFrom = edges[fromEdge];
477  int fromLane = (*i).fromLane;
478  bool fromLast = ((*i).fromCP == OPENDRIVE_CP_END) ^ ((*i).fromLane > 0 && !(*i).all);
479  fromEdge = fromLast ? odFrom->laneSections.back().sumoID : odFrom->laneSections[0].sumoID;
480 
481  std::string toEdge = (*i).toEdge;
482  if (edges.find(toEdge) == edges.end()) {
483  WRITE_WARNING("While setting connections: to-edge '" + toEdge + "' is not known.");
484  continue;
485  }
486 
487  OpenDriveEdge* odTo = edges[toEdge];
488  int toLane = (*i).toLane;
489  bool toLast = ((*i).toCP == OPENDRIVE_CP_END) || ((*i).toLane > 0);
490  toEdge = toLast ? odTo->laneSections.back().sumoID : odTo->laneSections[0].sumoID;
491 
492  if (fromLane == UNSET_CONNECTION) {
493  fromLane = toLast ? odTo->laneSections.back().laneMap.begin()->first : odTo->laneSections[0].laneMap.begin()->first;
494  }
495  if (fromLane < 0) {
496  fromEdge = revertID(fromEdge);
497  }
498  if (toLane == UNSET_CONNECTION) {
499  toLane = toLast ? odTo->laneSections.back().laneMap.begin()->first : odTo->laneSections[0].laneMap.begin()->first;
500  }
501  if (toLane < 0) {
502  toEdge = revertID(toEdge);
503  }
504  fromLane = fromLast ? odFrom->laneSections.back().laneMap[fromLane] : odFrom->laneSections[0].laneMap[fromLane];
505  toLane = toLast ? odTo->laneSections.back().laneMap[toLane] : odTo->laneSections[0].laneMap[toLane];
506  NBEdge* from = nb.getEdgeCont().retrieve(fromEdge);
507  NBEdge* to = nb.getEdgeCont().retrieve(toEdge);
508  if (from == 0) {
509  WRITE_WARNING("Could not find fromEdge representation of '" + fromEdge + "' in connection '" + (*i).origID + "'.");
510  }
511  if (to == 0) {
512  WRITE_WARNING("Could not find fromEdge representation of '" + toEdge + "' in connection '" + (*i).origID + "'.");
513  }
514  if (from == 0 || to == 0) {
515  continue;
516  }
517 
518  from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER);
519 
520  if ((*i).origID != "") {
521  // @todo: this is the most silly way to determine the connection
522  std::vector<NBEdge::Connection>& cons = from->getConnections();
523  for (std::vector<NBEdge::Connection>::iterator k = cons.begin(); k != cons.end(); ++k) {
524  if ((*k).fromLane == fromLane && (*k).toEdge == to && (*k).toLane == toLane) {
525  (*k).origID = (*i).origID + " " + toString((*i).origLane);
526  break;
527  }
528  }
529  }
530  }
531 
532 
533  // -------------------------
534  // traffic lights
535  // -------------------------
536  std::map<std::string, std::string> tlsControlled;
537  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
538  OpenDriveEdge* e = (*i).second;
539  for (std::vector<OpenDriveSignal>::const_iterator j = e->signals.begin(); j != e->signals.end(); ++j) {
540  if ((*j).type != "1000001") {
541  continue;
542  }
543  std::vector<OpenDriveLaneSection>::iterator k = e->laneSections.begin();
544  bool found = false;
545  for (; k != e->laneSections.end() - 1 && !found;) {
546  if ((*j).s > (*k).s && (*j).s <= (*(k + 1)).s) {
547  found = true;
548  } else {
549  ++k;
550  }
551  }
552 
553  // @todo: major problem, currently, still not completely solved:
554  // inner edges may have traffic lights, too. Nice on one hand, as directions can be recognized
555  // but hard to follow backwards
556  std::string id = (*k).sumoID;
557  if (id == "") {
558  if (e->junction != "") {
559  //WRITE_WARNING("Found a traffic light signal on an internal edge; will not build it (original edge id='" + e->id + "').");
560  std::string fromID, toID;
561  for (std::vector<OpenDriveLink>::const_iterator l = e->links.begin(); l != e->links.end(); ++l) {
562  if ((*l).linkType == OPENDRIVE_LT_PREDECESSOR && (*l).elementType == OPENDRIVE_ET_ROAD) {
563  if (fromID != "") {
564  WRITE_WARNING("Ambigous start of connection.");
565  }
566  fromID = (*l).elementID;
567  OpenDriveEdge* e = edges[fromID];
568  fromID = (*l).contactPoint == OPENDRIVE_CP_START ? e->laneSections[0].sumoID : e->laneSections.back().sumoID;
569  }
570  if ((*l).linkType == OPENDRIVE_LT_SUCCESSOR && (*l).elementType == OPENDRIVE_ET_ROAD) {
571  if (toID != "") {
572  WRITE_WARNING("Ambigous end of connection.");
573  }
574  toID = (*l).elementID;
575  OpenDriveEdge* e = edges[toID];
576  toID = (*l).contactPoint == OPENDRIVE_CP_START ? e->laneSections[0].sumoID : e->laneSections.back().sumoID;
577  }
578  }
579  id = fromID + "->" + toID;
580  } else {
581  WRITE_WARNING("Found a traffic light signal on an unknown edge (original edge id='" + e->id + "').");
582  continue;
583  }
584  }
585 
586  if ((*j).orientation > 0) {
587  id = "-" + id;
588  }
589  tlsControlled[id] = (*j).name;
590  }
591  }
592 
593  for (std::map<std::string, std::string>::iterator i = tlsControlled.begin(); i != tlsControlled.end(); ++i) {
594  std::string id = (*i).first;
595  if (id.find("->") != std::string::npos) {
596  id = id.substr(0, id.find("->"));
597  }
598  NBEdge* e = nb.getEdgeCont().retrieve(id);
599  if (e == 0) {
600  WRITE_WARNING("Could not find edge '" + id + "' while building its traffic light.");
601  continue;
602  }
603  NBNode* toNode = e->getToNode();
604  NBTrafficLightDefinition* tlDef = 0;
605  if (!toNode->isTLControlled()) {
607  tlDef = new NBOwnTLDef(toNode->getID(), toNode, 0, type);
608  if (!nb.getTLLogicCont().insert(tlDef)) {
609  // actually, nothing should fail here
610  delete tlDef;
611  throw ProcessError();
612  }
613  toNode->addTrafficLight(tlDef);
614  static_cast<NBOwnTLDef*>(tlDef)->setSinglePhase();
615  }
616  tlDef = *toNode->getControllingTLS().begin();
617  tlDef->addParameter("connection:" + id, (*i).second);
618  }
619 
620  // -------------------------
621  // clean up
622  // -------------------------
623  if (oc.exists("geometry.min-dist") && oc.isSet("geometry.min-dist")) {
624  oc.unSet("geometry.min-dist");
625  }
626  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
627  delete(*i).second;
628  }
629 }
630 
631 
632 
633 void
634 NIImporter_OpenDrive::buildConnectionsToOuter(const Connection& c, const std::map<std::string, OpenDriveEdge*>& innerEdges, std::vector<Connection>& into) {
635 
636  OpenDriveEdge* dest = innerEdges.find(c.toEdge)->second;
637  if (dest == 0) {
639  return;
640  }
641  const std::set<Connection>& conts = dest->connections;
642  for (std::set<Connection>::const_iterator i = conts.begin(); i != conts.end(); ++i) {
643  if (innerEdges.find((*i).toEdge) != innerEdges.end()) {
644  std::vector<Connection> t;
645  buildConnectionsToOuter(*i, innerEdges, t);
646  for (std::vector<Connection>::const_iterator j = t.begin(); j != t.end(); ++j) {
647  // @todo this section is unverified
648  Connection cn = (*j);
649  cn.fromEdge = c.fromEdge;
650  cn.fromLane = c.fromLane;
651  cn.fromCP = c.fromCP;
652  cn.all = c.all; // @todo "all" is a hack trying to avoid the "from is zero" problem;
653  into.push_back(cn);
654  }
655  } else {
656  if ((*i).fromLane == c.toLane) {
657  Connection cn = (*i);
658  cn.fromEdge = c.fromEdge;
659  cn.fromLane = c.fromLane;
660  cn.fromCP = c.fromCP;
661  cn.all = c.all;
662  cn.origID = c.toEdge;
663  cn.origLane = c.toLane;
664  into.push_back(cn);
665  }
666  }
667  }
668 }
669 
670 
671 void
672 NIImporter_OpenDrive::setEdgeLinks2(OpenDriveEdge& e, const std::map<std::string, OpenDriveEdge*>& edges) {
673  for (std::vector<OpenDriveLink>::iterator i = e.links.begin(); i != e.links.end(); ++i) {
674  OpenDriveLink& l = *i;
675  if (l.elementType != OPENDRIVE_ET_ROAD) {
676  // we assume that links to nodes are later given as connections to edges
677  continue;
678  }
679  // get the right direction of the connected edge
680  std::string connectedEdge = l.elementID;
681  std::string edgeID = e.id;
682 
683  OpenDriveLaneSection& laneSection = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e.laneSections.back() : e.laneSections[0];
684  const std::map<int, int>& laneMap = laneSection.laneMap;
685  if (laneSection.lanesByDir.find(OPENDRIVE_TAG_RIGHT) != laneSection.lanesByDir.end()) {
686  const std::vector<OpenDriveLane>& lanes = laneSection.lanesByDir.find(OPENDRIVE_TAG_RIGHT)->second;
687  for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
688  if (!myImportAllTypes && laneMap.find((*j).id) == laneMap.end()) {
689  continue;
690  }
691  Connection c; // @todo: give Connection a new name and a constructor
692  c.fromEdge = e.id;
693  c.fromLane = (*j).id;
695  c.toLane = l.linkType == OPENDRIVE_LT_SUCCESSOR ? (*j).successor : (*j).predecessor;
696  c.toEdge = connectedEdge;
697  c.toCP = l.contactPoint;
698  c.all = false;
699  if (l.linkType != OPENDRIVE_LT_SUCCESSOR) {
700  std::swap(c.fromEdge, c.toEdge);
701  std::swap(c.fromLane, c.toLane);
702  std::swap(c.fromCP, c.toCP);
703  }
704  if (edges.find(c.fromEdge) == edges.end()) {
705  WRITE_ERROR("While setting connections: incoming road '" + c.fromEdge + "' is not known.");
706  } else {
707  OpenDriveEdge* src = edges.find(c.fromEdge)->second;
708  src->connections.insert(c);
709  }
710  }
711  }
712  if (laneSection.lanesByDir.find(OPENDRIVE_TAG_LEFT) != laneSection.lanesByDir.end()) {
713  const std::vector<OpenDriveLane>& lanes = laneSection.lanesByDir.find(OPENDRIVE_TAG_LEFT)->second;
714  for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
715  if (!myImportAllTypes && laneMap.find((*j).id) == laneMap.end()) {
716  continue;
717  }
718  Connection c;
719  c.toEdge = e.id;
720  c.toLane = (*j).id;
722  c.fromLane = l.linkType == OPENDRIVE_LT_SUCCESSOR ? (*j).successor : (*j).predecessor;
723  c.fromEdge = connectedEdge;
724  c.fromCP = l.contactPoint;
725  c.all = false;
726  if (l.linkType != OPENDRIVE_LT_SUCCESSOR) {
727  std::swap(c.fromEdge, c.toEdge);
728  std::swap(c.fromLane, c.toLane);
729  std::swap(c.fromCP, c.toCP);
730  }
731  if (edges.find(c.fromEdge) == edges.end()) {
732  WRITE_ERROR("While setting connections: incoming road '" + c.fromEdge + "' is not known.");
733  } else {
734  OpenDriveEdge* src = edges.find(c.fromEdge)->second;
735  src->connections.insert(c);
736  }
737  }
738  }
739  }
740 }
741 
742 
743 std::string NIImporter_OpenDrive::revertID(const std::string& id) {
744  if (id[0] == '-') {
745  return id.substr(1);
746  }
747  return "-" + id;
748 }
749 
750 NBNode*
751 NIImporter_OpenDrive::getOrBuildNode(const std::string& id, const Position& pos,
752  NBNodeCont& nc) {
753  if (nc.retrieve(id) == 0) {
754  // not yet built; build now
755  if (!nc.insert(id, pos)) {
756  // !!! clean up
757  throw ProcessError("Could not add node '" + id + "'.");
758  }
759  }
760  return nc.retrieve(id);
761 }
762 
763 
764 void
766  const std::string& nodeID, NIImporter_OpenDrive::LinkType lt) {
767  NBNode* n = nc.retrieve(nodeID);
768  if (n == 0) {
769  throw ProcessError("Could not find node '" + nodeID + "'.");
770  }
771  if (lt == OPENDRIVE_LT_SUCCESSOR) {
772  if (e.to != 0 && e.to != n) {
773  throw ProcessError("Edge '" + e.id + "' has two end nodes.");
774  }
775  e.to = n;
776  } else {
777  if (e.from != 0 && e.from != n) {
778  throw ProcessError("Edge '" + e.id + "' has two start nodes.");
779  }
780  e.from = n;
781  }
782 }
783 
784 
785 
786 
787 
788 
789 
790 void
791 NIImporter_OpenDrive::computeShapes(std::map<std::string, OpenDriveEdge*>& edges) {
793  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
794  OpenDriveEdge& e = *(*i).second;
795  for (std::vector<OpenDriveGeometry>::iterator j = e.geometries.begin(); j != e.geometries.end(); ++j) {
796  OpenDriveGeometry& g = *j;
797  std::vector<Position> geom;
798  switch (g.type) {
800  break;
801  case OPENDRIVE_GT_LINE:
802  geom = geomFromLine(e, g);
803  break;
804  case OPENDRIVE_GT_SPIRAL:
805  geom = geomFromSpiral(e, g);
806  break;
807  case OPENDRIVE_GT_ARC:
808  geom = geomFromArc(e, g);
809  break;
810  case OPENDRIVE_GT_POLY3:
811  geom = geomFromPoly(e, g);
812  break;
813  default:
814  break;
815  }
816  for (std::vector<Position>::iterator k = geom.begin(); k != geom.end(); ++k) {
818  }
819  }
820  if (oc.exists("geometry.min-dist") && oc.isSet("geometry.min-dist")) {
821  e.geom.removeDoublePoints(oc.getFloat("geometry.min-dist"), true);
822  }
823  for (unsigned int j = 0; j < e.geom.size(); ++j) {
825  WRITE_ERROR("Unable to project coordinates for.");
826  }
827  }
828  }
829 }
830 
831 
832 void
833 NIImporter_OpenDrive::revisitLaneSections(const NBTypeCont& tc, std::map<std::string, OpenDriveEdge*>& edges) {
834  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
835  OpenDriveEdge& e = *(*i).second;
836  std::vector<OpenDriveLaneSection>& laneSections = e.laneSections;
837  // split by speed limits
838  std::vector<OpenDriveLaneSection> newSections;
839  for (std::vector<OpenDriveLaneSection>::iterator j = laneSections.begin(); j != laneSections.end(); ++j) {
840  std::vector<OpenDriveLaneSection> splitSections;
841  bool splitBySpeed = (*j).buildSpeedChanges(tc, splitSections);
842  if (!splitBySpeed) {
843  newSections.push_back(*j);
844  } else {
845  std::copy(splitSections.begin(), splitSections.end(), back_inserter(newSections));
846  }
847  }
848 
849  e.laneSections = newSections;
850  laneSections = e.laneSections;
851  SUMOReal lastS = -1;
852  // check whether the lane sections are in the right order
853  bool sorted = true;
854  for (std::vector<OpenDriveLaneSection>::const_iterator j = laneSections.begin(); j != laneSections.end() && sorted; ++j) {
855  if ((*j).s <= lastS) {
856  sorted = false;
857  }
858  lastS = (*j).s;
859  }
860  if (!sorted) {
861  WRITE_WARNING("The sections of edge '" + e.id + "' are not sorted properly.");
862  sort(e.laneSections.begin(), e.laneSections.end(), sections_by_s_sorter());
863  }
864  // check whether no duplicates of s-value occure
865  lastS = -1;
866  laneSections = e.laneSections;
867  for (std::vector<OpenDriveLaneSection>::iterator j = laneSections.begin(); j != laneSections.end();) {
868  bool simlarToLast = fabs((*j).s - lastS) < POSITION_EPS;
869  lastS = (*j).s;
870  if (simlarToLast) {
871  WRITE_WARNING("Almost duplicate s-value '" + toString(lastS) + "' for lane sections occured at edge '" + e.id + "'; second entry was removed.");
872  j = laneSections.erase(j);
873  } else {
874  ++j;
875  }
876  }
877  }
878 }
879 
880 
881 std::vector<Position>
883  UNUSED_PARAMETER(e);
884  std::vector<Position> ret;
885  ret.push_back(Position(g.x, g.y));
886  ret.push_back(calculateStraightEndPoint(g.hdg, g.length, Position(g.x, g.y)));
887  return ret;
888 }
889 
890 
891 std::vector<Position>
893  UNUSED_PARAMETER(e);
894  std::vector<Position> ret;
895  SUMOReal curveStart = g.params[0];
896  SUMOReal curveEnd = g.params[1];
897  Point2D<double> end;
898  EulerSpiral s(Point2D<double>(g.x, g.y), g.hdg, curveStart, (curveEnd - curveStart) / g.length, g.length);
899  std::vector<Point2D<double> > into;
900  s.computeSpiral(into, 1.);
901  for (std::vector<Point2D<double> >::iterator i = into.begin(); i != into.end(); ++i) {
902  ret.push_back(Position((*i).getX(), (*i).getY()));
903  }
904  return ret;
905 }
906 
907 
908 std::vector<Position>
910  UNUSED_PARAMETER(e);
911  std::vector<Position> ret;
912  SUMOReal dist = 0.0;
913  SUMOReal centerX = g.x;
914  SUMOReal centerY = g.y;
915  // left: positive value
916  SUMOReal curvature = g.params[0];
917  SUMOReal radius = 1. / curvature;
918  // center point
919  calculateCurveCenter(&centerX, &centerY, radius, g.hdg);
920  SUMOReal endX = g.x;
921  SUMOReal endY = g.y;
922  SUMOReal startX = g.x;
923  SUMOReal startY = g.y;
924  SUMOReal geo_posS = g.s;
925  SUMOReal geo_posE = g.s;
926  bool end = false;
927  do {
928  geo_posE += C_LENGTH;
929  if (geo_posE - g.s > g.length) {
930  geo_posE = g.s + g.length;
931  }
932  if (geo_posE - g.s > g.length) {
933  geo_posE = g.s + g.length;
934  }
935  calcPointOnCurve(&endX, &endY, centerX, centerY, radius, geo_posE - geo_posS);
936 
937  dist += (geo_posE - geo_posS);
938  //
939  ret.push_back(Position(startX, startY));
940  //
941  startX = endX;
942  startY = endY;
943  geo_posS = geo_posE;
944 
945  if (geo_posE - (g.s + g.length) < 0.001 && geo_posE - (g.s + g.length) > -0.001) {
946  end = true;
947  }
948  } while (!end);
949  return ret;
950 }
951 
952 
953 std::vector<Position>
955  UNUSED_PARAMETER(e);
956  std::vector<Position> ret;
957  for (SUMOReal off = 0; off < g.length + 2.; off += 2.) {
958  SUMOReal x = off;
959  SUMOReal y = g.params[0] + g.params[1] * off + g.params[2] * pow(off, 2.) + g.params[3] * pow(off, 3.);
960  SUMOReal s = sin(g.hdg);
961  SUMOReal c = cos(g.hdg);
962  SUMOReal xnew = x * c - y * s;
963  SUMOReal ynew = x * s + y * c;
964  ret.push_back(Position(g.x + xnew, g.y + ynew));
965  }
966  return ret;
967 }
968 
969 
970 Position
971 NIImporter_OpenDrive::calculateStraightEndPoint(double hdg, double length, const Position& start) {
972  double normx = 1.0f;
973  double normy = 0.0f;
974  double x2 = normx * cos(hdg) - normy * sin(hdg);
975  double y2 = normx * sin(hdg) + normy * cos(hdg);
976  normx = x2 * length;
977  normy = y2 * length;
978  return Position(start.x() + normx, start.y() + normy);
979 }
980 
981 
982 void
984  SUMOReal normX = 1.0;
985  SUMOReal normY = 0.0;
986  SUMOReal tmpX;
987  SUMOReal turn;
988  if (ad_radius > 0) {
989  turn = -1.0;
990  } else {
991  turn = 1.0;
992  }
993 
994  tmpX = normX;
995  normX = normX * cos(ad_hdg) + normY * sin(ad_hdg);
996  normY = tmpX * sin(ad_hdg) + normY * cos(ad_hdg);
997 
998  tmpX = normX;
999  normX = turn * normY;
1000  normY = -turn * tmpX;
1001 
1002  normX = fabs(ad_radius) * normX;
1003  normY = fabs(ad_radius) * normY;
1004 
1005  *ad_x += normX;
1006  *ad_y += normY;
1007 }
1008 
1009 
1010 void
1012  SUMOReal ad_r, SUMOReal ad_length) {
1013  double rotAngle = ad_length / fabs(ad_r);
1014  double vx = *ad_x - ad_centerX;
1015  double vy = *ad_y - ad_centerY;
1016  double tmpx;
1017 
1018  double turn;
1019  if (ad_r > 0) {
1020  turn = -1; //left
1021  } else {
1022  turn = 1; //right
1023  }
1024  tmpx = vx;
1025  vx = vx * cos(rotAngle) + turn * vy * sin(rotAngle);
1026  vy = -1 * turn * tmpx * sin(rotAngle) + vy * cos(rotAngle);
1027  *ad_x = vx + ad_centerX;
1028  *ad_y = vy + ad_centerY;
1029 }
1030 
1031 
1032 // ---------------------------------------------------------------------------
1033 // section
1034 // ---------------------------------------------------------------------------
1036  lanesByDir[OPENDRIVE_TAG_LEFT] = std::vector<OpenDriveLane>();
1037  lanesByDir[OPENDRIVE_TAG_RIGHT] = std::vector<OpenDriveLane>();
1038  lanesByDir[OPENDRIVE_TAG_CENTER] = std::vector<OpenDriveLane>();
1039 }
1040 
1041 
1042 void
1044  unsigned int sumoLane = 0;
1045  const std::vector<OpenDriveLane>& dirLanesR = lanesByDir.find(OPENDRIVE_TAG_RIGHT)->second;
1046  for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanesR.rbegin(); i != dirLanesR.rend(); ++i) {
1047  if (myImportAllTypes || (tc.knows((*i).type) && !tc.getShallBeDiscarded((*i).type))) {
1048  laneMap[(*i).id] = sumoLane++;
1049  }
1050  }
1051  rightLaneNumber = sumoLane;
1052  sumoLane = 0;
1053  const std::vector<OpenDriveLane>& dirLanesL = lanesByDir.find(OPENDRIVE_TAG_LEFT)->second;
1054  for (std::vector<OpenDriveLane>::const_iterator i = dirLanesL.begin(); i != dirLanesL.end(); ++i) {
1055  if (myImportAllTypes || (tc.knows((*i).type) && !tc.getShallBeDiscarded((*i).type))) {
1056  laneMap[(*i).id] = sumoLane++;
1057  }
1058  }
1059  leftLaneNumber = sumoLane;
1060 }
1061 
1062 
1063 std::map<int, int>
1065  std::map<int, int> ret;
1066  const std::vector<OpenDriveLane>& dirLanes = lanesByDir.find(dir)->second;
1067  for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanes.rbegin(); i != dirLanes.rend(); ++i) {
1068  std::map<int, int>::const_iterator toP = laneMap.find((*i).id);
1069  if (toP == laneMap.end()) {
1070  // the current lane is not available in SUMO
1071  continue;
1072  }
1073  int to = (*toP).second;
1074  int from = UNSET_CONNECTION;
1075  if ((*i).predecessor != UNSET_CONNECTION) {
1076  from = (*i).predecessor;
1077  }
1078  if (from != UNSET_CONNECTION) {
1079  std::map<int, int>::const_iterator fromP = prev.laneMap.find(from);
1080  if (fromP != prev.laneMap.end()) {
1081  from = (*fromP).second;
1082  } else {
1083  from = UNSET_CONNECTION;
1084  }
1085  }
1086  if (from != UNSET_CONNECTION && to != UNSET_CONNECTION) {
1087  if (ret.find(from) != ret.end()) {
1088 // WRITE_WARNING("double connection");
1089  }
1090  if (dir == OPENDRIVE_TAG_LEFT) {
1091  std::swap(from, to);
1092  }
1093  ret[from] = to;
1094  } else {
1095 // WRITE_WARNING("missing connection");
1096  }
1097  }
1098  return ret;
1099 }
1100 
1101 
1104  OpenDriveLaneSection ret(*this);
1105  ret.s += startPos;
1106  for (unsigned int k = 0; k != ret.lanesByDir[OPENDRIVE_TAG_RIGHT].size(); ++k) {
1108  l.speed = 0;
1109  std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator i = std::find_if(l.speeds.begin(), l.speeds.end(), same_position_finder(startPos));
1110  if (i != l.speeds.end()) {
1111  l.speed = (*i).second;
1112  }
1113  }
1114  for (unsigned int k = 0; k != ret.lanesByDir[OPENDRIVE_TAG_LEFT].size(); ++k) {
1116  std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator i = std::find_if(l.speeds.begin(), l.speeds.end(), same_position_finder(startPos));
1117  l.speed = 0;
1118  if (i != l.speeds.end()) {
1119  l.speed = (*i).second;
1120  }
1121  }
1122  return ret;
1123 }
1124 
1125 
1126 bool
1127 NIImporter_OpenDrive::OpenDriveLaneSection::buildSpeedChanges(const NBTypeCont& tc, std::vector<OpenDriveLaneSection>& newSections) {
1128  std::set<SUMOReal> speedChangePositions;
1129  // collect speed change positions and apply initial speed to the begin
1130  for (std::vector<OpenDriveLane>::iterator k = lanesByDir[OPENDRIVE_TAG_RIGHT].begin(); k != lanesByDir[OPENDRIVE_TAG_RIGHT].end(); ++k) {
1131  for (std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator l = (*k).speeds.begin(); l != (*k).speeds.end(); ++l) {
1132  speedChangePositions.insert((*l).first);
1133  if ((*l).first == 0) {
1134  (*k).speed = (*l).second;
1135  }
1136  }
1137  }
1138  for (std::vector<OpenDriveLane>::iterator k = lanesByDir[OPENDRIVE_TAG_LEFT].begin(); k != lanesByDir[OPENDRIVE_TAG_LEFT].end(); ++k) {
1139  for (std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator l = (*k).speeds.begin(); l != (*k).speeds.end(); ++l) {
1140  speedChangePositions.insert((*l).first);
1141  if ((*l).first == 0) {
1142  (*k).speed = (*l).second;
1143  }
1144  }
1145  }
1146  // do nothing if there is none
1147  if (speedChangePositions.size() == 0) {
1148  return false;
1149  }
1150  if (*speedChangePositions.begin() > 0) {
1151  speedChangePositions.insert(0);
1152  }
1153  //
1154  for (std::set<SUMOReal>::iterator i = speedChangePositions.begin(); i != speedChangePositions.end(); ++i) {
1155  if (i == speedChangePositions.begin()) {
1156  newSections.push_back(*this);
1157  } else {
1158  newSections.push_back(buildLaneSection(*i));
1159  }
1160  }
1161  // propagate speeds
1162  for (int i = 0; i != (int)newSections.size(); ++i) {
1163  OpenDriveLaneSection& ls = newSections[i];
1164  std::map<OpenDriveXMLTag, std::vector<OpenDriveLane> >& lanesByDir = ls.lanesByDir;
1165  for (std::map<OpenDriveXMLTag, std::vector<OpenDriveLane> >::iterator k = lanesByDir.begin(); k != lanesByDir.end(); ++k) {
1166  std::vector<OpenDriveLane>& lanes = (*k).second;
1167  for (int j = 0; j != (int)lanes.size(); ++j) {
1168  OpenDriveLane& l = lanes[j];
1169  if (l.speed != 0) {
1170  continue;
1171  }
1172  if (i > 0) {
1173  l.speed = newSections[i - 1].lanesByDir[(*k).first][j].speed;
1174  } else {
1175  tc.getSpeed(l.type);
1176  }
1177  }
1178  }
1179  }
1180  return true;
1181 }
1182 
1183 
1184 
1185 // ---------------------------------------------------------------------------
1186 // edge
1187 // ---------------------------------------------------------------------------
1188 int
1190  int prio = 1;
1191  for (std::vector<OpenDriveSignal>::const_iterator i = signals.begin(); i != signals.end(); ++i) {
1192  int tmp = 1;
1193  if ((*i).type == "301" || (*i).type == "306") {
1194  tmp = 2;
1195  }
1196  if ((*i).type == "205") {
1197  tmp = 0;
1198  }
1199  if (tmp != 1 && dir == OPENDRIVE_TAG_RIGHT && (*i).orientation > 0) {
1200  prio = tmp;
1201  }
1202  if (tmp != 1 && dir == OPENDRIVE_TAG_LEFT && (*i).orientation < 0) {
1203  prio = tmp;
1204  }
1205 
1206  }
1207  return prio;
1208 }
1209 
1210 
1211 
1212 // ---------------------------------------------------------------------------
1213 // loader methods
1214 // ---------------------------------------------------------------------------
1215 NIImporter_OpenDrive::NIImporter_OpenDrive(const NBTypeCont& tc, std::map<std::string, OpenDriveEdge*>& edges)
1217  myTypeContainer(tc), myCurrentEdge("", "", -1), myEdges(edges) {
1218 }
1219 
1220 
1222 }
1223 
1224 
1225 void
1227  const SUMOSAXAttributes& attrs) {
1228  bool ok = true;
1229  switch (element) {
1230  case OPENDRIVE_TAG_HEADER: {
1231  int majorVersion = attrs.get<int>(OPENDRIVE_ATTR_REVMAJOR, 0, ok);
1232  int minorVersion = attrs.get<int>(OPENDRIVE_ATTR_REVMINOR, 0, ok);
1233  if (majorVersion != 1 || minorVersion != 2) {
1234  WRITE_WARNING("Given openDrive file '" + getFileName() + "' uses version " + toString(majorVersion) + "." + toString(minorVersion) + ";\n Version 1.2 is supported.");
1235  }
1236  }
1237  break;
1238  case OPENDRIVE_TAG_ROAD: {
1239  std::string id = attrs.get<std::string>(OPENDRIVE_ATTR_ID, 0, ok);
1240  std::string junction = attrs.get<std::string>(OPENDRIVE_ATTR_JUNCTION, id.c_str(), ok);
1241  SUMOReal length = attrs.get<SUMOReal>(OPENDRIVE_ATTR_LENGTH, id.c_str(), ok);
1242  myCurrentEdge = OpenDriveEdge(id, junction, length);
1243  }
1244  break;
1246  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
1247  std::string elementType = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
1248  std::string elementID = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
1249  std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
1250  ? attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok)
1251  : "end";
1252  addLink(OPENDRIVE_LT_PREDECESSOR, elementType, elementID, contactPoint);
1253  }
1254  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
1255  int no = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1256  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1257  l.predecessor = no;
1258  }
1259  }
1260  break;
1261  case OPENDRIVE_TAG_SUCCESSOR: {
1262  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
1263  std::string elementType = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
1264  std::string elementID = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
1265  std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
1266  ? attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok)
1267  : "start";
1268  addLink(OPENDRIVE_LT_SUCCESSOR, elementType, elementID, contactPoint);
1269  }
1270  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
1271  int no = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1272  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1273  l.successor = no;
1274  }
1275  }
1276  break;
1277  case OPENDRIVE_TAG_GEOMETRY: {
1278  SUMOReal length = attrs.get<SUMOReal>(OPENDRIVE_ATTR_LENGTH, myCurrentEdge.id.c_str(), ok);
1279  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1280  SUMOReal x = attrs.get<SUMOReal>(OPENDRIVE_ATTR_X, myCurrentEdge.id.c_str(), ok);
1281  SUMOReal y = attrs.get<SUMOReal>(OPENDRIVE_ATTR_Y, myCurrentEdge.id.c_str(), ok);
1282  SUMOReal hdg = attrs.get<SUMOReal>(OPENDRIVE_ATTR_HDG, myCurrentEdge.id.c_str(), ok);
1283  myCurrentEdge.geometries.push_back(OpenDriveGeometry(length, s, x, y, hdg));
1284  }
1285  break;
1286  case OPENDRIVE_TAG_LINE: {
1287  std::vector<SUMOReal> vals;
1289  }
1290  break;
1291  case OPENDRIVE_TAG_SPIRAL: {
1292  std::vector<SUMOReal> vals;
1293  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVSTART, myCurrentEdge.id.c_str(), ok));
1294  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVEND, myCurrentEdge.id.c_str(), ok));
1296  }
1297  break;
1298  case OPENDRIVE_TAG_ARC: {
1299  std::vector<SUMOReal> vals;
1300  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVATURE, myCurrentEdge.id.c_str(), ok));
1302  }
1303  break;
1304  case OPENDRIVE_TAG_POLY3: {
1305  std::vector<SUMOReal> vals;
1306  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok));
1307  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_B, myCurrentEdge.id.c_str(), ok));
1308  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_C, myCurrentEdge.id.c_str(), ok));
1309  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_D, myCurrentEdge.id.c_str(), ok));
1311  }
1312  break;
1314  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1316  }
1317  break;
1318  case OPENDRIVE_TAG_LEFT:
1320  break;
1321  case OPENDRIVE_TAG_CENTER:
1323  break;
1324  case OPENDRIVE_TAG_RIGHT:
1326  break;
1327  case OPENDRIVE_TAG_LANE: {
1328  std::string type = attrs.get<std::string>(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
1329  int id = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1330  std::string level = attrs.hasAttribute(OPENDRIVE_ATTR_LEVEL)
1331  ? attrs.get<std::string>(OPENDRIVE_ATTR_LEVEL, myCurrentEdge.id.c_str(), ok)
1332  : "";
1334  ls.lanesByDir[myCurrentLaneDirection].push_back(OpenDriveLane(id, level, type));
1335  }
1336  break;
1337  case OPENDRIVE_TAG_SIGNAL: {
1338  int id = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1339  std::string type = attrs.get<std::string>(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
1340  std::string name = attrs.getOpt<std::string>(OPENDRIVE_ATTR_NAME, myCurrentEdge.id.c_str(), ok, "", false);
1341  int orientation = attrs.get<std::string>(OPENDRIVE_ATTR_ORIENTATION, myCurrentEdge.id.c_str(), ok) == "-" ? -1 : 1;
1342  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1343  bool dynamic = attrs.get<std::string>(OPENDRIVE_ATTR_DYNAMIC, myCurrentEdge.id.c_str(), ok) == "no" ? false : true;
1344  myCurrentEdge.signals.push_back(OpenDriveSignal(id, type, name, orientation, dynamic, s));
1345  }
1346  break;
1348  myCurrentJunctionID = attrs.get<std::string>(OPENDRIVE_ATTR_ID, myCurrentJunctionID.c_str(), ok);
1349  break;
1350  case OPENDRIVE_TAG_CONNECTION: {
1351  std::string id = attrs.get<std::string>(OPENDRIVE_ATTR_ID, myCurrentJunctionID.c_str(), ok);
1352  myCurrentIncomingRoad = attrs.get<std::string>(OPENDRIVE_ATTR_INCOMINGROAD, myCurrentJunctionID.c_str(), ok);
1354  std::string cp = attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentJunctionID.c_str(), ok);
1356  myConnectionWasEmpty = true;
1357  }
1358  break;
1359  case OPENDRIVE_TAG_LANELINK: {
1360  int from = attrs.get<int>(OPENDRIVE_ATTR_FROM, myCurrentJunctionID.c_str(), ok);
1361  int to = attrs.get<int>(OPENDRIVE_ATTR_TO, myCurrentJunctionID.c_str(), ok);
1362  Connection c;
1364  c.toEdge = myCurrentConnectingRoad;
1365  c.fromLane = from;
1366  c.toLane = to;
1367  c.fromCP = OPENDRIVE_CP_END;
1368  c.toCP = myCurrentContactPoint;
1369  c.all = false;
1370  if (myEdges.find(c.fromEdge) == myEdges.end()) {
1371  WRITE_ERROR("In laneLink-element: incoming road '" + c.fromEdge + "' is not known.");
1372  } else {
1373  OpenDriveEdge* e = myEdges.find(c.fromEdge)->second;
1374  e->connections.insert(c);
1375  myConnectionWasEmpty = false;
1376  }
1377  }
1378  break;
1379  case OPENDRIVE_TAG_WIDTH: {
1380  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 1] == OPENDRIVE_TAG_LANE) {
1381  SUMOReal width = attrs.get<SUMOReal>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok);
1382  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1383  l.width = MAX2(l.width, width);
1384  }
1385  }
1386  break;
1387  case OPENDRIVE_TAG_SPEED: {
1388  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 1] == OPENDRIVE_TAG_LANE) {
1389  SUMOReal speed = attrs.get<SUMOReal>(OPENDRIVE_ATTR_MAX, myCurrentEdge.id.c_str(), ok);
1390  SUMOReal pos = attrs.get<SUMOReal>(OPENDRIVE_ATTR_SOFFSET, myCurrentEdge.id.c_str(), ok);
1391  myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back().speeds.push_back(std::make_pair(pos, speed));
1392  }
1393  }
1394  break;
1395  default:
1396  break;
1397  }
1398  myElementStack.push_back(element);
1399 }
1400 
1401 
1402 void
1404  myElementStack.pop_back();
1405  switch (element) {
1406  case OPENDRIVE_TAG_ROAD:
1408  break;
1410  if (myConnectionWasEmpty) {
1411  Connection c;
1414  c.fromLane = 0;
1415  c.toLane = 0;
1418  c.all = true;
1419  if (myEdges.find(c.fromEdge) == myEdges.end()) {
1420  WRITE_ERROR("In laneLink-element: incoming road '" + c.fromEdge + "' is not known.");
1421  } else {
1422  OpenDriveEdge* e = myEdges.find(c.fromEdge)->second;
1423  e->connections.insert(c);
1424  }
1425  }
1426  break;
1428  myCurrentEdge.laneSections.back().buildLaneMapping(myTypeContainer);
1429  }
1430  break;
1431  default:
1432  break;
1433  }
1434 }
1435 
1436 
1437 
1438 void
1439 NIImporter_OpenDrive::addLink(LinkType lt, const std::string& elementType,
1440  const std::string& elementID,
1441  const std::string& contactPoint) {
1442  OpenDriveLink l(lt, elementID);
1443  // elementType
1444  if (elementType == "road") {
1446  } else if (elementType == "junction") {
1448  }
1449  // contact point
1450  if (contactPoint == "start") {
1452  } else if (contactPoint == "end") {
1454  }
1455  // add
1456  myCurrentEdge.links.push_back(l);
1457 }
1458 
1459 
1460 void
1461 NIImporter_OpenDrive::addGeometryShape(GeometryType type, const std::vector<SUMOReal>& vals) {
1462  // checks
1463  if (myCurrentEdge.geometries.size() == 0) {
1464  throw ProcessError("Mismatching paranthesis in geometry definition for road '" + myCurrentEdge.id + "'");
1465  }
1467  if (last.type != OPENDRIVE_GT_UNKNOWN) {
1468  throw ProcessError("Double geometry information for road '" + myCurrentEdge.id + "'");
1469  }
1470  // set
1471  last.type = type;
1472  last.params = vals;
1473 }
1474 
1475 
1476 bool
1478  if (c1.fromEdge != c2.fromEdge) {
1479  return c1.fromEdge < c2.fromEdge;
1480  }
1481  if (c1.toEdge != c2.toEdge) {
1482  return c1.toEdge < c2.toEdge;
1483  }
1484  if (c1.fromLane != c2.fromLane) {
1485  return c1.fromLane < c2.fromLane;
1486  }
1487  return c1.toLane < c2.toLane;
1488 }
1489 
1490 
1491 
1492 /****************************************************************************/
1493