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