SUMO - Simulation of Urban MObility
NIImporter_SUMO.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // Importer for networks stored in SUMO format
10 /****************************************************************************/
11 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
12 // Copyright (C) 2001-2016 DLR (http://www.dlr.de/) and contributors
13 /****************************************************************************/
14 //
15 // This file is part of SUMO.
16 // SUMO is free software: you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation, either version 3 of the License, or
19 // (at your option) any later version.
20 //
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 #include <string>
38 #include <utils/common/ToString.h>
42 #include <utils/xml/XMLSubSys.h>
46 #include <netbuild/NBEdge.h>
47 #include <netbuild/NBEdgeCont.h>
48 #include <netbuild/NBNode.h>
49 #include <netbuild/NBNodeCont.h>
51 #include <netbuild/NBNetBuilder.h>
52 #include "NILoader.h"
53 #include "NIXMLEdgesHandler.h"
54 #include "NIImporter_SUMO.h"
55 
56 #ifdef CHECK_MEMORY_LEAKS
57 #include <foreign/nvwa/debug_new.h>
58 #endif // CHECK_MEMORY_LEAKS
59 
60 
61 // ===========================================================================
62 // method definitions
63 // ===========================================================================
64 // ---------------------------------------------------------------------------
65 // static methods (interface in this case)
66 // ---------------------------------------------------------------------------
67 void
69  NIImporter_SUMO importer(nb);
70  importer._loadNetwork(oc);
71 }
72 
73 
74 // ---------------------------------------------------------------------------
75 // loader methods
76 // ---------------------------------------------------------------------------
78  : SUMOSAXHandler("sumo-network"),
79  myNetBuilder(nb),
80  myNodeCont(nb.getNodeCont()),
81  myTLLCont(nb.getTLLogicCont()),
82  myCurrentEdge(0),
83  myCurrentLane(0),
84  myCurrentTL(0),
85  myLocation(0),
87  myAmLefthand(false),
88  myCornerDetail(0),
89  myLinkDetail(-1) {
90 }
91 
92 
94  for (std::map<std::string, EdgeAttrs*>::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
95  EdgeAttrs* ed = (*i).second;
96  for (std::vector<LaneAttrs*>::const_iterator j = ed->lanes.begin(); j != ed->lanes.end(); ++j) {
97  delete *j;
98  }
99  delete ed;
100  }
101  delete myLocation;
102 }
103 
104 
105 void
107  // check whether the option is set (properly)
108  if (!oc.isUsableFileList("sumo-net-file")) {
109  return;
110  }
111  // parse file(s)
112  std::vector<std::string> files = oc.getStringVector("sumo-net-file");
113  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
114  if (!FileHelpers::isReadable(*file)) {
115  WRITE_ERROR("Could not open sumo-net-file '" + *file + "'.");
116  return;
117  }
118  setFileName(*file);
119  PROGRESS_BEGIN_MESSAGE("Parsing sumo-net from '" + *file + "'");
120  XMLSubSys::runParser(*this, *file, true);
122  }
123  // build edges
124  for (std::map<std::string, EdgeAttrs*>::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
125  EdgeAttrs* ed = (*i).second;
126  // skip internal edges
127  if (ed->func == EDGEFUNC_INTERNAL || ed->func == EDGEFUNC_CROSSING || ed->func == EDGEFUNC_WALKINGAREA) {
128  continue;
129  }
130  // get and check the nodes
131  NBNode* from = myNodeCont.retrieve(ed->fromNode);
132  NBNode* to = myNodeCont.retrieve(ed->toNode);
133  if (from == 0) {
134  WRITE_ERROR("Edge's '" + ed->id + "' from-node '" + ed->fromNode + "' is not known.");
135  continue;
136  }
137  if (to == 0) {
138  WRITE_ERROR("Edge's '" + ed->id + "' to-node '" + ed->toNode + "' is not known.");
139  continue;
140  }
141  // edge shape
142  PositionVector geom;
143  if (ed->shape.size() > 0) {
144  geom = ed->shape;
145  } else {
146  // either the edge has default shape consisting only of the two node
147  // positions or we have a legacy network
148  geom = reconstructEdgeShape(ed, from->getPosition(), to->getPosition());
149  }
150  // build and insert the edge
151  NBEdge* e = new NBEdge(ed->id, from, to,
152  ed->type, ed->maxSpeed,
153  (unsigned int) ed->lanes.size(),
155  geom, ed->streetName, "", ed->lsf, true); // always use tryIgnoreNodePositions to keep original shape
156  e->setLoadedLength(ed->length);
157  if (!myNetBuilder.getEdgeCont().insert(e)) {
158  WRITE_ERROR("Could not insert edge '" + ed->id + "'.");
159  delete e;
160  continue;
161  }
163  }
164  // assign further lane attributes (edges are built)
165  for (std::map<std::string, EdgeAttrs*>::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
166  EdgeAttrs* ed = (*i).second;
167  NBEdge* nbe = ed->builtEdge;
168  if (nbe == 0) { // inner edge or removed by explicit list, vclass, ...
169  continue;
170  }
171  for (unsigned int fromLaneIndex = 0; fromLaneIndex < (unsigned int) ed->lanes.size(); ++fromLaneIndex) {
172  LaneAttrs* lane = ed->lanes[fromLaneIndex];
173  // connections
174  const std::vector<Connection>& connections = lane->connections;
175  for (std::vector<Connection>::const_iterator c_it = connections.begin(); c_it != connections.end(); c_it++) {
176  const Connection& c = *c_it;
177  if (myEdges.count(c.toEdgeID) == 0) {
178  WRITE_ERROR("Unknown edge '" + c.toEdgeID + "' given in connection.");
179  continue;
180  }
181  NBEdge* toEdge = myEdges[c.toEdgeID]->builtEdge;
182  if (toEdge == 0) { // removed by explicit list, vclass, ...
183  continue;
184  }
185  if (nbe->hasConnectionTo(toEdge, c.toLaneIdx)) {
186  WRITE_WARNING("Target lane '" + toEdge->getLaneID(c.toLaneIdx) + "' has multiple connections from '" + nbe->getID() + "'.");
187  }
189  fromLaneIndex, toEdge, c.toLaneIdx, NBEdge::L2L_VALIDATED,
190  true, c.mayDefinitelyPass, c.keepClear, c.contPos);
191 
192  // maybe we have a tls-controlled connection
193  if (c.tlID != "" && myRailSignals.count(c.tlID) == 0) {
194  const std::map<std::string, NBTrafficLightDefinition*>& programs = myTLLCont.getPrograms(c.tlID);
195  if (programs.size() > 0) {
196  std::map<std::string, NBTrafficLightDefinition*>::const_iterator it;
197  for (it = programs.begin(); it != programs.end(); it++) {
198  NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(it->second);
199  if (tlDef) {
200  tlDef->addConnection(nbe, toEdge, fromLaneIndex, c.toLaneIdx, c.tlLinkNo);
201  } else {
202  throw ProcessError("Corrupt traffic light definition '" + c.tlID + "' (program '" + it->first + "')");
203  }
204  }
205  } else {
206  WRITE_ERROR("The traffic light '" + c.tlID + "' is not known.");
207  }
208  }
209  }
210  // allow/disallow XXX preferred
211  nbe->setPermissions(parseVehicleClasses(lane->allow, lane->disallow), fromLaneIndex);
212  // width, offset
213  nbe->setLaneWidth(fromLaneIndex, lane->width);
214  nbe->setEndOffset(fromLaneIndex, lane->endOffset);
215  nbe->setSpeed(fromLaneIndex, lane->maxSpeed);
216  }
218  if (!nbe->hasLaneSpecificWidth() && nbe->getLanes()[0].width != NBEdge::UNSPECIFIED_WIDTH) {
219  nbe->setLaneWidth(-1, nbe->getLaneWidth(0));
220  }
222  nbe->setEndOffset(-1, nbe->getEndOffset(0));
223  }
224  }
225  // insert loaded prohibitions
226  for (std::vector<Prohibition>::const_iterator it = myProhibitions.begin(); it != myProhibitions.end(); it++) {
227  NBEdge* prohibitedFrom = myEdges[it->prohibitedFrom]->builtEdge;
228  NBEdge* prohibitedTo = myEdges[it->prohibitedTo]->builtEdge;
229  NBEdge* prohibitorFrom = myEdges[it->prohibitorFrom]->builtEdge;
230  NBEdge* prohibitorTo = myEdges[it->prohibitorTo]->builtEdge;
231  if (prohibitedFrom == 0) {
232  WRITE_WARNING("Edge '" + it->prohibitedFrom + "' in prohibition was not built");
233  } else if (prohibitedTo == 0) {
234  WRITE_WARNING("Edge '" + it->prohibitedTo + "' in prohibition was not built");
235  } else if (prohibitorFrom == 0) {
236  WRITE_WARNING("Edge '" + it->prohibitorFrom + "' in prohibition was not built");
237  } else if (prohibitorTo == 0) {
238  WRITE_WARNING("Edge '" + it->prohibitorTo + "' in prohibition was not built");
239  } else {
240  NBNode* n = prohibitedFrom->getToNode();
242  NBConnection(prohibitorFrom, prohibitorTo),
243  NBConnection(prohibitedFrom, prohibitedTo));
244  }
245  }
246  if (!myHaveSeenInternalEdge) {
248  }
249  if (oc.isDefault("lefthand")) {
250  oc.set("lefthand", toString(myAmLefthand));
251  }
252  if (oc.isDefault("junctions.corner-detail")) {
253  oc.set("junctions.corner-detail", toString(myCornerDetail));
254  }
255  if (oc.isDefault("junctions.internal-link-detail") && myLinkDetail > 0) {
256  oc.set("junctions.internal-link-detail", toString(myLinkDetail));
257  }
258  if (!deprecatedVehicleClassesSeen.empty()) {
259  WRITE_WARNING("Deprecated vehicle class(es) '" + toString(deprecatedVehicleClassesSeen) + "' in input network.");
261  }
262  // add loaded crossings
263  if (!oc.getBool("no-internal-links")) {
264  for (std::map<std::string, std::vector<Crossing> >::const_iterator it = myPedestrianCrossings.begin(); it != myPedestrianCrossings.end(); ++it) {
265  NBNode* node = myNodeCont.retrieve((*it).first);
266  for (std::vector<Crossing>::const_iterator it_c = (*it).second.begin(); it_c != (*it).second.end(); ++it_c) {
267  const Crossing& crossing = (*it_c);
268  EdgeVector edges;
269  for (std::vector<std::string>::const_iterator it_e = crossing.crossingEdges.begin(); it_e != crossing.crossingEdges.end(); ++it_e) {
270  NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(*it_e);
271  // edge might have been removed due to options
272  if (edge != 0) {
273  edges.push_back(edge);
274  }
275  }
276  if (edges.size() > 0) {
277  node->addCrossing(edges, crossing.width, crossing.priority, true);
278  }
279  }
280  }
281  }
282  // add roundabouts
283  for (std::vector<std::vector<std::string> >::const_iterator it = myRoundabouts.begin(); it != myRoundabouts.end(); ++it) {
284  EdgeSet roundabout;
285  for (std::vector<std::string>::const_iterator it_r = it->begin(); it_r != it->end(); ++it_r) {
286  NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(*it_r);
287  if (edge == 0) {
288  if (!myNetBuilder.getEdgeCont().wasIgnored(*it_r)) {
289  WRITE_ERROR("Unknown edge '" + (*it_r) + "' in roundabout");
290  }
291  } else {
292  roundabout.insert(edge);
293  }
294  }
295  myNetBuilder.getEdgeCont().addRoundabout(roundabout);
296  }
297 }
298 
299 
300 
301 void
303  const SUMOSAXAttributes& attrs) {
304  /* our goal is to reproduce the input net faithfully
305  * there are different types of objects in the netfile:
306  * 1) those which must be loaded into NBNetBuilder-Containers for processing
307  * 2) those which can be ignored because they are recomputed based on group 1
308  * 3) those which are of no concern to NBNetBuilder but should be exposed to
309  * NETEDIT. We will probably have to patch NBNetBuilder to contain them
310  * and hand them over to NETEDIT
311  * alternative idea: those shouldn't really be contained within the
312  * network but rather in separate files. teach NETEDIT how to open those
313  * (POI?)
314  * 4) those which are of concern neither to NBNetBuilder nor NETEDIT and
315  * must be copied over - need to patch NBNetBuilder for this.
316  * copy unknown by default
317  */
318  switch (element) {
319  case SUMO_TAG_NET: {
320  bool ok;
321  myAmLefthand = attrs.getOpt<bool>(SUMO_ATTR_LEFTHAND, 0, ok, false);
322  myCornerDetail = attrs.getOpt<int>(SUMO_ATTR_CORNERDETAIL, 0, ok, 0);
323  myLinkDetail = attrs.getOpt<int>(SUMO_ATTR_LINKDETAIL, 0, ok, -1);
324  break;
325  }
326  case SUMO_TAG_EDGE:
327  addEdge(attrs);
328  break;
329  case SUMO_TAG_LANE:
330  addLane(attrs);
331  break;
332  case SUMO_TAG_JUNCTION:
333  addJunction(attrs);
334  break;
335  case SUMO_TAG_REQUEST:
336  addRequest(attrs);
337  break;
338  case SUMO_TAG_CONNECTION:
339  addConnection(attrs);
340  break;
341  case SUMO_TAG_TLLOGIC:
343  break;
344  case SUMO_TAG_PHASE:
345  addPhase(attrs, myCurrentTL);
346  break;
347  case SUMO_TAG_LOCATION:
348  myLocation = loadLocation(attrs);
349  break;
351  addProhibition(attrs);
352  break;
353  case SUMO_TAG_ROUNDABOUT:
354  addRoundabout(attrs);
355  break;
356  default:
357  break;
358  }
359 }
360 
361 
362 void
364  switch (element) {
365  case SUMO_TAG_EDGE:
366  if (myEdges.find(myCurrentEdge->id) != myEdges.end()) {
367  WRITE_ERROR("Edge '" + myCurrentEdge->id + "' occured at least twice in the input.");
368  } else {
370  }
371  myCurrentEdge = 0;
372  break;
373  case SUMO_TAG_LANE:
374  if (myCurrentEdge != 0) {
376  myCurrentEdge->lanes.push_back(myCurrentLane);
377  }
378  myCurrentLane = 0;
379  break;
380  case SUMO_TAG_TLLOGIC:
381  if (!myCurrentTL) {
382  WRITE_ERROR("Unmatched closing tag for tl-logic.");
383  } else {
384  if (!myTLLCont.insert(myCurrentTL)) {
385  WRITE_WARNING("Could not add program '" + myCurrentTL->getProgramID() + "' for traffic light '" + myCurrentTL->getID() + "'");
386  delete myCurrentTL;
387  }
388  myCurrentTL = 0;
389  }
390  break;
391  default:
392  break;
393  }
394 }
395 
396 
397 void
399  // get the id, report an error if not given or empty...
400  bool ok = true;
401  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
402  if (!ok) {
403  return;
404  }
405  myCurrentEdge = new EdgeAttrs();
407  myCurrentEdge->id = id;
408  // get the function
409  myCurrentEdge->func = attrs.getEdgeFunc(ok);
411  // add the crossing but don't do anything else
412  Crossing c;
413  c.edgeID = id;
416  return;
418  return; // skip internal edges
419  }
420  // get the type
421  myCurrentEdge->type = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok, "");
422  // get the origin and the destination node
423  myCurrentEdge->fromNode = attrs.getOpt<std::string>(SUMO_ATTR_FROM, id.c_str(), ok, "");
424  myCurrentEdge->toNode = attrs.getOpt<std::string>(SUMO_ATTR_TO, id.c_str(), ok, "");
425  myCurrentEdge->priority = attrs.getOpt<int>(SUMO_ATTR_PRIORITY, id.c_str(), ok, -1);
426  myCurrentEdge->type = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok, "");
430  myCurrentEdge->maxSpeed = 0;
431  myCurrentEdge->streetName = attrs.getOpt<std::string>(SUMO_ATTR_NAME, id.c_str(), ok, "");
432  if (myCurrentEdge->streetName != "" && OptionsCont::getOptions().isDefault("output.street-names")) {
433  OptionsCont::getOptions().set("output.street-names", "true");
434  }
435 
436  std::string lsfS = toString(LANESPREAD_RIGHT);
437  lsfS = attrs.getOpt<std::string>(SUMO_ATTR_SPREADTYPE, id.c_str(), ok, lsfS);
438  if (SUMOXMLDefinitions::LaneSpreadFunctions.hasString(lsfS)) {
440  } else {
441  WRITE_ERROR("Unknown spreadType '" + lsfS + "' for edge '" + id + "'.");
442  }
443 }
444 
445 
446 void
448  bool ok = true;
449  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
450  if (!ok) {
451  return;
452  }
453  if (!myCurrentEdge) {
454  WRITE_ERROR("Found lane '" + id + "' not within edge element");
455  return;
456  }
457  if (attrs.getOpt<bool>(SUMO_ATTR_CUSTOMSHAPE, 0, ok, false)) {
458  const std::string nodeID = NBNode::getNodeIDFromInternalLane(id);
459  myCustomShapeMaps[nodeID][id] = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok);
460  }
461  myCurrentLane = new LaneAttrs;
463  // save the width and the lane id of the crossing but don't do anything else
465  assert(crossings.size() > 0);
466  crossings.back().width = attrs.get<SUMOReal>(SUMO_ATTR_WIDTH, id.c_str(), ok);
467  return;
469  myHaveSeenInternalEdge = true;
470  return; // skip internal lanes
471  }
472  if (attrs.hasAttribute("maxspeed")) {
473  // !!! deprecated
474  myCurrentLane->maxSpeed = attrs.getFloat("maxspeed");
475  } else {
476  myCurrentLane->maxSpeed = attrs.get<SUMOReal>(SUMO_ATTR_SPEED, id.c_str(), ok);
477  }
478  try {
479  myCurrentLane->allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, id.c_str(), ok, "", false);
480  } catch (EmptyData e) {
481  // !!! deprecated
482  myCurrentLane->allow = "";
483  }
484  myCurrentLane->disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, id.c_str(), ok, "");
485  myCurrentLane->width = attrs.getOpt<SUMOReal>(SUMO_ATTR_WIDTH, id.c_str(), ok, (SUMOReal) NBEdge::UNSPECIFIED_WIDTH);
486  myCurrentLane->endOffset = attrs.getOpt<SUMOReal>(SUMO_ATTR_ENDOFFSET, id.c_str(), ok, (SUMOReal) NBEdge::UNSPECIFIED_OFFSET);
487  myCurrentLane->shape = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok);
488  // lane coordinates are derived (via lane spread) do not include them in convex boundary
489  NBNetBuilder::transformCoordinates(myCurrentLane->shape, false, myLocation);
490 }
491 
492 
493 void
495  // get the id, report an error if not given or empty...
497  myCurrentJunction.intLanes.clear();
498  myCurrentJunction.response.clear();
499  bool ok = true;
500  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
501  if (!ok) {
502  return;
503  }
504  if (id[0] == ':') { // internal node
505  return;
506  }
507  SumoXMLNodeType type = attrs.getNodeType(ok);
508  if (ok) {
509  if (type == NODETYPE_DEAD_END_DEPRECATED || type == NODETYPE_DEAD_END) {
510  // dead end is a computed status. Reset this to unknown so it will
511  // be corrected if additional connections are loaded
512  type = NODETYPE_UNKNOWN;
513  }
514  } else {
515  WRITE_WARNING("Unknown node type for junction '" + id + "'.");
516  }
517  Position pos = readPosition(attrs, id, ok);
519  NBNode* node = new NBNode(id, pos, type);
520  if (!myNodeCont.insert(node)) {
521  WRITE_ERROR("Problems on adding junction '" + id + "'.");
522  delete node;
523  return;
524  }
525  myCurrentJunction.node = node;
527  // set optional radius
528  if (attrs.hasAttribute(SUMO_ATTR_RADIUS)) {
529  node->setRadius(attrs.get<SUMOReal>(SUMO_ATTR_RADIUS, id.c_str(), ok));
530  }
531  // handle custom shape
532  if (attrs.getOpt<bool>(SUMO_ATTR_CUSTOMSHAPE, 0, ok, false)) {
533  node->setCustomShape(attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok));
534  }
535  if (myCustomShapeMaps.count(id) > 0) {
536  NBNode::CustomShapeMap customShapes = myCustomShapeMaps[id];
537  for (NBNode::CustomShapeMap::const_iterator it = customShapes.begin(); it != customShapes.end(); ++it) {
538  node->setCustomLaneShape(it->first, it->second);
539  }
540  }
541  if (type == NODETYPE_RAIL_SIGNAL || type == NODETYPE_RAIL_CROSSING) {
542  // both types of nodes come without a tlLogic
543  myRailSignals.insert(id);
544  }
545 }
546 
547 
548 void
550  if (myCurrentJunction.node != 0) {
551  bool ok = true;
552  myCurrentJunction.response.push_back(attrs.get<std::string>(SUMO_ATTR_RESPONSE, 0, ok));
553  }
554 }
555 
556 
557 void
559  bool ok = true;
560  std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, 0, ok);
561  if (myEdges.count(fromID) == 0) {
562  WRITE_ERROR("Unknown edge '" + fromID + "' given in connection.");
563  return;
564  }
565  EdgeAttrs* from = myEdges[fromID];
566  Connection conn;
567  conn.toEdgeID = attrs.get<std::string>(SUMO_ATTR_TO, 0, ok);
568  unsigned int fromLaneIdx = attrs.get<int>(SUMO_ATTR_FROM_LANE, 0, ok);
569  conn.toLaneIdx = attrs.get<int>(SUMO_ATTR_TO_LANE, 0, ok);
570  conn.tlID = attrs.getOpt<std::string>(SUMO_ATTR_TLID, 0, ok, "");
571  conn.mayDefinitelyPass = attrs.getOpt<bool>(SUMO_ATTR_PASS, 0, ok, false);
572  conn.keepClear = attrs.getOpt<bool>(SUMO_ATTR_KEEP_CLEAR, 0, ok, true);
574  if (conn.tlID != "") {
575  conn.tlLinkNo = attrs.get<int>(SUMO_ATTR_TLLINKINDEX, 0, ok);
576  }
577  if (from->lanes.size() <= (size_t) fromLaneIdx) {
578  WRITE_ERROR("Invalid lane index '" + toString(fromLaneIdx) + "' for connection from '" + fromID + "'.");
579  return;
580  }
581  from->lanes[fromLaneIdx]->connections.push_back(conn);
582 
583  // determine crossing priority
584  if (myPedestrianCrossings.size() > 0
585  && from->func == EDGEFUNC_WALKINGAREA
586  && myEdges[conn.toEdgeID]->func == EDGEFUNC_CROSSING) {
587  std::vector<Crossing>& crossings = myPedestrianCrossings[SUMOXMLDefinitions::getJunctionIDFromInternalEdge(fromID)];
588  for (std::vector<Crossing>::iterator it = crossings.begin(); it != crossings.end(); ++it) {
589  if (conn.toEdgeID == (*it).edgeID) {
590  if (conn.tlID != "") {
591  (*it).priority = true;
592  } else {
593  LinkState state = SUMOXMLDefinitions::LinkStates.get(attrs.get<std::string>(SUMO_ATTR_STATE, 0, ok));
594  (*it).priority = state == LINKSTATE_MAJOR;
595  }
596  }
597  }
598  }
599 }
600 
601 
602 void
604  bool ok = true;
605  std::string prohibitor = attrs.getOpt<std::string>(SUMO_ATTR_PROHIBITOR, 0, ok, "");
606  std::string prohibited = attrs.getOpt<std::string>(SUMO_ATTR_PROHIBITED, 0, ok, "");
607  if (!ok) {
608  return;
609  }
610  Prohibition p;
613  if (!ok) {
614  return;
615  }
616  myProhibitions.push_back(p);
617 }
618 
619 
621 NIImporter_SUMO::getLaneAttrsFromID(EdgeAttrs* edge, std::string lane_id) {
622  std::string edge_id;
623  unsigned int index;
624  interpretLaneID(lane_id, edge_id, index);
625  assert(edge->id == edge_id);
626  if (edge->lanes.size() <= (size_t) index) {
627  WRITE_ERROR("Unknown lane '" + lane_id + "' given in succedge.");
628  return 0;
629  } else {
630  return edge->lanes[index];
631  }
632 }
633 
634 
635 void
636 NIImporter_SUMO::interpretLaneID(const std::string& lane_id, std::string& edge_id, unsigned int& index) {
637  // assume lane_id = edge_id + '_' + index
638  size_t sep_index = lane_id.rfind('_');
639  if (sep_index == std::string::npos) {
640  WRITE_ERROR("Invalid lane id '" + lane_id + "' (missing '_').");
641  }
642  edge_id = lane_id.substr(0, sep_index);
643  std::string index_string = lane_id.substr(sep_index + 1);
644  try {
645  index = (unsigned int)TplConvert::_2int(index_string.c_str());
646  } catch (NumberFormatException) {
647  WRITE_ERROR("Invalid lane index '" + index_string + "' for lane '" + lane_id + "'.");
648  }
649 }
650 
651 
654  if (currentTL) {
655  WRITE_ERROR("Definition of tl-logic '" + currentTL->getID() + "' was not finished.");
656  return 0;
657  }
658  bool ok = true;
659  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
660  SUMOTime offset = TIME2STEPS(attrs.get<SUMOReal>(SUMO_ATTR_OFFSET, id.c_str(), ok));
661  std::string programID = attrs.getOpt<std::string>(SUMO_ATTR_PROGRAMID, id.c_str(), ok, "<unknown>");
662  std::string typeS = attrs.get<std::string>(SUMO_ATTR_TYPE, 0, ok);
663  TrafficLightType type;
664  if (SUMOXMLDefinitions::TrafficLightTypes.hasString(typeS)) {
666  } else {
667  WRITE_ERROR("Unknown traffic light type '" + typeS + "' for tlLogic '" + id + "'.");
668  return 0;
669  }
670  if (ok) {
671  return new NBLoadedSUMOTLDef(id, programID, offset, type);
672  } else {
673  return 0;
674  }
675 }
676 
677 
678 void
680  if (!currentTL) {
681  WRITE_ERROR("found phase without tl-logic");
682  return;
683  }
684  const std::string& id = currentTL->getID();
685  bool ok = true;
686  std::string state = attrs.get<std::string>(SUMO_ATTR_STATE, id.c_str(), ok);
687  SUMOTime duration = TIME2STEPS(attrs.get<SUMOReal>(SUMO_ATTR_DURATION, id.c_str(), ok));
688  if (duration < 0) {
689  WRITE_ERROR("Phase duration for tl-logic '" + id + "/" + currentTL->getProgramID() + "' must be positive.");
690  return;
691  }
692  // if the traffic light is an actuated traffic light, try to get
693  // the minimum and maximum durations
694  //SUMOTime minDuration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_MINDURATION, id.c_str(), ok, -1);
695  //SUMOTime maxDuration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_MAXDURATION, id.c_str(), ok, -1);
696  if (ok) {
697  currentTL->addPhase(duration, state);
698  }
699 }
700 
701 
703 NIImporter_SUMO::reconstructEdgeShape(const EdgeAttrs* edge, const Position& from, const Position& to) {
704  const PositionVector& firstLane = edge->lanes[0]->shape;
705  PositionVector result;
706  result.push_back(from);
707 
708  // reverse logic of NBEdge::computeLaneShape
709  // !!! this will only work for old-style constant width lanes
710  const size_t noLanes = edge->lanes.size();
711  SUMOReal offset;
712  if (edge->lsf == LANESPREAD_RIGHT) {
713  offset = (SUMO_const_laneWidth + SUMO_const_laneOffset) / 2.; // @todo: why is the lane offset counted in here?
714  } else {
715  offset = (SUMO_const_laneWidth) / 2. - (SUMO_const_laneWidth * (SUMOReal)noLanes - 1) / 2.;
716  }
717  for (unsigned int i = 1; i < firstLane.size() - 1; i++) {
718  const Position& from = firstLane[i - 1];
719  const Position& me = firstLane[i];
720  const Position& to = firstLane[i + 1];
721  Position offsets = PositionVector::sideOffset(from, me, offset);
722  Position offsets2 = PositionVector::sideOffset(me, to, offset);
723 
724  PositionVector l1(from - offsets, me - offsets);
725  l1.extrapolate(100);
726  PositionVector l2(me - offsets2, to - offsets2);
727  l2.extrapolate(100);
728  if (l1.intersects(l2)) {
729  result.push_back(l1.intersectionPosition2D(l2));
730  } else {
731  WRITE_WARNING("Could not reconstruct shape for edge '" + edge->id + "'.");
732  }
733  }
734 
735  result.push_back(to);
736  return result;
737 }
738 
739 
742  // @todo refactor parsing of location since its duplicated in NLHandler and PCNetProjectionLoader
743  bool ok = true;
744  GeoConvHelper* result = 0;
746  Boundary convBoundary = attrs.get<Boundary>(SUMO_ATTR_CONV_BOUNDARY, 0, ok);
747  Boundary origBoundary = attrs.get<Boundary>(SUMO_ATTR_ORIG_BOUNDARY, 0, ok);
748  std::string proj = attrs.get<std::string>(SUMO_ATTR_ORIG_PROJ, 0, ok);
749  if (ok) {
750  Position networkOffset = s[0];
751  result = new GeoConvHelper(proj, networkOffset, origBoundary, convBoundary);
752  GeoConvHelper::setLoaded(*result);
753  }
754  return result;
755 }
756 
757 
758 Position
759 NIImporter_SUMO::readPosition(const SUMOSAXAttributes& attrs, const std::string& id, bool& ok) {
760  SUMOReal x = attrs.get<SUMOReal>(SUMO_ATTR_X, id.c_str(), ok);
761  SUMOReal y = attrs.get<SUMOReal>(SUMO_ATTR_Y, id.c_str(), ok);
762  SUMOReal z = 0;
763  if (attrs.hasAttribute(SUMO_ATTR_Z)) {
764  z = attrs.get<SUMOReal>(SUMO_ATTR_Z, id.c_str(), ok);
765  }
766  return Position(x, y, z);
767 }
768 
769 
770 void
771 NIImporter_SUMO::parseProhibitionConnection(const std::string& attr, std::string& from, std::string& to, bool& ok) {
772  // split from/to
773  size_t div = attr.find("->");
774  if (div == std::string::npos) {
775  WRITE_ERROR("Missing connection divider in prohibition attribute '" + attr + "'");
776  ok = false;
777  }
778  from = attr.substr(0, div);
779  to = attr.substr(div + 2);
780  // check whether the definition includes a lane information and discard it
781  if (from.find('_') != std::string::npos) {
782  from = from.substr(0, from.find('_'));
783  }
784  if (to.find('_') != std::string::npos) {
785  to = to.substr(0, to.find('_'));
786  }
787  // check whether the edges are known
788  if (myEdges.count(from) == 0) {
789  WRITE_ERROR("Unknown edge prohibition '" + from + "'");
790  ok = false;
791  }
792  if (myEdges.count(to) == 0) {
793  WRITE_ERROR("Unknown edge prohibition '" + to + "'");
794  ok = false;
795  }
796 }
797 
798 
799 void
801  if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
803  } else {
804  WRITE_ERROR("Empty edges in roundabout.");
805  }
806 }
807 
808 
809 /****************************************************************************/
std::map< std::string, EdgeAttrs * > myEdges
Loaded edge definitions.
LaneAttrs * myCurrentLane
The currently parsed lanes&#39;s definition (to add the shape to)
The information about how to spread the lanes from the given position.
static Position sideOffset(const Position &beg, const Position &end, const SUMOReal amount)
bool hasConnectionTo(NBEdge *destEdge, unsigned int destLane, int fromLane=-1) const
Retrieves info about a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:812
std::vector< std::string > getStringVector(const std::string &name) const
Returns the list of string-vector-value of the named option (only for Option_String) ...
PositionVector shape
This edges&#39;s shape.
std::vector< Prohibition > myProhibitions
Loaded prohibitions.
static void addPhase(const SUMOSAXAttributes &attrs, NBLoadedSUMOTLDef *currentTL)
adds a phase to the traffic lights logic currently build
long long int SUMOTime
Definition: SUMOTime.h:43
static const SUMOReal UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:201
std::set< std::string > deprecatedVehicleClassesSeen
Whether vehicles must keep the junction clear.
const SUMOReal SUMO_const_laneWidth
Definition: StdDefs.h:49
whether a given shape is user-defined
static bool transformCoordinates(Position &from, bool includeInBoundary=true, GeoConvHelper *from_srs=0)
transforms loaded coordinates handles projections, offsets (using GeoConvHelper) and import of height...
static bool isReadable(std::string path)
Checks whether the given file is readable.
Definition: FileHelpers.cpp:58
NBNodeCont & myNodeCont
The node container to fill.
void addEdge(const SUMOSAXAttributes &attrs)
Parses an edge and stores the values in "myCurrentEdge".
void addRoundabout(const SUMOSAXAttributes &attrs)
Parses a roundabout and stores it in myEdgeCont.
SUMOReal maxSpeed
The maximum velocity allowed on this lane.
A loaded (complete) traffic light logic.
std::vector< LaneAttrs * > lanes
This edge&#39;s lanes.
static StringBijection< LaneSpreadFunction > LaneSpreadFunctions
bool hasLaneSpecificEndOffset() const
whether lanes differ in offset
Definition: NBEdge.cpp:1465
void setLaneWidth(int lane, SUMOReal width)
set lane specific width (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2294
void setSpeed(int lane, SUMOReal speed)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2349
Describes a pedestrian crossing.
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition: NBEdge.h:502
static std::string getJunctionIDFromInternalEdge(const std::string internalEdge)
return the junction id when given an edge of type internal, crossing or WalkingArea ...
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const std::string & getProgramID() const
Returns the ProgramID.
The representation of a single edge during network building.
Definition: NBEdge.h:70
void declareConnectionsAsLoaded()
Definition: NBEdge.h:1078
A connection description.
std::vector< std::string > response
static void setLoaded(const GeoConvHelper &loaded)
sets the coordinate transformation loaded from a location element
bool intersects(const Position &p1, const Position &p2) const
bool addLane2LaneConnection(unsigned int fromLane, NBEdge *dest, unsigned int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, SUMOReal contPos=UNSPECIFIED_CONTPOS)
Adds a connection between the specified this edge&#39;s lane and an approached one.
Definition: NBEdge.cpp:684
T MAX2(T a, T b)
Definition: StdDefs.h:75
SUMOReal getLaneWidth() const
Returns the default width of lanes of this edge.
Definition: NBEdge.h:449
void setPermissions(SVCPermissions permissions, int lane=-1)
set allowed/disallowed classes for the given lane or for all lanes if -1 is given ...
Definition: NBEdge.cpp:2365
bool myAmLefthand
whether the loaded network was built for lefthand traffic
static NBLoadedSUMOTLDef * initTrafficLightLogic(const SUMOSAXAttributes &attrs, NBLoadedSUMOTLDef *currentTL)
begins the reading of a traffic lights logic
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
static const SUMOReal UNSPECIFIED_CONTPOS
unspecified internal junction position
Definition: NBEdge.h:207
const SUMOReal SUMO_const_laneOffset
Definition: StdDefs.h:52
static StringBijection< LinkState > LinkStates
SUMOReal contPos
custom position for internal junction on this connection
static const SUMOReal UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:203
void setCustomShape(const PositionVector &shape)
set the junction shape
Definition: NBNode.cpp:1644
SAX-handler base for SUMO-files.
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false)
Runs the given handler on the given file; returns if everything&#39;s ok.
Definition: XMLSubSys.cpp:114
NIImporter_SUMO(NBNetBuilder &nb)
Constructor.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list...
virtual SumoXMLEdgeFunc getEdgeFunc(bool &ok) const =0
Returns the value of the named attribute.
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:48
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
std::map< std::string, NBNode::CustomShapeMap > myCustomShapeMaps
customLaneShape (cannot be added to the NBNode when parsed since the node doesn&#39;t yet exist ...
Describes the values found in a lane&#39;s definition.
The connection was computed and validated.
Definition: NBEdge.h:115
LaneAttrs * getLaneAttrsFromID(EdgeAttrs *edge, std::string lane_id)
Parses lane index from lane ID an retrieve lane from EdgeAttrs.
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:69
std::string toEdgeID
The id of the target edge.
bool myHaveSeenInternalEdge
whether the loaded network contains internal lanes
The state of a link.
std::map< std::string, PositionVector > CustomShapeMap
Definition: NBNode.h:82
void addLane(const SUMOSAXAttributes &attrs)
Parses a lane and stores the values in "myCurrentLane".
NBNetBuilder & myNetBuilder
The network builder to fill.
const std::string & getID() const
Returns the id.
Definition: Named.h:65
std::vector< std::vector< std::string > > myRoundabouts
loaded roundabout edges
void addConnection(const SUMOSAXAttributes &attrs)
Parses a connection and saves it into the lane&#39;s definition stored in "myCurrentLane".
static void parseStringVector(const std::string &def, std::vector< std::string > &into)
Splits the given string.
std::string toNode
The node this edge ends at.
const Position & getPosition() const
Returns the position of this node.
Definition: NBNode.h:228
The turning radius at an intersection in m.
Describes the values found in an edge&#39;s definition and this edge&#39;s lanes.
void setFileName(const std::string &name)
Sets the current file name.
std::set< NBEdge * > EdgeSet
Definition: NBCont.h:51
int myLinkDetail
the level of geometry detail for internal lanes in the loaded network
JunctionAttrs myCurrentJunction
The currently parsed junction definition to help in reconstructing crossings.
static methods for processing the coordinates conversion for the current net
Definition: GeoConvHelper.h:60
the edges of a route
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:161
std::string getLaneID(unsigned int lane) const
Definition: NBEdge.cpp:2166
std::vector< std::string > crossingEdges
std::string allow
This lane&#39;s allowed vehicle classes.
Encapsulated SAX-Attributes.
void setRadius(SUMOReal radius)
set the turning radius
Definition: NBNode.h:510
static GeoConvHelper * loadLocation(const SUMOSAXAttributes &attrs)
Parses network location description and registers it with GeoConveHelper::setLoaded.
static StringBijection< TrafficLightType > TrafficLightTypes
Describes the values found in a prohibition.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
Importer for networks stored in SUMO format.
std::string tlID
The id of the traffic light that controls this connection.
NBEdgeCont & getEdgeCont()
Returns the edge container.
Definition: NBNetBuilder.h:154
EdgeAttrs * myCurrentEdge
The currently parsed edge&#39;s definition (to add loaded lanes to)
A list of positions.
virtual SUMOReal getFloat(int id) const =0
Returns the SUMOReal-value of the named (by its enum-value) attribute.
bool isUsableFileList(const std::string &name) const
Checks whether the named option is usable as a file list (with at least a single file) ...
void parseProhibitionConnection(const std::string &attr, std::string &from, std::string &to, bool &ok)
parses connection string of a prohibition (very old school)
void haveLoadedNetworkWithoutInternalEdges()
notify about style of loaded network
Definition: NBNetBuilder.h:200
LaneSpreadFunction lsf
The lane spread function.
const std::map< std::string, NBTrafficLightDefinition * > & getPrograms(const std::string &id) const
Returns all programs for the given tl-id.
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic, in MSLink and GNEInternalLane.
void setCustomLaneShape(const std::string &laneID, const PositionVector &shape)
sets a custom shape for an internal lane
Definition: NBNode.cpp:1651
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:202
std::string disallow
This lane&#39;s disallowed vehicle classes.
unsigned int tlLinkNo
The index of this connection within the controlling traffic light.
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:54
void setLoadedLength(SUMOReal val)
Definition: NBEdge.cpp:2408
NBEdge * builtEdge
The built edge.
virtual SumoXMLNodeType getNodeType(bool &ok) const =0
Returns the value of the named attribute.
static PositionVector reconstructEdgeShape(const EdgeAttrs *edge, const Position &from, const Position &to)
reconstructs the edge shape from the node positions and the given lane shapes since we do not know th...
SumoXMLEdgeFunc func
This edge&#39;s function.
void _loadNetwork(OptionsCont &oc)
load the network
SUMOReal width
The width of this lane.
SUMOReal getEndOffset() const
Returns the offset to the destination node.
Definition: NBEdge.h:478
static void interpretLaneID(const std::string &lane_id, std::string &edge_id, unsigned int &index)
parses edge-id and index from lane-id
bool keepClear
Whether the junction must be kept clear coming from this connection.
std::vector< std::string > intLanes
SUMOReal endOffset
This lane&#39;s offset from the intersection.
std::string streetName
This edge&#39;s street name.
static void loadNetwork(OptionsCont &oc, NBNetBuilder &nb)
Loads content of the optionally given SUMO file.
SUMOReal maxSpeed
The maximum velocity allowed on this edge (!!!)
virtual std::vector< std::string > getStringVector(int attr) const =0
Tries to read given attribute assuming it is a string vector.
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:206
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
static int _2int(const E *const data)
Definition: TplConvert.h:114
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:369
std::vector< Connection > connections
This lane&#39;s connections.
void addJunction(const SUMOSAXAttributes &attrs)
Parses a junction and saves it in the node control.
void addCrossing(EdgeVector edges, SUMOReal width, bool priority, bool fromSumoNet=false)
add a pedestrian crossing to this node
Definition: NBNode.cpp:2445
std::string type
This edge&#39;s type.
bool set(const std::string &name, const std::string &value)
Sets the given value for the named option.
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:246
static const SUMOReal UNSPECIFIED_LOADED_LENGTH
no length override given
Definition: NBEdge.h:210
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
Instance responsible for building networks.
Definition: NBNetBuilder.h:113
unsigned int toLaneIdx
The index of the target lane.
void addPhase(SUMOTime duration, const std::string &state)
Adds a phase to the logic the new phase is inserted at the end of the list of already added phases...
std::vector< NBEdge * > EdgeVector
Definition: NBCont.h:41
int myCornerDetail
the level of corner detail in the loaded network
static Position readPosition(const SUMOSAXAttributes &attrs, const std::string &id, bool &ok)
read position from the given attributes, attribute errors to id
std::map< std::string, std::vector< Crossing > > myPedestrianCrossings
The pedestrian crossings found in the network.
A storage for options typed value containers)
Definition: OptionsCont.h:108
int priority
This edge&#39;s priority.
Position intersectionPosition2D(const Position &p1, const Position &p2, const SUMOReal withinDist=0.) const
std::string id
This edge&#39;s id.
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:80
void myEndElement(int element)
Called when a closing tag occurs.
This is an uncontrolled, major link, may pass.
std::string fromNode
The node this edge starts at.
Represents a single node (junction) during network building.
Definition: NBNode.h:74
T get(const std::string &str) const
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
~NIImporter_SUMO()
Destructor.
void addRequest(const SUMOSAXAttributes &attrs)
Parses a reques and saves selected attributes in myCurrentJunction.
GeoConvHelper * myLocation
The coordinate transformation which was used to build the loaded network.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
bool hasLaneSpecificWidth() const
whether lanes differ in width
Definition: NBEdge.cpp:1443
void addSortedLinkFoes(const NBConnection &mayDrive, const NBConnection &mustStop)
Definition: NBNode.cpp:1170
void setEndOffset(int lane, SUMOReal offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2333
#define SUMOReal
Definition: config.h:213
NBTrafficLightLogicCont & myTLLCont
The node container to fill.
SUMOReal length
The length of the edge if set explicitly.
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.
bool wasIgnored(std::string id) const
Returns whether the edge with the id was ignored during parsing.
Definition: NBEdgeCont.h:464
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:109
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:203
void addRoundabout(const EdgeSet &roundabout)
add user specified roundabout
Definition: NBEdgeCont.cpp:949
void addProhibition(const SUMOSAXAttributes &attrs)
Parses a prohibition and saves it.
NBLoadedSUMOTLDef * myCurrentTL
The currently parsed traffic light.
std::set< std::string > myRailSignals
list of node id with rail signals (no NBTrafficLightDefinition exists)
void addConnection(NBEdge *from, NBEdge *to, int fromLane, int toLane, int linkIndex)
Adds a connection and immediately informs the edges.
void extrapolate(const SUMOReal val, const bool onlyFirst=false)
TrafficLightType
static std::string getNodeIDFromInternalLane(const std::string id)
returns the node id for internal lanes, crossings and walkingareas
Definition: NBNode.cpp:2533