Eclipse SUMO - Simulation of Urban MObility
NIImporter_OpenDrive.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
17 // Importer for networks stored in openDrive format
18 /****************************************************************************/
19 
20 
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #include <config.h>
25 #include <string>
26 #include <cmath>
27 #include <iterator>
31 #include <utils/common/ToString.h>
37 #include <netbuild/NBEdge.h>
38 #include <netbuild/NBEdgeCont.h>
39 #include <netbuild/NBNode.h>
40 #include <netbuild/NBNodeCont.h>
41 #include <netbuild/NBNetBuilder.h>
42 #include <netbuild/NBOwnTLDef.h>
50 #include <utils/xml/XMLSubSys.h>
51 #include <utils/geom/Boundary.h>
52 #include "NILoader.h"
53 #include "NIImporter_OpenDrive.h"
54 
55 //#define DEBUG_VARIABLE_WIDTHS
56 //#define DEBUG_VARIABLE_SPEED
57 //#define DEBUG_CONNECTIONS
58 //#define DEBUG_SPIRAL
59 //#define DEBUG_INTERNALSHAPES
60 
61 #define DEBUG_COND(road) ((road)->id == "175")
62 #define DEBUG_COND2(edgeID) (StringUtils::startsWith((edgeID), "disabled"))
63 #define DEBUG_COND3(roadID) (roadID == "175")
64 
65 // ===========================================================================
66 // definitions
67 // ===========================================================================
68 
69 // ===========================================================================
70 // static variables
71 // ===========================================================================
99 
101 };
102 
103 
152  // towards xodr v1.4 speed:unit
154 
156 };
157 
158 
163 
164 // ===========================================================================
165 // method definitions
166 // ===========================================================================
167 // ---------------------------------------------------------------------------
168 // static methods (interface in this case)
169 // ---------------------------------------------------------------------------
170 void
172  // check whether the option is set (properly)
173  if (!oc.isUsableFileList("opendrive-files")) {
174  return;
175  }
176  // prepare types
177  myImportAllTypes = oc.getBool("opendrive.import-all-lanes");
178  myImportWidths = !oc.getBool("opendrive.ignore-widths");
179  myMinWidth = oc.getFloat("opendrive.min-width");
180  myImportInternalShapes = oc.getBool("opendrive.internal-shapes");
181  NBTypeCont& tc = nb.getTypeCont();
182  // build the handler
183  std::map<std::string, OpenDriveEdge*> edges;
184  NIImporter_OpenDrive handler(nb.getTypeCont(), edges);
185  // parse file(s)
186  std::vector<std::string> files = oc.getStringVector("opendrive-files");
187  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
188  if (!FileHelpers::isReadable(*file)) {
189  WRITE_ERROR("Could not open opendrive file '" + *file + "'.");
190  return;
191  }
192  handler.setFileName(*file);
193  PROGRESS_BEGIN_MESSAGE("Parsing opendrive from '" + *file + "'");
194  XMLSubSys::runParser(handler, *file);
196  }
197  // split inner/outer edges
198  std::map<std::string, OpenDriveEdge*> innerEdges, outerEdges;
199  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
200  if ((*i).second->isInner) {
201  innerEdges[(*i).first] = (*i).second;
202  } else {
203  outerEdges[(*i).first] = (*i).second;
204  }
205  }
206 
207  // convert geometries into a discretised representation
208  computeShapes(edges);
209  // check whether lane sections are valid and whether further must be introduced
210  revisitLaneSections(tc, edges);
211 
212  // -------------------------
213  // node building
214  // -------------------------
215  // build nodes#1
216  // look at all links which belong to a node, collect their bounding boxes
217  // and place the node in the middle of this bounding box
218  std::map<std::string, Boundary> posMap;
219  std::map<std::string, std::string> edge2junction;
220  // compute node positions
221  for (std::map<std::string, OpenDriveEdge*>::iterator i = innerEdges.begin(); i != innerEdges.end(); ++i) {
222  OpenDriveEdge* e = (*i).second;
223  assert(e->junction != "-1" && e->junction != "");
224  edge2junction[e->id] = e->junction;
225  if (posMap.find(e->junction) == posMap.end()) {
226  posMap[e->junction] = Boundary();
227  }
228  posMap[e->junction].add(e->geom.getBoxBoundary());
229  }
230  // build nodes
231  for (std::map<std::string, Boundary>::iterator i = posMap.begin(); i != posMap.end(); ++i) {
232  //std::cout << " import node=" << (*i).first << " z=" << (*i).second.getCenter() << " boundary=" << (*i).second << "\n";
233  if (!nb.getNodeCont().insert((*i).first, (*i).second.getCenter())) {
234  throw ProcessError("Could not add node '" + (*i).first + "'.");
235  }
236  }
237  // assign built nodes
238  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
239  OpenDriveEdge* e = (*i).second;
240  for (std::vector<OpenDriveLink>::iterator j = e->links.begin(); j != e->links.end(); ++j) {
241  OpenDriveLink& l = *j;
242  const std::string& nid = l.elementID;
243  if (l.elementType != OPENDRIVE_ET_ROAD) {
244  if (nb.getNodeCont().retrieve(nid) == nullptr) {
245  // not yet seen, build (possibly a junction without connections)
246  Position pos = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e->geom[-1] : e->geom[0];
247  if (!nb.getNodeCont().insert(nid, pos)) {
248  throw ProcessError("Could not build node '" + nid + "'.");
249  }
250  }
251  // set node information
253  continue;
254  }
255  if (edge2junction.find(l.elementID) != edge2junction.end()) {
256  // set node information of an internal road
257  setNodeSecure(nb.getNodeCont(), *e, edge2junction[l.elementID], l.linkType);
258  continue;
259  }
260  }
261  }
262  // we should now have all nodes set for links which are not outer edge-to-outer edge links
263 
264 
265  // build nodes#2
266  // build nodes for all outer edge-to-outer edge connections
267  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
268  OpenDriveEdge* e = (*i).second;
269  for (std::vector<OpenDriveLink>::iterator j = e->links.begin(); j != e->links.end(); ++j) {
270  OpenDriveLink& l = *j;
271  if (l.elementType != OPENDRIVE_ET_ROAD || edge2junction.find(l.elementID) != edge2junction.end()) {
272  // is a connection to an internal edge, or a node, skip
273  continue;
274  }
275  // we have a direct connection between to external edges
276  std::string id1 = e->id;
277  std::string id2 = l.elementID;
278  if (id1 < id2) {
279  std::swap(id1, id2);
280  }
281  std::string nid = id1 + "." + id2;
282  if (nb.getNodeCont().retrieve(nid) == nullptr) {
283  // not yet seen, build
284  Position pos = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e->geom[-1] : e->geom[0];
285  if (!nb.getNodeCont().insert(nid, pos)) {
286  throw ProcessError("Could not build node '" + nid + "'.");
287  }
288  }
289  /* debug-stuff
290  else {
291  Position pos = l.linkType==OPENDRIVE_LT_SUCCESSOR ? e.geom[e.geom.size()-1] : e.geom[0];
292  cout << nid << " " << pos << " " << nb.getNodeCont().retrieve(nid)->getPosition() << endl;
293  }
294  */
295  setNodeSecure(nb.getNodeCont(), *e, nid, l.linkType);
296  }
297  }
298  // we should now have start/end nodes for all outer edge-to-outer edge connections
299 
300 
301  // build nodes#3
302  // assign further nodes generated from inner-edges
303  // these nodes have not been assigned earlier, because the connections are referenced in inner-edges
304  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
305  OpenDriveEdge* e = (*i).second;
306  if (e->to != nullptr && e->from != nullptr) {
307  continue;
308  }
309  for (std::map<std::string, OpenDriveEdge*>::iterator j = innerEdges.begin(); j != innerEdges.end(); ++j) {
310  OpenDriveEdge* ie = (*j).second;
311  for (std::vector<OpenDriveLink>::iterator k = ie->links.begin(); k != ie->links.end(); ++k) {
312  OpenDriveLink& il = *k;
313  if (il.elementType != OPENDRIVE_ET_ROAD || il.elementID != e->id) {
314  // not conneted to the currently investigated outer edge
315  continue;
316  }
317  std::string nid = edge2junction[ie->id];
318  if (il.contactPoint == OPENDRIVE_CP_START) {
320  } else {
322  }
323  }
324  }
325 
326  }
327 
328  // build start/end nodes which were not defined previously
329  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
330  OpenDriveEdge* e = (*i).second;
331  if ((e->from == nullptr || e->to == nullptr) && e->geom.size() == 0) {
332  continue;
333  }
334  if (e->from == nullptr) {
335  const std::string nid = e->id + ".begin";
336  e->from = getOrBuildNode(nid, e->geom.front(), nb.getNodeCont());
337  }
338  if (e->to == nullptr) {
339  const std::string nid = e->id + ".end";
340  e->to = getOrBuildNode(nid, e->geom.back(), nb.getNodeCont());
341  }
342  }
343 
344 
345  // -------------------------
346  // edge building
347  // -------------------------
348  const double defaultSpeed = tc.getSpeed("");
349  const bool saveOrigIDs = OptionsCont::getOptions().getBool("output.original-names");
350  // build edges
351  for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
352  OpenDriveEdge* e = (*i).second;
353  if (e->geom.size() < 2) {
354  WRITE_WARNING("Ignoring road '" + e->id + "' without geometry.");
355  continue;
356  }
357  bool lanesBuilt = false;
358 
359  // go along the lane sections, build a node in between of each pair
360 
363 
365  NBNode* sFrom = e->from;
366  NBNode* sTo = e->to;
367  int priorityR = e->getPriority(OPENDRIVE_TAG_RIGHT);
368  int priorityL = e->getPriority(OPENDRIVE_TAG_LEFT);
369  double sB = 0;
370  double sE = e->length;
371  // 0-length geometries are possible if only the inner points are represented
372  PositionVector geomWithOffset = e->geom;
373  if (e->laneOffsets.size() > 0) {
374  try {
375  geomWithOffset.move2side(e->laneOffsets);
376  //std::cout << " e=" << e->id << " offsets=" << e->laneOffsets << " geom=" << e->geom << " geom2=" << geomWithOffset << "\n";
377  } catch (InvalidArgument&) {
378  WRITE_WARNING("Could not apply laneOffsets for edge '" + e->id + "'");
379  }
380  }
381  const double length2D = geomWithOffset.length2D();
382  double cF = length2D == 0 ? 1 : e->length / length2D;
383  NBEdge* prevRight = nullptr;
384  NBEdge* prevLeft = nullptr;
385 
386  // starting at the same node as ending, and no lane sections?
387  if (sFrom == sTo && e->laneSections.size() == 1) {
388  // --> loop, split!
390  ls.s = e->length / 2.;
391  e->laneSections.push_back(ls);
392  WRITE_WARNING("Edge '" + e->id + "' has to be split as it connects same junctions.")
393  }
394  sanitizeWidths(e);
395  if (myMinWidth > 0) {
396  const double minDist = oc.getFloat("opendrive.curve-resolution");
397  splitMinWidths(e, tc, minDist);
398  }
399 
400  // build along lane sections
401  for (std::vector<OpenDriveLaneSection>::iterator j = e->laneSections.begin(); j != e->laneSections.end(); ++j) {
402  // add internal node if needed
403  if (j == e->laneSections.end() - 1) {
404  sTo = e->to;
405  sE = e->length / cF;
406  } else {
407  double nextS = (j + 1)->s;
408  sTo = new NBNode(e->id + "." + toString(nextS), geomWithOffset.positionAtOffset(nextS));
409  if (!nb.getNodeCont().insert(sTo)) {
410  throw ProcessError("Could not add node '" + sTo->getID() + "'.");
411  }
412  sE = nextS / cF;
413  }
414  PositionVector geom = geomWithOffset.getSubpart2D(sB, sE);
415  std::string id = e->id;
416  if (sFrom != e->from || sTo != e->to) {
417  id = id + "." + toString((*j).s);
418  } else if (e->laneSections.size() == 1) {
419  id = id + ".0.00";
420  }
421 #ifdef DEBUG_VARIABLE_WIDTHS
422  if (DEBUG_COND(e)) {
423  std::cout << " id=" << id << " sB=" << sB << " sE=" << sE << " geom=" << geom << "\n";
424  }
425 #endif
426 
427  // build lanes to right
428  NBEdge* currRight = nullptr;
429  if ((*j).rightLaneNumber > 0) {
430  currRight = new NBEdge("-" + id, sFrom, sTo, (*j).rightType, defaultSpeed, (*j).rightLaneNumber, priorityR,
432  lanesBuilt = true;
433  const std::vector<OpenDriveLane>& lanes = (*j).lanesByDir[OPENDRIVE_TAG_RIGHT];
434  for (std::vector<OpenDriveLane>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
435  std::map<int, int>::const_iterator lp = (*j).laneMap.find((*k).id);
436  if (lp != (*j).laneMap.end()) {
437  int sumoLaneIndex = lp->second;
438  setLaneAttributes(e, currRight->getLaneStruct(sumoLaneIndex), *k, saveOrigIDs, tc);
439  }
440  }
441  if (!nb.getEdgeCont().insert(currRight, myImportAllTypes)) {
442  throw ProcessError("Could not add edge '" + currRight->getID() + "'.");
443  }
444  if (nb.getEdgeCont().wasIgnored(id)) {
445  prevRight = nullptr;
446  } else {
447  // connect lane sections
448  if (prevRight != nullptr) {
449  std::map<int, int> connections = (*j).getInnerConnections(OPENDRIVE_TAG_RIGHT, *(j - 1));
450  for (std::map<int, int>::const_iterator k = connections.begin(); k != connections.end(); ++k) {
451 #ifdef DEBUG_CONNECTIONS
452  if (DEBUG_COND(e)) {
453  std::cout << "addCon1 from=" << prevRight->getID() << "_" << (*k).first << " to=" << currRight->getID() << "_" << (*k).second << "\n";
454  }
455 #endif
456  prevRight->addLane2LaneConnection((*k).first, currRight, (*k).second, NBEdge::L2L_VALIDATED);
457  }
458  }
459  prevRight = currRight;
460  }
461  }
462 
463  // build lanes to left
464  NBEdge* currLeft = nullptr;
465  if ((*j).leftLaneNumber > 0) {
466  currLeft = new NBEdge(id, sTo, sFrom, (*j).leftType, defaultSpeed, (*j).leftLaneNumber, priorityL,
468  lanesBuilt = true;
469  const std::vector<OpenDriveLane>& lanes = (*j).lanesByDir[OPENDRIVE_TAG_LEFT];
470  for (std::vector<OpenDriveLane>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
471  std::map<int, int>::const_iterator lp = (*j).laneMap.find((*k).id);
472  if (lp != (*j).laneMap.end()) {
473  int sumoLaneIndex = lp->second;
474  setLaneAttributes(e, currLeft->getLaneStruct(sumoLaneIndex), *k, saveOrigIDs, tc);
475  }
476  }
477  if (!nb.getEdgeCont().insert(currLeft, myImportAllTypes)) {
478  throw ProcessError("Could not add edge '" + currLeft->getID() + "'.");
479  }
480  if (nb.getEdgeCont().wasIgnored(id)) {
481  prevLeft = nullptr;
482  } else {
483  // connect lane sections
484  if (prevLeft != nullptr) {
485  std::map<int, int> connections = (*j).getInnerConnections(OPENDRIVE_TAG_LEFT, *(j - 1));
486  for (std::map<int, int>::const_iterator k = connections.begin(); k != connections.end(); ++k) {
487 #ifdef DEBUG_CONNECTIONS
488  if (DEBUG_COND(e)) {
489  std::cout << "addCon2 from=" << currLeft->getID() << "_" << (*k).first << " to=" << prevLeft->getID() << "_" << (*k).second << "\n";
490  }
491 #endif
492  currLeft->addLane2LaneConnection((*k).first, prevLeft, (*k).second, NBEdge::L2L_VALIDATED);
493  }
494  }
495  prevLeft = currLeft;
496  }
497  }
498  (*j).sumoID = id;
499 
500 
501  sB = sE;
502  sFrom = sTo;
503  }
504  // optionally write road objects
505  if (oc.isSet("polygon-output")) {
506  const bool writeGeo = GeoConvHelper::getLoaded().usingGeoProjection() && (
507  oc.isDefault("proj.plain-geo") || oc.getBool("proj.plain-geo"));
508  OutputDevice& dev = OutputDevice::getDevice(oc.getString("polygon-output"));
509  dev.writeXMLHeader("additional", "additional_file.xsd");
510  //SUMOPolygon poly("road_" + e->id, "road", RGBColor::BLUE, e->geom, true, false);
511  //poly.writeXML(dev, false);
512  for (auto& o : e->objects) {
513  Position ref = e->geom.positionAtOffset2D(o.s, -o.t);
514  if (o.radius >= 0) {
515  // cicrular shape
516  // GeoConvHelper::getFinal is not ready yet
518  PointOfInterest poly(o.id, o.type, RGBColor::YELLOW, ref, true, "", -1, 0);
519  poly.setParameter("name", o.name);
520  poly.writeXML(dev, writeGeo);
521  } else {
522  // rectangular shape
523  PositionVector centerLine;
524  centerLine.push_back(Position(-o.length / 2, 0));
525  centerLine.push_back(Position(o.length / 2, 0));
526  double roadHdg = e->geom.rotationAtOffset(o.s);
527  centerLine.rotate2D(roadHdg + o.hdg);
528  //PointOfInterest poiRef("ref_" + o.id, "", RGBColor::CYAN, ref, false, "", 0, 0, Shape::DEFAULT_LAYER + 2);
529  //poiRef.writeXML(dev, false);
530  centerLine.add(ref);
531  //SUMOPolygon polyCenter("center_" + o.id, "", RGBColor::MAGENTA, centerLine, true, false, Shape::DEFAULT_LAYER + 1);
532  //polyCenter.writeXML(dev, false);
533  centerLine.move2side(o.width / 2);
534  PositionVector shape = centerLine;
535  centerLine.move2side(-o.width);
536  shape.append(centerLine.reverse(), POSITION_EPS);
537  if (writeGeo) {
538  // GeoConvHelper::getFinal is not ready yet
539  for (int i = 0; i < (int) shape.size(); i++) {
541  }
542  }
543  SUMOPolygon poly(o.id, o.type, RGBColor::YELLOW, shape, true, true, 1);
544  poly.setParameter("name", o.name);
545  poly.writeXML(dev, writeGeo);
546  }
547  }
548  }
549  if (!lanesBuilt) {
550  WRITE_WARNING("Edge '" + e->id + "' has no lanes.");
551  }
552  }
553 
554  // -------------------------
555  // connections building
556  // -------------------------
557  // generate explicit lane-to-lane connections
558  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
559  setEdgeLinks2(*(*i).second, edges);
560  }
561  // compute connections across intersections, if any
562  std::vector<Connection> connections2;
563  for (std::map<std::string, OpenDriveEdge*>::iterator j = edges.begin(); j != edges.end(); ++j) {
564  const std::set<Connection>& conns = (*j).second->connections;
565 
566  for (std::set<Connection>::const_iterator i = conns.begin(); i != conns.end(); ++i) {
567  if (innerEdges.find((*i).fromEdge) != innerEdges.end()) {
568  // connections starting at inner edges are processed by starting from outer edges
569  continue;
570  }
571  if (innerEdges.find((*i).toEdge) != innerEdges.end()) {
572  std::set<Connection> seen;
573  buildConnectionsToOuter(*i, innerEdges, connections2, seen);
574  } else {
575  connections2.push_back(*i);
576  }
577  }
578  }
579  // set connections
580  for (std::vector<Connection>::const_iterator i = connections2.begin(); i != connections2.end(); ++i) {
581 #ifdef DEBUG_CONNECTIONS
582  std::cout << "connections2 " << (*i).getDescription() << "\n";
583 #endif
584  std::string fromEdge = (*i).fromEdge;
585  if (edges.find(fromEdge) == edges.end()) {
586  WRITE_WARNING("While setting connections: from-edge '" + fromEdge + "' is not known.");
587  continue;
588  }
589  OpenDriveEdge* odFrom = edges[fromEdge];
590  int fromLane = (*i).fromLane;
591  bool fromLast = ((*i).fromCP == OPENDRIVE_CP_END) && ((*i).fromLane < 0);
592  fromEdge = fromLast ? odFrom->laneSections.back().sumoID : odFrom->laneSections[0].sumoID;
593 
594  std::string toEdge = (*i).toEdge;
595  if (edges.find(toEdge) == edges.end()) {
596  WRITE_WARNING("While setting connections: to-edge '" + toEdge + "' is not known.");
597  continue;
598  }
599 
600  OpenDriveEdge* odTo = edges[toEdge];
601  int toLane = (*i).toLane;
602  bool toLast = ((*i).toCP == OPENDRIVE_CP_END) || ((*i).toLane > 0);
603  toEdge = toLast ? odTo->laneSections.back().sumoID : odTo->laneSections[0].sumoID;
604 
605  if (fromLane == UNSET_CONNECTION) {
606  continue;
607  }
608  if (fromLane < 0) {
609  fromEdge = revertID(fromEdge);
610  }
611  if (toLane == UNSET_CONNECTION) {
612  continue;
613  }
614  if (toLane < 0) {
615  toEdge = revertID(toEdge);
616  }
617  fromLane = fromLast ? odFrom->laneSections.back().laneMap[fromLane] : odFrom->laneSections[0].laneMap[fromLane];
618  toLane = toLast ? odTo->laneSections.back().laneMap[toLane] : odTo->laneSections[0].laneMap[toLane];
619  NBEdge* from = nb.getEdgeCont().retrieve(fromEdge);
620  NBEdge* to = nb.getEdgeCont().retrieve(toEdge);
621  if (from == nullptr) {
622  WRITE_WARNING("Could not find fromEdge representation of '" + fromEdge + "' in connection '" + (*i).origID + "'.");
623  }
624  if (to == nullptr) {
625  WRITE_WARNING("Could not find fromEdge representation of '" + toEdge + "' in connection '" + (*i).origID + "'.");
626  }
627  if (from == nullptr || to == nullptr) {
628  continue;
629  }
630 
631 #ifdef DEBUG_CONNECTIONS
632  if (DEBUG_COND2(from->getID())) {
633  std::cout << "addCon3 from=" << from->getID() << "_" << fromLane << " to=" << to->getID() << "_" << toLane << "\n";
634  }
635 #endif
636  from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER, false, false, true,
640  (*i).shape);
641 
642  if ((*i).origID != "" && saveOrigIDs) {
643  // @todo: this is the most silly way to determine the connection
644  std::vector<NBEdge::Connection>& cons = from->getConnections();
645  for (std::vector<NBEdge::Connection>::iterator k = cons.begin(); k != cons.end(); ++k) {
646  if ((*k).fromLane == fromLane && (*k).toEdge == to && (*k).toLane == toLane) {
647  (*k).setParameter(SUMO_PARAM_ORIGID, (*i).origID + "_" + toString((*i).origLane));
648  break;
649  }
650  }
651  }
652  }
653 
654 
655  // -------------------------
656  // traffic lights
657  // -------------------------
658  std::map<std::string, std::string> tlsControlled;
659  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
660  OpenDriveEdge* e = (*i).second;
661  for (std::vector<OpenDriveSignal>::const_iterator j = e->signals.begin(); j != e->signals.end(); ++j) {
662  if ((*j).type != "1000001") { // traffic_light (Section 6.11)
663  continue;
664  }
665  std::vector<OpenDriveLaneSection>::iterator k = e->laneSections.begin();
666  bool found = false;
667  for (; k != e->laneSections.end() - 1 && !found;) {
668  if ((*j).s > (*k).s && (*j).s <= (*(k + 1)).s) {
669  found = true;
670  } else {
671  ++k;
672  }
673  }
674 
675  // @todo: major problem, currently, still not completely solved:
676  // inner edges may have traffic lights, too. Nice on one hand, as directions can be recognized
677  // but hard to follow backwards
678  std::string id = (*k).sumoID;
679  if (id == "") {
680  if (e->junction != "") {
681  //WRITE_WARNING("Found a traffic light signal on an internal edge; will not build it (original edge id='" + e->id + "').");
682  std::string fromID, toID;
683  for (std::vector<OpenDriveLink>::const_iterator l = e->links.begin(); l != e->links.end(); ++l) {
684  if ((*l).linkType == OPENDRIVE_LT_PREDECESSOR && (*l).elementType == OPENDRIVE_ET_ROAD) {
685  if (fromID != "") {
686  WRITE_WARNING("Ambigous start of connection.");
687  }
688  OpenDriveEdge* e = edges[(*l).elementID];
689  if ((*l).contactPoint == OPENDRIVE_CP_START) {
690  fromID = e->laneSections[0].sumoID;
691  if ((*j).orientation < 0) {
692  fromID = "-" + fromID;
693  }
694  } else {
695  fromID = e->laneSections.back().sumoID;
696  if ((*j).orientation > 0) {
697  fromID = "-" + fromID;
698  }
699  }
700  }
701  if ((*l).linkType == OPENDRIVE_LT_SUCCESSOR && (*l).elementType == OPENDRIVE_ET_ROAD) {
702  if (toID != "") {
703  WRITE_WARNING("Ambigous end of connection.");
704  }
705  OpenDriveEdge* e = edges[(*l).elementID];
706  toID = (*l).contactPoint == OPENDRIVE_CP_START ? e->laneSections[0].sumoID : e->laneSections.back().sumoID;
707  }
708  }
709  id = fromID + "->" + toID;
710  } else {
711  WRITE_WARNING("Found a traffic light signal on an unknown edge (original edge id='" + e->id + "').");
712  continue;
713  }
714  } else {
715  if ((*j).orientation > 0) {
716  id = "-" + id;
717  }
718  }
719  tlsControlled[id] = (*j).name;
720  }
721  }
722 
723  for (std::map<std::string, std::string>::iterator i = tlsControlled.begin(); i != tlsControlled.end(); ++i) {
724  std::string id = (*i).first;
725  if (id.find("->") != std::string::npos) {
726  id = id.substr(0, id.find("->"));
727  }
728  NBEdge* e = nb.getEdgeCont().retrieve(id);
729  if (e == nullptr) {
730  WRITE_WARNING("Could not find edge '" + id + "' while building its traffic light.");
731  continue;
732  }
733  NBNode* toNode = e->getToNode();
734  if (!toNode->isTLControlled()) {
736  NBOwnTLDef* tlDef = new NBOwnTLDef(toNode->getID(), toNode, 0, type);
737  if (!nb.getTLLogicCont().insert(tlDef)) {
738  // actually, nothing should fail here
739  delete tlDef;
740  throw ProcessError();
741  }
742  toNode->addTrafficLight(tlDef);
743  //tlDef->setSinglePhase();
744  }
745  NBTrafficLightDefinition* tlDef = *toNode->getControllingTLS().begin();
746  tlDef->setParameter("connection:" + id, (*i).second);
747  }
748 
749  // -------------------------
750  // clean up
751  // -------------------------
752  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
753  delete (*i).second;
754  }
755 }
756 
757 void
758 NIImporter_OpenDrive::setLaneAttributes(const OpenDriveEdge* e, NBEdge::Lane& sumoLane, const OpenDriveLane& odLane, bool saveOrigIDs, const NBTypeCont& tc) {
759  if (saveOrigIDs) {
760  sumoLane.setParameter(SUMO_PARAM_ORIGID, e->id + "_" + toString(odLane.id));
761  }
762  sumoLane.speed = odLane.speed != 0 ? odLane.speed : tc.getSpeed(odLane.type);
763  sumoLane.permissions = tc.getPermissions(odLane.type);
764  sumoLane.width = myImportWidths && odLane.width != NBEdge::UNSPECIFIED_WIDTH ? odLane.width : tc.getWidth(odLane.type);
765  sumoLane.type = odLane.type;
766 
767  const double widthResolution = tc.getWidthResolution(odLane.type);
768  const double maxWidth = tc.getMaxWidth(odLane.type);
769 
770  const bool forbiddenNarrow = (sumoLane.width < myMinWidth
771  && (sumoLane.permissions & SVC_PASSENGER) != 0
772  && sumoLane.width < tc.getWidth(odLane.type));
773 
774  if (sumoLane.width >= 0 && widthResolution > 0) {
775  sumoLane.width = floor(sumoLane.width / widthResolution + 0.5) * widthResolution;
776  if (forbiddenNarrow && sumoLane.width >= myMinWidth) {
777  sumoLane.width -= widthResolution;
778  if (sumoLane.width <= 0) {
780  }
781  } else if (sumoLane.width == 0) {
782  // round up when close to 0
783  sumoLane.width = widthResolution;
784  }
785  }
786  if (maxWidth > 0) {
787  sumoLane.width = MIN2(sumoLane.width, maxWidth);
788  }
789  if (forbiddenNarrow) {
790  // avoid narrow passenger car lanes (especially at sections with varying width)
792  }
793 }
794 
795 void
796 NIImporter_OpenDrive::buildConnectionsToOuter(const Connection& c, const std::map<std::string, OpenDriveEdge*>& innerEdges, std::vector<Connection>& into, std::set<Connection>& seen) {
797 
798  OpenDriveEdge* dest = innerEdges.find(c.toEdge)->second;
799 #ifdef DEBUG_CONNECTIONS
800  if (DEBUG_COND3(c.fromEdge)) {
801  std::cout << " buildConnectionsToOuter " << c.getDescription() << "\n";
802  std::cout << " dest=" << (dest == nullptr ? "NULL" : dest->id) << " seenlist=";
803  for (std::set<Connection>::const_iterator i = seen.begin(); i != seen.end(); ++i) {
804  std::cout << " " << (*i).fromEdge << "," << (*i).toEdge << " ";
805  }
806  std::cout << "\n";
807  }
808 #endif
809  if (dest == nullptr) {
811  return;
812  }
813  seen.insert(c);
814  const std::set<Connection>& conts = dest->connections;
815  for (std::set<Connection>::const_iterator i = conts.begin(); i != conts.end(); ++i) {
816  auto innerEdgesIt = innerEdges.find((*i).toEdge);
817 #ifdef DEBUG_CONNECTIONS
818  if (DEBUG_COND3(c.fromEdge)) {
819  std::cout << " toInner=" << (innerEdgesIt != innerEdges.end()) << " destCon " << (*i).getDescription() << "\n";
820  }
821 #endif
822  if (innerEdgesIt != innerEdges.end()) {
823  std::vector<Connection> t;
824  if (seen.count(*i) == 0) {
825  buildConnectionsToOuter(*i, innerEdges, t, seen);
826  for (std::vector<Connection>::const_iterator j = t.begin(); j != t.end(); ++j) {
827  // @todo this section is unverified
828  Connection cn = (*j);
829  cn.fromEdge = c.fromEdge;
830  cn.fromLane = c.fromLane;
831  cn.fromCP = c.fromCP;
832  cn.all = c.all; // @todo "all" is a hack trying to avoid the "from is zero" problem;
834  cn.shape = innerEdgesIt->second->geom + c.shape;
835  }
836  into.push_back(cn);
837  }
838  } else {
839  WRITE_WARNING("Circular connections in junction including roads '" + c.fromEdge + "' and '" + c.toEdge + "', loop size " + toString(seen.size()));
840  }
841  } else {
842  if (laneSectionsConnected(dest, c.toLane, (*i).fromLane)) {
843  Connection cn = (*i);
844  cn.fromEdge = c.fromEdge;
845  cn.fromLane = c.fromLane;
846  cn.fromCP = c.fromCP;
847  cn.all = c.all;
848  cn.origID = c.toEdge;
849  cn.origLane = c.toLane;
851  OpenDriveXMLTag lanesDir;
852  cn.shape = dest->geom;
853  // determine which lane of dest belongs to this connection
854  int referenceLane = 0;
855  int offsetFactor = 1;
856  if (c.toCP == OPENDRIVE_CP_END) {
857  offsetFactor = -1;
858  lanesDir = OPENDRIVE_TAG_LEFT;
859  for (const auto& destLane : dest->laneSections.front().lanesByDir[lanesDir]) {
860  if (destLane.successor == c.fromLane) {
861  referenceLane = destLane.id;
862  break;
863  }
864  }
865  } else {
866  lanesDir = OPENDRIVE_TAG_RIGHT;
867  for (const auto& destLane : dest->laneSections.front().lanesByDir[lanesDir]) {
868  if (destLane.predecessor == c.fromLane) {
869  referenceLane = destLane.id;
870  break;
871  }
872  }
873  }
874  // compute offsets
875  //if (cn.fromEdge == "1014000" && dest->id == "3001022") {
876  // std::cout << "computeOffsets\n";
877  //}
878  std::vector<double> offsets(dest->geom.size(), 0);
879  if (dest->laneOffsets.size() > 0) {
880  offsets = dest->laneOffsets;
881  }
882 #ifdef DEBUG_INTERNALSHAPES
883  std::string destPred;
884 #endif
885  double s = 0;
886  int iShape = 0;
887  for (int laneSectionIndex = 0; laneSectionIndex < (int)dest->laneSections.size(); laneSectionIndex++) {
888  auto& laneSection = dest->laneSections[laneSectionIndex];
889  const double nextS = laneSectionIndex + 1 < (int)dest->laneSections.size() ? dest->laneSections[laneSectionIndex + 1].s : std::numeric_limits<double>::max();
890  int i = iShape; // shape index at the start of the current lane section
891  double sStart = s; // distance offset a the start of the current lane section
892  double finalS = s; // final distance value after processing this segment
893  int finalI = i;
894  for (const OpenDriveLane& destLane : laneSection.lanesByDir[lanesDir]) {
895  // each lane of the current segment repeats the same section of shape points and distance offsets
896  double sectionS = 0;
897  i = iShape;
898  s = sStart;
899 #ifdef DEBUG_INTERNALSHAPES
900  destPred += " lane=" + toString(destLane.id)
901  + " pred=" + toString(destLane.predecessor)
902  + " succ=" + toString(destLane.successor)
903  + " wStart=" + toString(destLane.widthData.front().computeAt(0))
904  + " wEnd=" + toString(destLane.widthData.front().computeAt(cn.shape.length2D()))
905  + " width=" + toString(destLane.width) + "\n";
906 #endif
907  if (abs(destLane.id) <= abs(referenceLane)) {
908  const double multiplier = offsetFactor * (destLane.id == referenceLane ? 0.5 : 1);
909 #ifdef DEBUG_INTERNALSHAPES
910  destPred += " multiplier=" + toString(multiplier) + "\n";
911 #endif
912  int widthDataIndex = 0;
913  while (s < nextS && i < (int)cn.shape.size()) {
914  if (i > 0) {
915  const double dist = cn.shape[i - 1].distanceTo2D(cn.shape[i]);
916  s += dist;
917  sectionS += dist;
918 
919  }
920  while (widthDataIndex + 1 < (int)destLane.widthData.size()
921  && sectionS >= destLane.widthData[widthDataIndex + 1].s) {
922  widthDataIndex++;
923  }
924  offsets[i] += destLane.widthData[widthDataIndex].computeAt(sectionS) * multiplier;
925  //if (cn.fromEdge == "1014000" && dest->id == "3001022") {
926  // std::cout << " i=" << i << " s=" << s << " lane=" << destLane.id << " rlane=" << referenceLane /*<< " nextS=" << nextS << */ << " lsIndex=" << laneSectionIndex << " wI=" << widthDataIndex << " wSize=" << destLane.widthData.size() << " m=" << multiplier << " o=" << offsets[i] << "\n";
927  //}
928  i++;
929  }
930  finalS = s;
931  finalI = i;
932  } else if (finalS == s) {
933  // update finalS without changing offsets
934  while (s < nextS && i < (int)cn.shape.size()) {
935  if (i > 0) {
936  const double dist = cn.shape[i - 1].distanceTo2D(cn.shape[i]);
937  s += dist;
938  finalS += dist;
939 
940  }
941  i++;
942  }
943  finalI = i;
944 
945  }
946  }
947  // advance values for the next lane section
948  iShape = finalI;
949  s = finalS;
950  }
951  try {
952  cn.shape.move2side(offsets);
953  } catch (InvalidArgument&) {
954  WRITE_WARNING("Could not import internal lane shape from edge '" + c.fromEdge + "' to edge '" + c.toEdge);
955  cn.shape.clear();
956  }
957 #ifdef DEBUG_INTERNALSHAPES
958  std::cout << "internalShape "
959  << c.getDescription()
960  << " dest=" << dest->id
961  << " refLane=" << referenceLane
962  << " destPred\n" << destPred
963  << " offsets=" << offsets
964  << "\n shape=" << dest->geom
965  << "\n shape2=" << cn.shape
966  << "\n";
967 #endif
968  if (c.toCP == OPENDRIVE_CP_END) {
969  cn.shape = cn.shape.reverse();
970  }
971  }
972 #ifdef DEBUG_CONNECTIONS
973  if (DEBUG_COND3(c.fromEdge)) {
974  std::cout << " added connection\n";
975  }
976 #endif
977  into.push_back(cn);
978  }
979  }
980  }
981 }
982 
983 
984 bool
986  if (edge->laneSections.size() == 1) {
987  return in == out;
988  } else {
989  // there could be spacing lanes (type 'none') that lead to a shift in lane index
990  for (auto it = edge->laneSections.begin(); it + 1 < edge->laneSections.end(); it++) {
991  OpenDriveLaneSection& laneSection = *it;
992  if (laneSection.lanesByDir.find(OPENDRIVE_TAG_RIGHT) != laneSection.lanesByDir.end()) {
993  for (OpenDriveLane& lane : laneSection.lanesByDir.find(OPENDRIVE_TAG_RIGHT)->second) {
994  if (lane.id == in) {
995  in = lane.successor;
996  }
997  }
998  }
999  if (laneSection.lanesByDir.find(OPENDRIVE_TAG_LEFT) != laneSection.lanesByDir.end()) {
1000  for (OpenDriveLane& lane : laneSection.lanesByDir.find(OPENDRIVE_TAG_LEFT)->second) {
1001  if (lane.id == in) {
1002  in = lane.successor;
1003  }
1004  }
1005  }
1006  }
1007  return in == out;
1008  }
1009 }
1010 
1011 
1012 void
1013 NIImporter_OpenDrive::setEdgeLinks2(OpenDriveEdge& e, const std::map<std::string, OpenDriveEdge*>& edges) {
1014  for (std::vector<OpenDriveLink>::iterator i = e.links.begin(); i != e.links.end(); ++i) {
1015  OpenDriveLink& l = *i;
1016  if (l.elementType != OPENDRIVE_ET_ROAD) {
1017  // we assume that links to nodes are later given as connections to edges
1018  continue;
1019  }
1020  // get the right direction of the connected edge
1021  std::string connectedEdge = l.elementID;
1022  std::string edgeID = e.id;
1023 
1024  OpenDriveLaneSection& laneSection = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e.laneSections.back() : e.laneSections[0];
1025  const std::map<int, int>& laneMap = laneSection.laneMap;
1026 #ifdef DEBUG_CONNECTIONS
1027  if (DEBUG_COND(&e)) {
1028  std::cout << "edge=" << e.id << " eType=" << l.elementType << " lType=" << l.linkType << " connectedEdge=" << connectedEdge << " laneSection=" << laneSection.s << " map:\n";
1029  std::cout << joinToString(laneMap, "\n", ":") << "\n";
1030  }
1031 #endif
1032  if (laneSection.lanesByDir.find(OPENDRIVE_TAG_RIGHT) != laneSection.lanesByDir.end()) {
1033  const std::vector<OpenDriveLane>& lanes = laneSection.lanesByDir.find(OPENDRIVE_TAG_RIGHT)->second;
1034  for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
1035  if (!myImportAllTypes && laneMap.find((*j).id) == laneMap.end()) {
1036  continue;
1037  }
1038  Connection c; // @todo: give Connection a new name and a constructor
1039  c.fromEdge = e.id;
1040  c.fromLane = (*j).id;
1042  c.toLane = l.linkType == OPENDRIVE_LT_SUCCESSOR ? (*j).successor : (*j).predecessor;
1043  c.toEdge = connectedEdge;
1044  c.toCP = l.contactPoint;
1045  c.all = false;
1046  if (l.linkType != OPENDRIVE_LT_SUCCESSOR) {
1047  std::swap(c.fromEdge, c.toEdge);
1048  std::swap(c.fromLane, c.toLane);
1049  std::swap(c.fromCP, c.toCP);
1050  }
1051  if (edges.find(c.fromEdge) == edges.end()) {
1052  WRITE_ERROR("While setting connections: incoming road '" + c.fromEdge + "' is not known.");
1053  } else {
1054  OpenDriveEdge* src = edges.find(c.fromEdge)->second;
1055  src->connections.insert(c);
1056 #ifdef DEBUG_CONNECTIONS
1057  if (DEBUG_COND(src)) {
1058  std::cout << "insertConRight from=" << src->id << "_" << c.fromLane << " to=" << c.toEdge << "_" << c.toLane << "\n";
1059  }
1060 #endif
1061  }
1062  }
1063  }
1064  if (laneSection.lanesByDir.find(OPENDRIVE_TAG_LEFT) != laneSection.lanesByDir.end()) {
1065  const std::vector<OpenDriveLane>& lanes = laneSection.lanesByDir.find(OPENDRIVE_TAG_LEFT)->second;
1066  for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
1067  if (!myImportAllTypes && laneMap.find((*j).id) == laneMap.end()) {
1068  continue;
1069  }
1070  Connection c;
1071  c.toEdge = e.id;
1072  c.toLane = (*j).id;
1073  c.toCP = OPENDRIVE_CP_END;
1074  c.fromLane = l.linkType == OPENDRIVE_LT_SUCCESSOR ? (*j).successor : (*j).predecessor;
1075  c.fromEdge = connectedEdge;
1076  c.fromCP = l.contactPoint;
1077  c.all = false;
1078  if (l.linkType != OPENDRIVE_LT_SUCCESSOR) {
1079  std::swap(c.fromEdge, c.toEdge);
1080  std::swap(c.fromLane, c.toLane);
1081  std::swap(c.fromCP, c.toCP);
1082  }
1083  if (edges.find(c.fromEdge) == edges.end()) {
1084  WRITE_ERROR("While setting connections: incoming road '" + c.fromEdge + "' is not known.");
1085  } else {
1086  OpenDriveEdge* src = edges.find(c.fromEdge)->second;
1087  src->connections.insert(c);
1088 #ifdef DEBUG_CONNECTIONS
1089  if (DEBUG_COND(src)) {
1090  std::cout << "insertConLeft from=" << src->id << "_" << c.fromLane << " to=" << c.toEdge << "_" << c.toLane << "\n";
1091  }
1092 #endif
1093  }
1094  }
1095  }
1096  }
1097 }
1098 
1099 
1100 std::string NIImporter_OpenDrive::revertID(const std::string& id) {
1101  if (id[0] == '-') {
1102  return id.substr(1);
1103  }
1104  return "-" + id;
1105 }
1106 
1107 
1108 NBNode*
1109 NIImporter_OpenDrive::getOrBuildNode(const std::string& id, const Position& pos,
1110  NBNodeCont& nc) {
1111  if (nc.retrieve(id) == nullptr) {
1112  // not yet built; build now
1113  if (!nc.insert(id, pos)) {
1114  // !!! clean up
1115  throw ProcessError("Could not add node '" + id + "'.");
1116  }
1117  }
1118  return nc.retrieve(id);
1119 }
1120 
1121 
1122 void
1124  const std::string& nodeID, NIImporter_OpenDrive::LinkType lt) {
1125  NBNode* n = nc.retrieve(nodeID);
1126  if (n == nullptr) {
1127  throw ProcessError("Could not find node '" + nodeID + "'.");
1128  }
1129  if (lt == OPENDRIVE_LT_SUCCESSOR) {
1130  if (e.to != nullptr && e.to != n) {
1131  throw ProcessError("Edge '" + e.id + "' has two end nodes ('" + e.to->getID() + "' and '" + nodeID + "').");
1132  }
1133  e.to = n;
1134  } else {
1135  if (e.from != nullptr && e.from != n) {
1136  throw ProcessError("Edge '" + e.id + "' has two start nodes ('" + e.from->getID() + "' and '" + nodeID + "').");
1137  }
1138  e.from = n;
1139  }
1140 }
1141 
1142 bool
1144  if (e.elevations.size() > 1) {
1145  return true;
1146  }
1147  for (OpenDriveElevation& el : e.elevations) {
1148  if (el.c != 0 || el.d != 0) {
1149  return true;
1150  }
1151  }
1152  return false;
1153 }
1154 
1155 void
1156 NIImporter_OpenDrive::computeShapes(std::map<std::string, OpenDriveEdge*>& edges) {
1158  const double res = oc.getFloat("opendrive.curve-resolution");
1159  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
1160  OpenDriveEdge& e = *(*i).second;
1162  const double lineRes = hasNonLinearElevation(e) ? res : -1;
1163  Position last;
1164  for (std::vector<OpenDriveGeometry>::iterator j = e.geometries.begin(); j != e.geometries.end(); ++j) {
1165  OpenDriveGeometry& g = *j;
1166  PositionVector geom;
1167  switch (g.type) {
1168  case OPENDRIVE_GT_UNKNOWN:
1169  break;
1170  case OPENDRIVE_GT_LINE:
1171  geom = geomFromLine(e, g, lineRes);
1172  break;
1173  case OPENDRIVE_GT_SPIRAL:
1174  geom = geomFromSpiral(e, g, res);
1175  break;
1176  case OPENDRIVE_GT_ARC:
1177  geom = geomFromArc(e, g, res);
1178  break;
1179  case OPENDRIVE_GT_POLY3:
1180  geom = geomFromPoly(e, g, res);
1181  break;
1183  geom = geomFromParamPoly(e, g, res);
1184  break;
1185  default:
1186  break;
1187  }
1188  if (e.geom.size() > 0 && prevType == OPENDRIVE_GT_LINE) {
1189  // remove redundant end point of the previous geometry segment
1190  // (the start point of the current segment should have the same value)
1191  // this avoids geometry errors due to imprecision
1192  if (!e.geom.back().almostSame(geom.front())) {
1193  const int index = (int)(j - e.geometries.begin());
1194  WRITE_WARNING("Mismatched geometry for edge '" + e.id + "' between geometry segments " + toString(index - 1) + " and " + toString(index) + ".");
1195  }
1196  e.geom.pop_back();
1197  }
1198  //std::cout << " adding geometry to road=" << e.id << " old=" << e.geom << " new=" << geom << "\n";
1199  for (PositionVector::iterator k = geom.begin(); k != geom.end(); ++k) {
1200  last = *k;
1202  }
1203  prevType = g.type;
1204  }
1205  if (e.geom.size() == 1 && e.geom.front() != last) {
1206  // avoid length-1 geometry due to almostSame check
1207  e.geom.push_back(last);
1208  }
1209  if (oc.exists("geometry.min-dist") && !oc.isDefault("geometry.min-dist")) {
1210  e.geom.removeDoublePoints(oc.getFloat("geometry.min-dist"), true);
1211  }
1213  WRITE_ERROR("Unable to project coordinates for edge '" + e.id + "'.");
1214  }
1215  // add z-data
1216  int k = 0;
1217  double pos = 0;
1218  //std::cout << " edge=" << e.id << " geom.size=" << e.geom.size() << " geom.len=" << e.geom.length2D() << " ele.size=" << e.elevations.size() << "\n";
1219  for (std::vector<OpenDriveElevation>::iterator j = e.elevations.begin(); j != e.elevations.end(); ++j) {
1220  const OpenDriveElevation& el = *j;
1221  const double sNext = (j + 1) == e.elevations.end() ? std::numeric_limits<double>::max() : (*(j + 1)).s;
1222  while (k < (int)e.geom.size() && pos < sNext) {
1223  const double z = el.computeAt(pos);
1224  //std::cout << " edge=" << e.id << " k=" << k << " sNext=" << sNext << " pos=" << pos << " z=" << z << " el.s=" << el.s << " el.a=" << el.a << " el.b=" << el.b << " el.c=" << el.c << " el.d=" << el.d << "\n";
1225  e.geom[k].add(0, 0, z);
1226  k++;
1227  if (k < (int)e.geom.size()) {
1228  // XXX pos understimates the actual position since the
1229  // actual geometry between k-1 and k could be curved
1230  pos += e.geom[k - 1].distanceTo2D(e.geom[k]);
1231  }
1232  }
1233  }
1234  // add laneoffset
1235  if (e.offsets.size() > 0) {
1236  // make sure there are intermediate points for each offset-section
1237  for (std::vector<OpenDriveLaneOffset>::iterator j = e.offsets.begin(); j != e.offsets.end(); ++j) {
1238  const OpenDriveLaneOffset& el = *j;
1239  // check wether we need to insert a new point at dist
1240  Position pS = e.geom.positionAtOffset2D(el.s);
1241  int iS = e.geom.indexOfClosest(pS);
1242  // prevent close spacing to reduce impact of rounding errors in z-axis
1243  if (pS.distanceTo2D(e.geom[iS]) > POSITION_EPS) {
1244  e.geom.insertAtClosest(pS, false);
1245  //std::cout << " edge=" << e.id << " inserting pos=" << pS << " s=" << el.s << " iS=" << iS << " dist=" << pS.distanceTo2D(e.geom[iS]) << "\n";
1246  }
1247  }
1248  // XXX add further points for sections with non-constant offset
1249  // shift each point orthogonally by the specified offset
1250  int k = 0;
1251  double pos = 0;
1252  for (std::vector<OpenDriveLaneOffset>::iterator j = e.offsets.begin(); j != e.offsets.end(); ++j) {
1253  const OpenDriveLaneOffset& el = *j;
1254  const double sNext = (j + 1) == e.offsets.end() ? std::numeric_limits<double>::max() : (*(j + 1)).s;
1255  while (k < (int)e.geom.size() && pos < sNext) {
1256  const double offset = el.computeAt(pos);
1257  e.laneOffsets.push_back(fabs(offset) > POSITION_EPS ? -offset : 0);
1258  k++;
1259  if (k < (int)e.geom.size()) {
1260  // XXX pos understimates the actual position since the
1261  // actual geometry between k-1 and k could be curved
1262  pos += e.geom[k - 1].distanceTo2D(e.geom[k]);
1263  }
1264  }
1265  }
1266  }
1267  //std::cout << " loaded geometry " << e.id << "=" << e.geom << "\n";
1268  }
1269 }
1270 
1271 
1272 void
1273 NIImporter_OpenDrive::revisitLaneSections(const NBTypeCont& tc, std::map<std::string, OpenDriveEdge*>& edges) {
1274  for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
1275  OpenDriveEdge& e = *(*i).second;
1276 #ifdef DEBUG_VARIABLE_SPEED
1277  if (DEBUG_COND(&e)) {
1278  gDebugFlag1 = true;
1279  std::cout << "revisitLaneSections e=" << e.id << "\n";
1280  }
1281 #endif
1282  std::vector<OpenDriveLaneSection>& laneSections = e.laneSections;
1283  // split by speed limits
1284  std::vector<OpenDriveLaneSection> newSections;
1285  for (std::vector<OpenDriveLaneSection>::iterator j = laneSections.begin(); j != laneSections.end(); ++j) {
1286  std::vector<OpenDriveLaneSection> splitSections;
1287  bool splitBySpeed = (*j).buildSpeedChanges(tc, splitSections);
1288  if (!splitBySpeed) {
1289  newSections.push_back(*j);
1290  } else {
1291  std::copy(splitSections.begin(), splitSections.end(), back_inserter(newSections));
1292  }
1293  }
1294 
1295  e.laneSections = newSections;
1296  laneSections = e.laneSections;
1297  double lastS = -1;
1298  // check whether the lane sections are in the right order
1299  bool sorted = true;
1300  for (std::vector<OpenDriveLaneSection>::const_iterator j = laneSections.begin(); j != laneSections.end() && sorted; ++j) {
1301  if ((*j).s <= lastS) {
1302  sorted = false;
1303  }
1304  lastS = (*j).s;
1305  }
1306  if (!sorted) {
1307  WRITE_WARNING("The sections of edge '" + e.id + "' are not sorted properly.");
1308  sort(e.laneSections.begin(), e.laneSections.end(), sections_by_s_sorter());
1309  }
1310  // check whether no duplicates of s-value occure
1311  lastS = -1;
1312  laneSections = e.laneSections;
1313  for (std::vector<OpenDriveLaneSection>::iterator j = laneSections.begin(); j != laneSections.end();) {
1314  bool simlarToLast = fabs((*j).s - lastS) < POSITION_EPS;
1315  lastS = (*j).s;
1316  // keep all lane sections for connecting roads because they are
1317  // needed to establish connectivity (laneSectionsConnected)
1318  if (simlarToLast && !e.isInner) {
1319  WRITE_WARNING("Almost duplicate s-value '" + toString(lastS) + "' for lane sections occurred at edge '" + e.id + "'; second entry was removed.");
1320  j = laneSections.erase(j);
1321  } else {
1322  ++j;
1323  }
1324  }
1325 #ifdef DEBUG_VARIABLE_SPEED
1326  gDebugFlag1 = false;
1327 #endif
1328  }
1329 }
1330 
1331 
1334  UNUSED_PARAMETER(e);
1335  PositionVector ret;
1336  Position start(g.x, g.y);
1337  Position end = calculateStraightEndPoint(g.hdg, g.length, start);
1338  if (resolution > 0 && g.length > 0) {
1339  const int numPoints = (int)ceil(g.length / resolution) + 1;
1340  double dx = (end.x() - start.x()) / (numPoints - 1);
1341  double dy = (end.y() - start.y()) / (numPoints - 1);
1342  for (int i = 0; i < numPoints; i++) {
1343  ret.push_back(Position(g.x + i * dx, g.y + i * dy));
1344  }
1345  } else {
1346  ret.push_back(start);
1347  ret.push_back(end);
1348  }
1349  return ret;
1350 }
1351 
1352 
1355  UNUSED_PARAMETER(e);
1356  PositionVector ret;
1357  double curveStart = g.params[0];
1358  double curveEnd = g.params[1];
1359  try {
1360  double cDot = (curveEnd - curveStart) / g.length;
1361  if (cDot == 0 || g.length == 0) {
1362  WRITE_WARNING("Could not compute spiral geometry for edge '" + e.id + "' (cDot=" + toString(cDot) + " length=" + toString(g.length) + ").");
1363  ret.push_back(Position(g.x, g.y));
1364  return ret;
1365  }
1366  double sStart = curveStart / cDot;
1367  double sEnd = curveEnd / cDot;
1368  double x = 0;
1369  double y = 0;
1370  double t = 0;
1371  double tStart = 0;
1372  double s;
1373  odrSpiral(sStart, cDot, &x, &y, &tStart);
1374  for (s = sStart; s <= sEnd; s += resolution) {
1375  odrSpiral(s, cDot, &x, &y, &t);
1376  ret.push_back(Position(x, y));
1377  }
1378  if (s != sEnd /*&& ret.size() == 1*/) {
1379  odrSpiral(sEnd, cDot, &x, &y, &t);
1380  ret.push_back(Position(x, y));
1381  }
1382  //if (s != sEnd && ret.size() > 2) {
1383  // ret.pop_back();
1384  //}
1385  assert(ret.size() >= 2);
1386  assert(ret[0] != ret[1]);
1387  // shift start to coordinate origin
1388  PositionVector ret1 = ret;
1389  ret.add(ret.front() * -1);
1390  // rotate
1391  PositionVector ret2 = ret;
1392  ret.rotate2D(g.hdg - tStart);
1393 #ifdef DEBUG_SPIRAL
1394  std::cout
1395  << std::setprecision(4)
1396  << "edge=" << e.id << " s=" << g.s
1397  << " cStart=" << curveStart
1398  << " cEnd=" << curveEnd
1399  << " cDot=" << cDot
1400  << " sStart=" << sStart
1401  << " sEnd=" << sEnd
1402  << " g.hdg=" << GeomHelper::naviDegree(g.hdg)
1403  << " tStart=" << GeomHelper::naviDegree(tStart)
1404  << "\n beforeShift=" << ret1
1405  << "\n beforeRot=" << ret2
1406  << "\n";
1407 #endif
1408  // shift to geometry start
1409  ret.add(g.x, g.y, 0);
1410  } catch (const std::runtime_error& error) {
1411  WRITE_WARNING("Could not compute spiral geometry for edge '" + e.id + "' (" + error.what() + ").");
1412  ret.push_back(Position(g.x, g.y));
1413  }
1414  return ret.getSubpart2D(0, g.length);
1415 }
1416 
1417 
1420  UNUSED_PARAMETER(e);
1421  PositionVector ret;
1422  double dist = 0.0;
1423  double centerX = g.x;
1424  double centerY = g.y;
1425  // left: positive value
1426  double curvature = g.params[0];
1427  double radius = 1. / curvature;
1428  // center point
1429  calculateCurveCenter(&centerX, &centerY, radius, g.hdg);
1430  double endX = g.x;
1431  double endY = g.y;
1432  double startX = g.x;
1433  double startY = g.y;
1434  double geo_posS = g.s;
1435  double geo_posE = g.s;
1436  bool end = false;
1437  do {
1438  geo_posE += resolution;
1439  if (geo_posE - g.s > g.length) {
1440  geo_posE = g.s + g.length;
1441  }
1442  if (geo_posE - g.s > g.length) {
1443  geo_posE = g.s + g.length;
1444  }
1445  calcPointOnCurve(&endX, &endY, centerX, centerY, radius, geo_posE - geo_posS);
1446 
1447  dist += (geo_posE - geo_posS);
1448  //
1449  ret.push_back(Position(startX, startY));
1450  //
1451  startX = endX;
1452  startY = endY;
1453  geo_posS = geo_posE;
1454 
1455  if (geo_posE - (g.s + g.length) < 0.001 && geo_posE - (g.s + g.length) > -0.001) {
1456  end = true;
1457  }
1458  } while (!end);
1459  return ret.getSubpart2D(0, g.length);
1460 }
1461 
1462 
1465  UNUSED_PARAMETER(e);
1466  const double s = sin(g.hdg);
1467  const double c = cos(g.hdg);
1468  PositionVector ret;
1469  for (double off = 0; off < g.length + 2.; off += resolution) {
1470  double x = off;
1471  double y = g.params[0] + g.params[1] * off + g.params[2] * pow(off, 2.) + g.params[3] * pow(off, 3.);
1472  double xnew = x * c - y * s;
1473  double ynew = x * s + y * c;
1474  ret.push_back(Position(g.x + xnew, g.y + ynew));
1475  }
1476  return ret.getSubpart2D(0, g.length);
1477 }
1478 
1479 
1482  UNUSED_PARAMETER(e);
1483  const double s = sin(g.hdg);
1484  const double c = cos(g.hdg);
1485  const double pMax = g.params[8] <= 0 ? g.length : g.params[8];
1486  const double pStep = pMax / ceil(g.length / resolution);
1487  PositionVector ret;
1488  for (double p = 0; p <= pMax + pStep; p += pStep) {
1489  double x = g.params[0] + g.params[1] * p + g.params[2] * pow(p, 2.) + g.params[3] * pow(p, 3.);
1490  double y = g.params[4] + g.params[5] * p + g.params[6] * pow(p, 2.) + g.params[7] * pow(p, 3.);
1491  double xnew = x * c - y * s;
1492  double ynew = x * s + y * c;
1493  ret.push_back(Position(g.x + xnew, g.y + ynew));
1494  }
1495  return ret.getSubpart2D(0, g.length);
1496 }
1497 
1498 
1499 Position
1500 NIImporter_OpenDrive::calculateStraightEndPoint(double hdg, double length, const Position& start) {
1501  double normx = 1.0f;
1502  double normy = 0.0f;
1503  double x2 = normx * cos(hdg) - normy * sin(hdg);
1504  double y2 = normx * sin(hdg) + normy * cos(hdg);
1505  normx = x2 * length;
1506  normy = y2 * length;
1507  return Position(start.x() + normx, start.y() + normy);
1508 }
1509 
1510 
1511 void
1512 NIImporter_OpenDrive::calculateCurveCenter(double* ad_x, double* ad_y, double ad_radius, double ad_hdg) {
1513  double normX = 1.0;
1514  double normY = 0.0;
1515  double tmpX;
1516  double turn;
1517  if (ad_radius > 0) {
1518  turn = -1.0;
1519  } else {
1520  turn = 1.0;
1521  }
1522 
1523  tmpX = normX;
1524  normX = normX * cos(ad_hdg) + normY * sin(ad_hdg);
1525  normY = tmpX * sin(ad_hdg) + normY * cos(ad_hdg);
1526 
1527  tmpX = normX;
1528  normX = turn * normY;
1529  normY = -turn * tmpX;
1530 
1531  normX = fabs(ad_radius) * normX;
1532  normY = fabs(ad_radius) * normY;
1533 
1534  *ad_x += normX;
1535  *ad_y += normY;
1536 }
1537 
1538 
1539 void
1540 NIImporter_OpenDrive::calcPointOnCurve(double* ad_x, double* ad_y, double ad_centerX, double ad_centerY,
1541  double ad_r, double ad_length) {
1542  double rotAngle = ad_length / fabs(ad_r);
1543  double vx = *ad_x - ad_centerX;
1544  double vy = *ad_y - ad_centerY;
1545  double tmpx;
1546 
1547  double turn;
1548  if (ad_r > 0) {
1549  turn = -1; //left
1550  } else {
1551  turn = 1; //right
1552  }
1553  tmpx = vx;
1554  vx = vx * cos(rotAngle) + turn * vy * sin(rotAngle);
1555  vy = -1 * turn * tmpx * sin(rotAngle) + vy * cos(rotAngle);
1556  *ad_x = vx + ad_centerX;
1557  *ad_y = vy + ad_centerY;
1558 }
1559 
1560 
1561 // ---------------------------------------------------------------------------
1562 // section
1563 // ---------------------------------------------------------------------------
1565  lanesByDir[OPENDRIVE_TAG_LEFT] = std::vector<OpenDriveLane>();
1566  lanesByDir[OPENDRIVE_TAG_RIGHT] = std::vector<OpenDriveLane>();
1567  lanesByDir[OPENDRIVE_TAG_CENTER] = std::vector<OpenDriveLane>();
1568 }
1569 
1570 
1571 void
1573  int sumoLane = 0;
1574  bool singleType = true;
1575  std::vector<std::string> types;
1576  const std::vector<OpenDriveLane>& dirLanesR = lanesByDir.find(OPENDRIVE_TAG_RIGHT)->second;
1577  for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanesR.rbegin(); i != dirLanesR.rend(); ++i) {
1578  if (myImportAllTypes || (tc.knows((*i).type) && !tc.getShallBeDiscarded((*i).type))) {
1579  laneMap[(*i).id] = sumoLane++;
1580  types.push_back((*i).type);
1581  if (types.front() != types.back()) {
1582  singleType = false;
1583  }
1584  }
1585  }
1586  rightLaneNumber = sumoLane;
1587  rightType = sumoLane > 0 ? (singleType ? types.front() : joinToString(types, "|")) : "";
1588  sumoLane = 0;
1589  singleType = true;
1590  types.clear();
1591  const std::vector<OpenDriveLane>& dirLanesL = lanesByDir.find(OPENDRIVE_TAG_LEFT)->second;
1592  for (std::vector<OpenDriveLane>::const_iterator i = dirLanesL.begin(); i != dirLanesL.end(); ++i) {
1593  if (myImportAllTypes || (tc.knows((*i).type) && !tc.getShallBeDiscarded((*i).type))) {
1594  laneMap[(*i).id] = sumoLane++;
1595  types.push_back((*i).type);
1596  if (types.front() != types.back()) {
1597  singleType = false;
1598  }
1599  }
1600  }
1601  leftLaneNumber = sumoLane;
1602  leftType = sumoLane > 0 ? (singleType ? types.front() : joinToString(types, "|")) : "";
1603 }
1604 
1605 
1606 std::map<int, int>
1608  std::map<int, int> ret;
1609  const std::vector<OpenDriveLane>& dirLanes = lanesByDir.find(dir)->second;
1610  for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanes.rbegin(); i != dirLanes.rend(); ++i) {
1611  std::map<int, int>::const_iterator toP = laneMap.find((*i).id);
1612  if (toP == laneMap.end()) {
1613  // the current lane is not available in SUMO
1614  continue;
1615  }
1616  int to = (*toP).second;
1617  int from = UNSET_CONNECTION;
1618  if ((*i).predecessor != UNSET_CONNECTION) {
1619  from = (*i).predecessor;
1620  }
1621  if (from != UNSET_CONNECTION) {
1622  std::map<int, int>::const_iterator fromP = prev.laneMap.find(from);
1623  if (fromP != prev.laneMap.end()) {
1624  from = (*fromP).second;
1625  } else {
1626  from = UNSET_CONNECTION;
1627  }
1628  }
1629  if (from != UNSET_CONNECTION && to != UNSET_CONNECTION) {
1630  if (ret.find(from) != ret.end()) {
1631 // WRITE_WARNING("double connection");
1632  }
1633  if (dir == OPENDRIVE_TAG_LEFT) {
1634  std::swap(from, to);
1635  }
1636  ret[from] = to;
1637  } else {
1638 // WRITE_WARNING("missing connection");
1639  }
1640  }
1641  return ret;
1642 }
1643 
1644 
1647  OpenDriveLaneSection ret(*this);
1648  ret.s += startPos;
1649  for (int k = 0; k < (int)ret.lanesByDir[OPENDRIVE_TAG_RIGHT].size(); ++k) {
1651  l.speed = 0;
1652  std::vector<std::pair<double, double> >::const_iterator i = std::find_if(l.speeds.begin(), l.speeds.end(), same_position_finder(startPos));
1653  if (i != l.speeds.end()) {
1654  l.speed = (*i).second;
1655  }
1656  }
1657  for (int k = 0; k < (int)ret.lanesByDir[OPENDRIVE_TAG_LEFT].size(); ++k) {
1659  std::vector<std::pair<double, double> >::const_iterator i = std::find_if(l.speeds.begin(), l.speeds.end(), same_position_finder(startPos));
1660  l.speed = 0;
1661  if (i != l.speeds.end()) {
1662  l.speed = (*i).second;
1663  }
1664  }
1665  return ret;
1666 }
1667 
1668 
1669 bool
1670 NIImporter_OpenDrive::OpenDriveLaneSection::buildSpeedChanges(const NBTypeCont& tc, std::vector<OpenDriveLaneSection>& newSections) {
1671  std::set<double> speedChangePositions;
1672  // collect speed change positions and apply initial speed to the begin
1673  for (std::vector<OpenDriveLane>::iterator k = lanesByDir[OPENDRIVE_TAG_RIGHT].begin(); k != lanesByDir[OPENDRIVE_TAG_RIGHT].end(); ++k) {
1674  for (std::vector<std::pair<double, double> >::const_iterator l = (*k).speeds.begin(); l != (*k).speeds.end(); ++l) {
1675  speedChangePositions.insert((*l).first);
1676  if ((*l).first == 0) {
1677  (*k).speed = (*l).second;
1678  }
1679  }
1680  }
1681  for (std::vector<OpenDriveLane>::iterator k = lanesByDir[OPENDRIVE_TAG_LEFT].begin(); k != lanesByDir[OPENDRIVE_TAG_LEFT].end(); ++k) {
1682  for (std::vector<std::pair<double, double> >::const_iterator l = (*k).speeds.begin(); l != (*k).speeds.end(); ++l) {
1683  speedChangePositions.insert((*l).first);
1684  if ((*l).first == 0) {
1685  (*k).speed = (*l).second;
1686  }
1687  }
1688  }
1689  // do nothing if there is none
1690  if (speedChangePositions.size() == 0) {
1691  return false;
1692  }
1693  if (*speedChangePositions.begin() > 0) {
1694  speedChangePositions.insert(0);
1695  }
1696 #ifdef DEBUG_VARIABLE_SPEED
1697  if (gDebugFlag1) std::cout
1698  << " buildSpeedChanges sectionStart=" << s
1699  << " speedChangePositions=" << joinToString(speedChangePositions, ", ")
1700  << "\n";
1701 #endif
1702  for (std::set<double>::iterator i = speedChangePositions.begin(); i != speedChangePositions.end(); ++i) {
1703  if (i == speedChangePositions.begin()) {
1704  newSections.push_back(*this);
1705  } else {
1706  newSections.push_back(buildLaneSection(*i));
1707  }
1708  }
1709  // propagate speeds
1710  for (int i = 0; i != (int)newSections.size(); ++i) {
1711  OpenDriveLaneSection& ls = newSections[i];
1712  std::map<OpenDriveXMLTag, std::vector<OpenDriveLane> >& lanesByDir = ls.lanesByDir;
1713  for (std::map<OpenDriveXMLTag, std::vector<OpenDriveLane> >::iterator k = lanesByDir.begin(); k != lanesByDir.end(); ++k) {
1714  std::vector<OpenDriveLane>& lanes = (*k).second;
1715  for (int j = 0; j != (int)lanes.size(); ++j) {
1716  OpenDriveLane& l = lanes[j];
1717  if (l.speed != 0) {
1718  continue;
1719  }
1720  if (i > 0) {
1721  l.speed = newSections[i - 1].lanesByDir[(*k).first][j].speed;
1722  } else {
1723  tc.getSpeed(l.type);
1724  }
1725  }
1726  }
1727  }
1728  return true;
1729 }
1730 
1731 
1732 
1733 // ---------------------------------------------------------------------------
1734 // edge
1735 // ---------------------------------------------------------------------------
1736 int
1738  // for signal interpretations see https://de.wikipedia.org/wiki/Bildtafel_der_Verkehrszeichen_in_der_Bundesrepublik_Deutschland_seit_2013
1739  int prio = 1;
1740  for (std::vector<OpenDriveSignal>::const_iterator i = signals.begin(); i != signals.end(); ++i) {
1741  int tmp = 1;
1742  if ((*i).type == "301" || (*i).type == "306") { // priority road or local priority
1743  tmp = 2;
1744  }
1745  if ((*i).type == "205" /*|| (*i).type == "206"*/) { // yield or stop
1746  tmp = 0;
1747  }
1748  if (tmp != 1 && dir == OPENDRIVE_TAG_RIGHT && (*i).orientation > 0) {
1749  prio = tmp;
1750  }
1751  if (tmp != 1 && dir == OPENDRIVE_TAG_LEFT && (*i).orientation < 0) {
1752  prio = tmp;
1753  }
1754 
1755  }
1756  return prio;
1757 }
1758 
1759 
1760 
1761 // ---------------------------------------------------------------------------
1762 // loader methods
1763 // ---------------------------------------------------------------------------
1764 NIImporter_OpenDrive::NIImporter_OpenDrive(const NBTypeCont& tc, std::map<std::string, OpenDriveEdge*>& edges)
1766  myTypeContainer(tc), myCurrentEdge("", "", "", -1), myEdges(edges) {
1767 }
1768 
1769 
1771 }
1772 
1773 
1774 void
1776  const SUMOSAXAttributes& attrs) {
1777  bool ok = true;
1778  switch (element) {
1779  case OPENDRIVE_TAG_HEADER: {
1780  int majorVersion = attrs.get<int>(OPENDRIVE_ATTR_REVMAJOR, nullptr, ok);
1781  int minorVersion = attrs.get<int>(OPENDRIVE_ATTR_REVMINOR, nullptr, ok);
1782  if (majorVersion != 1 || minorVersion != 2) {
1783  // TODO: leave note of exceptions
1784  WRITE_WARNING("Given openDrive file '" + getFileName() + "' uses version " + toString(majorVersion) + "." + toString(minorVersion) + ";\n Version 1.2 is supported.");
1785  }
1786  }
1787  break;
1788  case OPENDRIVE_TAG_ROAD: {
1789  std::string id = attrs.get<std::string>(OPENDRIVE_ATTR_ID, nullptr, ok);
1790  std::string streetName = attrs.getOpt<std::string>(OPENDRIVE_ATTR_NAME, nullptr, ok, "", false);
1791  std::string junction = attrs.get<std::string>(OPENDRIVE_ATTR_JUNCTION, id.c_str(), ok);
1792  double length = attrs.get<double>(OPENDRIVE_ATTR_LENGTH, id.c_str(), ok);
1793  myCurrentEdge = OpenDriveEdge(id, streetName, junction, length);
1794  }
1795  break;
1797  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
1798  std::string elementType = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
1799  std::string elementID = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
1800  std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
1801  ? attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok)
1802  : "end";
1803  addLink(OPENDRIVE_LT_PREDECESSOR, elementType, elementID, contactPoint);
1804  }
1805  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
1806  int no = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1807  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1808  l.predecessor = no;
1809  }
1810  }
1811  break;
1812  case OPENDRIVE_TAG_SUCCESSOR: {
1813  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
1814  std::string elementType = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
1815  std::string elementID = attrs.get<std::string>(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
1816  std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
1817  ? attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok)
1818  : "start";
1819  addLink(OPENDRIVE_LT_SUCCESSOR, elementType, elementID, contactPoint);
1820  }
1821  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
1822  int no = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1823  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1824  l.successor = no;
1825  }
1826  }
1827  break;
1828  case OPENDRIVE_TAG_GEOMETRY: {
1829  double length = attrs.get<double>(OPENDRIVE_ATTR_LENGTH, myCurrentEdge.id.c_str(), ok);
1830  double s = attrs.get<double>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1831  double x = attrs.get<double>(OPENDRIVE_ATTR_X, myCurrentEdge.id.c_str(), ok);
1832  double y = attrs.get<double>(OPENDRIVE_ATTR_Y, myCurrentEdge.id.c_str(), ok);
1833  double hdg = attrs.get<double>(OPENDRIVE_ATTR_HDG, myCurrentEdge.id.c_str(), ok);
1834  myCurrentEdge.geometries.push_back(OpenDriveGeometry(length, s, x, y, hdg));
1835  }
1836  break;
1837  case OPENDRIVE_TAG_ELEVATION: {
1838  double s = attrs.get<double>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1839  double a = attrs.get<double>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok);
1840  double b = attrs.get<double>(OPENDRIVE_ATTR_B, myCurrentEdge.id.c_str(), ok);
1841  double c = attrs.get<double>(OPENDRIVE_ATTR_C, myCurrentEdge.id.c_str(), ok);
1842  double d = attrs.get<double>(OPENDRIVE_ATTR_D, myCurrentEdge.id.c_str(), ok);
1843  myCurrentEdge.elevations.push_back(OpenDriveElevation(s, a, b, c, d));
1844  }
1845  break;
1846  case OPENDRIVE_TAG_LINE: {
1847  if (myElementStack.size() > 0 && myElementStack.back() == OPENDRIVE_TAG_GEOMETRY) {
1848  std::vector<double> vals;
1850  }
1851  }
1852  break;
1853  case OPENDRIVE_TAG_SPIRAL: {
1854  std::vector<double> vals;
1855  vals.push_back(attrs.get<double>(OPENDRIVE_ATTR_CURVSTART, myCurrentEdge.id.c_str(), ok));
1856  vals.push_back(attrs.get<double>(OPENDRIVE_ATTR_CURVEND, myCurrentEdge.id.c_str(), ok));
1858  }
1859  break;
1860  case OPENDRIVE_TAG_ARC: {
1861  std::vector<double> vals;
1862  vals.push_back(attrs.get<double>(OPENDRIVE_ATTR_CURVATURE, myCurrentEdge.id.c_str(), ok));
1864  }
1865  break;
1866  case OPENDRIVE_TAG_POLY3: {
1867  std::vector<double> vals;
1868  vals.push_back(attrs.get<double>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok));
1869  vals.push_back(attrs.get<double>(OPENDRIVE_ATTR_B, myCurrentEdge.id.c_str(), ok));
1870  vals.push_back(attrs.get<double>(OPENDRIVE_ATTR_C, myCurrentEdge.id.c_str(), ok));
1871  vals.push_back(attrs.get<double>(OPENDRIVE_ATTR_D, myCurrentEdge.id.c_str(), ok));
1873  }
1874  break;
1875  case OPENDRIVE_TAG_PARAMPOLY3: {
1876  std::vector<double> vals;
1877  vals.push_back(attrs.get<double>(OPENDRIVE_ATTR_AU, myCurrentEdge.id.c_str(), ok));
1878  vals.push_back(attrs.get<double>(OPENDRIVE_ATTR_BU, myCurrentEdge.id.c_str(), ok));
1879  vals.push_back(attrs.get<double>(OPENDRIVE_ATTR_CU, myCurrentEdge.id.c_str(), ok));
1880  vals.push_back(attrs.get<double>(OPENDRIVE_ATTR_DU, myCurrentEdge.id.c_str(), ok));
1881  vals.push_back(attrs.get<double>(OPENDRIVE_ATTR_AV, myCurrentEdge.id.c_str(), ok));
1882  vals.push_back(attrs.get<double>(OPENDRIVE_ATTR_BV, myCurrentEdge.id.c_str(), ok));
1883  vals.push_back(attrs.get<double>(OPENDRIVE_ATTR_CV, myCurrentEdge.id.c_str(), ok));
1884  vals.push_back(attrs.get<double>(OPENDRIVE_ATTR_DV, myCurrentEdge.id.c_str(), ok));
1885  const std::string pRange = attrs.getOpt<std::string>(OPENDRIVE_ATTR_PRANGE, myCurrentEdge.id.c_str(), ok, "normalized", false);
1886  if (pRange == "normalized") {
1887  vals.push_back(1.0);
1888  } else if (pRange == "arcLength") {
1889  vals.push_back(-1.0);
1890  } else {
1891  WRITE_WARNING("Ignoring invalid pRange value '" + pRange + "' for road '" + myCurrentEdge.id + "'.");
1892  vals.push_back(1.0);
1893  }
1895  }
1896  break;
1898  double s = attrs.get<double>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1899  if (myCurrentEdge.laneSections.size() > 0) {
1900  myCurrentEdge.laneSections.back().length = s - myCurrentEdge.laneSections.back().s;
1901  }
1903  // possibly updated by the next laneSection
1904  myCurrentEdge.laneSections.back().length = myCurrentEdge.length - s;
1905  }
1906  break;
1907  case OPENDRIVE_TAG_LANEOFFSET: {
1908  double s = attrs.get<double>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1909  double a = attrs.get<double>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok);
1910  double b = attrs.get<double>(OPENDRIVE_ATTR_B, myCurrentEdge.id.c_str(), ok);
1911  double c = attrs.get<double>(OPENDRIVE_ATTR_C, myCurrentEdge.id.c_str(), ok);
1912  double d = attrs.get<double>(OPENDRIVE_ATTR_D, myCurrentEdge.id.c_str(), ok);
1913  myCurrentEdge.offsets.push_back(OpenDriveLaneOffset(s, a, b, c, d));
1914  }
1915  break;
1916  case OPENDRIVE_TAG_LEFT:
1918  break;
1919  case OPENDRIVE_TAG_CENTER:
1921  break;
1922  case OPENDRIVE_TAG_RIGHT:
1924  break;
1925  case OPENDRIVE_TAG_LANE: {
1926  std::string type = attrs.get<std::string>(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
1927  int id = attrs.get<int>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1928  std::string level = attrs.hasAttribute(OPENDRIVE_ATTR_LEVEL)
1929  ? attrs.get<std::string>(OPENDRIVE_ATTR_LEVEL, myCurrentEdge.id.c_str(), ok)
1930  : "";
1932  ls.lanesByDir[myCurrentLaneDirection].push_back(OpenDriveLane(id, level, type));
1933  }
1934  break;
1935  case OPENDRIVE_TAG_SIGNAL: {
1936  std::string id = attrs.get<std::string>(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1937  std::string type = attrs.get<std::string>(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
1938  std::string name = attrs.getOpt<std::string>(OPENDRIVE_ATTR_NAME, myCurrentEdge.id.c_str(), ok, "", false);
1939  int orientation = attrs.get<std::string>(OPENDRIVE_ATTR_ORIENTATION, myCurrentEdge.id.c_str(), ok) == "-" ? -1 : 1;
1940  double s = attrs.get<double>(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok);
1941  bool dynamic = attrs.get<std::string>(OPENDRIVE_ATTR_DYNAMIC, myCurrentEdge.id.c_str(), ok) == "no" ? false : true;
1942  myCurrentEdge.signals.push_back(OpenDriveSignal(id, type, name, orientation, dynamic, s));
1943  }
1944  break;
1946  myCurrentJunctionID = attrs.get<std::string>(OPENDRIVE_ATTR_ID, myCurrentJunctionID.c_str(), ok);
1947  break;
1948  case OPENDRIVE_TAG_CONNECTION: {
1949  std::string id = attrs.get<std::string>(OPENDRIVE_ATTR_ID, myCurrentJunctionID.c_str(), ok);
1950  myCurrentIncomingRoad = attrs.get<std::string>(OPENDRIVE_ATTR_INCOMINGROAD, myCurrentJunctionID.c_str(), ok);
1952  std::string cp = attrs.get<std::string>(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentJunctionID.c_str(), ok);
1954  myConnectionWasEmpty = true;
1955  }
1956  break;
1957  case OPENDRIVE_TAG_LANELINK: {
1958  int from = attrs.get<int>(OPENDRIVE_ATTR_FROM, myCurrentJunctionID.c_str(), ok);
1959  int to = attrs.get<int>(OPENDRIVE_ATTR_TO, myCurrentJunctionID.c_str(), ok);
1960  Connection c;
1962  c.toEdge = myCurrentConnectingRoad;
1963  c.fromLane = from;
1964  c.toLane = to;
1965  c.fromCP = OPENDRIVE_CP_END;
1966  c.toCP = myCurrentContactPoint;
1967  c.all = false;
1968  if (myEdges.find(c.fromEdge) == myEdges.end()) {
1969  WRITE_ERROR("In laneLink-element: incoming road '" + c.fromEdge + "' is not known.");
1970  } else {
1971  OpenDriveEdge* e = myEdges.find(c.fromEdge)->second;
1972  e->connections.insert(c);
1973  myConnectionWasEmpty = false;
1974  }
1975  }
1976  break;
1977  case OPENDRIVE_TAG_WIDTH: {
1978  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 1] == OPENDRIVE_TAG_LANE) {
1979  const double s = attrs.get<double>(OPENDRIVE_ATTR_SOFFSET, myCurrentEdge.id.c_str(), ok);
1980  const double a = attrs.get<double>(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok);
1981  const double b = attrs.get<double>(OPENDRIVE_ATTR_B, myCurrentEdge.id.c_str(), ok);
1982  const double c = attrs.get<double>(OPENDRIVE_ATTR_C, myCurrentEdge.id.c_str(), ok);
1983  const double d = attrs.get<double>(OPENDRIVE_ATTR_D, myCurrentEdge.id.c_str(), ok);
1984  OpenDriveLane& l = myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back();
1985  l.width = MAX2(l.width, a);
1986  l.widthData.push_back(OpenDriveWidth(s, a, b, c, d));
1987 #ifdef DEBUG_VARIABLE_WIDTHS
1988  if (DEBUG_COND(&myCurrentEdge)) {
1989  std::cout << " road=" << myCurrentEdge.id
1990  << std::setprecision(gPrecision)
1991  << " junction=" << myCurrentEdge.junction
1992  << " section=" << myCurrentEdge.laneSections.size() - 1
1993  << " dir=" << myCurrentLaneDirection << " lane=" << l.id
1994  << " type=" << l.type
1995  << " width=" << l.width
1996  << " a=" << a
1997  << " b=" << b
1998  << " c=" << c
1999  << " d=" << d
2000  << " s=" << s
2001  << " entries=" << l.widthData.size()
2002  << "\n";
2003  }
2004 #endif
2005  }
2006  }
2007  break;
2008  case OPENDRIVE_TAG_SPEED: {
2009  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 1] == OPENDRIVE_TAG_LANE) {
2010  double speed = attrs.get<double>(OPENDRIVE_ATTR_MAX, myCurrentEdge.id.c_str(), ok);
2011  double pos = attrs.get<double>(OPENDRIVE_ATTR_SOFFSET, myCurrentEdge.id.c_str(), ok);
2012  // required for xodr v1.4
2013  const std::string unit = attrs.getOpt<std::string>(OPENDRIVE_ATTR_UNIT, myCurrentEdge.id.c_str(), ok, "", false);
2014  // now convert the speed to reasonable default SI [m/s]
2015  if (!unit.empty()) {
2016  // something to be done at all ?
2017  if (unit == "km/h") {
2018  speed /= 3.6;
2019  }
2020  if (unit == "mph") {
2021  speed *= 1.609344 / 3.6;
2022  }
2023  // IGNORING unknown units.
2024  }
2025  myCurrentEdge.laneSections.back().lanesByDir[myCurrentLaneDirection].back().speeds.push_back(std::make_pair(pos, speed));
2026  }
2027  }
2028  break;
2029  case OPENDRIVE_TAG_OBJECT: {
2030  if (!attrs.hasAttribute(OPENDRIVE_ATTR_ID)) {
2031  WRITE_WARNING("Ignoring object without id at edge '" + toString(myCurrentEdge.id) + "'.");
2032  break;
2033  }
2034  OpenDriveObject o;
2035  o.id = attrs.get<std::string>(OPENDRIVE_ATTR_ID, 0, ok);
2036  o.type = attrs.getOpt<std::string>(OPENDRIVE_ATTR_TYPE, o.id.c_str(), ok, "", false);
2037  o.name = attrs.getOpt<std::string>(OPENDRIVE_ATTR_NAME, o.id.c_str(), ok, "", false);
2038  o.s = attrs.get<double>(OPENDRIVE_ATTR_S, o.id.c_str(), ok);
2039  o.t = attrs.get<double>(OPENDRIVE_ATTR_T, o.id.c_str(), ok);
2040  o.width = attrs.getOpt<double>(OPENDRIVE_ATTR_WIDTH, o.id.c_str(), ok, -1);
2041  o.length = attrs.getOpt<double>(OPENDRIVE_ATTR_LENGTH, o.id.c_str(), ok, -1);
2042  o.radius = attrs.getOpt<double>(OPENDRIVE_ATTR_RADIUS, o.id.c_str(), ok, -1);
2043  o.hdg = attrs.getOpt<double>(OPENDRIVE_ATTR_HDG, o.id.c_str(), ok, 0);
2044  myCurrentEdge.objects.push_back(o);
2045  }
2046  break;
2047  case OPENDRIVE_TAG_REPEAT: {
2048  if (myCurrentEdge.objects.empty()) {
2049  WRITE_ERROR("Repeat without object at edge '" + toString(myCurrentEdge.id) + "'.");
2050  ok = false;
2051  } else {
2053  const std::string baseID = o.id;
2054  double dist = attrs.get<double>(OPENDRIVE_ATTR_DISTANCE, o.id.c_str(), ok);
2055  if (dist == 0) {
2056  // continuous feature. Split into parts (XXX exmport as a single polygon #5235)
2057  dist = OptionsCont::getOptions().getFloat("opendrive.curve-resolution");
2058  }
2059 
2060  myCurrentEdge.objects.pop_back();
2061  const double length = attrs.get<double>(OPENDRIVE_ATTR_LENGTH, o.id.c_str(), ok);
2062  o.s = attrs.getOpt<double>(OPENDRIVE_ATTR_S, o.id.c_str(), ok, o.s);
2063  double wStart = attrs.getOpt<double>(OPENDRIVE_ATTR_WIDTHSTART, o.id.c_str(), ok, o.width);
2064  double wEnd = attrs.getOpt<double>(OPENDRIVE_ATTR_WIDTHEND, o.id.c_str(), ok, o.width);
2065  double tStart = attrs.getOpt<double>(OPENDRIVE_ATTR_TSTART, o.id.c_str(), ok, o.t);
2066  double tEnd = attrs.getOpt<double>(OPENDRIVE_ATTR_TEND, o.id.c_str(), ok, o.t);
2067  int index = 0;
2068  for (double x = 0; x <= length + NUMERICAL_EPS; x += dist) {
2069  o.id = baseID + "#" + toString(index++);
2070  const double a = x / length;
2071  o.width = wStart * (1 - a) + wEnd * a;
2072  o.t = tStart * (1 - a) + tEnd * a;
2073  myCurrentEdge.objects.push_back(o);
2074  o.s += dist;
2075  }
2076  }
2077  }
2078  break;
2079  default:
2080  break;
2081  }
2082  myElementStack.push_back(element);
2083 }
2084 
2085 
2086 void
2087 NIImporter_OpenDrive::myCharacters(int element, const std::string& cdata) {
2088  if (element == OPENDRIVE_TAG_GEOREFERENCE) {
2089  size_t i = cdata.find("+proj");
2090  if (i != std::string::npos) {
2091  const std::string proj = cdata.substr(i);
2092  if (proj != "") {
2093  GeoConvHelper* result = nullptr;
2094  Boundary convBoundary;
2095  Boundary origBoundary;
2096  Position networkOffset(0, 0);
2097  // XXX read values from the header
2098  convBoundary.add(Position(0, 0));
2099  origBoundary.add(Position(0, 0));
2100  try {
2101  result = new GeoConvHelper(proj, networkOffset, origBoundary, convBoundary);
2102  GeoConvHelper::setLoaded(*result);
2103  } catch (ProcessError& e) {
2104  WRITE_ERROR("Could not set projection. (" + std::string(e.what()) + ")");
2105  }
2106  }
2107  } else {
2108  WRITE_WARNING("geoReference format '" + cdata + "' currently not supported");
2109  }
2110  }
2111 }
2112 
2113 
2114 void
2116  myElementStack.pop_back();
2117  switch (element) {
2118  case OPENDRIVE_TAG_ROAD:
2120  break;
2122  if (myConnectionWasEmpty) {
2123  Connection c;
2126  c.fromLane = 0;
2127  c.toLane = 0;
2130  c.all = true;
2131  if (myEdges.find(c.fromEdge) == myEdges.end()) {
2132  WRITE_ERROR("In laneLink-element: incoming road '" + c.fromEdge + "' is not known.");
2133  } else {
2134  OpenDriveEdge* e = myEdges.find(c.fromEdge)->second;
2135  e->connections.insert(c);
2136  }
2137  }
2138  break;
2140  myCurrentEdge.laneSections.back().buildLaneMapping(myTypeContainer);
2141  }
2142  break;
2143  default:
2144  break;
2145  }
2146 }
2147 
2148 
2149 
2150 void
2151 NIImporter_OpenDrive::addLink(LinkType lt, const std::string& elementType,
2152  const std::string& elementID,
2153  const std::string& contactPoint) {
2154  OpenDriveLink l(lt, elementID);
2155  // elementType
2156  if (elementType == "road") {
2158  } else if (elementType == "junction") {
2160  }
2161  // contact point
2162  if (contactPoint == "start") {
2164  } else if (contactPoint == "end") {
2166  }
2167  // add
2168  myCurrentEdge.links.push_back(l);
2169 }
2170 
2171 
2172 void
2173 NIImporter_OpenDrive::addGeometryShape(GeometryType type, const std::vector<double>& vals) {
2174  // checks
2175  if (myCurrentEdge.geometries.size() == 0) {
2176  throw ProcessError("Mismatching paranthesis in geometry definition for road '" + myCurrentEdge.id + "'");
2177  }
2179  if (last.type != OPENDRIVE_GT_UNKNOWN) {
2180  throw ProcessError("Double geometry information for road '" + myCurrentEdge.id + "'");
2181  }
2182  // set
2183  last.type = type;
2184  last.params = vals;
2185 }
2186 
2187 
2188 bool
2190  if (c1.fromEdge != c2.fromEdge) {
2191  return c1.fromEdge < c2.fromEdge;
2192  }
2193  if (c1.toEdge != c2.toEdge) {
2194  return c1.toEdge < c2.toEdge;
2195  }
2196  if (c1.fromLane != c2.fromLane) {
2197  return c1.fromLane < c2.fromLane;
2198  }
2199  return c1.toLane < c2.toLane;
2200 }
2201 
2202 void
2204 #ifdef DEBUG_VARIABLE_WIDTHS
2205  if (DEBUG_COND(e)) {
2206  gDebugFlag1 = true;
2207  std::cout << "sanitizeWidths e=" << e->id << " sections=" << e->laneSections.size() << "\n";
2208  }
2209 #endif
2210  for (OpenDriveLaneSection& sec : e->laneSections) {
2211  // filter widths within the current section (#5888).
2212  // @note, Short laneSections could also be worth filtering alltogether
2213  if (sec.rightLaneNumber > 0) {
2215  }
2216  if (sec.leftLaneNumber > 0) {
2218  }
2219  }
2220 }
2221 
2222 void
2223 NIImporter_OpenDrive::sanitizeWidths(std::vector<OpenDriveLane>& lanes, double length) {
2224  for (OpenDriveLane& l : lanes) {
2225  if (l.widthData.size() > 0) {
2226  auto& wd = l.widthData;
2227  const double threshold = POSITION_EPS;
2228  double maxNoShort = -std::numeric_limits<double>::max();
2229  double seen = 0;
2230  for (int i = 0; i < (int)wd.size(); i++) {
2231  const double wdLength = i < (int)wd.size() - 1 ? wd[i + 1].s - wd[i].s : length - seen;
2232  seen += wdLength;
2233  if (wdLength > threshold) {
2234  maxNoShort = MAX2(maxNoShort, wd[i].a);
2235  }
2236  }
2237  if (maxNoShort > 0) {
2238  l.width = maxNoShort;
2239  }
2240  }
2241  }
2242 }
2243 
2244 
2245 void
2247  std::vector<OpenDriveLaneSection> newSections;
2248 #ifdef DEBUG_VARIABLE_WIDTHS
2249  if (DEBUG_COND(e)) {
2250  gDebugFlag1 = true;
2251  std::cout << "splitMinWidths e=" << e->id << " sections=" << e->laneSections.size() << "\n";
2252  }
2253 #endif
2254  for (std::vector<OpenDriveLaneSection>::iterator j = e->laneSections.begin(); j != e->laneSections.end(); ++j) {
2255  OpenDriveLaneSection& sec = *j;
2256  std::vector<double> splitPositions;
2257  const double sectionEnd = (j + 1) == e->laneSections.end() ? e->length : (*(j + 1)).s;
2258  const int section = (int)(j - e->laneSections.begin());
2259 #ifdef DEBUG_VARIABLE_WIDTHS
2260  if (DEBUG_COND(e)) {
2261  std::cout << " findWidthSplit section=" << section << " sectionStart=" << sec.s << " sectionOrigStart=" << sec.sOrig << " sectionEnd=" << sectionEnd << "\n";
2262  }
2263 #endif
2264  if (sec.rightLaneNumber > 0) {
2265  findWidthSplit(tc, sec.lanesByDir[OPENDRIVE_TAG_RIGHT], section, sec.sOrig, sectionEnd, splitPositions);
2266  }
2267  if (sec.leftLaneNumber > 0) {
2268  findWidthSplit(tc, sec.lanesByDir[OPENDRIVE_TAG_LEFT], section, sec.sOrig, sectionEnd, splitPositions);
2269  }
2270  newSections.push_back(sec);
2271  std::sort(splitPositions.begin(), splitPositions.end());
2272  // filter out tiny splits
2273  double prevSplit = sec.s;
2274  for (std::vector<double>::iterator it = splitPositions.begin(); it != splitPositions.end();) {
2275  if ((*it) - prevSplit < minDist || sectionEnd - (*it) < minDist) {
2276  // avoid tiny (or duplicate) splits
2277 #ifdef DEBUG_VARIABLE_WIDTHS
2278  if (DEBUG_COND(e)) {
2279  std::cout << " skip close split=" << (*it) << " prevSplit=" << prevSplit << "\n";
2280  }
2281 #endif
2282  it = splitPositions.erase(it);
2283  } else if ((*it) < sec.s) {
2284  // avoid splits for another section
2285 #ifdef DEBUG_VARIABLE_WIDTHS
2286  if (DEBUG_COND(e)) {
2287  std::cout << " skip early split=" << (*it) << " s=" << sec.s << "\n";
2288  }
2289 #endif
2290  it = splitPositions.erase(it);
2291  } else {
2292  prevSplit = *it;
2293  it++;
2294  }
2295  }
2296 
2297  if (splitPositions.size() > 0) {
2298 #ifdef DEBUG_VARIABLE_WIDTHS
2299  if (DEBUG_COND(e)) {
2300  std::cout << " road=" << e->id << " splitMinWidths section=" << section
2301  << " start=" << sec.s
2302  << " origStart=" << sec.sOrig
2303  << " end=" << sectionEnd << " minDist=" << minDist
2304  << " splitPositions=" << toString(splitPositions) << "\n";
2305  }
2306 #endif
2307 #ifdef DEBUG_VARIABLE_WIDTHS
2308  if (DEBUG_COND(e)) {
2309  std::cout << "first section...\n";
2310  }
2311 #endif
2312  recomputeWidths(newSections.back(), sec.sOrig, splitPositions.front(), sec.sOrig, sectionEnd);
2313  for (std::vector<double>::iterator it = splitPositions.begin(); it != splitPositions.end(); ++it) {
2314  OpenDriveLaneSection secNew = sec;
2315  secNew.s = *it;
2316 #ifdef DEBUG_VARIABLE_WIDTHS
2317  if (DEBUG_COND(e)) {
2318  std::cout << "splitAt " << secNew.s << "\n";
2319  }
2320 #endif
2321  newSections.push_back(secNew);
2322  if (secNew.rightLaneNumber > 0) {
2323  setStraightConnections(newSections.back().lanesByDir[OPENDRIVE_TAG_RIGHT]);
2324  }
2325  if (secNew.leftLaneNumber > 0) {
2326  setStraightConnections(newSections.back().lanesByDir[OPENDRIVE_TAG_LEFT]);
2327  }
2328  double end = (it + 1) == splitPositions.end() ? sectionEnd : *(it + 1);
2329  recomputeWidths(newSections.back(), secNew.s, end, sec.sOrig, sectionEnd);
2330  }
2331  }
2332  }
2333  gDebugFlag1 = false;
2334  e->laneSections = newSections;
2335 }
2336 
2337 
2338 void
2339 NIImporter_OpenDrive::findWidthSplit(const NBTypeCont& tc, std::vector<OpenDriveLane>& lanes,
2340  int section, double sectionStart, double sectionEnd,
2341  std::vector<double>& splitPositions) {
2342  UNUSED_PARAMETER(section);
2343  for (std::vector<OpenDriveLane>::iterator k = lanes.begin(); k != lanes.end(); ++k) {
2344  OpenDriveLane& l = *k;
2345  SVCPermissions permissions = tc.getPermissions(l.type) & ~(SVC_PEDESTRIAN | SVC_BICYCLE);
2346  if (l.widthData.size() > 0 && tc.knows(l.type) && !tc.getShallBeDiscarded(l.type) && permissions != 0) {
2347  double sPrev = l.widthData.front().s;
2348  double wPrev = l.widthData.front().computeAt(sPrev);
2349  if (gDebugFlag1) std::cout
2350  << "findWidthSplit section=" << section
2351  << " sectionStart=" << sectionStart
2352  << " sectionEnd=" << sectionEnd
2353  << " lane=" << l.id
2354  << " type=" << l.type
2355  << " widthEntries=" << l.widthData.size() << "\n"
2356  << " s=" << sPrev
2357  << " w=" << wPrev
2358  << "\n";
2359  for (std::vector<OpenDriveWidth>::iterator it_w = l.widthData.begin(); it_w != l.widthData.end(); ++it_w) {
2360  double sEnd = (it_w + 1) != l.widthData.end() ? (*(it_w + 1)).s : sectionEnd - sectionStart;
2361  double w = (*it_w).computeAt(sEnd);
2362  if (gDebugFlag1) std::cout
2363  << " sEnd=" << sEnd
2364  << " s=" << (*it_w).s
2365  << " a=" << (*it_w).a << " b=" << (*it_w).b << " c=" << (*it_w).c << " d=" << (*it_w).d
2366  << " w=" << w
2367  << "\n";
2368  const double changeDist = fabs(myMinWidth - wPrev);
2369  if (((wPrev < myMinWidth) && (w > myMinWidth))
2370  || ((wPrev > myMinWidth) && (w < myMinWidth))) {
2371  double splitPos = sPrev + (sEnd - sPrev) / fabs(w - wPrev) * changeDist;
2372  double wSplit = (*it_w).computeAt(splitPos);
2373  if (gDebugFlag1) {
2374  std::cout << " candidate splitPos=" << splitPos << " w=" << wSplit << "\n";
2375  }
2376  // ensure that the thin part is actually thin enough
2377  while (wSplit > myMinWidth) {
2378  if (wPrev < myMinWidth) {
2379  // getting wider
2380  splitPos -= POSITION_EPS;
2381  if (splitPos < sPrev) {
2382  if (gDebugFlag1) {
2383  std::cout << " aborting search splitPos=" << splitPos << " wSplit=" << wSplit << " sPrev=" << sPrev << " wPrev=" << wPrev << "\n";
2384  }
2385  splitPos = sPrev;
2386  break;
2387  }
2388  } else {
2389  // getting thinner
2390  splitPos += POSITION_EPS;
2391  if (splitPos > sEnd) {
2392  if (gDebugFlag1) {
2393  std::cout << " aborting search splitPos=" << splitPos << " wSplit=" << wSplit << " sEnd=" << sEnd << " w=" << w << "\n";
2394  }
2395  splitPos = sEnd;
2396  break;
2397  }
2398  }
2399  wSplit = (*it_w).computeAt(splitPos);
2400  if (gDebugFlag1) {
2401  std::cout << " refined splitPos=" << splitPos << " w=" << wSplit << "\n";
2402  }
2403  }
2404  splitPositions.push_back(sectionStart + splitPos);
2405  }
2406  // //wPrev = wSplit;
2407  //} else if ((fabs(wPrev) < NUMERICAL_EPS && w > POSITION_EPS)
2408  // || (wPrev > POSITION_EPS && fabs(w) < NUMERICAL_EPS)) {
2409  // splitPositions.push_back(sectionStart + sPrev);
2410  // if (gDebugFlag1) std::cout << " laneDisappears candidate splitPos=" << sPrev << " wPrev=" << wPrev << " w=" << w<< "\n";
2411  //}
2412  wPrev = w;
2413  sPrev = sEnd;
2414  }
2415  }
2416  }
2417 }
2418 
2419 
2420 void
2421 NIImporter_OpenDrive::setStraightConnections(std::vector<OpenDriveLane>& lanes) {
2422  for (std::vector<OpenDriveLane>::iterator k = lanes.begin(); k != lanes.end(); ++k) {
2423  (*k).predecessor = (*k).id;
2424  }
2425 }
2426 
2427 
2428 void
2429 NIImporter_OpenDrive::recomputeWidths(OpenDriveLaneSection& sec, double start, double end, double sectionStart, double sectionEnd) {
2430  if (sec.rightLaneNumber > 0) {
2431  recomputeWidths(sec.lanesByDir[OPENDRIVE_TAG_RIGHT], start, end, sectionStart, sectionEnd);
2432  }
2433  if (sec.leftLaneNumber > 0) {
2434  recomputeWidths(sec.lanesByDir[OPENDRIVE_TAG_LEFT], start, end, sectionStart, sectionEnd);
2435  }
2436 }
2437 
2438 
2439 void
2440 NIImporter_OpenDrive::recomputeWidths(std::vector<OpenDriveLane>& lanes, double start, double end, double sectionStart, double sectionEnd) {
2441  for (std::vector<OpenDriveLane>::iterator k = lanes.begin(); k != lanes.end(); ++k) {
2442  OpenDriveLane& l = *k;
2443  if (l.widthData.size() > 0) {
2444 #ifdef DEBUG_VARIABLE_WIDTHS
2445  if (gDebugFlag1) std::cout
2446  << "recomputeWidths lane=" << l.id
2447  << " type=" << l.type
2448  << " start=" << start
2449  << " end=" << end
2450  << " sectionStart=" << sectionStart
2451  << " sectionEnd=" << sectionEnd
2452  << " widthEntries=" << l.widthData.size() << "\n"
2453  << "\n";
2454 #endif
2455  l.width = 0;
2456  double sPrev = l.widthData.front().s;
2457  double sPrevAbs = sPrev + sectionStart;
2458  for (std::vector<OpenDriveWidth>::iterator it_w = l.widthData.begin(); it_w != l.widthData.end(); ++it_w) {
2459  double sEnd = (it_w + 1) != l.widthData.end() ? (*(it_w + 1)).s : sectionEnd - sectionStart;
2460  double sEndAbs = sEnd + sectionStart;
2461 #ifdef DEBUG_VARIABLE_WIDTHS
2462  if (gDebugFlag1) std::cout
2463  << " sPrev=" << sPrev << " sPrevAbs=" << sPrevAbs
2464  << " sEnd=" << sEnd << " sEndAbs=" << sEndAbs
2465  << " widthData s=" << (*it_w).s
2466  << " a=" << (*it_w).a
2467  << " b=" << (*it_w).b
2468  << " c=" << (*it_w).c
2469  << " d=" << (*it_w).d
2470  << "\n";
2471 #endif
2472  if (sPrevAbs <= start && sEndAbs >= start) {
2473 #ifdef DEBUG_VARIABLE_WIDTHS
2474  if (gDebugFlag1) {
2475  std::cout << " atStart=" << start << " pos=" << start - sectionStart << " w=" << (*it_w).computeAt(start - sectionStart) << "\n";
2476  }
2477 #endif
2478  l.width = MAX2(l.width, (*it_w).computeAt(start - sectionStart));
2479  }
2480  if (sPrevAbs <= end && sEndAbs >= end) {
2481 #ifdef DEBUG_VARIABLE_WIDTHS
2482  if (gDebugFlag1) {
2483  std::cout << " atEnd=" << end << " pos=" << end - sectionStart << " w=" << (*it_w).computeAt(end - sectionStart) << "\n";
2484  }
2485 #endif
2486  l.width = MAX2(l.width, (*it_w).computeAt(end - sectionStart));
2487  }
2488  if (start <= sPrevAbs && end >= sPrevAbs) {
2489 #ifdef DEBUG_VARIABLE_WIDTHS
2490  if (gDebugFlag1) {
2491  std::cout << " atSPrev=" << sPrev << " w=" << (*it_w).computeAt(sPrev) << "\n";
2492  }
2493 #endif
2494  l.width = MAX2(l.width, (*it_w).computeAt(sPrev));
2495  }
2496  if (start <= sEndAbs && end >= sEndAbs) {
2497 #ifdef DEBUG_VARIABLE_WIDTHS
2498  if (gDebugFlag1) {
2499  std::cout << " atSEnd=" << sEnd << " w=" << (*it_w).computeAt(sEnd) << "\n";
2500  }
2501 #endif
2502  l.width = MAX2(l.width, (*it_w).computeAt(sEnd));
2503  }
2504 #ifdef DEBUG_VARIABLE_WIDTHS
2505  if (gDebugFlag1) {
2506  std::cout << " sPrev=" << sPrev << " sEnd=" << sEnd << " l.width=" << l.width << "\n";
2507  }
2508 #endif
2509  sPrev = sEnd;
2510  sPrevAbs = sEndAbs;
2511  }
2512  }
2513  }
2514 }
2515 
2516 /****************************************************************************/
2517 
NIImporter_OpenDrive::OpenDriveEdge::getPriority
int getPriority(OpenDriveXMLTag dir) const
Returns the edge's priority, regarding the direction.
Definition: NIImporter_OpenDrive.cpp:1737
NIImporter_OpenDrive::OpenDriveSignal
Representation of a signal.
Definition: NIImporter_OpenDrive.h:369
NIImporter_OpenDrive::OpenDriveEdge::to
NBNode * to
Definition: NIImporter_OpenDrive.h:474
NIImporter_OpenDrive::OPENDRIVE_TAG_SIGNAL
@ OPENDRIVE_TAG_SIGNAL
Definition: NIImporter_OpenDrive.h:100
NIImporter_OpenDrive::OPENDRIVE_TAG_CENTER
@ OPENDRIVE_TAG_CENTER
Definition: NIImporter_OpenDrive.h:97
OptionsCont::isSet
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
Definition: OptionsCont.cpp:135
Boundary.h
UNUSED_PARAMETER
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:31
NBEdge::UNSPECIFIED_OFFSET
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:318
NIImporter_OpenDrive::addLink
void addLink(LinkType lt, const std::string &elementType, const std::string &elementID, const std::string &contactPoint)
Definition: NIImporter_OpenDrive.cpp:2151
NIImporter_OpenDrive::myImportInternalShapes
static bool myImportInternalShapes
Definition: NIImporter_OpenDrive.h:590
SVC_PEDESTRIAN
@ SVC_PEDESTRIAN
pedestrian
Definition: SUMOVehicleClass.h:156
NIImporter_OpenDrive::OPENDRIVE_ATTR_LEVEL
@ OPENDRIVE_ATTR_LEVEL
Definition: NIImporter_OpenDrive.h:157
NIImporter_OpenDrive::OpenDriveEdge
Representation of an openDrive "link".
Definition: NIImporter_OpenDrive.h:440
NIImporter_OpenDrive::OPENDRIVE_TAG_SUCCESSOR
@ OPENDRIVE_TAG_SUCCESSOR
Definition: NIImporter_OpenDrive.h:85
NIImporter_OpenDrive::OpenDriveLaneSection::sOrig
double sOrig
The original starting offset of this lane section (differs from s if the section had to be split)
Definition: NIImporter_OpenDrive.h:347
ToString.h
XMLSubSys::runParser
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false)
Runs the given handler on the given file; returns if everything's ok.
Definition: XMLSubSys.cpp:112
NIImporter_OpenDrive::myTypeContainer
const NBTypeCont & myTypeContainer
Definition: NIImporter_OpenDrive.h:575
NIImporter_OpenDrive::OpenDriveLaneSection::getInnerConnections
std::map< int, int > getInnerConnections(OpenDriveXMLTag dir, const OpenDriveLaneSection &prev)
Returns the links from the previous to this lane section.
Definition: NIImporter_OpenDrive.cpp:1607
NBEdge::Lane::speed
double speed
The speed allowed on this lane.
Definition: NBEdge.h:150
SUMOSAXAttributes::hasAttribute
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
MIN2
T MIN2(T a, T b)
Definition: StdDefs.h:73
NIImporter_OpenDrive::Poly3::computeAt
double computeAt(double pos) const
Definition: NIImporter_OpenDrive.h:269
SVC_EMERGENCY
@ SVC_EMERGENCY
public emergency vehicles
Definition: SUMOVehicleClass.h:143
NBEdgeCont::retrieve
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:246
WRITE_WARNING
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:275
NIImporter_OpenDrive::OpenDriveLaneSection::laneMap
std::map< int, int > laneMap
A mapping from OpenDrive to SUMO-index (the first is signed, the second unsigned)
Definition: NIImporter_OpenDrive.h:351
SUMOPolygon::writeXML
void writeXML(OutputDevice &out, bool geo=false)
Definition: SUMOPolygon.cpp:49
NIImporter_OpenDrive::geomFromPoly
static PositionVector geomFromPoly(const OpenDriveEdge &e, const OpenDriveGeometry &g, double resolution)
Definition: NIImporter_OpenDrive.cpp:1464
NIImporter_OpenDrive::OPENDRIVE_GT_SPIRAL
@ OPENDRIVE_GT_SPIRAL
Definition: NIImporter_OpenDrive.h:201
NIImporter_OpenDrive::myCurrentLaneDirection
OpenDriveXMLTag myCurrentLaneDirection
Definition: NIImporter_OpenDrive.h:580
NBEdge::Lane::type
std::string type
the type of this lane
Definition: NBEdge.h:182
NBNetBuilder
Instance responsible for building networks.
Definition: NBNetBuilder.h:109
NIImporter_OpenDrive::OPENDRIVE_TAG_CONNECTION
@ OPENDRIVE_TAG_CONNECTION
Definition: NIImporter_OpenDrive.h:102
NIImporter_OpenDrive::OPENDRIVE_ATTR_FROM
@ OPENDRIVE_ATTR_FROM
Definition: NIImporter_OpenDrive.h:162
NIImporter_OpenDrive::OpenDriveEdge::junction
std::string junction
The id of the junction the edge belongs to.
Definition: NIImporter_OpenDrive.h:466
NIImporter_OpenDrive::OPENDRIVE_GT_UNKNOWN
@ OPENDRIVE_GT_UNKNOWN
Definition: NIImporter_OpenDrive.h:199
NIImporter_OpenDrive::OpenDriveLaneSection::length
double length
The length of this lane section.
Definition: NIImporter_OpenDrive.h:349
OutputDevice
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:63
GeomConvHelper.h
NIImporter_OpenDrive::OPENDRIVE_TAG_LANELINK
@ OPENDRIVE_TAG_LANELINK
Definition: NIImporter_OpenDrive.h:103
NIImporter_OpenDrive::OpenDriveGeometry::x
double x
Definition: NIImporter_OpenDrive.h:247
NUMERICAL_EPS
#define NUMERICAL_EPS
Definition: config.h:148
PositionVector::getSubpart2D
PositionVector getSubpart2D(double beginOffset, double endOffset) const
get subpart of a position vector in two dimensions (Z is ignored)
Definition: PositionVector.cpp:746
OptionsCont.h
PositionVector::rotate2D
void rotate2D(double angle)
Definition: PositionVector.cpp:1503
NIImporter_OpenDrive::OpenDriveLane::width
double width
Definition: NIImporter_OpenDrive.h:308
LANESPREAD_RIGHT
@ LANESPREAD_RIGHT
Definition: SUMOXMLDefinitions.h:1098
NIImporter_OpenDrive::OPENDRIVE_ATTR_DISTANCE
@ OPENDRIVE_ATTR_DISTANCE
Definition: NIImporter_OpenDrive.h:126
SUMOSAXAttributes::get
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
Definition: SUMOSAXAttributes.h:492
NIImporter_OpenDrive::OPENDRIVE_TAG_GEOMETRY
@ OPENDRIVE_TAG_GEOMETRY
Definition: NIImporter_OpenDrive.h:88
MsgHandler.h
NIImporter_OpenDrive::OpenDriveEdge::connections
std::set< Connection > connections
Definition: NIImporter_OpenDrive.h:479
NIImporter_OpenDrive::OpenDriveEdge::laneSections
std::vector< OpenDriveLaneSection > laneSections
Definition: NIImporter_OpenDrive.h:477
NIImporter_OpenDrive::geomFromSpiral
static PositionVector geomFromSpiral(const OpenDriveEdge &e, const OpenDriveGeometry &g, double resolution)
Definition: NIImporter_OpenDrive.cpp:1354
RGBColor::YELLOW
static const RGBColor YELLOW
Definition: RGBColor.h:192
NIImporter_OpenDrive::OpenDriveLaneSection
Representation of a lane section.
Definition: NIImporter_OpenDrive.h:317
GeoConvHelper::setLoaded
static void setLoaded(const GeoConvHelper &loaded)
sets the coordinate transformation loaded from a location element
Definition: GeoConvHelper.cpp:539
NIImporter_OpenDrive::Connection::fromLane
int fromLane
Definition: NIImporter_OpenDrive.h:397
NIImporter_OpenDrive::sanitizeWidths
static void sanitizeWidths(OpenDriveEdge *e)
Definition: NIImporter_OpenDrive.cpp:2203
NBNodeCont::insert
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:78
NIImporter_OpenDrive::Connection::all
bool all
Definition: NIImporter_OpenDrive.h:401
NIImporter_OpenDrive::NIImporter_OpenDrive
NIImporter_OpenDrive(const NBTypeCont &tc, std::map< std::string, OpenDriveEdge * > &edges)
Constructor.
Definition: NIImporter_OpenDrive.cpp:1764
OptionsCont::getString
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
Definition: OptionsCont.cpp:201
PointOfInterest::writeXML
void writeXML(OutputDevice &out, const bool geo=false, const double zOffset=0., const std::string laneID="", const double pos=0., const double posLat=0.)
Definition: PointOfInterest.h:123
SUMOSAXHandler.h
NIImporter_OpenDrive::OPENDRIVE_TAG_ELEVATION
@ OPENDRIVE_TAG_ELEVATION
Definition: NIImporter_OpenDrive.h:106
FileHelpers.h
TrafficLightType
TrafficLightType
Definition: SUMOXMLDefinitions.h:1197
cn
static double cn[6]
Definition: odrSpiral.cpp:63
NIImporter_OpenDrive::OpenDriveObject::length
double length
Definition: NIImporter_OpenDrive.h:427
NBNetBuilder::transformCoordinates
static bool transformCoordinates(PositionVector &from, bool includeInBoundary=true, GeoConvHelper *from_srs=0)
Definition: NBNetBuilder.cpp:660
NIImporter_OpenDrive::OPENDRIVE_ATTR_C
@ OPENDRIVE_ATTR_C
Definition: NIImporter_OpenDrive.h:145
OptionsCont::exists
bool exists(const std::string &name) const
Returns the information whether the named option is known.
Definition: OptionsCont.cpp:129
NIImporter_OpenDrive::OPENDRIVE_ATTR_CONTACTPOINT
@ OPENDRIVE_ATTR_CONTACTPOINT
Definition: NIImporter_OpenDrive.h:134
GeomHelper::naviDegree
static double naviDegree(const double angle)
Definition: GeomHelper.cpp:193
NBEdgeCont.h
GeoConvHelper.h
NIImporter_OpenDrive::OpenDriveLane
Representation of a lane.
Definition: NIImporter_OpenDrive.h:291
NIImporter_OpenDrive::OpenDriveLane::speed
double speed
The lane's speed (set in post-processing)
Definition: NIImporter_OpenDrive.h:307
OptionsCont::getBool
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
Definition: OptionsCont.cpp:222
NBOwnTLDef
A traffic light logics which must be computed (only nodes/edges are given)
Definition: NBOwnTLDef.h:46
SVC_BICYCLE
@ SVC_BICYCLE
vehicle is a bicycle
Definition: SUMOVehicleClass.h:179
OptionsCont::getOptions
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:57
NIImporter_OpenDrive::myCharacters
void myCharacters(int element, const std::string &chars)
Callback method for characters to implement by derived classes.
Definition: NIImporter_OpenDrive.cpp:2087
NBTypeCont::getMaxWidth
double getMaxWidth(const std::string &type) const
Returns the maximum edge/lane widths of the given type.
Definition: NBTypeCont.cpp:205
NIImporter_OpenDrive.h
NBEdgeCont::insert
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:153
NIImporter_OpenDrive::OPENDRIVE_ATTR_A
@ OPENDRIVE_ATTR_A
Definition: NIImporter_OpenDrive.h:143
NIImporter_OpenDrive::OPENDRIVE_ATTR_DU
@ OPENDRIVE_ATTR_DU
Definition: NIImporter_OpenDrive.h:150
GeoConvHelper::getLoaded
static GeoConvHelper & getLoaded()
the coordinate transformation that was loaded fron an input file
Definition: GeoConvHelper.h:91
NIImporter_OpenDrive::calculateStraightEndPoint
static Position calculateStraightEndPoint(double hdg, double length, const Position &start)
Definition: NIImporter_OpenDrive.cpp:1500
NIImporter_OpenDrive::OPENDRIVE_TAG_SPIRAL
@ OPENDRIVE_TAG_SPIRAL
Definition: NIImporter_OpenDrive.h:90
NIImporter_OpenDrive::OpenDriveObject::t
double t
Definition: NIImporter_OpenDrive.h:425
NIImporter_OpenDrive::OpenDriveEdge::signals
std::vector< OpenDriveSignal > signals
Definition: NIImporter_OpenDrive.h:478
NIImporter_OpenDrive::OPENDRIVE_ATTR_INCOMINGROAD
@ OPENDRIVE_ATTR_INCOMINGROAD
Definition: NIImporter_OpenDrive.h:160
NIImporter_OpenDrive::OpenDriveLaneOffset
Poly3 OpenDriveLaneOffset
Definition: NIImporter_OpenDrive.h:283
NIImporter_OpenDrive::OPENDRIVE_ATTR_AU
@ OPENDRIVE_ATTR_AU
Definition: NIImporter_OpenDrive.h:147
NIImporter_OpenDrive::OPENDRIVE_ATTR_WIDTH
@ OPENDRIVE_ATTR_WIDTH
Definition: NIImporter_OpenDrive.h:124
NBEdge::L2L_USER
@ L2L_USER
The connection was given by the user.
Definition: NBEdge.h:133
PositionVector
A list of positions.
Definition: PositionVector.h:45
NIImporter_OpenDrive::Connection::fromEdge
std::string fromEdge
Definition: NIImporter_OpenDrive.h:395
odrSpiral
void odrSpiral(double s, double cDot, double *x, double *y, double *t)
Definition: odrSpiral.cpp:231
NBTypeCont::knows
bool knows(const std::string &type) const
Returns whether the named type is in the container.
Definition: NBTypeCont.cpp:71
NIImporter_OpenDrive::OPENDRIVE_ATTR_S
@ OPENDRIVE_ATTR_S
Definition: NIImporter_OpenDrive.h:135
NIImporter_OpenDrive::OpenDriveObject::radius
double radius
Definition: NIImporter_OpenDrive.h:430
NIImporter_OpenDrive::OpenDriveXMLTag
OpenDriveXMLTag
Numbers representing openDrive-XML - element names.
Definition: NIImporter_OpenDrive.h:80
GeoConvHelper
static methods for processing the coordinates conversion for the current net
Definition: GeoConvHelper.h:55
NIImporter_OpenDrive::OPENDRIVE_GT_ARC
@ OPENDRIVE_GT_ARC
Definition: NIImporter_OpenDrive.h:202
NIImporter_OpenDrive::OPENDRIVE_TAG_REPEAT
@ OPENDRIVE_TAG_REPEAT
Definition: NIImporter_OpenDrive.h:109
PositionVector::getBoxBoundary
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
Definition: PositionVector.cpp:390
GeoConvHelper::usingGeoProjection
bool usingGeoProjection() const
Returns whether a transformation from geo to metric coordinates will be performed.
Definition: GeoConvHelper.cpp:281
NIImporter_OpenDrive::myConnectionWasEmpty
bool myConnectionWasEmpty
Definition: NIImporter_OpenDrive.h:585
SVC_AUTHORITY
@ SVC_AUTHORITY
authorities vehicles
Definition: SUMOVehicleClass.h:145
NIImporter_OpenDrive::OPENDRIVE_ATTR_WIDTHSTART
@ OPENDRIVE_ATTR_WIDTHSTART
Definition: NIImporter_OpenDrive.h:129
NIImporter_OpenDrive::OPENDRIVE_ATTR_CV
@ OPENDRIVE_ATTR_CV
Definition: NIImporter_OpenDrive.h:153
NBNodeCont
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:59
NBNetBuilder::getEdgeCont
NBEdgeCont & getEdgeCont()
Definition: NBNetBuilder.h:150
NIImporter_OpenDrive::revisitLaneSections
static void revisitLaneSections(const NBTypeCont &tc, std::map< std::string, OpenDriveEdge * > &edges)
Rechecks lane sections of the given edges.
Definition: NIImporter_OpenDrive.cpp:1273
NIImporter_OpenDrive::OPENDRIVE_ATTR_TEND
@ OPENDRIVE_ATTR_TEND
Definition: NIImporter_OpenDrive.h:128
NIImporter_OpenDrive::OpenDriveLane::type
std::string type
The lane's type.
Definition: NIImporter_OpenDrive.h:303
NBTypeCont::getWidthResolution
double getWidthResolution(const std::string &type) const
Returns the resolution for interpreting edge/lane widths of the given type.
Definition: NBTypeCont.cpp:200
NBEdge
The representation of a single edge during network building.
Definition: NBEdge.h:91
NIImporter_OpenDrive::geomFromLine
static PositionVector geomFromLine(const OpenDriveEdge &e, const OpenDriveGeometry &g, double resolution)
Definition: NIImporter_OpenDrive.cpp:1333
OptionsCont::getStringVector
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
Definition: OptionsCont.cpp:235
NIImporter_OpenDrive::OpenDriveObject::id
std::string id
Definition: NIImporter_OpenDrive.h:423
NIImporter_OpenDrive::OpenDriveGeometry::s
double s
Definition: NIImporter_OpenDrive.h:246
NIImporter_OpenDrive::OpenDriveObject::s
double s
Definition: NIImporter_OpenDrive.h:424
NIImporter_OpenDrive::OPENDRIVE_ATTR_ELEMENTID
@ OPENDRIVE_ATTR_ELEMENTID
Definition: NIImporter_OpenDrive.h:133
NIImporter_OpenDrive::OPENDRIVE_ATTR_PRANGE
@ OPENDRIVE_ATTR_PRANGE
Definition: NIImporter_OpenDrive.h:155
MAX2
T MAX2(T a, T b)
Definition: StdDefs.h:79
PositionVector::add
void add(double xoff, double yoff, double zoff)
Definition: PositionVector.cpp:617
NIImporter_OpenDrive::OpenDriveElevation
Poly3 OpenDriveElevation
LaneOffset has the same fields as Elevation.
Definition: NIImporter_OpenDrive.h:282
NIImporter_OpenDrive::OPENDRIVE_ATTR_ID
@ OPENDRIVE_ATTR_ID
Definition: NIImporter_OpenDrive.h:122
DEBUG_COND2
#define DEBUG_COND2(edgeID)
Definition: NIImporter_OpenDrive.cpp:62
NIImporter_OpenDrive::OpenDriveLane::id
int id
The lane's id.
Definition: NIImporter_OpenDrive.h:301
NIImporter_OpenDrive::OPENDRIVE_ATTR_CURVSTART
@ OPENDRIVE_ATTR_CURVSTART
Definition: NIImporter_OpenDrive.h:140
NIImporter_OpenDrive::Connection
A connection between two roads.
Definition: NIImporter_OpenDrive.h:394
NIImporter_OpenDrive
Importer for networks stored in openDrive format.
Definition: NIImporter_OpenDrive.h:53
NIImporter_OpenDrive::OPENDRIVE_TAG_ROAD
@ OPENDRIVE_TAG_ROAD
Definition: NIImporter_OpenDrive.h:83
NIImporter_OpenDrive::OPENDRIVE_TAG_OBJECT
@ OPENDRIVE_TAG_OBJECT
Definition: NIImporter_OpenDrive.h:108
odrSpiral.h
NIImporter_OpenDrive::Connection::getDescription
std::string getDescription() const
Definition: NIImporter_OpenDrive.h:406
NBEdge::getToNode
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:498
NIImporter_OpenDrive::OPENDRIVE_ATTR_ELEMENTTYPE
@ OPENDRIVE_ATTR_ELEMENTTYPE
Definition: NIImporter_OpenDrive.h:132
NBNode::isTLControlled
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:313
NIImporter_OpenDrive::Poly3::d
double d
Definition: NIImporter_OpenDrive.h:278
OptionsCont::isUsableFileList
bool isUsableFileList(const std::string &name) const
Checks whether the named option is usable as a file list (with at least a single file)
Definition: OptionsCont.cpp:356
NIImporter_OpenDrive::Poly3::c
double c
Definition: NIImporter_OpenDrive.h:277
NIImporter_OpenDrive::OPENDRIVE_ATTR_WIDTHEND
@ OPENDRIVE_ATTR_WIDTHEND
Definition: NIImporter_OpenDrive.h:130
NIImporter_OpenDrive::OPENDRIVE_ATTR_CURVATURE
@ OPENDRIVE_ATTR_CURVATURE
Definition: NIImporter_OpenDrive.h:142
NIImporter_OpenDrive::OpenDriveGeometry::y
double y
Definition: NIImporter_OpenDrive.h:248
PositionVector::push_back_noDoublePos
void push_back_noDoublePos(const Position &p)
insert in back a non double position
Definition: PositionVector.cpp:1295
NIImporter_OpenDrive::OPENDRIVE_GT_LINE
@ OPENDRIVE_GT_LINE
Definition: NIImporter_OpenDrive.h:200
NIImporter_OpenDrive::OPENDRIVE_ATTR_BV
@ OPENDRIVE_ATTR_BV
Definition: NIImporter_OpenDrive.h:152
NIImporter_OpenDrive::myEndElement
void myEndElement(int element)
Called when a closing tag occurs.
Definition: NIImporter_OpenDrive.cpp:2115
StringBijection
Definition: StringBijection.h:43
NIImporter_OpenDrive::OpenDriveEdge::isInner
bool isInner
Definition: NIImporter_OpenDrive.h:481
NIImporter_OpenDrive::geomFromParamPoly
static PositionVector geomFromParamPoly(const OpenDriveEdge &e, const OpenDriveGeometry &g, double resolution)
Definition: NIImporter_OpenDrive.cpp:1481
NIImporter_OpenDrive::OPENDRIVE_ATTR_X
@ OPENDRIVE_ATTR_X
Definition: NIImporter_OpenDrive.h:137
NIImporter_OpenDrive::OpenDriveGeometry
Representation of an OpenDrive geometry part.
Definition: NIImporter_OpenDrive.h:233
NIImporter_OpenDrive::OpenDriveEdge::objects
std::vector< OpenDriveObject > objects
Definition: NIImporter_OpenDrive.h:480
NIImporter_OpenDrive::OpenDriveEdge::length
double length
The length of the edge.
Definition: NIImporter_OpenDrive.h:468
NIImporter_OpenDrive::OPENDRIVE_ATTR_DYNAMIC
@ OPENDRIVE_ATTR_DYNAMIC
Definition: NIImporter_OpenDrive.h:159
NIImporter_OpenDrive::splitMinWidths
static void splitMinWidths(OpenDriveEdge *e, const NBTypeCont &tc, double minDist)
Definition: NIImporter_OpenDrive.cpp:2246
NIImporter_OpenDrive::OPENDRIVE_ATTR_T
@ OPENDRIVE_ATTR_T
Definition: NIImporter_OpenDrive.h:136
SVCPermissions
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
Definition: SUMOVehicleClass.h:218
NIImporter_OpenDrive::calcPointOnCurve
static void calcPointOnCurve(double *ad_x, double *ad_y, double ad_centerX, double ad_centerY, double ad_r, double ad_length)
Definition: NIImporter_OpenDrive.cpp:1540
NIImporter_OpenDrive::OPENDRIVE_TAG_LANE
@ OPENDRIVE_TAG_LANE
Definition: NIImporter_OpenDrive.h:99
NBEdge::UNSPECIFIED_CONTPOS
static const double UNSPECIFIED_CONTPOS
unspecified internal junction position
Definition: NBEdge.h:324
NBTypeCont::getSpeed
double getSpeed(const std::string &type) const
Returns the maximal velocity for the given type [m/s].
Definition: NBTypeCont.cpp:177
StringBijection::get
T get(const std::string &str) const
Definition: StringBijection.h:97
NIImporter_OpenDrive::OPENDRIVE_ATTR_RADIUS
@ OPENDRIVE_ATTR_RADIUS
Definition: NIImporter_OpenDrive.h:125
NIImporter_OpenDrive::buildConnectionsToOuter
static void buildConnectionsToOuter(const Connection &c, const std::map< std::string, OpenDriveEdge * > &innerEdges, std::vector< Connection > &into, std::set< Connection > &seen)
Definition: NIImporter_OpenDrive.cpp:796
NIImporter_OpenDrive::OpenDriveLaneSection::rightLaneNumber
int rightLaneNumber
The number of lanes on the right and on the left side, respectively.
Definition: NIImporter_OpenDrive.h:357
SUMO_PARAM_ORIGID
const std::string SUMO_PARAM_ORIGID
SVC_PASSENGER
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
Definition: SUMOVehicleClass.h:159
PositionVector::positionAtOffset
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
Definition: PositionVector.cpp:248
NIImporter_OpenDrive::OpenDriveGeometry::hdg
double hdg
Definition: NIImporter_OpenDrive.h:249
Boundary
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:41
NIImporter_OpenDrive::OpenDriveObject::name
std::string name
Definition: NIImporter_OpenDrive.h:422
OutputDevice.h
NBNetBuilder.h
NIImporter_OpenDrive::OPENDRIVE_TAG_LANEOFFSET
@ OPENDRIVE_TAG_LANEOFFSET
Definition: NIImporter_OpenDrive.h:95
ProcessError
Definition: UtilExceptions.h:39
NIImporter_OpenDrive::myImportWidths
static bool myImportWidths
Definition: NIImporter_OpenDrive.h:588
NIImporter_OpenDrive::OPENDRIVE_TAG_RIGHT
@ OPENDRIVE_TAG_RIGHT
Definition: NIImporter_OpenDrive.h:98
NIImporter_OpenDrive::Poly3
Definition: NIImporter_OpenDrive.h:258
GeoConvHelper::cartesian2geo
void cartesian2geo(Position &cartesian) const
Converts the given cartesian (shifted) position to its geo (lat/long) representation.
Definition: GeoConvHelper.cpp:293
NIImporter_OpenDrive::OpenDriveEdge::offsets
std::vector< OpenDriveLaneOffset > offsets
Definition: NIImporter_OpenDrive.h:472
Position
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:38
NBNode::addTrafficLight
void addTrafficLight(NBTrafficLightDefinition *tlDef)
Adds a traffic light to the list of traffic lights that control this node.
Definition: NBNode.cpp:361
Position::x
double x() const
Returns the x-position.
Definition: Position.h:56
NIImporter_OpenDrive::OpenDriveEdge::links
std::vector< OpenDriveLink > links
Definition: NIImporter_OpenDrive.h:469
Boundary::add
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:78
NIImporter_OpenDrive::OpenDriveLaneSection::buildSpeedChanges
bool buildSpeedChanges(const NBTypeCont &tc, std::vector< OpenDriveLaneSection > &newSections)
Definition: NIImporter_OpenDrive.cpp:1670
NIImporter_OpenDrive::OPENDRIVE_ATTR_TYPE
@ OPENDRIVE_ATTR_TYPE
Definition: NIImporter_OpenDrive.h:156
PositionVector::append
void append(const PositionVector &v, double sameThreshold=2.0)
Definition: PositionVector.cpp:696
NIImporter_OpenDrive::OPENDRIVE_TAG_PREDECESSOR
@ OPENDRIVE_TAG_PREDECESSOR
Definition: NIImporter_OpenDrive.h:84
UtilExceptions.h
NIImporter_OpenDrive::OPENDRIVE_TAG_LINE
@ OPENDRIVE_TAG_LINE
Definition: NIImporter_OpenDrive.h:89
OptionsCont
A storage for options typed value containers)
Definition: OptionsCont.h:89
NBTypeCont::getShallBeDiscarded
bool getShallBeDiscarded(const std::string &type) const
Returns the information whether edges of this type shall be discarded.
Definition: NBTypeCont.cpp:195
NBEdge::getLaneStruct
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1287
NBEdge::Lane::width
double width
This lane's width.
Definition: NBEdge.h:166
NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE
static const double UNSPECIFIED_VISIBILITY_DISTANCE
unspecified foe visibility for connections
Definition: NBEdge.h:327
NIImporter_OpenDrive::myEdges
std::map< std::string, OpenDriveEdge * > & myEdges
Definition: NIImporter_OpenDrive.h:578
SUMOSAXAttributes::getOpt
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.
Definition: SUMOSAXAttributes.h:518
NIImporter_OpenDrive::OPENDRIVE_TAG_NOTHING
@ OPENDRIVE_TAG_NOTHING
Definition: NIImporter_OpenDrive.h:81
NIImporter_OpenDrive::OPENDRIVE_ATTR_NAME
@ OPENDRIVE_ATTR_NAME
Definition: NIImporter_OpenDrive.h:166
PositionVector::indexOfClosest
int indexOfClosest(const Position &p) const
index of the closest position to p
Definition: PositionVector.cpp:940
PositionVector::length2D
double length2D() const
Returns the length.
Definition: PositionVector.cpp:497
NBEdge::UNSPECIFIED_SPEED
static const double UNSPECIFIED_SPEED
unspecified lane speed
Definition: NBEdge.h:321
NIImporter_OpenDrive::OPENDRIVE_TAG_GEOREFERENCE
@ OPENDRIVE_TAG_GEOREFERENCE
Definition: NIImporter_OpenDrive.h:107
NIImporter_OpenDrive::GeometryType
GeometryType
OpenDrive geometry type enumeration.
Definition: NIImporter_OpenDrive.h:198
NIImporter_OpenDrive::OPENDRIVE_ATTR_Y
@ OPENDRIVE_ATTR_Y
Definition: NIImporter_OpenDrive.h:138
NBEdge::L2L_VALIDATED
@ L2L_VALIDATED
The connection was computed and validated.
Definition: NBEdge.h:135
NIImporter_OpenDrive::myCurrentIncomingRoad
std::string myCurrentIncomingRoad
Definition: NIImporter_OpenDrive.h:582
PositionVector::insertAtClosest
int insertAtClosest(const Position &p, bool interpolateZ)
inserts p between the two closest positions
Definition: PositionVector.cpp:959
NIImporter_OpenDrive::OPENDRIVE_TAG_LEFT
@ OPENDRIVE_TAG_LEFT
Definition: NIImporter_OpenDrive.h:96
NBNodeCont::retrieve
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:107
OptionsCont::isDefault
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
Definition: OptionsCont.cpp:163
NIImporter_OpenDrive::OpenDriveEdge::laneOffsets
std::vector< double > laneOffsets
Definition: NIImporter_OpenDrive.h:476
NIImporter_OpenDrive::OpenDriveObject::hdg
double hdg
Definition: NIImporter_OpenDrive.h:431
NIImporter_OpenDrive::OPENDRIVE_ATTR_HDG
@ OPENDRIVE_ATTR_HDG
Definition: NIImporter_OpenDrive.h:139
NIImporter_OpenDrive::OPENDRIVE_TAG_LANESECTION
@ OPENDRIVE_TAG_LANESECTION
Definition: NIImporter_OpenDrive.h:94
NIImporter_OpenDrive::OpenDriveObject::width
double width
Definition: NIImporter_OpenDrive.h:428
DEBUG_COND3
#define DEBUG_COND3(roadID)
Definition: NIImporter_OpenDrive.cpp:63
NIImporter_OpenDrive::setEdgeLinks2
static void setEdgeLinks2(OpenDriveEdge &e, const std::map< std::string, OpenDriveEdge * > &edges)
Definition: NIImporter_OpenDrive.cpp:1013
NIImporter_OpenDrive::OpenDriveEdge::id
std::string id
The id of the edge.
Definition: NIImporter_OpenDrive.h:462
Position::distanceTo2D
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:243
NIImporter_OpenDrive::OpenDriveEdge::elevations
std::vector< OpenDriveElevation > elevations
Definition: NIImporter_OpenDrive.h:471
NIImporter_OpenDrive::myStartElement
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
Definition: NIImporter_OpenDrive.cpp:1775
NIImporter_OpenDrive::OPENDRIVE_LT_SUCCESSOR
@ OPENDRIVE_LT_SUCCESSOR
Definition: NIImporter_OpenDrive.h:174
OptionsCont::getFloat
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
Definition: OptionsCont.cpp:208
NIImporter_OpenDrive::myCurrentEdge
OpenDriveEdge myCurrentEdge
Definition: NIImporter_OpenDrive.h:576
SUMOPolygon
Definition: SUMOPolygon.h:46
NBNodeCont.h
toString
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:47
StringUtils.h
NIImporter_OpenDrive::revertID
static std::string revertID(const std::string &id)
Definition: NIImporter_OpenDrive.cpp:1100
NIImporter_OpenDrive::OpenDriveGeometry::length
double length
Definition: NIImporter_OpenDrive.h:245
PointOfInterest.h
OutputDevice::getDevice
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
Definition: OutputDevice.cpp:54
NILoader.h
NIImporter_OpenDrive::myElementStack
std::vector< int > myElementStack
Definition: NIImporter_OpenDrive.h:579
Position::y
double y() const
Returns the y-position.
Definition: Position.h:61
PROGRESS_BEGIN_MESSAGE
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:278
operator<
bool operator<(const NIImporter_OpenDrive::Connection &c1, const NIImporter_OpenDrive::Connection &c2)
Definition: NIImporter_OpenDrive.cpp:2189
NIImporter_OpenDrive::OpenDriveLaneSection::lanesByDir
std::map< OpenDriveXMLTag, std::vector< OpenDriveLane > > lanesByDir
The lanes, sorted by their direction.
Definition: NIImporter_OpenDrive.h:353
NIImporter_OpenDrive::OPENDRIVE_ATTR_REVMAJOR
@ OPENDRIVE_ATTR_REVMAJOR
Definition: NIImporter_OpenDrive.h:120
NIImporter_OpenDrive::OpenDriveLaneSection::OpenDriveLaneSection
OpenDriveLaneSection(double sArg)
Constructor.
Definition: NIImporter_OpenDrive.cpp:1564
NIImporter_OpenDrive::OPENDRIVE_CP_START
@ OPENDRIVE_CP_START
Definition: NIImporter_OpenDrive.h:192
NBTypeCont::getPermissions
SVCPermissions getPermissions(const std::string &type) const
Returns allowed vehicle classes for the given type.
Definition: NBTypeCont.cpp:221
PositionVector::positionAtOffset2D
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
Definition: PositionVector.cpp:273
NIImporter_OpenDrive::OPENDRIVE_ATTR_CURVEND
@ OPENDRIVE_ATTR_CURVEND
Definition: NIImporter_OpenDrive.h:141
NIImporter_OpenDrive::geomFromArc
static PositionVector geomFromArc(const OpenDriveEdge &e, const OpenDriveGeometry &g, double resolution)
Definition: NIImporter_OpenDrive.cpp:1419
NBTypeCont
A storage for available types of edges.
Definition: NBTypeCont.h:54
NIImporter_OpenDrive::OPENDRIVE_CP_END
@ OPENDRIVE_CP_END
Definition: NIImporter_OpenDrive.h:193
PositionVector::reverse
PositionVector reverse() const
reverse position vector
Definition: PositionVector.cpp:1086
NBNetBuilder::getTLLogicCont
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
Definition: NBNetBuilder.h:165
PositionVector::rotationAtOffset
double rotationAtOffset(double pos) const
Returns the rotation at the given length.
Definition: PositionVector.cpp:294
NIImporter_OpenDrive::OPENDRIVE_ATTR_SOFFSET
@ OPENDRIVE_ATTR_SOFFSET
Definition: NIImporter_OpenDrive.h:165
NIImporter_OpenDrive::hasNonLinearElevation
static bool hasNonLinearElevation(OpenDriveEdge &e)
Definition: NIImporter_OpenDrive.cpp:1143
NIImporter_OpenDrive::OPENDRIVE_ATTR_D
@ OPENDRIVE_ATTR_D
Definition: NIImporter_OpenDrive.h:146
NBNode::getControllingTLS
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node (The set of tls that control this node)
Definition: NBNode.h:318
NIImporter_OpenDrive::calculateCurveCenter
static void calculateCurveCenter(double *ad_x, double *ad_y, double ad_radius, double ad_hdg)
Definition: NIImporter_OpenDrive.cpp:1512
InvalidArgument
Definition: UtilExceptions.h:56
NBEdge::Lane
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:142
GenericSAXHandler::getFileName
const std::string & getFileName() const
returns the current file name
Definition: GenericSAXHandler.cpp:74
NIImporter_OpenDrive::OPENDRIVE_ATTR_NOTHING
@ OPENDRIVE_ATTR_NOTHING
Definition: NIImporter_OpenDrive.h:119
NIImporter_OpenDrive::OPENDRIVE_ATTR_DV
@ OPENDRIVE_ATTR_DV
Definition: NIImporter_OpenDrive.h:154
NIImporter_OpenDrive::myMinWidth
static double myMinWidth
Definition: NIImporter_OpenDrive.h:589
NIImporter_OpenDrive::Connection::fromCP
ContactPoint fromCP
Definition: NIImporter_OpenDrive.h:399
NIImporter_OpenDrive::OpenDriveGeometry::params
std::vector< double > params
Definition: NIImporter_OpenDrive.h:251
NIImporter_OpenDrive::OpenDriveLaneSection::s
double s
The starting offset of this lane section.
Definition: NIImporter_OpenDrive.h:345
NIImporter_OpenDrive::OPENDRIVE_TAG_WIDTH
@ OPENDRIVE_TAG_WIDTH
Definition: NIImporter_OpenDrive.h:104
NIImporter_OpenDrive::same_position_finder
Definition: NIImporter_OpenDrive.h:498
NIImporter_OpenDrive::myCurrentContactPoint
ContactPoint myCurrentContactPoint
Definition: NIImporter_OpenDrive.h:584
PROGRESS_DONE_MESSAGE
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:279
NBTypeCont::getWidth
double getWidth(const std::string &type) const
Returns the lane width for the given type [m].
Definition: NBTypeCont.cpp:227
NIImporter_OpenDrive::OpenDriveLane::speeds
std::vector< std::pair< double, double > > speeds
List of positions/speeds of speed changes.
Definition: NIImporter_OpenDrive.h:306
NBEdge::Lane::permissions
SVCPermissions permissions
List of vehicle types that are allowed on this lane.
Definition: NBEdge.h:153
NIImporter_OpenDrive::OpenDriveWidth
Poly3 OpenDriveWidth
Definition: NIImporter_OpenDrive.h:284
NIImporter_OpenDrive::getOrBuildNode
static NBNode * getOrBuildNode(const std::string &id, const Position &pos, NBNodeCont &nc)
Builds a node or returns the already built.
Definition: NIImporter_OpenDrive.cpp:1109
NIImporter_OpenDrive::recomputeWidths
static void recomputeWidths(OpenDriveLaneSection &sec, double start, double end, double sectionStart, double sectionEnd)
Definition: NIImporter_OpenDrive.cpp:2429
NIImporter_OpenDrive::setStraightConnections
static void setStraightConnections(std::vector< OpenDriveLane > &lanes)
Definition: NIImporter_OpenDrive.cpp:2421
joinToString
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:246
NBEdge::UNSPECIFIED_WIDTH
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:315
NIImporter_OpenDrive::OPENDRIVE_TAG_SPEED
@ OPENDRIVE_TAG_SPEED
Definition: NIImporter_OpenDrive.h:105
DEBUG_COND
#define DEBUG_COND(road)
Definition: NIImporter_OpenDrive.cpp:61
NIImporter_OpenDrive::laneSectionsConnected
static bool laneSectionsConnected(OpenDriveEdge *edge, int in, int out)
Definition: NIImporter_OpenDrive.cpp:985
Parameterised::setParameter
void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
Definition: Parameterised.cpp:46
SUMOXMLDefinitions::TrafficLightTypes
static StringBijection< TrafficLightType > TrafficLightTypes
traffic light types
Definition: SUMOXMLDefinitions.h:1392
NIImporter_OpenDrive::OPENDRIVE_ET_ROAD
@ OPENDRIVE_ET_ROAD
Definition: NIImporter_OpenDrive.h:183
NIImporter_OpenDrive::OPENDRIVE_ATTR_TSTART
@ OPENDRIVE_ATTR_TSTART
Definition: NIImporter_OpenDrive.h:127
NIImporter_OpenDrive::OPENDRIVE_ATTR_REVMINOR
@ OPENDRIVE_ATTR_REVMINOR
Definition: NIImporter_OpenDrive.h:121
NIImporter_OpenDrive::openDriveAttrs
static StringBijection< int >::Entry openDriveAttrs[]
The names of openDrive-XML attributes (for passing to GenericSAXHandler)
Definition: NIImporter_OpenDrive.h:657
UNSET_CONNECTION
#define UNSET_CONNECTION
Definition: NIImporter_OpenDrive.h:43
GenericSAXHandler::error
void error(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Handler for XML-errors.
Definition: GenericSAXHandler.cpp:205
FileHelpers::isReadable
static bool isReadable(std::string path)
Checks whether the given file is readable.
Definition: FileHelpers.cpp:49
NIImporter_OpenDrive::OPENDRIVE_ATTR_MAX
@ OPENDRIVE_ATTR_MAX
Definition: NIImporter_OpenDrive.h:164
NIImporter_OpenDrive::OPENDRIVE_GT_POLY3
@ OPENDRIVE_GT_POLY3
Definition: NIImporter_OpenDrive.h:203
config.h
NIImporter_OpenDrive::OpenDriveLaneSection::leftLaneNumber
int leftLaneNumber
Definition: NIImporter_OpenDrive.h:357
NIImporter_OpenDrive::OPENDRIVE_ATTR_AV
@ OPENDRIVE_ATTR_AV
Definition: NIImporter_OpenDrive.h:151
NIImporter_OpenDrive::setLaneAttributes
static void setLaneAttributes(const OpenDriveEdge *e, NBEdge::Lane &sumoLane, const OpenDriveLane &odLane, bool saveOrigIDs, const NBTypeCont &tc)
Definition: NIImporter_OpenDrive.cpp:758
NIImporter_OpenDrive::OPENDRIVE_TAG_POLY3
@ OPENDRIVE_TAG_POLY3
Definition: NIImporter_OpenDrive.h:92
NIImporter_OpenDrive::Poly3::s
double s
Definition: NIImporter_OpenDrive.h:274
gDebugFlag1
bool gDebugFlag1
global utility flags for debugging
Definition: StdDefs.cpp:32
PointOfInterest
A point-of-interest.
Definition: PointOfInterest.h:43
NIImporter_OpenDrive::OPENDRIVE_ATTR_CONNECTINGROAD
@ OPENDRIVE_ATTR_CONNECTINGROAD
Definition: NIImporter_OpenDrive.h:161
gPrecision
int gPrecision
the precision for floating point outputs
Definition: StdDefs.cpp:26
NIImporter_OpenDrive::OPENDRIVE_TAG_HEADER
@ OPENDRIVE_TAG_HEADER
Definition: NIImporter_OpenDrive.h:82
NIImporter_OpenDrive::LinkType
LinkType
OpenDrive link type enumeration.
Definition: NIImporter_OpenDrive.h:173
NIImporter_OpenDrive::OPENDRIVE_ATTR_JUNCTION
@ OPENDRIVE_ATTR_JUNCTION
Definition: NIImporter_OpenDrive.h:131
NIImporter_OpenDrive::OpenDriveEdge::geometries
std::vector< OpenDriveGeometry > geometries
Definition: NIImporter_OpenDrive.h:470
NIImporter_OpenDrive::Connection::shape
PositionVector shape
Definition: NIImporter_OpenDrive.h:404
NIImporter_OpenDrive::OpenDriveObject
Definition: NIImporter_OpenDrive.h:420
NIImporter_OpenDrive::OPENDRIVE_TAG_JUNCTION
@ OPENDRIVE_TAG_JUNCTION
Definition: NIImporter_OpenDrive.h:101
NIImporter_OpenDrive::~NIImporter_OpenDrive
~NIImporter_OpenDrive()
Destructor.
Definition: NIImporter_OpenDrive.cpp:1770
NIImporter_OpenDrive::OPENDRIVE_ATTR_B
@ OPENDRIVE_ATTR_B
Definition: NIImporter_OpenDrive.h:144
NIImporter_OpenDrive::OPENDRIVE_ET_JUNCTION
@ OPENDRIVE_ET_JUNCTION
Definition: NIImporter_OpenDrive.h:184
OutputDevice::writeXMLHeader
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >())
Writes an XML header with optional configuration.
Definition: OutputDevice.cpp:227
NBNode
Represents a single node (junction) during network building.
Definition: NBNode.h:67
NBOwnTLDef.h
NIImporter_OpenDrive::OpenDriveObject::type
std::string type
Definition: NIImporter_OpenDrive.h:421
NBTrafficLightLogicCont.h
SUMOPolygon.h
NIImporter_OpenDrive::OPENDRIVE_GT_PARAMPOLY3
@ OPENDRIVE_GT_PARAMPOLY3
Definition: NIImporter_OpenDrive.h:204
NIImporter_OpenDrive::OpenDriveLaneSection::buildLaneSection
OpenDriveLaneSection buildLaneSection(double startPos)
Definition: NIImporter_OpenDrive.cpp:1646
NIImporter_OpenDrive::OPENDRIVE_LT_PREDECESSOR
@ OPENDRIVE_LT_PREDECESSOR
Definition: NIImporter_OpenDrive.h:175
NIImporter_OpenDrive::OPENDRIVE_ATTR_TO
@ OPENDRIVE_ATTR_TO
Definition: NIImporter_OpenDrive.h:163
NBNetBuilder::getNodeCont
NBNodeCont & getNodeCont()
Returns a reference to the node container.
Definition: NBNetBuilder.h:155
GenericSAXHandler
A handler which converts occuring elements and attributes into enums.
Definition: GenericSAXHandler.h:67
NIImporter_OpenDrive::addGeometryShape
void addGeometryShape(GeometryType type, const std::vector< double > &vals)
Definition: NIImporter_OpenDrive.cpp:2173
NIImporter_OpenDrive::OPENDRIVE_ATTR_BU
@ OPENDRIVE_ATTR_BU
Definition: NIImporter_OpenDrive.h:148
NBTrafficLightLogicCont::insert
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
Definition: NBTrafficLightLogicCont.cpp:73
NIImporter_OpenDrive::setNodeSecure
static void setNodeSecure(NBNodeCont &nc, OpenDriveEdge &e, const std::string &nodeID, NIImporter_OpenDrive::LinkType lt)
Definition: NIImporter_OpenDrive.cpp:1123
NBNetBuilder::getTypeCont
NBTypeCont & getTypeCont()
Returns a reference to the type container.
Definition: NBNetBuilder.h:160
NIImporter_OpenDrive::OPENDRIVE_ATTR_ORIENTATION
@ OPENDRIVE_ATTR_ORIENTATION
Definition: NIImporter_OpenDrive.h:158
NBNode.h
NIImporter_OpenDrive::Connection::toCP
ContactPoint toCP
Definition: NIImporter_OpenDrive.h:400
NIImporter_OpenDrive::OpenDriveEdge::geom
PositionVector geom
Definition: NIImporter_OpenDrive.h:475
NIImporter_OpenDrive::OPENDRIVE_TAG_ARC
@ OPENDRIVE_TAG_ARC
Definition: NIImporter_OpenDrive.h:91
SUMOSAXAttributes
Encapsulated SAX-Attributes.
Definition: SUMOSAXAttributes.h:56
NIImporter_OpenDrive::OPENDRIVE_ATTR_UNIT
@ OPENDRIVE_ATTR_UNIT
Definition: NIImporter_OpenDrive.h:167
NIImporter_OpenDrive::OPENDRIVE_ATTR_LENGTH
@ OPENDRIVE_ATTR_LENGTH
Definition: NIImporter_OpenDrive.h:123
Named::getID
const std::string & getID() const
Returns the id.
Definition: Named.h:76
POSITION_EPS
#define POSITION_EPS
Definition: config.h:172
NIImporter_OpenDrive::myCurrentConnectingRoad
std::string myCurrentConnectingRoad
Definition: NIImporter_OpenDrive.h:583
WRITE_ERROR
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:283
NIImporter_OpenDrive::OpenDriveEdge::from
NBNode * from
Definition: NIImporter_OpenDrive.h:473
NIImporter_OpenDrive::OpenDriveLaneSection::buildLaneMapping
void buildLaneMapping(const NBTypeCont &tc)
Build the mapping from OpenDrive to SUMO lanes.
Definition: NIImporter_OpenDrive.cpp:1572
NBEdge::addLane2LaneConnection
bool addLane2LaneConnection(int fromLane, NBEdge *dest, int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE, double speed=UNSPECIFIED_SPEED, const PositionVector &customShape=PositionVector::EMPTY, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED, SVCPermissions=SVC_UNSPECIFIED)
Adds a connection between the specified this edge's lane and an approached one.
Definition: NBEdge.cpp:984
NBEdge::getConnections
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:934
NIImporter_OpenDrive::OPENDRIVE_TAG_PARAMPOLY3
@ OPENDRIVE_TAG_PARAMPOLY3
Definition: NIImporter_OpenDrive.h:93
NIImporter_OpenDrive::sections_by_s_sorter
A class for sorting lane sections by their s-value.
Definition: NIImporter_OpenDrive.h:486
NIImporter_OpenDrive::loadNetwork
static void loadNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Loads content of the optionally given SUMO file.
Definition: NIImporter_OpenDrive.cpp:171
SUMOXMLDefinitions.h
NIImporter_OpenDrive::Connection::toEdge
std::string toEdge
Definition: NIImporter_OpenDrive.h:396
NBEdgeCont::wasIgnored
bool wasIgnored(std::string id) const
Returns whether the edge with the id was ignored during parsing.
Definition: NBEdgeCont.h:501
NIImporter_OpenDrive::myImportAllTypes
static bool myImportAllTypes
Definition: NIImporter_OpenDrive.h:587
PositionVector::move2side
void move2side(double amount, double maxExtension=100)
move position vector to side using certain ammount
Definition: PositionVector.cpp:1103
NIImporter_OpenDrive::findWidthSplit
static void findWidthSplit(const NBTypeCont &tc, std::vector< OpenDriveLane > &lanes, int section, double sectionStart, double sectionEnd, std::vector< double > &splitPositions)
Definition: NIImporter_OpenDrive.cpp:2339
NBTrafficLightDefinition
The base class for traffic light logic definitions.
Definition: NBTrafficLightDefinition.h:67
NIImporter_OpenDrive::OPENDRIVE_ATTR_CU
@ OPENDRIVE_ATTR_CU
Definition: NIImporter_OpenDrive.h:149
PositionVector::removeDoublePoints
void removeDoublePoints(double minDist=POSITION_EPS, bool assertLength=false)
Removes positions if too near.
Definition: PositionVector.cpp:1344
NBEdge.h
GenericSAXHandler::setFileName
void setFileName(const std::string &name)
Sets the current file name.
Definition: GenericSAXHandler.cpp:68
XMLSubSys.h
NIImporter_OpenDrive::OpenDriveGeometry::type
GeometryType type
Definition: NIImporter_OpenDrive.h:250
NIImporter_OpenDrive::OpenDriveLane::widthData
std::vector< OpenDriveWidth > widthData
Definition: NIImporter_OpenDrive.h:309
NIImporter_OpenDrive::myCurrentJunctionID
std::string myCurrentJunctionID
Definition: NIImporter_OpenDrive.h:581
NIImporter_OpenDrive::OpenDriveEdge::streetName
std::string streetName
The road name of the edge.
Definition: NIImporter_OpenDrive.h:464
NIImporter_OpenDrive::Connection::toLane
int toLane
Definition: NIImporter_OpenDrive.h:398
NBEdge::getID
const std::string & getID() const
Definition: NBEdge.h:1380
NIImporter_OpenDrive::computeShapes
static void computeShapes(std::map< std::string, OpenDriveEdge * > &edges)
Computes a polygon representation of each edge's geometry.
Definition: NIImporter_OpenDrive.cpp:1156
NIImporter_OpenDrive::openDriveTags
static StringBijection< int >::Entry openDriveTags[]
The names of openDrive-XML elements (for passing to GenericSAXHandler)
Definition: NIImporter_OpenDrive.h:654