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-2015 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),
86  myHaveSeenInternalEdge(false)
87 {}
88 
89 
91  for (std::map<std::string, EdgeAttrs*>::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
92  EdgeAttrs* ed = (*i).second;
93  for (std::vector<LaneAttrs*>::const_iterator j = ed->lanes.begin(); j != ed->lanes.end(); ++j) {
94  delete *j;
95  }
96  delete ed;
97  }
98  delete myLocation;
99 }
100 
101 
102 void
104  // check whether the option is set (properly)
105  if (!oc.isUsableFileList("sumo-net-file")) {
106  return;
107  }
108  // parse file(s)
109  std::vector<std::string> files = oc.getStringVector("sumo-net-file");
110  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
111  if (!FileHelpers::isReadable(*file)) {
112  WRITE_ERROR("Could not open sumo-net-file '" + *file + "'.");
113  return;
114  }
115  setFileName(*file);
116  PROGRESS_BEGIN_MESSAGE("Parsing sumo-net from '" + *file + "'");
117  XMLSubSys::runParser(*this, *file, true);
119  }
120  // build edges
121  for (std::map<std::string, EdgeAttrs*>::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
122  EdgeAttrs* ed = (*i).second;
123  // skip internal edges
124  if (ed->func == EDGEFUNC_INTERNAL || ed->func == EDGEFUNC_CROSSING || ed->func == EDGEFUNC_WALKINGAREA) {
125  continue;
126  }
127  // get and check the nodes
128  NBNode* from = myNodeCont.retrieve(ed->fromNode);
129  NBNode* to = myNodeCont.retrieve(ed->toNode);
130  if (from == 0) {
131  WRITE_ERROR("Edge's '" + ed->id + "' from-node '" + ed->fromNode + "' is not known.");
132  continue;
133  }
134  if (to == 0) {
135  WRITE_ERROR("Edge's '" + ed->id + "' to-node '" + ed->toNode + "' is not known.");
136  continue;
137  }
138  // edge shape
139  PositionVector geom;
140  if (ed->shape.size() > 0) {
141  geom = ed->shape;
142  } else {
143  // either the edge has default shape consisting only of the two node
144  // positions or we have a legacy network
145  geom = reconstructEdgeShape(ed, from->getPosition(), to->getPosition());
146  }
147  // build and insert the edge
148  NBEdge* e = new NBEdge(ed->id, from, to,
149  ed->type, ed->maxSpeed,
150  (unsigned int) ed->lanes.size(),
152  geom, ed->streetName, ed->lsf, true); // always use tryIgnoreNodePositions to keep original shape
153  e->setLoadedLength(ed->length);
154  if (!myNetBuilder.getEdgeCont().insert(e)) {
155  WRITE_ERROR("Could not insert edge '" + ed->id + "'.");
156  delete e;
157  continue;
158  }
160  }
161  // assign further lane attributes (edges are built)
162  for (std::map<std::string, EdgeAttrs*>::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
163  EdgeAttrs* ed = (*i).second;
164  NBEdge* nbe = ed->builtEdge;
165  if (nbe == 0) { // inner edge or removed by explicit list, vclass, ...
166  continue;
167  }
168  for (unsigned int fromLaneIndex = 0; fromLaneIndex < (unsigned int) ed->lanes.size(); ++fromLaneIndex) {
169  LaneAttrs* lane = ed->lanes[fromLaneIndex];
170  // connections
171  const std::vector<Connection>& connections = lane->connections;
172  for (std::vector<Connection>::const_iterator c_it = connections.begin(); c_it != connections.end(); c_it++) {
173  const Connection& c = *c_it;
174  if (myEdges.count(c.toEdgeID) == 0) {
175  WRITE_ERROR("Unknown edge '" + c.toEdgeID + "' given in connection.");
176  continue;
177  }
178  NBEdge* toEdge = myEdges[c.toEdgeID]->builtEdge;
179  if (toEdge == 0) { // removed by explicit list, vclass, ...
180  continue;
181  }
182  if (nbe->hasConnectionTo(toEdge, c.toLaneIdx)) {
183  WRITE_WARNING("Target lane '" + toEdge->getLaneID(c.toLaneIdx) + "' has multiple connections from '" + nbe->getID() + "'.");
184  }
186  fromLaneIndex, toEdge, c.toLaneIdx, NBEdge::L2L_VALIDATED,
187  true, c.mayDefinitelyPass);
188 
189  // maybe we have a tls-controlled connection
190  if (c.tlID != "" && myRailSignals.count(c.tlID) == 0) {
191  const std::map<std::string, NBTrafficLightDefinition*>& programs = myTLLCont.getPrograms(c.tlID);
192  if (programs.size() > 0) {
193  std::map<std::string, NBTrafficLightDefinition*>::const_iterator it;
194  for (it = programs.begin(); it != programs.end(); it++) {
195  NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(it->second);
196  if (tlDef) {
197  tlDef->addConnection(nbe, toEdge, fromLaneIndex, c.toLaneIdx, c.tlLinkNo);
198  } else {
199  throw ProcessError("Corrupt traffic light definition '" + c.tlID + "' (program '" + it->first + "')");
200  }
201  }
202  } else {
203  WRITE_ERROR("The traffic light '" + c.tlID + "' is not known.");
204  }
205  }
206  }
207  // allow/disallow XXX preferred
208  nbe->setPermissions(parseVehicleClasses(lane->allow, lane->disallow), fromLaneIndex);
209  // width, offset
210  nbe->setLaneWidth(fromLaneIndex, lane->width);
211  nbe->setEndOffset(fromLaneIndex, lane->endOffset);
212  nbe->setSpeed(fromLaneIndex, lane->maxSpeed);
213  }
215  if (!nbe->hasLaneSpecificWidth() && nbe->getLanes()[0].width != NBEdge::UNSPECIFIED_WIDTH) {
216  nbe->setLaneWidth(-1, nbe->getLaneWidth(0));
217  }
219  nbe->setEndOffset(-1, nbe->getEndOffset(0));
220  }
221  }
222  // insert loaded prohibitions
223  for (std::vector<Prohibition>::const_iterator it = myProhibitions.begin(); it != myProhibitions.end(); it++) {
224  NBEdge* prohibitedFrom = myEdges[it->prohibitedFrom]->builtEdge;
225  if (prohibitedFrom == 0) {
226  WRITE_ERROR("Edge '" + it->prohibitedFrom + "' in prohibition was not built");
227  } else {
228  NBNode* n = prohibitedFrom->getToNode();
230  NBConnection(myEdges[it->prohibitorFrom]->builtEdge, myEdges[it->prohibitorTo]->builtEdge),
231  NBConnection(prohibitedFrom, myEdges[it->prohibitedTo]->builtEdge));
232  }
233  }
234  if (!myHaveSeenInternalEdge && oc.isDefault("no-internal-links")) {
235  oc.set("no-internal-links", "true");
236  }
237  if (!deprecatedVehicleClassesSeen.empty()) {
238  WRITE_WARNING("Deprecated vehicle class(es) '" + toString(deprecatedVehicleClassesSeen) + "' in input network.");
240  }
241  // add loaded crossings
242  for (std::map<std::string, std::vector<Crossing> >::const_iterator it = myPedestrianCrossings.begin(); it != myPedestrianCrossings.end(); ++it) {
243  NBNode* node = myNodeCont.retrieve((*it).first);
244  for (std::vector<Crossing>::const_iterator it_c = (*it).second.begin(); it_c != (*it).second.end(); ++it_c) {
245  const Crossing& crossing = (*it_c);
246  EdgeVector edges;
247  for (std::vector<std::string>::const_iterator it_e = crossing.crossingEdges.begin(); it_e != crossing.crossingEdges.end(); ++it_e) {
248  NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(*it_e);
249  // edge might have been removed due to options
250  if (edge != 0) {
251  edges.push_back(edge);
252  }
253  }
254  if (edges.size() > 0) {
255  node->addCrossing(edges, crossing.width, crossing.priority);
256  }
257  }
258  }
259  // add roundabouts
260  for (std::vector<std::vector<std::string> >::const_iterator it = myRoundabouts.begin(); it != myRoundabouts.end(); ++it) {
261  EdgeSet roundabout;
262  for (std::vector<std::string>::const_iterator it_r = it->begin(); it_r != it->end(); ++it_r) {
263  NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(*it_r);
264  if (edge == 0) {
265  if (!myNetBuilder.getEdgeCont().wasIgnored(*it_r)) {
266  WRITE_ERROR("Unknown edge '" + (*it_r) + "' in roundabout");
267  }
268  } else {
269  roundabout.insert(edge);
270  }
271  }
272  myNetBuilder.getEdgeCont().addRoundabout(roundabout);
273  }
274 }
275 
276 
277 
278 void
280  const SUMOSAXAttributes& attrs) {
281  /* our goal is to reproduce the input net faithfully
282  * there are different types of objects in the netfile:
283  * 1) those which must be loaded into NBNetBuilder-Containers for processing
284  * 2) those which can be ignored because they are recomputed based on group 1
285  * 3) those which are of no concern to NBNetBuilder but should be exposed to
286  * NETEDIT. We will probably have to patch NBNetBuilder to contain them
287  * and hand them over to NETEDIT
288  * alternative idea: those shouldn't really be contained within the
289  * network but rather in separate files. teach NETEDIT how to open those
290  * (POI?)
291  * 4) those which are of concern neither to NBNetBuilder nor NETEDIT and
292  * must be copied over - need to patch NBNetBuilder for this.
293  * copy unknown by default
294  */
295  switch (element) {
296  case SUMO_TAG_EDGE:
297  addEdge(attrs);
298  break;
299  case SUMO_TAG_LANE:
300  addLane(attrs);
301  break;
302  case SUMO_TAG_JUNCTION:
303  addJunction(attrs);
304  break;
305  case SUMO_TAG_REQUEST:
306  addRequest(attrs);
307  break;
308  case SUMO_TAG_CONNECTION:
309  addConnection(attrs);
310  break;
311  case SUMO_TAG_TLLOGIC:
313  break;
314  case SUMO_TAG_PHASE:
315  addPhase(attrs, myCurrentTL);
316  break;
317  case SUMO_TAG_LOCATION:
318  myLocation = loadLocation(attrs);
319  break;
321  addProhibition(attrs);
322  break;
323  case SUMO_TAG_ROUNDABOUT:
324  addRoundabout(attrs);
325  break;
326  default:
327  break;
328  }
329 }
330 
331 
332 void
334  switch (element) {
335  case SUMO_TAG_EDGE:
336  if (myEdges.find(myCurrentEdge->id) != myEdges.end()) {
337  WRITE_ERROR("Edge '" + myCurrentEdge->id + "' occured at least twice in the input.");
338  } else {
340  }
341  myCurrentEdge = 0;
342  break;
343  case SUMO_TAG_LANE:
344  if (myCurrentEdge != 0) {
346  myCurrentEdge->lanes.push_back(myCurrentLane);
347  }
348  myCurrentLane = 0;
349  break;
350  case SUMO_TAG_TLLOGIC:
351  if (!myCurrentTL) {
352  WRITE_ERROR("Unmatched closing tag for tl-logic.");
353  } else {
354  if (!myTLLCont.insert(myCurrentTL)) {
355  WRITE_WARNING("Could not add program '" + myCurrentTL->getProgramID() + "' for traffic light '" + myCurrentTL->getID() + "'");
356  delete myCurrentTL;
357  }
358  myCurrentTL = 0;
359  }
360  break;
361  case SUMO_TAG_JUNCTION:
362  // in a network without internal lanes, we do not need to check for crossings
363  if (myCurrentJunction.node != 0 && myCurrentJunction.intLanes.size() > 0) {
364  assert(myCurrentJunction.intLanes.size() == myCurrentJunction.response.size());
365  std::vector<Crossing>& crossings = myPedestrianCrossings[myCurrentJunction.node->getID()];
366  for (std::vector<Crossing>::iterator it = crossings.begin(); it != crossings.end(); ++it) {
367  for (int i = 0; i < (int)myCurrentJunction.intLanes.size(); ++i) {
368  if (myCurrentJunction.intLanes[i] == (*it).laneID) {
369  (*it).priority = myCurrentJunction.response[i].find("1") == std::string::npos;
370  }
371  }
372  }
373  }
374  default:
375  break;
376  }
377 }
378 
379 
380 void
382  // get the id, report an error if not given or empty...
383  bool ok = true;
384  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
385  if (!ok) {
386  return;
387  }
388  myCurrentEdge = new EdgeAttrs();
390  myCurrentEdge->id = id;
391  // get the function
392  myCurrentEdge->func = attrs.getEdgeFunc(ok);
394  // add the crossing crossing but don't do anything else
395  Crossing c;
398  return;
400  return; // skip internal edges
401  }
402  // get the type
403  myCurrentEdge->type = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok, "");
404  // get the origin and the destination node
405  myCurrentEdge->fromNode = attrs.getOpt<std::string>(SUMO_ATTR_FROM, id.c_str(), ok, "");
406  myCurrentEdge->toNode = attrs.getOpt<std::string>(SUMO_ATTR_TO, id.c_str(), ok, "");
407  myCurrentEdge->priority = attrs.getOpt<int>(SUMO_ATTR_PRIORITY, id.c_str(), ok, -1);
408  myCurrentEdge->type = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok, "");
412  myCurrentEdge->maxSpeed = 0;
413  myCurrentEdge->streetName = attrs.getOpt<std::string>(SUMO_ATTR_NAME, id.c_str(), ok, "");
414  if (myCurrentEdge->streetName != "" && OptionsCont::getOptions().isDefault("output.street-names")) {
415  OptionsCont::getOptions().set("output.street-names", "true");
416  }
417 
418  std::string lsfS = toString(LANESPREAD_RIGHT);
419  lsfS = attrs.getOpt<std::string>(SUMO_ATTR_SPREADTYPE, id.c_str(), ok, lsfS);
420  if (SUMOXMLDefinitions::LaneSpreadFunctions.hasString(lsfS)) {
422  } else {
423  WRITE_ERROR("Unknown spreadType '" + lsfS + "' for edge '" + id + "'.");
424  }
425 }
426 
427 
428 void
430  bool ok = true;
431  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
432  if (!ok) {
433  return;
434  }
435  if (!myCurrentEdge) {
436  WRITE_ERROR("Found lane '" + id + "' not within edge element");
437  return;
438  }
439  if (attrs.getOpt<bool>(SUMO_ATTR_CUSTOMSHAPE, 0, ok, false)) {
440  const std::string nodeID = NBNode::getNodeIDFromInternalLane(id);
441  myCustomShapeMaps[nodeID][id] = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok);
442  }
443  myCurrentLane = new LaneAttrs;
445  // save the width and the lane id of the crossing but don't do anything else
447  assert(crossings.size() > 0);
448  crossings.back().laneID = id;
449  crossings.back().width = attrs.get<SUMOReal>(SUMO_ATTR_WIDTH, id.c_str(), ok);
450  return;
452  myHaveSeenInternalEdge = true;
453  return; // skip internal lanes
454  }
455  if (attrs.hasAttribute("maxspeed")) {
456  // !!! deprecated
457  myCurrentLane->maxSpeed = attrs.getFloat("maxspeed");
458  } else {
459  myCurrentLane->maxSpeed = attrs.get<SUMOReal>(SUMO_ATTR_SPEED, id.c_str(), ok);
460  }
461  try {
462  myCurrentLane->allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, id.c_str(), ok, "", false);
463  } catch (EmptyData e) {
464  // !!! deprecated
465  myCurrentLane->allow = "";
466  }
467  myCurrentLane->disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, id.c_str(), ok, "");
470  myCurrentLane->shape = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok);
471  // lane coordinates are derived (via lane spread) do not include them in convex boundary
473 }
474 
475 
476 void
478  // get the id, report an error if not given or empty...
480  myCurrentJunction.intLanes.clear();
481  myCurrentJunction.response.clear();
482  bool ok = true;
483  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
484  if (!ok) {
485  return;
486  }
487  if (id[0] == ':') { // internal node
488  return;
489  }
490  SumoXMLNodeType type = attrs.getNodeType(ok);
491  if (ok) {
492  if (type == NODETYPE_DEAD_END_DEPRECATED || type == NODETYPE_DEAD_END) {
493  // dead end is a computed status. Reset this to unknown so it will
494  // be corrected if additional connections are loaded
495  type = NODETYPE_UNKNOWN;
496  }
497  } else {
498  WRITE_WARNING("Unknown node type for junction '" + id + "'.");
499  }
500  Position pos = readPosition(attrs, id, ok);
502  NBNode* node = new NBNode(id, pos, type);
503  if (!myNodeCont.insert(node)) {
504  WRITE_ERROR("Problems on adding junction '" + id + "'.");
505  delete node;
506  return;
507  }
508  myCurrentJunction.node = node;
510  // set optional radius
511  if (attrs.hasAttribute(SUMO_ATTR_RADIUS)) {
512  node->setRadius(attrs.get<SUMOReal>(SUMO_ATTR_RADIUS, id.c_str(), ok));
513  }
514  // handle custom shape
515  if (attrs.getOpt<bool>(SUMO_ATTR_CUSTOMSHAPE, 0, ok, false)) {
516  node->setCustomShape(attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok));
517  }
518  if (myCustomShapeMaps.count(id) > 0) {
519  NBNode::CustomShapeMap customShapes = myCustomShapeMaps[id];
520  for (NBNode::CustomShapeMap::const_iterator it = customShapes.begin(); it != customShapes.end(); ++it) {
521  node->setCustomLaneShape(it->first, it->second);
522  }
523  }
524  if (type == NODETYPE_RAIL_SIGNAL) {
525  myRailSignals.insert(id);
526  }
527 }
528 
529 
530 void
532  if (myCurrentJunction.node != 0) {
533  bool ok = true;
534  myCurrentJunction.response.push_back(attrs.get<std::string>(SUMO_ATTR_RESPONSE, 0, ok));
535  }
536 }
537 
538 
539 void
541  bool ok = true;
542  std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, 0, ok);
543  if (myEdges.count(fromID) == 0) {
544  WRITE_ERROR("Unknown edge '" + fromID + "' given in connection.");
545  return;
546  }
547  EdgeAttrs* from = myEdges[fromID];
548  Connection conn;
549  conn.toEdgeID = attrs.get<std::string>(SUMO_ATTR_TO, 0, ok);
550  unsigned int fromLaneIdx = attrs.get<int>(SUMO_ATTR_FROM_LANE, 0, ok);
551  conn.toLaneIdx = attrs.get<int>(SUMO_ATTR_TO_LANE, 0, ok);
552  conn.tlID = attrs.getOpt<std::string>(SUMO_ATTR_TLID, 0, ok, "");
553  conn.mayDefinitelyPass = attrs.getOpt<bool>(SUMO_ATTR_PASS, 0, ok, false);
554  if (conn.tlID != "") {
555  conn.tlLinkNo = attrs.get<int>(SUMO_ATTR_TLLINKINDEX, 0, ok);
556  }
557  if (from->lanes.size() <= (size_t) fromLaneIdx) {
558  WRITE_ERROR("Invalid lane index '" + toString(fromLaneIdx) + "' for connection from '" + fromID + "'.");
559  return;
560  }
561  from->lanes[fromLaneIdx]->connections.push_back(conn);
562 }
563 
564 
565 void
567  bool ok = true;
568  std::string prohibitor = attrs.getOpt<std::string>(SUMO_ATTR_PROHIBITOR, 0, ok, "");
569  std::string prohibited = attrs.getOpt<std::string>(SUMO_ATTR_PROHIBITED, 0, ok, "");
570  if (!ok) {
571  return;
572  }
573  Prohibition p;
576  if (!ok) {
577  return;
578  }
579  myProhibitions.push_back(p);
580 }
581 
582 
584 NIImporter_SUMO::getLaneAttrsFromID(EdgeAttrs* edge, std::string lane_id) {
585  std::string edge_id;
586  unsigned int index;
587  interpretLaneID(lane_id, edge_id, index);
588  assert(edge->id == edge_id);
589  if (edge->lanes.size() <= (size_t) index) {
590  WRITE_ERROR("Unknown lane '" + lane_id + "' given in succedge.");
591  return 0;
592  } else {
593  return edge->lanes[index];
594  }
595 }
596 
597 
598 void
599 NIImporter_SUMO::interpretLaneID(const std::string& lane_id, std::string& edge_id, unsigned int& index) {
600  // assume lane_id = edge_id + '_' + index
601  size_t sep_index = lane_id.rfind('_');
602  if (sep_index == std::string::npos) {
603  WRITE_ERROR("Invalid lane id '" + lane_id + "' (missing '_').");
604  }
605  edge_id = lane_id.substr(0, sep_index);
606  std::string index_string = lane_id.substr(sep_index + 1);
607  try {
608  index = (unsigned int)TplConvert::_2int(index_string.c_str());
609  } catch (NumberFormatException) {
610  WRITE_ERROR("Invalid lane index '" + index_string + "' for lane '" + lane_id + "'.");
611  }
612 }
613 
614 
617  if (currentTL) {
618  WRITE_ERROR("Definition of tl-logic '" + currentTL->getID() + "' was not finished.");
619  return 0;
620  }
621  bool ok = true;
622  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
623  SUMOTime offset = TIME2STEPS(attrs.get<SUMOReal>(SUMO_ATTR_OFFSET, id.c_str(), ok));
624  std::string programID = attrs.getOpt<std::string>(SUMO_ATTR_PROGRAMID, id.c_str(), ok, "<unknown>");
625  std::string typeS = attrs.get<std::string>(SUMO_ATTR_TYPE, 0, ok);
626  TrafficLightType type;
627  if (SUMOXMLDefinitions::TrafficLightTypes.hasString(typeS)) {
629  } else {
630  WRITE_ERROR("Unknown traffic light type '" + typeS + "' for tlLogic '" + id + "'.");
631  return 0;
632  }
633  if (ok) {
634  return new NBLoadedSUMOTLDef(id, programID, offset, type);
635  } else {
636  return 0;
637  }
638 }
639 
640 
641 void
643  if (!currentTL) {
644  WRITE_ERROR("found phase without tl-logic");
645  return;
646  }
647  const std::string& id = currentTL->getID();
648  bool ok = true;
649  std::string state = attrs.get<std::string>(SUMO_ATTR_STATE, id.c_str(), ok);
650  SUMOTime duration = TIME2STEPS(attrs.get<SUMOReal>(SUMO_ATTR_DURATION, id.c_str(), ok));
651  if (duration < 0) {
652  WRITE_ERROR("Phase duration for tl-logic '" + id + "/" + currentTL->getProgramID() + "' must be positive.");
653  return;
654  }
655  // if the traffic light is an actuated traffic light, try to get
656  // the minimum and maximum durations
657  //SUMOTime minDuration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_MINDURATION, id.c_str(), ok, -1);
658  //SUMOTime maxDuration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_MAXDURATION, id.c_str(), ok, -1);
659  if (ok) {
660  currentTL->addPhase(duration, state);
661  }
662 }
663 
664 
666 NIImporter_SUMO::reconstructEdgeShape(const EdgeAttrs* edge, const Position& from, const Position& to) {
667  const PositionVector& firstLane = edge->lanes[0]->shape;
668  PositionVector result;
669  result.push_back(from);
670 
671  // reverse logic of NBEdge::computeLaneShape
672  // !!! this will only work for old-style constant width lanes
673  const size_t noLanes = edge->lanes.size();
674  SUMOReal offset;
675  if (edge->lsf == LANESPREAD_RIGHT) {
676  offset = (SUMO_const_laneWidth + SUMO_const_laneOffset) / 2.; // @todo: why is the lane offset counted in here?
677  } else {
678  offset = (SUMO_const_laneWidth) / 2. - (SUMO_const_laneWidth * (SUMOReal)noLanes - 1) / 2.;
679  }
680  for (unsigned int i = 1; i < firstLane.size() - 1; i++) {
681  Position from = firstLane[i - 1];
682  Position me = firstLane[i];
683  Position to = firstLane[i + 1];
684  std::pair<SUMOReal, SUMOReal> offsets = NBEdge::laneOffset(from, me, offset, false);
685  std::pair<SUMOReal, SUMOReal> offsets2 = NBEdge::laneOffset(me, to, offset, false);
686 
687  Line l1(
688  Position(from.x() + offsets.first, from.y() + offsets.second),
689  Position(me.x() + offsets.first, me.y() + offsets.second));
690  l1.extrapolateBy(100);
691  Line l2(
692  Position(me.x() + offsets2.first, me.y() + offsets2.second),
693  Position(to.x() + offsets2.first, to.y() + offsets2.second));
694  l2.extrapolateBy(100);
695  if (l1.intersects(l2)) {
696  result.push_back(l1.intersectsAt(l2));
697  } else {
698  WRITE_WARNING("Could not reconstruct shape for edge '" + edge->id + "'.");
699  }
700  }
701 
702  result.push_back(to);
703  return result;
704 }
705 
706 
709  // @todo refactor parsing of location since its duplicated in NLHandler and PCNetProjectionLoader
710  bool ok = true;
711  GeoConvHelper* result = 0;
713  Boundary convBoundary = attrs.get<Boundary>(SUMO_ATTR_CONV_BOUNDARY, 0, ok);
714  Boundary origBoundary = attrs.get<Boundary>(SUMO_ATTR_ORIG_BOUNDARY, 0, ok);
715  std::string proj = attrs.get<std::string>(SUMO_ATTR_ORIG_PROJ, 0, ok);
716  if (ok) {
717  Position networkOffset = s[0];
718  result = new GeoConvHelper(proj, networkOffset, origBoundary, convBoundary);
719  GeoConvHelper::setLoaded(*result);
720  }
721  return result;
722 }
723 
724 
725 Position
726 NIImporter_SUMO::readPosition(const SUMOSAXAttributes& attrs, const std::string& id, bool& ok) {
727  SUMOReal x = attrs.get<SUMOReal>(SUMO_ATTR_X, id.c_str(), ok);
728  SUMOReal y = attrs.get<SUMOReal>(SUMO_ATTR_Y, id.c_str(), ok);
729  SUMOReal z = 0;
730  if (attrs.hasAttribute(SUMO_ATTR_Z)) {
731  z = attrs.get<SUMOReal>(SUMO_ATTR_Z, id.c_str(), ok);
732  }
733  return Position(x, y, z);
734 }
735 
736 
737 void
738 NIImporter_SUMO::parseProhibitionConnection(const std::string& attr, std::string& from, std::string& to, bool& ok) {
739  // split from/to
740  size_t div = attr.find("->");
741  if (div == std::string::npos) {
742  WRITE_ERROR("Missing connection divider in prohibition attribute '" + attr + "'");
743  ok = false;
744  }
745  from = attr.substr(0, div);
746  to = attr.substr(div + 2);
747  // check whether the definition includes a lane information and discard it
748  if (from.find('_') != std::string::npos) {
749  from = from.substr(0, from.find('_'));
750  }
751  if (to.find('_') != std::string::npos) {
752  to = to.substr(0, to.find('_'));
753  }
754  // check whether the edges are known
755  if (myEdges.count(from) == 0) {
756  WRITE_ERROR("Unknown edge prohibition '" + from + "'");
757  ok = false;
758  }
759  if (myEdges.count(to) == 0) {
760  WRITE_ERROR("Unknown edge prohibition '" + to + "'");
761  ok = false;
762  }
763 }
764 
765 
766 void
768  if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
770  } else {
771  WRITE_ERROR("Empty edges in roundabout.");
772  }
773 }
774 
775 
776 /****************************************************************************/
std::map< std::string, EdgeAttrs * > myEdges
Loaded edge definitions.
LaneAttrs * myCurrentLane
The currently parsed lanes's definition (to add the shape to)
The information about how to spread the lanes from the given position.
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:759
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'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
static const SUMOReal UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:201
std::set< std::string > deprecatedVehicleClassesSeen
const SUMOReal SUMO_const_laneWidth
Definition: StdDefs.h:46
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's lanes.
static StringBijection< LaneSpreadFunction > LaneSpreadFunctions
bool hasLaneSpecificEndOffset() const
whether lanes differ in offset
Definition: NBEdge.cpp:1493
void setLaneWidth(int lane, SUMOReal width)
set lane specific width (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2156
void setSpeed(int lane, SUMOReal speed)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2211
Describes a pedestrian crossing.
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition: NBEdge.h:510
static std::string getJunctionIDFromInternalEdge(const std::string internalEdge)
return the junction id when given an edge of type internal, crossing or WalkingArea ...
const std::string & getProgramID() const
Returns the ProgramID.
The representation of a single edge during network building.
Definition: NBEdge.h:71
void declareConnectionsAsLoaded()
Definition: NBEdge.h:1069
A connection description.
std::vector< std::string > response
void addCrossing(EdgeVector edges, SUMOReal width, bool priority)
add a pedestrian crossing to this node
Definition: NBNode.cpp:2198
static void setLoaded(const GeoConvHelper &loaded)
sets the coordinate transformation loaded from a location element
static std::pair< SUMOReal, SUMOReal > laneOffset(const Position &from, const Position &to, SUMOReal laneCenterOffset, bool leftHand)
Computes the offset from the edge shape on the current segment.
Definition: NBEdge.cpp:1394
bool addLane2LaneConnection(unsigned int fromLane, NBEdge *dest, unsigned int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false)
Adds a connection between the specified this edge's lane and an approached one.
Definition: NBEdge.cpp:649
T MAX2(T a, T b)
Definition: StdDefs.h:74
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:2227
static NBLoadedSUMOTLDef * initTrafficLightLogic(const SUMOSAXAttributes &attrs, NBLoadedSUMOTLDef *currentTL)
begins the reading of a traffic lights logic
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
const SUMOReal SUMO_const_laneOffset
Definition: StdDefs.h:49
static const SUMOReal UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:203
void setCustomShape(const PositionVector &shape)
set the junction shape
Definition: NBNode.cpp:1467
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's ok.
Definition: XMLSubSys.cpp:114
NIImporter_SUMO(NBNetBuilder &nb)
Constructor.
SUMOReal x() const
Returns the x-position.
Definition: Position.h:63
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't yet exist ...
Describes the values found in a lane's definition.
The connection was computed and validated.
Definition: NBEdge.h:116
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:67
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:83
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:60
std::vector< std::vector< std::string > > myRoundabouts
loaded roundabout edges
void addConnection(const SUMOSAXAttributes &attrs)
Parses a connection and saves it into the lane'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:239
The turning radius at an intersection in m.
Describes the values found in an edge's definition and this edge's lanes.
void setFileName(const std::string &name)
Sets the current file name.
std::set< NBEdge * > EdgeSet
Definition: NBCont.h:51
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:170
std::string getLaneID(unsigned int lane) const
Definition: NBEdge.cpp:2048
std::vector< std::string > crossingEdges
std::string allow
This lane's allowed vehicle classes.
Encapsulated SAX-Attributes.
void setRadius(SUMOReal radius)
set the turning radius
Definition: NBNode.h:511
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'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)
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.
Definition: Line.h:51
void setCustomLaneShape(const std::string &laneID, const PositionVector &shape)
sets a custom shape for an internal lane
Definition: NBNode.cpp:1474
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:202
std::string disallow
This lane'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:53
void setLoadedLength(SUMOReal val)
Definition: NBEdge.cpp:2270
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'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 intersects(const Line &l) const
Definition: Line.cpp:180
std::vector< std::string > intLanes
SUMOReal endOffset
This lane's offset from the intersection.
std::string streetName
This edge'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:205
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
void extrapolateBy(SUMOReal length)
Definition: Line.cpp:60
void push_back(const PositionVector &p)
Appends all positions from the given vector.
static int _2int(const E *const data)
Definition: TplConvert.h:114
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:371
std::vector< Connection > connections
This lane's connections.
void addJunction(const SUMOSAXAttributes &attrs)
Parses a junction and saves it in the node control.
std::string type
This edge'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:258
static const SUMOReal UNSPECIFIED_LOADED_LENGTH
no length override given
Definition: NBEdge.h:208
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
SUMOReal y() const
Returns the y-position.
Definition: Position.h:68
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's priority.
std::string id
This edge's id.
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:79
void myEndElement(int element)
Called when a closing tag occurs.
int SUMOTime
Definition: SUMOTime.h:43
std::string fromNode
The node this edge starts at.
Represents a single node (junction) during network building.
Definition: NBNode.h:75
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.
PositionVector shape
This lane's shape (needed to reconstruct edge shape for legacy networks)
bool hasLaneSpecificWidth() const
whether lanes differ in width
Definition: NBEdge.cpp:1471
void addSortedLinkFoes(const NBConnection &mayDrive, const NBConnection &mustStop)
Definition: NBNode.cpp:1054
void setEndOffset(int lane, SUMOReal offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2195
#define SUMOReal
Definition: config.h:218
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:471
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:108
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:920
void addProhibition(const SUMOSAXAttributes &attrs)
Parses a prohibition and saves it.
Position intersectsAt(const Line &l) const
Definition: Line.cpp:174
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.
TrafficLightType
static std::string getNodeIDFromInternalLane(const std::string id)
returns the node id for internal lanes, crossings and walkingareas
Definition: NBNode.cpp:2283