SUMO - Simulation of Urban MObility
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.dlr.de/
13 // Copyright (C) 2001-2016 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 // static variables
72 // ===========================================================================
96 
98 };
99 
100 
141 
143 };
144 
145 
148 
149 // ===========================================================================
150 // method definitions
151 // ===========================================================================
152 // ---------------------------------------------------------------------------
153 // static methods (interface in this case)
154 // ---------------------------------------------------------------------------
155 void
157  // check whether the option is set (properly)
158  if (!oc.isUsableFileList("opendrive-files")) {
159  return;
160  }
161  // prepare types
162  myImportAllTypes = oc.getBool("opendrive.import-all-lanes");
163  myImportWidths = !oc.getBool("opendrive.ignore-widths");
164  NBTypeCont& tc = nb.getTypeCont();
165  // build the handler
166  std::map<std::string, OpenDriveEdge*> edges;
167  NIImporter_OpenDrive handler(nb.getTypeCont(), edges);
168  // parse file(s)
169  std::vector<std::string> files = oc.getStringVector("opendrive-files");
170  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
171  if (!FileHelpers::isReadable(*file)) {
172  WRITE_ERROR("Could not open opendrive file '" + *file + "'.");
173  return;
174  }
175  handler.setFileName(*file);
176  PROGRESS_BEGIN_MESSAGE("Parsing opendrive from '" + *file + "'");
177  XMLSubSys::runParser(handler, *file);
179  }
180  // split inner/outer edges
181  std::map<std::string, OpenDriveEdge*> innerEdges, outerEdges;
182  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
183  if ((*i).second->isInner) {
184  innerEdges[(*i).first] = (*i).second;
185  } else {
186  outerEdges[(*i).first] = (*i).second;
187  }
188  }
189 
190  // convert geometries into a discretised representation
191  computeShapes(edges);
192  // check whether lane sections are valid and whether further must be introduced
193  revisitLaneSections(tc, edges);
194 
195  // -------------------------
196  // node building
197  // -------------------------
198  // build nodes#1
199  // look at all links which belong to a node, collect their bounding boxes
200  // and place the node in the middle of this bounding box
201  std::map<std::string, Boundary> posMap;
202  std::map<std::string, std::string> edge2junction;
203  // compute node positions
204  for (std::map<std::string, OpenDriveEdge*>::iterator i = innerEdges.begin(); i != innerEdges.end(); ++i) {
205  OpenDriveEdge* e = (*i).second;
206  assert(e->junction != "-1" && e->junction != "");
207  edge2junction[e->id] = e->junction;
208  if (posMap.find(e->junction) == posMap.end()) {
209  posMap[e->junction] = Boundary();
210  }
211  posMap[e->junction].add(e->geom.getBoxBoundary());
212  }
213  // build nodes
214  for (std::map<std::string, Boundary>::iterator i = posMap.begin(); i != posMap.end(); ++i) {
215  if (!nb.getNodeCont().insert((*i).first, (*i).second.getCenter())) {
216  throw ProcessError("Could not add node '" + (*i).first + "'.");
217  }
218  }
219  // assign built nodes
220  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
221  OpenDriveEdge* e = (*i).second;
222  for (std::vector<OpenDriveLink>::iterator j = e->links.begin(); j != e->links.end(); ++j) {
223  OpenDriveLink& l = *j;
224  const std::string& nid = l.elementID;
225  if (l.elementType != OPENDRIVE_ET_ROAD) {
226  if (nb.getNodeCont().retrieve(nid) == 0) {
227  // not yet seen, build (possibly a junction without connections)
228  Position pos = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e->geom[-1] : e->geom[0];
229  if (!nb.getNodeCont().insert(nid, pos)) {
230  throw ProcessError("Could not build node '" + nid + "'.");
231  }
232  }
233  // set node information
235  continue;
236  }
237  if (edge2junction.find(l.elementID) != edge2junction.end()) {
238  // set node information of an internal road
239  setNodeSecure(nb.getNodeCont(), *e, edge2junction[l.elementID], l.linkType);
240  continue;
241  }
242  }
243  }
244  // we should now have all nodes set for links which are not outer edge-to-outer edge links
245 
246 
247  // build nodes#2
248  // build nodes for all outer edge-to-outer edge connections
249  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
250  OpenDriveEdge* e = (*i).second;
251  for (std::vector<OpenDriveLink>::iterator j = e->links.begin(); j != e->links.end(); ++j) {
252  OpenDriveLink& l = *j;
253  if (l.elementType != OPENDRIVE_ET_ROAD || edge2junction.find(l.elementID) != edge2junction.end()) {
254  // is a connection to an internal edge, or a node, skip
255  continue;
256  }
257  // we have a direct connection between to external edges
258  std::string id1 = e->id;
259  std::string id2 = l.elementID;
260  if (id1 < id2) {
261  std::swap(id1, id2);
262  }
263  std::string nid = id1 + "." + id2;
264  if (nb.getNodeCont().retrieve(nid) == 0) {
265  // not yet seen, build
266  Position pos = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e->geom[-1] : e->geom[0];
267  if (!nb.getNodeCont().insert(nid, pos)) {
268  throw ProcessError("Could not build node '" + nid + "'.");
269  }
270  }
271  /* debug-stuff
272  else {
273  Position pos = l.linkType==OPENDRIVE_LT_SUCCESSOR ? e.geom[e.geom.size()-1] : e.geom[0];
274  cout << nid << " " << pos << " " << nb.getNodeCont().retrieve(nid)->getPosition() << endl;
275  }
276  */
277  setNodeSecure(nb.getNodeCont(), *e, nid, l.linkType);
278  }
279  }
280  // we should now have start/end nodes for all outer edge-to-outer edge connections
281 
282 
283  // build nodes#3
284  // assign further nodes generated from inner-edges
285  // these nodes have not been assigned earlier, because the connections are referenced in inner-edges
286  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
287  OpenDriveEdge* e = (*i).second;
288  if (e->to != 0 && e->from != 0) {
289  continue;
290  }
291  for (std::map<std::string, OpenDriveEdge*>::iterator j = innerEdges.begin(); j != innerEdges.end(); ++j) {
292  OpenDriveEdge* ie = (*j).second;
293  for (std::vector<OpenDriveLink>::iterator k = ie->links.begin(); k != ie->links.end(); ++k) {
294  OpenDriveLink& il = *k;
295  if (il.elementType != OPENDRIVE_ET_ROAD || il.elementID != e->id) {
296  // not conneted to the currently investigated outer edge
297  continue;
298  }
299  std::string nid = edge2junction[ie->id];
300  if (il.contactPoint == OPENDRIVE_CP_START) {
302  } else {
304  }
305  }
306  }
307 
308  }
309 
310  // build start/end nodes which were not defined previously
311  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
312  OpenDriveEdge* e = (*i).second;
313  if (e->from == 0) {
314  const std::string nid = e->id + ".begin";
315  e->from = getOrBuildNode(nid, e->geom.front(), nb.getNodeCont());
316  }
317  if (e->to == 0) {
318  const std::string nid = e->id + ".end";
319  e->to = getOrBuildNode(nid, e->geom.back(), nb.getNodeCont());
320  }
321  }
322 
323 
324  // -------------------------
325  // edge building
326  // -------------------------
327  SUMOReal defaultSpeed = tc.getSpeed("");
328  // build edges
329  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
330  OpenDriveEdge* e = (*i).second;
331  bool lanesBuilt = false;
332 
333  // go along the lane sections, build a node in between of each pair
334 
337 
339  NBNode* sFrom = e->from;
340  NBNode* sTo = e->to;
341  int priorityR = e->getPriority(OPENDRIVE_TAG_RIGHT);
342  int priorityL = e->getPriority(OPENDRIVE_TAG_LEFT);
343  SUMOReal sB = 0;
344  SUMOReal sE = e->length;
345  // 0-length geometries are possible if only the inner points are represented
346  const SUMOReal length2D = e->geom.length2D();
347  SUMOReal cF = length2D == 0 ? 1 : e->length / length2D;
348  NBEdge* prevRight = 0;
349  NBEdge* prevLeft = 0;
350 
351  // starting at the same node as ending, and no lane sections?
352  if (sFrom == sTo && e->laneSections.size() == 1) {
353  // --> loop, split!
355  ls.s = e->length / 2.;
356  e->laneSections.push_back(ls);
357  WRITE_WARNING("Edge '" + e->id + "' has to be split as it connects same junctions.")
358  }
359 
360  // build along lane sections
361  for (std::vector<OpenDriveLaneSection>::iterator j = e->laneSections.begin(); j != e->laneSections.end(); ++j) {
362  // add internal node if needed
363  if (j == e->laneSections.end() - 1) {
364  sTo = e->to;
365  sE = e->length / cF;
366  } else {
367  SUMOReal nextS = (j + 1)->s;
368  sTo = new NBNode(e->id + "." + toString(nextS), e->geom.positionAtOffset(nextS));
369  if (!nb.getNodeCont().insert(sTo)) {
370  throw ProcessError("Could not add node '" + sTo->getID() + "'.");
371  }
372  sE = nextS / cF;
373  }
374  PositionVector geom = e->geom.getSubpart2D(sB, sE);
375  std::string id = e->id;
376  if (sFrom != e->from || sTo != e->to) {
377  id = id + "." + toString((*j).s);
378  } else if (e->laneSections.size() == 1) {
379  id = id + ".0.00";
380  }
381 
382  // build lanes to right
383  NBEdge* currRight = 0;
384  if ((*j).rightLaneNumber > 0) {
385  currRight = new NBEdge("-" + id, sFrom, sTo, (*j).rightType, defaultSpeed, (*j).rightLaneNumber, priorityR,
387  if (!nb.getEdgeCont().insert(currRight, myImportAllTypes)) {
388  throw ProcessError("Could not add edge '" + currRight->getID() + "'.");
389  }
390  lanesBuilt = true;
391  const std::vector<OpenDriveLane>& lanes = (*j).lanesByDir[OPENDRIVE_TAG_RIGHT];
392  for (std::vector<OpenDriveLane>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
393  std::map<int, int>::const_iterator lp = (*j).laneMap.find((*k).id);
394  if (lp != (*j).laneMap.end()) {
395  int sumoLaneIndex = lp->second;
396  NBEdge::Lane& sumoLane = currRight->getLaneStruct(sumoLaneIndex);
397  const OpenDriveLane& odLane = *k;
398 
399  sumoLane.origID = e->id + " -" + toString((*k).id);
400  sumoLane.speed = odLane.speed != 0 ? odLane.speed : tc.getSpeed(odLane.type);
401  sumoLane.permissions = tc.getPermissions(odLane.type);
402  sumoLane.width = myImportWidths && odLane.width != 0 ? odLane.width : tc.getWidth(odLane.type);
403  }
404  }
405  // connect lane sections
406  if (prevRight != 0) {
407  std::map<int, int> connections = (*j).getInnerConnections(OPENDRIVE_TAG_RIGHT, *(j - 1));
408  for (std::map<int, int>::const_iterator k = connections.begin(); k != connections.end(); ++k) {
409  prevRight->addLane2LaneConnection((*k).first, currRight, (*k).second, NBEdge::L2L_VALIDATED);
410  }
411  }
412  prevRight = currRight;
413  }
414 
415  // build lanes to left
416  NBEdge* currLeft = 0;
417  if ((*j).leftLaneNumber > 0) {
418  currLeft = new NBEdge(id, sTo, sFrom, (*j).leftType, defaultSpeed, (*j).leftLaneNumber, priorityL,
420  if (!nb.getEdgeCont().insert(currLeft, myImportAllTypes)) {
421  throw ProcessError("Could not add edge '" + currLeft->getID() + "'.");
422  }
423  lanesBuilt = true;
424  const std::vector<OpenDriveLane>& lanes = (*j).lanesByDir[OPENDRIVE_TAG_LEFT];
425  for (std::vector<OpenDriveLane>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
426  std::map<int, int>::const_iterator lp = (*j).laneMap.find((*k).id);
427  if (lp != (*j).laneMap.end()) {
428  int sumoLaneIndex = lp->second;
429  NBEdge::Lane& sumoLane = currLeft->getLaneStruct(sumoLaneIndex);
430  const OpenDriveLane& odLane = *k;
431 
432  sumoLane.origID = e->id + " " + toString((*k).id);
433  sumoLane.speed = odLane.speed != 0 ? odLane.speed : tc.getSpeed(odLane.type);
434  sumoLane.permissions = tc.getPermissions(odLane.type);
435  sumoLane.width = myImportWidths && odLane.width != 0 ? odLane.width : tc.getWidth(odLane.type);
436  }
437  }
438  // connect lane sections
439  if (prevLeft != 0) {
440  std::map<int, int> connections = (*j).getInnerConnections(OPENDRIVE_TAG_LEFT, *(j - 1));
441  for (std::map<int, int>::const_iterator k = connections.begin(); k != connections.end(); ++k) {
442  currLeft->addLane2LaneConnection((*k).first, prevLeft, (*k).second, NBEdge::L2L_VALIDATED);
443  }
444  }
445  prevLeft = currLeft;
446  }
447  (*j).sumoID = id;
448 
449 
450  sB = sE;
451  sFrom = sTo;
452  }
453  if (!lanesBuilt) {
454  WRITE_WARNING("Edge '" + e->id + "' has no lanes.");
455  }
456  }
457 
458  // -------------------------
459  // connections building
460  // -------------------------
461  // generate explicit lane-to-lane connections
462  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
463  setEdgeLinks2(*(*i).second, edges);
464  }
465  // compute connections across intersections, if any
466  std::vector<Connection> connections2;
467  for (std::map<std::string, OpenDriveEdge*>::iterator j = edges.begin(); j != edges.end(); ++j) {
468  const std::set<Connection>& conns = (*j).second->connections;
469 
470  for (std::set<Connection>::const_iterator i = conns.begin(); i != conns.end(); ++i) {
471  if (innerEdges.find((*i).fromEdge) != innerEdges.end()) {
472  // connections starting at inner edges are processed by starting from outer edges
473  continue;
474  }
475  if (innerEdges.find((*i).toEdge) != innerEdges.end()) {
476  buildConnectionsToOuter(*i, innerEdges, connections2);
477  } else {
478  connections2.push_back(*i);
479  }
480  }
481  }
482  // set connections
483  for (std::vector<Connection>::const_iterator i = connections2.begin(); i != connections2.end(); ++i) {
484  std::string fromEdge = (*i).fromEdge;
485  if (edges.find(fromEdge) == edges.end()) {
486  WRITE_WARNING("While setting connections: from-edge '" + fromEdge + "' is not known.");
487  continue;
488  }
489  OpenDriveEdge* odFrom = edges[fromEdge];
490  int fromLane = (*i).fromLane;
491  bool fromLast = ((*i).fromCP == OPENDRIVE_CP_END) ^ ((*i).fromLane > 0 && !(*i).all);
492  fromEdge = fromLast ? odFrom->laneSections.back().sumoID : odFrom->laneSections[0].sumoID;
493 
494  std::string toEdge = (*i).toEdge;
495  if (edges.find(toEdge) == edges.end()) {
496  WRITE_WARNING("While setting connections: to-edge '" + toEdge + "' is not known.");
497  continue;
498  }
499 
500  OpenDriveEdge* odTo = edges[toEdge];
501  int toLane = (*i).toLane;
502  bool toLast = ((*i).toCP == OPENDRIVE_CP_END) || ((*i).toLane > 0);
503  toEdge = toLast ? odTo->laneSections.back().sumoID : odTo->laneSections[0].sumoID;
504 
505  if (fromLane == UNSET_CONNECTION) {
506  fromLane = toLast ? odTo->laneSections.back().laneMap.begin()->first : odTo->laneSections[0].laneMap.begin()->first;
507  }
508  if (fromLane < 0) {
509  fromEdge = revertID(fromEdge);
510  }
511  if (toLane == UNSET_CONNECTION) {
512  toLane = toLast ? odTo->laneSections.back().laneMap.begin()->first : odTo->laneSections[0].laneMap.begin()->first;
513  }
514  if (toLane < 0) {
515  toEdge = revertID(toEdge);
516  }
517  fromLane = fromLast ? odFrom->laneSections.back().laneMap[fromLane] : odFrom->laneSections[0].laneMap[fromLane];
518  toLane = toLast ? odTo->laneSections.back().laneMap[toLane] : odTo->laneSections[0].laneMap[toLane];
519  NBEdge* from = nb.getEdgeCont().retrieve(fromEdge);
520  NBEdge* to = nb.getEdgeCont().retrieve(toEdge);
521  if (from == 0) {
522  WRITE_WARNING("Could not find fromEdge representation of '" + fromEdge + "' in connection '" + (*i).origID + "'.");
523  }
524  if (to == 0) {
525  WRITE_WARNING("Could not find fromEdge representation of '" + toEdge + "' in connection '" + (*i).origID + "'.");
526  }
527  if (from == 0 || to == 0) {
528  continue;
529  }
530 
531  from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER);
532 
533  if ((*i).origID != "") {
534  // @todo: this is the most silly way to determine the connection
535  std::vector<NBEdge::Connection>& cons = from->getConnections();
536  for (std::vector<NBEdge::Connection>::iterator k = cons.begin(); k != cons.end(); ++k) {
537  if ((*k).fromLane == fromLane && (*k).toEdge == to && (*k).toLane == toLane) {
538  (*k).origID = (*i).origID + " " + toString((*i).origLane);
539  break;
540  }
541  }
542  }
543  }
544 
545 
546  // -------------------------
547  // traffic lights
548  // -------------------------
549  std::map<std::string, std::string> tlsControlled;
550  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
551  OpenDriveEdge* e = (*i).second;
552  for (std::vector<OpenDriveSignal>::const_iterator j = e->signals.begin(); j != e->signals.end(); ++j) {
553  if ((*j).type != "1000001") { // traffic_light (Section 6.11)
554  continue;
555  }
556  std::vector<OpenDriveLaneSection>::iterator k = e->laneSections.begin();
557  bool found = false;
558  for (; k != e->laneSections.end() - 1 && !found;) {
559  if ((*j).s > (*k).s && (*j).s <= (*(k + 1)).s) {
560  found = true;
561  } else {
562  ++k;
563  }
564  }
565 
566  // @todo: major problem, currently, still not completely solved:
567  // inner edges may have traffic lights, too. Nice on one hand, as directions can be recognized
568  // but hard to follow backwards
569  std::string id = (*k).sumoID;
570  if (id == "") {
571  if (e->junction != "") {
572  //WRITE_WARNING("Found a traffic light signal on an internal edge; will not build it (original edge id='" + e->id + "').");
573  std::string fromID, toID;
574  for (std::vector<OpenDriveLink>::const_iterator l = e->links.begin(); l != e->links.end(); ++l) {
575  if ((*l).linkType == OPENDRIVE_LT_PREDECESSOR && (*l).elementType == OPENDRIVE_ET_ROAD) {
576  if (fromID != "") {
577  WRITE_WARNING("Ambigous start of connection.");
578  }
579  fromID = (*l).elementID;
580  OpenDriveEdge* e = edges[fromID];
581  fromID = (*l).contactPoint == OPENDRIVE_CP_START ? e->laneSections[0].sumoID : e->laneSections.back().sumoID;
582  }
583  if ((*l).linkType == OPENDRIVE_LT_SUCCESSOR && (*l).elementType == OPENDRIVE_ET_ROAD) {
584  if (toID != "") {
585  WRITE_WARNING("Ambigous end of connection.");
586  }
587  toID = (*l).elementID;
588  OpenDriveEdge* e = edges[toID];
589  toID = (*l).contactPoint == OPENDRIVE_CP_START ? e->laneSections[0].sumoID : e->laneSections.back().sumoID;
590  }
591  }
592  id = fromID + "->" + toID;
593  } else {
594  WRITE_WARNING("Found a traffic light signal on an unknown edge (original edge id='" + e->id + "').");
595  continue;
596  }
597  }
598 
599  if ((*j).orientation > 0) {
600  id = "-" + id;
601  }
602  tlsControlled[id] = (*j).name;
603  }
604  }
605 
606  for (std::map<std::string, std::string>::iterator i = tlsControlled.begin(); i != tlsControlled.end(); ++i) {
607  std::string id = (*i).first;
608  if (id.find("->") != std::string::npos) {
609  id = id.substr(0, id.find("->"));
610  }
611  NBEdge* e = nb.getEdgeCont().retrieve(id);
612  if (e == 0) {
613  WRITE_WARNING("Could not find edge '" + id + "' while building its traffic light.");
614  continue;
615  }
616  NBNode* toNode = e->getToNode();
617  if (!toNode->isTLControlled()) {
619  NBOwnTLDef* tlDef = new NBOwnTLDef(toNode->getID(), toNode, 0, type);
620  if (!nb.getTLLogicCont().insert(tlDef)) {
621  // actually, nothing should fail here
622  delete tlDef;
623  throw ProcessError();
624  }
625  toNode->addTrafficLight(tlDef);
626  //tlDef->setSinglePhase();
627  }
628  NBTrafficLightDefinition* tlDef = *toNode->getControllingTLS().begin();
629  tlDef->addParameter("connection:" + id, (*i).second);
630  }
631 
632  // -------------------------
633  // clean up
634  // -------------------------
635  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
636  delete(*i).second;
637  }
638 }
639 
640 
641 void
642 NIImporter_OpenDrive::buildConnectionsToOuter(const Connection& c, const std::map<std::string, OpenDriveEdge*>& innerEdges, std::vector<Connection>& into) {
643 
644  OpenDriveEdge* dest = innerEdges.find(c.toEdge)->second;
645  if (dest == 0) {
647  return;
648  }
649  const std::set<Connection>& conts = dest->connections;
650  for (std::set<Connection>::const_iterator i = conts.begin(); i != conts.end(); ++i) {
651  if (innerEdges.find((*i).toEdge) != innerEdges.end()) {
652  std::vector<Connection> t;
653  buildConnectionsToOuter(*i, innerEdges, t);
654  for (std::vector<Connection>::const_iterator j = t.begin(); j != t.end(); ++j) {
655  // @todo this section is unverified
656  Connection cn = (*j);
657  cn.fromEdge = c.fromEdge;
658  cn.fromLane = c.fromLane;
659  cn.fromCP = c.fromCP;
660  cn.all = c.all; // @todo "all" is a hack trying to avoid the "from is zero" problem;
661  into.push_back(cn);
662  }
663  } else {
664  if ((*i).fromLane == c.toLane) {
665  Connection cn = (*i);
666  cn.fromEdge = c.fromEdge;
667  cn.fromLane = c.fromLane;
668  cn.fromCP = c.fromCP;
669  cn.all = c.all;
670  cn.origID = c.toEdge;
671  cn.origLane = c.toLane;
672  into.push_back(cn);
673  }
674  }
675  }
676 }
677 
678 
679 void
680 NIImporter_OpenDrive::setEdgeLinks2(OpenDriveEdge& e, const std::map<std::string, OpenDriveEdge*>& edges) {
681  for (std::vector<OpenDriveLink>::iterator i = e.links.begin(); i != e.links.end(); ++i) {
682  OpenDriveLink& l = *i;
683  if (l.elementType != OPENDRIVE_ET_ROAD) {
684  // we assume that links to nodes are later given as connections to edges
685  continue;
686  }
687  // get the right direction of the connected edge
688  std::string connectedEdge = l.elementID;
689  std::string edgeID = e.id;
690 
691  OpenDriveLaneSection& laneSection = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e.laneSections.back() : e.laneSections[0];
692  const std::map<int, int>& laneMap = laneSection.laneMap;
693  if (laneSection.lanesByDir.find(OPENDRIVE_TAG_RIGHT) != laneSection.lanesByDir.end()) {
694  const std::vector<OpenDriveLane>& lanes = laneSection.lanesByDir.find(OPENDRIVE_TAG_RIGHT)->second;
695  for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
696  if (!myImportAllTypes && laneMap.find((*j).id) == laneMap.end()) {
697  continue;
698  }
699  Connection c; // @todo: give Connection a new name and a constructor
700  c.fromEdge = e.id;
701  c.fromLane = (*j).id;
703  c.toLane = l.linkType == OPENDRIVE_LT_SUCCESSOR ? (*j).successor : (*j).predecessor;
704  c.toEdge = connectedEdge;
705  c.toCP = l.contactPoint;
706  c.all = false;
707  if (l.linkType != OPENDRIVE_LT_SUCCESSOR) {
708  std::swap(c.fromEdge, c.toEdge);
709  std::swap(c.fromLane, c.toLane);
710  std::swap(c.fromCP, c.toCP);
711  }
712  if (edges.find(c.fromEdge) == edges.end()) {
713  WRITE_ERROR("While setting connections: incoming road '" + c.fromEdge + "' is not known.");
714  } else {
715  OpenDriveEdge* src = edges.find(c.fromEdge)->second;
716  src->connections.insert(c);
717  }
718  }
719  }
720  if (laneSection.lanesByDir.find(OPENDRIVE_TAG_LEFT) != laneSection.lanesByDir.end()) {
721  const std::vector<OpenDriveLane>& lanes = laneSection.lanesByDir.find(OPENDRIVE_TAG_LEFT)->second;
722  for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
723  if (!myImportAllTypes && laneMap.find((*j).id) == laneMap.end()) {
724  continue;
725  }
726  Connection c;
727  c.toEdge = e.id;
728  c.toLane = (*j).id;
730  c.fromLane = l.linkType == OPENDRIVE_LT_SUCCESSOR ? (*j).successor : (*j).predecessor;
731  c.fromEdge = connectedEdge;
732  c.fromCP = l.contactPoint;
733  c.all = false;
734  if (l.linkType != OPENDRIVE_LT_SUCCESSOR) {
735  std::swap(c.fromEdge, c.toEdge);
736  std::swap(c.fromLane, c.toLane);
737  std::swap(c.fromCP, c.toCP);
738  }
739  if (edges.find(c.fromEdge) == edges.end()) {
740  WRITE_ERROR("While setting connections: incoming road '" + c.fromEdge + "' is not known.");
741  } else {
742  OpenDriveEdge* src = edges.find(c.fromEdge)->second;
743  src->connections.insert(c);
744  }
745  }
746  }
747  }
748 }
749 
750 
751 std::string NIImporter_OpenDrive::revertID(const std::string& id) {
752  if (id[0] == '-') {
753  return id.substr(1);
754  }
755  return "-" + id;
756 }
757 
758 
759 NBNode*
760 NIImporter_OpenDrive::getOrBuildNode(const std::string& id, const Position& pos,
761  NBNodeCont& nc) {
762  if (nc.retrieve(id) == 0) {
763  // not yet built; build now
764  if (!nc.insert(id, pos)) {
765  // !!! clean up
766  throw ProcessError("Could not add node '" + id + "'.");
767  }
768  }
769  return nc.retrieve(id);
770 }
771 
772 
773 void
775  const std::string& nodeID, NIImporter_OpenDrive::LinkType lt) {
776  NBNode* n = nc.retrieve(nodeID);
777  if (n == 0) {
778  throw ProcessError("Could not find node '" + nodeID + "'.");
779  }
780  if (lt == OPENDRIVE_LT_SUCCESSOR) {
781  if (e.to != 0 && e.to != n) {
782  throw ProcessError("Edge '" + e.id + "' has two end nodes.");
783  }
784  e.to = n;
785  } else {
786  if (e.from != 0 && e.from != n) {
787  throw ProcessError("Edge '" + e.id + "' has two start nodes.");
788  }
789  e.from = n;
790  }
791 }
792 
793 
794 void
795 NIImporter_OpenDrive::computeShapes(std::map<std::string, OpenDriveEdge*>& edges) {
797  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
798  OpenDriveEdge& e = *(*i).second;
800  for (std::vector<OpenDriveGeometry>::iterator j = e.geometries.begin(); j != e.geometries.end(); ++j) {
801  OpenDriveGeometry& g = *j;
802  PositionVector geom;
803  switch (g.type) {
805  break;
806  case OPENDRIVE_GT_LINE:
807  geom = geomFromLine(e, g);
808  break;
809  case OPENDRIVE_GT_SPIRAL:
810  geom = geomFromSpiral(e, g);
811  break;
812  case OPENDRIVE_GT_ARC:
813  geom = geomFromArc(e, g);
814  break;
815  case OPENDRIVE_GT_POLY3:
816  geom = geomFromPoly(e, g);
817  break;
819  geom = geomFromParamPoly(e, g);
820  break;
821  default:
822  break;
823  }
824  if (e.geom.size() > 0 && prevType == OPENDRIVE_GT_LINE) {
825  // remove redundant end point of the previous geometry segment
826  // (the start point of the current segment should have the same value)
827  // this avoids geometry errors due to imprecision
828  if (!e.geom.back().almostSame(geom.front())) {
829  const int index = (int)(j - e.geometries.begin());
830  WRITE_WARNING("Mismatched geometry for edge '" + e.id + "' between geometry segments " + toString(index - 1) + " and " + toString(index) + ".");
831  }
832  e.geom.pop_back();
833  }
834  for (PositionVector::iterator k = geom.begin(); k != geom.end(); ++k) {
836  }
837  prevType = g.type;
838  }
839  if (oc.exists("geometry.min-dist") && !oc.isDefault("geometry.min-dist")) {
840  e.geom.removeDoublePoints(oc.getFloat("geometry.min-dist"), true);
841  }
842  for (int j = 0; j < (int)e.geom.size(); ++j) {
844  WRITE_ERROR("Unable to project coordinates for.");
845  }
846  }
847  // add z-data
848  int k = 0;
849  SUMOReal pos = 0;
850  for (std::vector<OpenDriveElevation>::iterator j = e.elevations.begin(); j != e.elevations.end(); ++j) {
851  const OpenDriveElevation& el = *j;
852  const SUMOReal sNext = (j + 1) == e.elevations.end() ? std::numeric_limits<SUMOReal>::max() : (*(j + 1)).s;
853  while (k < (int)e.geom.size() && pos < sNext) {
854  const SUMOReal ds = pos - el.s;
855  const SUMOReal z = el.a + el.b * ds + el.c * ds * ds + el.d * ds * ds * ds;
856  //std::cout << " edge=" << e.id << " k=" << k << " sNext=" << sNext << " pos=" << pos << " z=" << z << " pos=" << pos << " ds=" << ds << " el.s=" << el.s << "el.a=" << el.a << " el.b=" << el.b << " el.c=" << el.c << " el.d=" << el.d << "\n";
857  e.geom[k].add(0, 0, z);
858  k++;
859  if (k < (int)e.geom.size()) {
860  // XXX pos understimates the actual position since the
861  // actual geometry between k-1 and k could be curved
862  pos += e.geom[k - 1].distanceTo2D(e.geom[k]);
863  }
864  }
865  }
866  }
867 }
868 
869 
870 void
871 NIImporter_OpenDrive::revisitLaneSections(const NBTypeCont& tc, std::map<std::string, OpenDriveEdge*>& edges) {
872  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
873  OpenDriveEdge& e = *(*i).second;
874  std::vector<OpenDriveLaneSection>& laneSections = e.laneSections;
875  // split by speed limits
876  std::vector<OpenDriveLaneSection> newSections;
877  for (std::vector<OpenDriveLaneSection>::iterator j = laneSections.begin(); j != laneSections.end(); ++j) {
878  std::vector<OpenDriveLaneSection> splitSections;
879  bool splitBySpeed = (*j).buildSpeedChanges(tc, splitSections);
880  if (!splitBySpeed) {
881  newSections.push_back(*j);
882  } else {
883  std::copy(splitSections.begin(), splitSections.end(), back_inserter(newSections));
884  }
885  }
886 
887  e.laneSections = newSections;
888  laneSections = e.laneSections;
889  SUMOReal lastS = -1;
890  // check whether the lane sections are in the right order
891  bool sorted = true;
892  for (std::vector<OpenDriveLaneSection>::const_iterator j = laneSections.begin(); j != laneSections.end() && sorted; ++j) {
893  if ((*j).s <= lastS) {
894  sorted = false;
895  }
896  lastS = (*j).s;
897  }
898  if (!sorted) {
899  WRITE_WARNING("The sections of edge '" + e.id + "' are not sorted properly.");
900  sort(e.laneSections.begin(), e.laneSections.end(), sections_by_s_sorter());
901  }
902  // check whether no duplicates of s-value occure
903  lastS = -1;
904  laneSections = e.laneSections;
905  for (std::vector<OpenDriveLaneSection>::iterator j = laneSections.begin(); j != laneSections.end();) {
906  bool simlarToLast = fabs((*j).s - lastS) < POSITION_EPS;
907  lastS = (*j).s;
908  if (simlarToLast) {
909  WRITE_WARNING("Almost duplicate s-value '" + toString(lastS) + "' for lane sections occured at edge '" + e.id + "'; second entry was removed.");
910  j = laneSections.erase(j);
911  } else {
912  ++j;
913  }
914  }
915  }
916 }
917 
918 
921  UNUSED_PARAMETER(e);
922  PositionVector ret;
923  ret.push_back(Position(g.x, g.y));
924  ret.push_back(calculateStraightEndPoint(g.hdg, g.length, Position(g.x, g.y)));
925  return ret;
926 }
927 
928 
931  UNUSED_PARAMETER(e);
932  PositionVector ret;
933  SUMOReal curveStart = g.params[0];
934  SUMOReal curveEnd = g.params[1];
935  Point2D<double> end;
936  try {
937  EulerSpiral s(Point2D<double>(g.x, g.y), g.hdg, curveStart, (curveEnd - curveStart) / g.length, g.length);
938  std::vector<Point2D<double> > into;
939  s.computeSpiral(into, 1.);
940  for (std::vector<Point2D<double> >::iterator i = into.begin(); i != into.end(); ++i) {
941  ret.push_back(Position((*i).getX(), (*i).getY()));
942  }
943  } catch (const std::runtime_error& error) {
944  WRITE_WARNING("Could not compute spiral geometry for edge '" + e.id + "' (" + error.what() + ").");
945  ret.push_back(Position(g.x, g.y));
946  }
947  return ret.getSubpart2D(0, g.length);
948 }
949 
950 
953  UNUSED_PARAMETER(e);
954  PositionVector ret;
955  SUMOReal dist = 0.0;
956  SUMOReal centerX = g.x;
957  SUMOReal centerY = g.y;
958  // left: positive value
959  SUMOReal curvature = g.params[0];
960  SUMOReal radius = 1. / curvature;
961  // center point
962  calculateCurveCenter(&centerX, &centerY, radius, g.hdg);
963  SUMOReal endX = g.x;
964  SUMOReal endY = g.y;
965  SUMOReal startX = g.x;
966  SUMOReal startY = g.y;
967  SUMOReal geo_posS = g.s;
968  SUMOReal geo_posE = g.s;
969  bool end = false;
970  do {
971  geo_posE += C_LENGTH;
972  if (geo_posE - g.s > g.length) {
973  geo_posE = g.s + g.length;
974  }
975  if (geo_posE - g.s > g.length) {
976  geo_posE = g.s + g.length;
977  }
978  calcPointOnCurve(&endX, &endY, centerX, centerY, radius, geo_posE - geo_posS);
979 
980  dist += (geo_posE - geo_posS);
981  //
982  ret.push_back(Position(startX, startY));
983  //
984  startX = endX;
985  startY = endY;
986  geo_posS = geo_posE;
987 
988  if (geo_posE - (g.s + g.length) < 0.001 && geo_posE - (g.s + g.length) > -0.001) {
989  end = true;
990  }
991  } while (!end);
992  return ret.getSubpart2D(0, g.length);
993 }
994 
995 
998  UNUSED_PARAMETER(e);
999  const SUMOReal s = sin(g.hdg);
1000  const SUMOReal c = cos(g.hdg);
1001  PositionVector ret;
1002  for (SUMOReal off = 0; off < g.length + 2.; off += 2.) {
1003  SUMOReal x = off;
1004  SUMOReal y = g.params[0] + g.params[1] * off + g.params[2] * pow(off, 2.) + g.params[3] * pow(off, 3.);
1005  SUMOReal xnew = x * c - y * s;
1006  SUMOReal ynew = x * s + y * c;
1007  ret.push_back(Position(g.x + xnew, g.y + ynew));
1008  }
1009  return ret.getSubpart2D(0, g.length);
1010 }
1011 
1012 
1015  UNUSED_PARAMETER(e);
1016  const SUMOReal s = sin(g.hdg);
1017  const SUMOReal c = cos(g.hdg);
1018  const SUMOReal pMax = g.params[8];
1019  // import with 2m resolution
1020  const SUMOReal pStep = pMax / ceil(g.length / 2.0);
1021  PositionVector ret;
1022  for (SUMOReal p = 0; p < pMax + pStep; p += pStep) {
1023  SUMOReal x = g.params[0] + g.params[1] * p + g.params[2] * pow(p, 2.) + g.params[3] * pow(p, 3.);
1024  SUMOReal y = g.params[4] + g.params[5] * p + g.params[6] * pow(p, 2.) + g.params[7] * pow(p, 3.);
1025  SUMOReal xnew = x * c - y * s;
1026  SUMOReal ynew = x * s + y * c;
1027  ret.push_back(Position(g.x + xnew, g.y + ynew));
1028  }
1029  return ret.getSubpart2D(0, g.length);
1030 }
1031 
1032 
1033 Position
1034 NIImporter_OpenDrive::calculateStraightEndPoint(double hdg, double length, const Position& start) {
1035  double normx = 1.0f;
1036  double normy = 0.0f;
1037  double x2 = normx * cos(hdg) - normy * sin(hdg);
1038  double y2 = normx * sin(hdg) + normy * cos(hdg);
1039  normx = x2 * length;
1040  normy = y2 * length;
1041  return Position(start.x() + normx, start.y() + normy);
1042 }
1043 
1044 
1045 void
1047  SUMOReal normX = 1.0;
1048  SUMOReal normY = 0.0;
1049  SUMOReal tmpX;
1050  SUMOReal turn;
1051  if (ad_radius > 0) {
1052  turn = -1.0;
1053  } else {
1054  turn = 1.0;
1055  }
1056 
1057  tmpX = normX;
1058  normX = normX * cos(ad_hdg) + normY * sin(ad_hdg);
1059  normY = tmpX * sin(ad_hdg) + normY * cos(ad_hdg);
1060 
1061  tmpX = normX;
1062  normX = turn * normY;
1063  normY = -turn * tmpX;
1064 
1065  normX = fabs(ad_radius) * normX;
1066  normY = fabs(ad_radius) * normY;
1067 
1068  *ad_x += normX;
1069  *ad_y += normY;
1070 }
1071 
1072 
1073 void
1075  SUMOReal ad_r, SUMOReal ad_length) {
1076  double rotAngle = ad_length / fabs(ad_r);
1077  double vx = *ad_x - ad_centerX;
1078  double vy = *ad_y - ad_centerY;
1079  double tmpx;
1080 
1081  double turn;
1082  if (ad_r > 0) {
1083  turn = -1; //left
1084  } else {
1085  turn = 1; //right
1086  }
1087  tmpx = vx;
1088  vx = vx * cos(rotAngle) + turn * vy * sin(rotAngle);
1089  vy = -1 * turn * tmpx * sin(rotAngle) + vy * cos(rotAngle);
1090  *ad_x = vx + ad_centerX;
1091  *ad_y = vy + ad_centerY;
1092 }
1093 
1094 
1095 // ---------------------------------------------------------------------------
1096 // section
1097 // ---------------------------------------------------------------------------
1099  lanesByDir[OPENDRIVE_TAG_LEFT] = std::vector<OpenDriveLane>();
1100  lanesByDir[OPENDRIVE_TAG_RIGHT] = std::vector<OpenDriveLane>();
1101  lanesByDir[OPENDRIVE_TAG_CENTER] = std::vector<OpenDriveLane>();
1102 }
1103 
1104 
1105 void
1107  int sumoLane = 0;
1108  bool singleType = true;
1109  std::vector<std::string> types;
1110  const std::vector<OpenDriveLane>& dirLanesR = lanesByDir.find(OPENDRIVE_TAG_RIGHT)->second;
1111  for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanesR.rbegin(); i != dirLanesR.rend(); ++i) {
1112  if (myImportAllTypes || (tc.knows((*i).type) && !tc.getShallBeDiscarded((*i).type))) {
1113  laneMap[(*i).id] = sumoLane++;
1114  types.push_back((*i).type);
1115  if (types.front() != types.back()) {
1116  singleType = false;
1117  }
1118  }
1119  }
1120  rightLaneNumber = sumoLane;
1121  rightType = sumoLane > 0 ? (singleType ? types.front() : joinToString(types, "|")) : "";
1122  sumoLane = 0;
1123  singleType = true;
1124  types.clear();
1125  const std::vector<OpenDriveLane>& dirLanesL = lanesByDir.find(OPENDRIVE_TAG_LEFT)->second;
1126  for (std::vector<OpenDriveLane>::const_iterator i = dirLanesL.begin(); i != dirLanesL.end(); ++i) {
1127  if (myImportAllTypes || (tc.knows((*i).type) && !tc.getShallBeDiscarded((*i).type))) {
1128  laneMap[(*i).id] = sumoLane++;
1129  types.push_back((*i).type);
1130  if (types.front() != types.back()) {
1131  singleType = false;
1132  }
1133  }
1134  }
1135  leftLaneNumber = sumoLane;
1136  leftType = sumoLane > 0 ? (singleType ? types.front() : joinToString(types, "|")) : "";
1137 }
1138 
1139 
1140 std::map<int, int>
1142  std::map<int, int> ret;
1143  const std::vector<OpenDriveLane>& dirLanes = lanesByDir.find(dir)->second;
1144  for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanes.rbegin(); i != dirLanes.rend(); ++i) {
1145  std::map<int, int>::const_iterator toP = laneMap.find((*i).id);
1146  if (toP == laneMap.end()) {
1147  // the current lane is not available in SUMO
1148  continue;
1149  }
1150  int to = (*toP).second;
1151  int from = UNSET_CONNECTION;
1152  if ((*i).predecessor != UNSET_CONNECTION) {
1153  from = (*i).predecessor;
1154  }
1155  if (from != UNSET_CONNECTION) {
1156  std::map<int, int>::const_iterator fromP = prev.laneMap.find(from);
1157  if (fromP != prev.laneMap.end()) {
1158  from = (*fromP).second;
1159  } else {
1160  from = UNSET_CONNECTION;
1161  }
1162  }
1163  if (from != UNSET_CONNECTION && to != UNSET_CONNECTION) {
1164  if (ret.find(from) != ret.end()) {
1165 // WRITE_WARNING("double connection");
1166  }
1167  if (dir == OPENDRIVE_TAG_LEFT) {
1168  std::swap(from, to);
1169  }
1170  ret[from] = to;
1171  } else {
1172 // WRITE_WARNING("missing connection");
1173  }
1174  }
1175  return ret;
1176 }
1177 
1178 
1181  OpenDriveLaneSection ret(*this);
1182  ret.s += startPos;
1183  for (int k = 0; k < (int)ret.lanesByDir[OPENDRIVE_TAG_RIGHT].size(); ++k) {
1185  l.speed = 0;
1186  std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator i = std::find_if(l.speeds.begin(), l.speeds.end(), same_position_finder(startPos));
1187  if (i != l.speeds.end()) {
1188  l.speed = (*i).second;
1189  }
1190  }
1191  for (int k = 0; k < (int)ret.lanesByDir[OPENDRIVE_TAG_LEFT].size(); ++k) {
1193  std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator i = std::find_if(l.speeds.begin(), l.speeds.end(), same_position_finder(startPos));
1194  l.speed = 0;
1195  if (i != l.speeds.end()) {
1196  l.speed = (*i).second;
1197  }
1198  }
1199  return ret;
1200 }
1201 
1202 
1203 bool
1204 NIImporter_OpenDrive::OpenDriveLaneSection::buildSpeedChanges(const NBTypeCont& tc, std::vector<OpenDriveLaneSection>& newSections) {
1205  std::set<SUMOReal> speedChangePositions;
1206  // collect speed change positions and apply initial speed to the begin
1207  for (std::vector<OpenDriveLane>::iterator k = lanesByDir[OPENDRIVE_TAG_RIGHT].begin(); k != lanesByDir[OPENDRIVE_TAG_RIGHT].end(); ++k) {
1208  for (std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator l = (*k).speeds.begin(); l != (*k).speeds.end(); ++l) {
1209  speedChangePositions.insert((*l).first);
1210  if ((*l).first == 0) {
1211  (*k).speed = (*l).second;
1212  }
1213  }
1214  }
1215  for (std::vector<OpenDriveLane>::iterator k = lanesByDir[OPENDRIVE_TAG_LEFT].begin(); k != lanesByDir[OPENDRIVE_TAG_LEFT].end(); ++k) {
1216  for (std::vector<std::pair<SUMOReal, SUMOReal> >::const_iterator l = (*k).speeds.begin(); l != (*k).speeds.end(); ++l) {
1217  speedChangePositions.insert((*l).first);
1218  if ((*l).first == 0) {
1219  (*k).speed = (*l).second;
1220  }
1221  }
1222  }
1223  // do nothing if there is none
1224  if (speedChangePositions.size() == 0) {
1225  return false;
1226  }
1227  if (*speedChangePositions.begin() > 0) {
1228  speedChangePositions.insert(0);
1229  }
1230  //
1231  for (std::set<SUMOReal>::iterator i = speedChangePositions.begin(); i != speedChangePositions.end(); ++i) {
1232  if (i == speedChangePositions.begin()) {
1233  newSections.push_back(*this);
1234  } else {
1235  newSections.push_back(buildLaneSection(*i));
1236  }
1237  }
1238  // propagate speeds
1239  for (int i = 0; i != (int)newSections.size(); ++i) {
1240  OpenDriveLaneSection& ls = newSections[i];
1241  std::map<OpenDriveXMLTag, std::vector<OpenDriveLane> >& lanesByDir = ls.lanesByDir;
1242  for (std::map<OpenDriveXMLTag, std::vector<OpenDriveLane> >::iterator k = lanesByDir.begin(); k != lanesByDir.end(); ++k) {
1243  std::vector<OpenDriveLane>& lanes = (*k).second;
1244  for (int j = 0; j != (int)lanes.size(); ++j) {
1245  OpenDriveLane& l = lanes[j];
1246  if (l.speed != 0) {
1247  continue;
1248  }
1249  if (i > 0) {
1250  l.speed = newSections[i - 1].lanesByDir[(*k).first][j].speed;
1251  } else {
1252  tc.getSpeed(l.type);
1253  }
1254  }
1255  }
1256  }
1257  return true;
1258 }
1259 
1260 
1261 
1262 // ---------------------------------------------------------------------------
1263 // edge
1264 // ---------------------------------------------------------------------------
1265 int
1267  int prio = 1;
1268  for (std::vector<OpenDriveSignal>::const_iterator i = signals.begin(); i != signals.end(); ++i) {
1269  int tmp = 1;
1270  if ((*i).type == "301" || (*i).type == "306") {
1271  tmp = 2;
1272  }
1273  if ((*i).type == "205") {
1274  tmp = 0;
1275  }
1276  if (tmp != 1 && dir == OPENDRIVE_TAG_RIGHT && (*i).orientation > 0) {
1277  prio = tmp;
1278  }
1279  if (tmp != 1 && dir == OPENDRIVE_TAG_LEFT && (*i).orientation < 0) {
1280  prio = tmp;
1281  }
1282 
1283  }
1284  return prio;
1285 }
1286 
1287 
1288 
1289 // ---------------------------------------------------------------------------
1290 // loader methods
1291 // ---------------------------------------------------------------------------
1292 NIImporter_OpenDrive::NIImporter_OpenDrive(const NBTypeCont& tc, std::map<std::string, OpenDriveEdge*>& edges)
1294  myTypeContainer(tc), myCurrentEdge("", "", "", -1), myEdges(edges) {
1295 }
1296 
1297 
1299 }
1300 
1301 
1302 void
1304  const SUMOSAXAttributes& attrs) {
1305  bool ok = true;
1306  switch (element) {
1307  case OPENDRIVE_TAG_HEADER: {
1308  int majorVersion = attrs.get<int>(OPENDRIVE_ATTR_REVMAJOR, 0, ok);
1309  int minorVersion = attrs.get<int>(OPENDRIVE_ATTR_REVMINOR, 0, ok);
1310  if (majorVersion != 1 || minorVersion != 2) {
1311  WRITE_WARNING("Given openDrive file '" + getFileName() + "' uses version " + toString(majorVersion) + "." + toString(minorVersion) + ";\n Version 1.2 is supported.");
1312  }
1313  }
1314  break;
1315  case OPENDRIVE_TAG_ROAD: {
1316  std::string id = attrs.get<std::string>(OPENDRIVE_ATTR_ID, 0, ok);
1317  std::string streetName = attrs.getOpt<std::string>(OPENDRIVE_ATTR_NAME, 0, ok, "", false);
1318  std::string junction = attrs.get<std::string>(OPENDRIVE_ATTR_JUNCTION, id.c_str(), ok);
1319  SUMOReal length = attrs.get<SUMOReal>(OPENDRIVE_ATTR_LENGTH, id.c_str(), ok);
1320  myCurrentEdge = OpenDriveEdge(id, streetName, junction, length);
1321  }
1322  break;
1324  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
1325  std::string elementType = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
1326  std::string elementID = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
1327  std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
1328  ? attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok)
1329  : "end";
1330  addLink(OPENDRIVE_LT_PREDECESSOR, elementType, elementID, contactPoint);
1331  }
1332  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
1333  int no = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1334  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1335  l.predecessor = no;
1336  }
1337  }
1338  break;
1339  case OPENDRIVE_TAG_SUCCESSOR: {
1340  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
1341  std::string elementType = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
1342  std::string elementID = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
1343  std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
1344  ? attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok)
1345  : "start";
1346  addLink(OPENDRIVE_LT_SUCCESSOR, elementType, elementID, contactPoint);
1347  }
1348  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
1349  int no = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1350  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1351  l.successor = no;
1352  }
1353  }
1354  break;
1355  case OPENDRIVE_TAG_GEOMETRY: {
1356  SUMOReal length = attrs.get<SUMOReal>(OPENDRIVE_ATTR_LENGTH, myCurrentEdge.id.c_str(), ok);
1357  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1358  SUMOReal x = attrs.get<SUMOReal>(OPENDRIVE_ATTR_X, myCurrentEdge.id.c_str(), ok);
1359  SUMOReal y = attrs.get<SUMOReal>(OPENDRIVE_ATTR_Y, myCurrentEdge.id.c_str(), ok);
1360  SUMOReal hdg = attrs.get<SUMOReal>(OPENDRIVE_ATTR_HDG, myCurrentEdge.id.c_str(), ok);
1361  myCurrentEdge.geometries.push_back(OpenDriveGeometry(length, s, x, y, hdg));
1362  }
1363  break;
1364  case OPENDRIVE_TAG_ELEVATION: {
1365  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1366  SUMOReal a = attrs.get<SUMOReal>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok);
1367  SUMOReal b = attrs.get<SUMOReal>(OPENDRIVE_ATTR_B, myCurrentEdge.id.c_str(), ok);
1368  SUMOReal c = attrs.get<SUMOReal>(OPENDRIVE_ATTR_C, myCurrentEdge.id.c_str(), ok);
1369  SUMOReal d = attrs.get<SUMOReal>(OPENDRIVE_ATTR_D, myCurrentEdge.id.c_str(), ok);
1370  myCurrentEdge.elevations.push_back(OpenDriveElevation(s, a, b, c, d));
1371  }
1372  break;
1373  case OPENDRIVE_TAG_LINE: {
1374  std::vector<SUMOReal> vals;
1376  }
1377  break;
1378  case OPENDRIVE_TAG_SPIRAL: {
1379  std::vector<SUMOReal> vals;
1380  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVSTART, myCurrentEdge.id.c_str(), ok));
1381  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVEND, myCurrentEdge.id.c_str(), ok));
1383  }
1384  break;
1385  case OPENDRIVE_TAG_ARC: {
1386  std::vector<SUMOReal> vals;
1387  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CURVATURE, myCurrentEdge.id.c_str(), ok));
1389  }
1390  break;
1391  case OPENDRIVE_TAG_POLY3: {
1392  std::vector<SUMOReal> vals;
1393  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok));
1394  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_B, myCurrentEdge.id.c_str(), ok));
1395  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_C, myCurrentEdge.id.c_str(), ok));
1396  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_D, myCurrentEdge.id.c_str(), ok));
1398  }
1399  break;
1400  case OPENDRIVE_TAG_PARAMPOLY3: {
1401  std::vector<SUMOReal> vals;
1402  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_AU, myCurrentEdge.id.c_str(), ok));
1403  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_BU, myCurrentEdge.id.c_str(), ok));
1404  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CU, myCurrentEdge.id.c_str(), ok));
1405  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_DU, myCurrentEdge.id.c_str(), ok));
1406  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_AV, myCurrentEdge.id.c_str(), ok));
1407  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_BV, myCurrentEdge.id.c_str(), ok));
1408  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_CV, myCurrentEdge.id.c_str(), ok));
1409  vals.push_back(attrs.get<SUMOReal>(OPENDRIVE_ATTR_DV, myCurrentEdge.id.c_str(), ok));
1410  vals.push_back(attrs.getOpt<SUMOReal>(OPENDRIVE_ATTR_PRANGE, myCurrentEdge.id.c_str(), ok, 1.0, false));
1412  }
1413  break;
1415  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1417  }
1418  break;
1419  case OPENDRIVE_TAG_LEFT:
1421  break;
1422  case OPENDRIVE_TAG_CENTER:
1424  break;
1425  case OPENDRIVE_TAG_RIGHT:
1427  break;
1428  case OPENDRIVE_TAG_LANE: {
1429  std::string type = attrs.get<std::string>(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
1430  int id = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1431  std::string level = attrs.hasAttribute(OPENDRIVE_ATTR_LEVEL)
1432  ? attrs.get<std::string>(OPENDRIVE_ATTR_LEVEL, myCurrentEdge.id.c_str(), ok)
1433  : "";
1435  ls.lanesByDir[myCurrentLaneDirection].push_back(OpenDriveLane(id, level, type));
1436  }
1437  break;
1438  case OPENDRIVE_TAG_SIGNAL: {
1439  int id = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1440  std::string type = attrs.get<std::string>(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
1441  std::string name = attrs.getOpt<std::string>(OPENDRIVE_ATTR_NAME, myCurrentEdge.id.c_str(), ok, "", false);
1442  int orientation = attrs.get<std::string>(OPENDRIVE_ATTR_ORIENTATION, myCurrentEdge.id.c_str(), ok) == "-" ? -1 : 1;
1443  SUMOReal s = attrs.get<SUMOReal>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1444  bool dynamic = attrs.get<std::string>(OPENDRIVE_ATTR_DYNAMIC, myCurrentEdge.id.c_str(), ok) == "no" ? false : true;
1445  myCurrentEdge.signals.push_back(OpenDriveSignal(id, type, name, orientation, dynamic, s));
1446  }
1447  break;
1449  myCurrentJunctionID = attrs.get<std::string>(OPENDRIVE_ATTR_ID, myCurrentJunctionID.c_str(), ok);
1450  break;
1451  case OPENDRIVE_TAG_CONNECTION: {
1452  std::string id = attrs.get<std::string>(OPENDRIVE_ATTR_ID, myCurrentJunctionID.c_str(), ok);
1453  myCurrentIncomingRoad = attrs.get<std::string>(OPENDRIVE_ATTR_INCOMINGROAD, myCurrentJunctionID.c_str(), ok);
1455  std::string cp = attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentJunctionID.c_str(), ok);
1457  myConnectionWasEmpty = true;
1458  }
1459  break;
1460  case OPENDRIVE_TAG_LANELINK: {
1461  int from = attrs.get<int>(OPENDRIVE_ATTR_FROM, myCurrentJunctionID.c_str(), ok);
1462  int to = attrs.get<int>(OPENDRIVE_ATTR_TO, myCurrentJunctionID.c_str(), ok);
1463  Connection c;
1465  c.toEdge = myCurrentConnectingRoad;
1466  c.fromLane = from;
1467  c.toLane = to;
1468  c.fromCP = OPENDRIVE_CP_END;
1469  c.toCP = myCurrentContactPoint;
1470  c.all = false;
1471  if (myEdges.find(c.fromEdge) == myEdges.end()) {
1472  WRITE_ERROR("In laneLink-element: incoming road '" + c.fromEdge + "' is not known.");
1473  } else {
1474  OpenDriveEdge* e = myEdges.find(c.fromEdge)->second;
1475  e->connections.insert(c);
1476  myConnectionWasEmpty = false;
1477  }
1478  }
1479  break;
1480  case OPENDRIVE_TAG_WIDTH: {
1481  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 1] == OPENDRIVE_TAG_LANE) {
1482  SUMOReal width = attrs.get<SUMOReal>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok);
1483  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1484  l.width = MAX2(l.width, width);
1485  }
1486  }
1487  break;
1488  case OPENDRIVE_TAG_SPEED: {
1489  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 1] == OPENDRIVE_TAG_LANE) {
1490  SUMOReal speed = attrs.get<SUMOReal>(OPENDRIVE_ATTR_MAX, myCurrentEdge.id.c_str(), ok);
1491  SUMOReal pos = attrs.get<SUMOReal>(OPENDRIVE_ATTR_SOFFSET, myCurrentEdge.id.c_str(), ok);
1492  myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back().speeds.push_back(std::make_pair(pos, speed));
1493  }
1494  }
1495  break;
1496  default:
1497  break;
1498  }
1499  myElementStack.push_back(element);
1500 }
1501 
1502 
1503 void
1505  myElementStack.pop_back();
1506  switch (element) {
1507  case OPENDRIVE_TAG_ROAD:
1509  break;
1511  if (myConnectionWasEmpty) {
1512  Connection c;
1515  c.fromLane = 0;
1516  c.toLane = 0;
1519  c.all = true;
1520  if (myEdges.find(c.fromEdge) == myEdges.end()) {
1521  WRITE_ERROR("In laneLink-element: incoming road '" + c.fromEdge + "' is not known.");
1522  } else {
1523  OpenDriveEdge* e = myEdges.find(c.fromEdge)->second;
1524  e->connections.insert(c);
1525  }
1526  }
1527  break;
1529  myCurrentEdge.laneSections.back().buildLaneMapping(myTypeContainer);
1530  }
1531  break;
1532  default:
1533  break;
1534  }
1535 }
1536 
1537 
1538 
1539 void
1540 NIImporter_OpenDrive::addLink(LinkType lt, const std::string& elementType,
1541  const std::string& elementID,
1542  const std::string& contactPoint) {
1543  OpenDriveLink l(lt, elementID);
1544  // elementType
1545  if (elementType == "road") {
1547  } else if (elementType == "junction") {
1549  }
1550  // contact point
1551  if (contactPoint == "start") {
1553  } else if (contactPoint == "end") {
1555  }
1556  // add
1557  myCurrentEdge.links.push_back(l);
1558 }
1559 
1560 
1561 void
1562 NIImporter_OpenDrive::addGeometryShape(GeometryType type, const std::vector<SUMOReal>& vals) {
1563  // checks
1564  if (myCurrentEdge.geometries.size() == 0) {
1565  throw ProcessError("Mismatching paranthesis in geometry definition for road '" + myCurrentEdge.id + "'");
1566  }
1568  if (last.type != OPENDRIVE_GT_UNKNOWN) {
1569  throw ProcessError("Double geometry information for road '" + myCurrentEdge.id + "'");
1570  }
1571  // set
1572  last.type = type;
1573  last.params = vals;
1574 }
1575 
1576 
1577 bool
1579  if (c1.fromEdge != c2.fromEdge) {
1580  return c1.fromEdge < c2.fromEdge;
1581  }
1582  if (c1.toEdge != c2.toEdge) {
1583  return c1.toEdge < c2.toEdge;
1584  }
1585  if (c1.fromLane != c2.fromLane) {
1586  return c1.fromLane < c2.fromLane;
1587  }
1588  return c1.toLane < c2.toLane;
1589 }
1590 
1591 
1592 
1593 /****************************************************************************/
1594 
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) ...
std::string rightType
the composite type built from all used lane types
static const SUMOReal UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:237
static PositionVector geomFromLine(const OpenDriveEdge &e, const OpenDriveGeometry &g)
static StringBijection< int >::Entry openDriveAttrs[]
The names of openDrive-XML attributes (for passing to GenericSAXHandler)
NBTypeCont & getTypeCont()
Returns the type container.
Definition: NBNetBuilder.h:169
static bool transformCoordinates(Position &from, bool includeInBoundary=true, GeoConvHelper *from_srs=0)
transforms loaded coordinates handles projections, offsets (using GeoConvHelper) and import of height...
PositionVector getSubpart2D(SUMOReal beginOffset, SUMOReal endOffset) const
get subpart of a position vector in two dimensions (Z is ignored)
void addLink(LinkType lt, const std::string &elementType, const std::string &elementID, const std::string &contactPoint)
static bool isReadable(std::string path)
Checks whether the given file is readable.
Definition: FileHelpers.cpp:58
std::string junction
The id of the junction the edge belongs to.
std::vector< OpenDriveElevation > elevations
GeometryType
OpenDrive geometry type enumeration.
int rightLaneNumber
The number of lanes on the right and on the left side, respectively.
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:304
static void buildConnectionsToOuter(const Connection &c, const std::map< std::string, OpenDriveEdge * > &innerEdges, std::vector< Connection > &into)
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 "link".
The base class for traffic light logic definitions.
ContactPoint myCurrentContactPoint
SUMOReal s
The starting offset of this lane section.
T MAX2(T a, T b)
Definition: StdDefs.h:75
static PositionVector geomFromArc(const OpenDriveEdge &e, const OpenDriveGeometry &g)
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)
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1117
static const SUMOReal UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:240
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false)
Runs the given handler on the given file; returns if everything&#39;s ok.
Definition: XMLSubSys.cpp:114
SUMOReal x() const
Returns the x-position.
Definition: Position.h:63
friend bool operator<(const Connection &c1, const Connection &c2)
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:39
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:48
SUMOReal getWidth(const std::string &type) const
Returns the lane width for the given type [m].
Definition: NBTypeCont.cpp:221
static NBNode * getOrBuildNode(const std::string &id, const Position &pos, NBNodeCont &nc)
Builds a node or returns the already built.
void error(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Handler for XML-errors.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
The connection was computed and validated.
Definition: NBEdge.h:117
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:69
static std::string revertID(const std::string &id)
PositionVector reverse() const
reverse position vector
#define C_LENGTH
SUMOReal speed
The speed allowed on this lane.
Definition: NBEdge.h:132
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:124
const std::string & getID() const
Returns the id.
Definition: Named.h:66
SUMOReal length2D() const
Returns the length.
SVCPermissions permissions
List of vehicle types that are allowed on this lane.
Definition: NBEdge.h:135
std::vector< OpenDriveLink > links
A handler which converts occuring elements and attributes into enums.
OpenDriveLaneSection buildLaneSection(SUMOReal startPos)
#define max(a, b)
Definition: polyfonts.c:65
SUMOReal getSpeed(const std::string &type) const
Returns the maximal velocity for the given type [m/s].
Definition: NBTypeCont.cpp:185
const std::string & getFileName() const
returns the current file name
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node.
Definition: NBNode.h:318
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:162
std::string type
The lane&#39;s type.
int getPriority(OpenDriveXMLTag dir) const
Returns the edge&#39;s priority, regarding the direction.
Encapsulated SAX-Attributes.
static StringBijection< TrafficLightType > TrafficLightTypes
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
NBEdgeCont & getEdgeCont()
Returns the edge container.
Definition: NBNetBuilder.h:153
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.
void add(SUMOReal xoff, SUMOReal yoff, SUMOReal zoff)
static void loadNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Loads content of the optionally given SUMO file.
NIImporter_OpenDrive(const NBTypeCont &tc, std::map< std::string, OpenDriveEdge * > &edges)
Constructor.
bool isUsableFileList(const std::string &name) const
Checks whether the named option is usable as a file list (with at least a single file) ...
bool buildSpeedChanges(const NBTypeCont &tc, std::vector< OpenDriveLaneSection > &newSections)
const NBTypeCont & myTypeContainer
bool addLane2LaneConnection(int fromLane, NBEdge *dest, int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, SUMOReal contPos=UNSPECIFIED_CONTPOS, SUMOReal visibility=UNSPECIFIED_VISIBILITY_DISTANCE)
Adds a connection between the specified this edge&#39;s lane and an approached one.
Definition: NBEdge.cpp:802
SUMOReal width
The lane&#39;s width;.
Position positionAtOffset(SUMOReal pos, SUMOReal lateralOffset=0) const
Returns the position at the given length.
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:202
#define POSITION_EPS
Definition: config.h:188
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
OpenDriveXMLTag
Numbers representing openDrive-XML - element names.
bool knows(const std::string &type) const
Returns whether the named type is in the container.
Definition: NBTypeCont.cpp:79
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
The connection was given by the user.
Definition: NBEdge.h:115
static PositionVector geomFromSpiral(const OpenDriveEdge &e, const OpenDriveGeometry &g)
static PositionVector geomFromPoly(const OpenDriveEdge &e, const OpenDriveGeometry &g)
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list...
static StringBijection< int >::Entry openDriveTags[]
The names of openDrive-XML elements (for passing to GenericSAXHandler)
std::string origID
An original ID, if given.
Definition: NBEdge.h:147
void buildLaneMapping(const NBTypeCont &tc)
Build the mapping from OpenDrive to SUMO lanes.
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:206
std::vector< OpenDriveSignal > signals
LinkType
OpenDrive link type enumeration.
void addParameter(const std::string &key, const std::string &value)
Adds a parameter.
static void computeShapes(std::map< std::string, OpenDriveEdge * > &edges)
Computes a polygon representation of each edge&#39;s geometry.
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:416
void addTrafficLight(NBTrafficLightDefinition *tlDef)
Adds a traffic light to the list of traffic lights that control this node.
Definition: NBNode.cpp:314
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:247
std::map< int, int > getInnerConnections(OpenDriveXMLTag dir, const OpenDriveLaneSection &prev)
Returns the links from the previous to this lane section.
NBNodeCont & getNodeCont()
Returns the node container.
Definition: NBNetBuilder.h:161
SUMOReal speed
The lane&#39;s speed (set in post-processing)
Instance responsible for building networks.
Definition: NBNetBuilder.h:112
Representation of an OpenDrive geometry part.
bool getShallBeDiscarded(const std::string &type) const
Returns the information whether edges of this type shall be discarded.
Definition: NBTypeCont.cpp:203
SUMOReal y() const
Returns the y-position.
Definition: Position.h:68
A storage for options typed value containers)
Definition: OptionsCont.h:99
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:81
NBTrafficLightLogicCont & getTLLogicCont()
Returns the traffic light logics container.
Definition: NBNetBuilder.h:177
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
T get(const std::string &str) const
A class for sorting lane sections by their s-value.
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:188
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
static PositionVector geomFromParamPoly(const OpenDriveEdge &e, const OpenDriveGeometry &g)
#define SUMOReal
Definition: config.h:214
static void setNodeSecure(NBNodeCont &nc, OpenDriveEdge &e, const std::string &nodeID, NIImporter_OpenDrive::LinkType lt)
void push_back_noDoublePos(const Position &p)
insert in back a non double position
A connection between two roads.
void addGeometryShape(GeometryType type, const std::vector< SUMOReal > &vals)
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue, bool report=true) const
Tries to read given attribute assuming it is an int.
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:110
SVCPermissions getPermissions(const std::string &type) const
Returns allowed vehicle classes for the given type.
Definition: NBTypeCont.cpp:215
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:203
A traffic light logics which must be computed (only nodes/edges are given)
Definition: NBOwnTLDef.h:54
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:803
Importer for networks stored in openDrive format.
std::vector< std::pair< SUMOReal, SUMOReal > > speeds
List of positions/speeds of speed changes.
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:144
#define UNSET_CONNECTION
TrafficLightType
A storage for available types of edges.
Definition: NBTypeCont.h:62
std::string streetName
The road name of the edge.
void myEndElement(int element)
Called when a closing tag occurs.
static void revisitLaneSections(const NBTypeCont &tc, std::map< std::string, OpenDriveEdge * > &edges)
Rechecks lane sections of the given edges.
Coefficients of an elevation profile (3rd degree polynomial)