SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NLHandler.cpp
Go to the documentation of this file.
1 /****************************************************************************/
12 // The XML-Handler for network loading
13 /****************************************************************************/
14 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
15 // Copyright (C) 2001-2013 DLR (http://www.dlr.de/) and contributors
16 /****************************************************************************/
17 //
18 // This file is part of SUMO.
19 // SUMO is free software: you can redistribute it and/or modify
20 // it under the terms of the GNU General Public License as published by
21 // the Free Software Foundation, either version 3 of the License, or
22 // (at your option) any later version.
23 //
24 /****************************************************************************/
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #include <string>
35 #include "NLHandler.h"
36 #include "NLEdgeControlBuilder.h"
38 #include "NLDetectorBuilder.h"
39 #include "NLTriggerBuilder.h"
43 #include <utils/common/SUMOTime.h>
46 #include <utils/common/RGBColor.h>
48 #include <microsim/MSGlobals.h>
49 #include <microsim/MSLane.h>
50 #include <microsim/MSBitSetLogic.h>
58 #include <utils/shapes/Shape.h>
60 
61 #ifdef CHECK_MEMORY_LEAKS
62 #include <foreign/nvwa/debug_new.h>
63 #endif // CHECK_MEMORY_LEAKS
64 
65 
66 // ===========================================================================
67 // method definitions
68 // ===========================================================================
69 NLHandler::NLHandler(const std::string& file, MSNet& net,
70  NLDetectorBuilder& detBuilder,
71  NLTriggerBuilder& triggerBuilder,
72  NLEdgeControlBuilder& edgeBuilder,
73  NLJunctionControlBuilder& junctionBuilder)
74  : MSRouteHandler(file, true),
75  myNet(net), myActionBuilder(net),
76  myCurrentIsInternalToSkip(false),
77  myDetectorBuilder(detBuilder), myTriggerBuilder(triggerBuilder),
78  myEdgeControlBuilder(edgeBuilder), myJunctionControlBuilder(junctionBuilder),
79  myAmInTLLogicMode(false), myCurrentIsBroken(false),
80  myHaveWarnedAboutDeprecatedLanes(false),
81  myLastParameterised(0),
82  myHaveSeenInternalEdge(false) {}
83 
84 
86 
87 
88 void
90  const SUMOSAXAttributes& attrs) {
91  try {
92  switch (element) {
93  case SUMO_TAG_EDGE:
94  beginEdgeParsing(attrs);
95  break;
96  case SUMO_TAG_LANE:
97  addLane(attrs);
98  break;
99  case SUMO_TAG_POLY:
100  addPoly(attrs);
101  break;
102  case SUMO_TAG_POI:
103  addPOI(attrs);
104  break;
105  case SUMO_TAG_JUNCTION:
106  openJunction(attrs);
107  initJunctionLogic(attrs);
108  break;
109  case SUMO_TAG_PHASE:
110  addPhase(attrs);
111  break;
112  case SUMO_TAG_CONNECTION:
113  addConnection(attrs);
114  break;
115  case SUMO_TAG_TLLOGIC:
116  initTrafficLightLogic(attrs);
117  break;
118  case SUMO_TAG_REQUEST:
119  addRequest(attrs);
120  break;
121  case SUMO_TAG_WAUT:
122  openWAUT(attrs);
123  break;
125  addWAUTSwitch(attrs);
126  break;
128  addWAUTJunction(attrs);
129  break;
130  case SUMO_TAG_E1DETECTOR:
132  addE1Detector(attrs);
133  break;
134  case SUMO_TAG_E2DETECTOR:
136  addE2Detector(attrs);
137  break;
138  case SUMO_TAG_E3DETECTOR:
140  beginE3Detector(attrs);
141  break;
142  case SUMO_TAG_DET_ENTRY:
143  addE3Entry(attrs);
144  break;
145  case SUMO_TAG_DET_EXIT:
146  addE3Exit(attrs);
147  break;
149  addInstantE1Detector(attrs);
150  break;
151  case SUMO_TAG_VSS:
153  break;
154  case SUMO_TAG_CALIBRATOR:
156  break;
157  case SUMO_TAG_REROUTER:
159  break;
160  case SUMO_TAG_BUS_STOP:
162  break;
163  case SUMO_TAG_VTYPEPROBE:
164  addVTypeProbeDetector(attrs);
165  break;
166  case SUMO_TAG_ROUTEPROBE:
167  addRouteProbeDetector(attrs);
168  break;
171  break;
174  break;
175  case SUMO_TAG_TIMEDEVENT:
177  break;
178  case SUMO_TAG_VAPORIZER:
180  break;
181  case SUMO_TAG_LOCATION:
182  setLocation(attrs);
183  break;
184  case SUMO_TAG_TAZ:
185  addDistrict(attrs);
186  break;
187  case SUMO_TAG_TAZSOURCE:
188  addDistrictEdge(attrs, true);
189  break;
190  case SUMO_TAG_TAZSINK:
191  addDistrictEdge(attrs, false);
192  break;
193  default:
194  break;
195  }
196  } catch (InvalidArgument& e) {
197  WRITE_ERROR(e.what());
198  }
199  MSRouteHandler::myStartElement(element, attrs);
200  if (element == SUMO_TAG_PARAM) {
201  addParam(attrs);
202  }
203 }
204 
205 
206 void
208  switch (element) {
209  case SUMO_TAG_EDGE:
210  closeEdge();
211  break;
212  case SUMO_TAG_JUNCTION:
213  if (!myCurrentIsBroken) {
214  try {
217  } catch (InvalidArgument& e) {
218  WRITE_ERROR(e.what());
219  }
220  }
221  break;
222  case SUMO_TAG_TLLOGIC:
223  try {
225  } catch (InvalidArgument& e) {
226  WRITE_ERROR(e.what());
227  }
228  myAmInTLLogicMode = false;
229  break;
230  case SUMO_TAG_WAUT:
231  closeWAUT();
232  break;
233  case SUMO_TAG_E3DETECTOR:
235  endE3Detector();
236  break;
237  case SUMO_TAG_NET:
239  break;
240  default:
241  break;
242  }
244  if (element != SUMO_TAG_PARAM) {
246  }
247 }
248 
249 
250 
251 // ---- the root/edge - element
252 void
254  bool ok = true;
255  myCurrentIsBroken = false;
256  // get the id, report an error if not given or empty...
257  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
258  if (!ok) {
259  myCurrentIsBroken = true;
260  return;
261  }
262  // omit internal edges if not wished
263  if (!MSGlobals::gUsingInternalLanes && id[0] == ':') {
264  myHaveSeenInternalEdge = true;
266  return;
267  }
269  // parse the function
270  const SumoXMLEdgeFunc func = attrs.getEdgeFunc(ok);
271  if (!ok) {
272  WRITE_ERROR("Edge '" + id + "' has an invalid type.");
273  myCurrentIsBroken = true;
274  return;
275  }
276  // interpret the function
278  switch (func) {
279  case EDGEFUNC_NORMAL:
280  funcEnum = MSEdge::EDGEFUNCTION_NORMAL;
281  break;
282  case EDGEFUNC_CONNECTOR:
283  case EDGEFUNC_SINK:
284  case EDGEFUNC_SOURCE:
286  break;
287  case EDGEFUNC_INTERNAL:
289  break;
290  }
291  // get the street name
292  std::string streetName = attrs.getOpt<std::string>(SUMO_ATTR_NAME, id.c_str(), ok, "");
293  if (!ok) {
294  myCurrentIsBroken = true;
295  return;
296  }
297  //
298  try {
299  myEdgeControlBuilder.beginEdgeParsing(id, funcEnum, streetName);
300  } catch (InvalidArgument& e) {
301  WRITE_ERROR(e.what());
302  myCurrentIsBroken = true;
303  }
304 }
305 
306 
307 void
309  // omit internal edges if not wished and broken edges
311  return;
312  }
313  try {
315  MSEdge::dictionary(e->getID(), e);
316  } catch (InvalidArgument& e) {
317  WRITE_ERROR(e.what());
318  }
319 }
320 
321 
322 // ---- the root/edge/lanes/lane - element
323 void
325  // omit internal edges if not wished and broken edges
327  return;
328  }
329  bool ok = true;
330  // get the id, report an error if not given or empty...
331  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
332  if (!ok) {
333  myCurrentIsBroken = true;
334  return;
335  }
336  SUMOReal maxSpeed = attrs.get<SUMOReal>(SUMO_ATTR_SPEED, id.c_str(), ok);
337  SUMOReal length = attrs.get<SUMOReal>(SUMO_ATTR_LENGTH, id.c_str(), ok);
338  std::string allow;
339  try {
340  bool dummy;
341  allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, id.c_str(), dummy, "", false);
342  } catch (EmptyData e) {
343  // !!! deprecated
344  }
345  std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, id.c_str(), ok, "");
346  SUMOReal width = attrs.getOpt<SUMOReal>(SUMO_ATTR_WIDTH, id.c_str(), ok, SUMO_const_laneWidth);
347  PositionVector shape = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok);
348  if (shape.size() < 2) {
349  WRITE_ERROR("Shape of lane '" + id + "' is broken.\n Can not build according edge.");
350  myCurrentIsBroken = true;
351  return;
352  }
353  SVCPermissions permissions = parseVehicleClasses(allow, disallow);
354  myCurrentIsBroken |= !ok;
355  if (!myCurrentIsBroken) {
356  try {
357  MSLane* lane = myEdgeControlBuilder.addLane(id, maxSpeed, length, shape, width, permissions);
358  // insert the lane into the lane-dictionary, checking
359  if (!MSLane::dictionary(id, lane)) {
360  delete lane;
361  WRITE_ERROR("Another lane with the id '" + id + "' exists.");
362  myCurrentIsBroken = true;
363  }
364  myLastParameterised = lane;
365  } catch (InvalidArgument& e) {
366  WRITE_ERROR(e.what());
367  }
368  }
369 }
370 
371 
372 // ---- the root/junction - element
373 void
375  myCurrentIsBroken = false;
376  bool ok = true;
377  // get the id, report an error if not given or empty...
378  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
379  if (!ok) {
380  myCurrentIsBroken = true;
381  return;
382  }
383  PositionVector shape;
384  if (attrs.hasAttribute(SUMO_ATTR_SHAPE)) {
385  // inner junctions have no shape
386  shape = attrs.getOpt<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok, PositionVector());
387  }
388  SUMOReal x = attrs.get<SUMOReal>(SUMO_ATTR_X, id.c_str(), ok);
389  SUMOReal y = attrs.get<SUMOReal>(SUMO_ATTR_Y, id.c_str(), ok);
390  bool typeOK = true;
391  SumoXMLNodeType type = attrs.getNodeType(typeOK);
392  if (!typeOK) {
393  WRITE_ERROR("An unknown or invalid junction type occured in junction '" + id + "'.");
394  ok = false;
395  }
396  std::string key = attrs.getOpt<std::string>(SUMO_ATTR_KEY, id.c_str(), ok, "");
397  // incoming lanes
398  std::vector<MSLane*> incomingLanes;
399  parseLanes(id, attrs.getStringSecure(SUMO_ATTR_INCLANES, ""), incomingLanes, ok);
400  // internal lanes
401  std::vector<MSLane*> internalLanes;
402 #ifdef HAVE_INTERNAL_LANES
404  parseLanes(id, attrs.getStringSecure(SUMO_ATTR_INTLANES, ""), internalLanes, ok);
405  }
406 #endif
407  if (!ok) {
408  myCurrentIsBroken = true;
409  } else {
410  try {
411  myJunctionControlBuilder.openJunction(id, key, type, x, y, shape, incomingLanes, internalLanes);
412  } catch (InvalidArgument& e) {
413  WRITE_ERROR(e.what() + std::string("\n Can not build according junction."));
414  myCurrentIsBroken = true;
415  }
416  }
417 }
418 
419 
420 void
421 NLHandler::parseLanes(const std::string& junctionID,
422  const std::string& def, std::vector<MSLane*>& into, bool& ok) {
423  StringTokenizer st(def);
424  while (ok && st.hasNext()) {
425  std::string laneID = st.next();
426  MSLane* lane = MSLane::dictionary(laneID);
427  if (!MSGlobals::gUsingInternalLanes && laneID[0] == ':') {
428  continue;
429  }
430  if (lane == 0) {
431  WRITE_ERROR("An unknown lane ('" + laneID + "') was tried to be set as incoming to junction '" + junctionID + "'.");
432  ok = false;
433  continue;
434  }
435  into.push_back(lane);
436  }
437 }
438 // ----
439 
440 void
442  bool ok = true;
443  std::string key = attrs.get<std::string>(SUMO_ATTR_KEY, 0, ok);
444  std::string val = attrs.get<std::string>(SUMO_ATTR_VALUE, 0, ok);
445  if (myLastParameterised != 0) {
447  }
448  // set
449  if (ok && myAmInTLLogicMode) {
450  assert(key != "");
451  assert(val != "");
453  }
454 }
455 
456 
457 void
459  myCurrentIsBroken = false;
460  bool ok = true;
461  // get the id, report an error if not given or empty...
462  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
463  if (!ok) {
464  myCurrentIsBroken = true;
465  return;
466  }
467  SUMOTime t = attrs.getOptSUMOTimeReporting(SUMO_ATTR_REF_TIME, id.c_str(), ok, 0);
468  std::string pro = attrs.get<std::string>(SUMO_ATTR_START_PROG, id.c_str(), ok);
469  if (!ok) {
470  myCurrentIsBroken = true;
471  }
472  if (!myCurrentIsBroken) {
473  myCurrentWAUTID = id;
474  try {
476  } catch (InvalidArgument& e) {
477  WRITE_ERROR(e.what());
478  myCurrentIsBroken = true;
479  }
480  }
481 }
482 
483 
484 void
486  bool ok = true;
488  std::string to = attrs.get<std::string>(SUMO_ATTR_TO, myCurrentWAUTID.c_str(), ok);
489  if (!ok) {
490  myCurrentIsBroken = true;
491  }
492  if (!myCurrentIsBroken) {
493  try {
495  } catch (InvalidArgument& e) {
496  WRITE_ERROR(e.what());
497  myCurrentIsBroken = true;
498  }
499  }
500 }
501 
502 
503 void
505  bool ok = true;
506  std::string wautID = attrs.get<std::string>(SUMO_ATTR_WAUT_ID, 0, ok);
507  std::string junctionID = attrs.get<std::string>(SUMO_ATTR_JUNCTION_ID, 0, ok);
508  std::string procedure = attrs.getOpt<std::string>(SUMO_ATTR_PROCEDURE, 0, ok, "");
509  bool synchron = attrs.getOpt<bool>(SUMO_ATTR_SYNCHRON, 0, ok, false);
510  if (!ok) {
511  myCurrentIsBroken = true;
512  }
513  try {
514  if (!myCurrentIsBroken) {
515  myJunctionControlBuilder.getTLLogicControlToUse().addWAUTJunction(wautID, junctionID, procedure, synchron);
516  }
517  } catch (InvalidArgument& e) {
518  WRITE_ERROR(e.what());
519  myCurrentIsBroken = true;
520  }
521 }
522 
523 
524 
525 
526 
527 
528 
529 void
531  bool ok = true;
532  const SUMOReal INVALID_POSITION(-1000000);
533  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
534  SUMOReal x = attrs.getOpt<SUMOReal>(SUMO_ATTR_X, id.c_str(), ok, INVALID_POSITION);
535  SUMOReal y = attrs.getOpt<SUMOReal>(SUMO_ATTR_Y, id.c_str(), ok, INVALID_POSITION);
536  SUMOReal lon = attrs.getOpt<SUMOReal>(SUMO_ATTR_LON, id.c_str(), ok, INVALID_POSITION);
537  SUMOReal lat = attrs.getOpt<SUMOReal>(SUMO_ATTR_LAT, id.c_str(), ok, INVALID_POSITION);
538  SUMOReal lanePos = attrs.getOpt<SUMOReal>(SUMO_ATTR_POSITION, id.c_str(), ok, INVALID_POSITION);
539  SUMOReal layer = attrs.getOpt<SUMOReal>(SUMO_ATTR_LAYER, id.c_str(), ok, (SUMOReal)GLO_POI);
540  std::string type = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok, "");
541  std::string laneID = attrs.getOpt<std::string>(SUMO_ATTR_LANE, id.c_str(), ok, "");
542  RGBColor color = attrs.hasAttribute(SUMO_ATTR_COLOR) ? attrs.get<RGBColor>(SUMO_ATTR_COLOR, id.c_str(), ok) : RGBColor::RED;
543  SUMOReal angle = attrs.getOpt<SUMOReal>(SUMO_ATTR_ANGLE, id.c_str(), ok, Shape::DEFAULT_ANGLE);
544  std::string imgFile = attrs.getOpt<std::string>(SUMO_ATTR_IMGFILE, id.c_str(), ok, Shape::DEFAULT_IMG_FILE);
545  if (imgFile != "" && !FileHelpers::isAbsolute(imgFile)) {
547  }
548  SUMOReal width = attrs.getOpt<SUMOReal>(SUMO_ATTR_WIDTH, id.c_str(), ok, Shape::DEFAULT_IMG_WIDTH);
549  SUMOReal height = attrs.getOpt<SUMOReal>(SUMO_ATTR_HEIGHT, id.c_str(), ok, Shape::DEFAULT_IMG_HEIGHT);
550  if (!ok) {
551  return;
552  }
553  Position pos(x, y);
554  if (x == INVALID_POSITION || y == INVALID_POSITION) {
555  // try computing x,y from lane,pos
556  if (laneID != "") {
557  MSLane* lane = MSLane::dictionary(laneID);
558  if (lane == 0) {
559  WRITE_ERROR("Lane '" + laneID + "' to place a poi '" + id + "'on is not known.");
560  return;
561  }
562  if (lanePos < 0) {
563  lanePos = lane->getLength() + lanePos;
564  }
565  pos = lane->geometryPositionAtOffset(lanePos);
566  } else {
567  // try computing x,y from lon,lat
568  if (lat == INVALID_POSITION || lon == INVALID_POSITION) {
569  WRITE_ERROR("Either (x,y), (lon,lat) or (lane,pos) must be specified for poi '" + id + "'.");
570  return;
571  } else if (!GeoConvHelper::getFinal().usingGeoProjection()) {
572  WRITE_ERROR("(lon, lat) is specified for poi '" + id + "' but no geo-conversion is specified for the network.");
573  return;
574  }
575  pos.set(lon, lat);
577  }
578  }
579  if (!myNet.getShapeContainer().addPOI(id, type, color, layer, angle, imgFile, pos, width, height)) {
580  WRITE_ERROR("PoI '" + id + "' already exists.");
581  }
582 }
583 
584 
585 void
587  bool ok = true;
588  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
589  // get the id, report an error if not given or empty...
590  if (!ok) {
591  return;
592  }
593  SUMOReal layer = attrs.getOpt<SUMOReal>(SUMO_ATTR_LAYER, id.c_str(), ok, (SUMOReal)GLO_POLYGON);
594  bool fill = attrs.getOpt<bool>(SUMO_ATTR_FILL, id.c_str(), ok, false);
595  std::string type = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok, "");
596  std::string colorStr = attrs.get<std::string>(SUMO_ATTR_COLOR, id.c_str(), ok);
597  RGBColor color = attrs.get<RGBColor>(SUMO_ATTR_COLOR, id.c_str(), ok);
598  PositionVector shape = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok);
599  SUMOReal angle = attrs.getOpt<SUMOReal>(SUMO_ATTR_ANGLE, id.c_str(), ok, Shape::DEFAULT_ANGLE);
600  std::string imgFile = attrs.getOpt<std::string>(SUMO_ATTR_IMGFILE, id.c_str(), ok, Shape::DEFAULT_IMG_FILE);
601  if (imgFile != "" && !FileHelpers::isAbsolute(imgFile)) {
603  }
604  if (shape.size() != 0) {
605  if (!myNet.getShapeContainer().addPolygon(id, type, color, layer, angle, imgFile, shape, fill)) {
606  WRITE_ERROR("Polygon '" + id + "' already exists.");
607  }
608  }
609 }
610 
611 
612 void
614  if (myCurrentIsBroken) {
615  return;
616  }
617  bool ok = true;
618  int request = attrs.get<int>(SUMO_ATTR_INDEX, 0, ok);
619  bool cont = false;
620 #ifdef HAVE_INTERNAL_LANES
621  cont = attrs.getOpt<bool>(SUMO_ATTR_CONT, 0, ok, false);
622 #endif
623  std::string response = attrs.get<std::string>(SUMO_ATTR_RESPONSE, 0, ok);
624  std::string foes = attrs.get<std::string>(SUMO_ATTR_FOES, 0, ok);
625  if (!ok) {
626  return;
627  }
628  // store received information
629  if (request >= 0 && response.length() > 0) {
630  try {
631  myJunctionControlBuilder.addLogicItem(request, response, foes, cont);
632  } catch (InvalidArgument& e) {
633  WRITE_ERROR(e.what());
634  }
635  }
636 }
637 
638 
639 void
641  if (myCurrentIsBroken) {
642  return;
643  }
644  bool ok = true;
645  // we either a have a junction or a legacy network with ROWLogic
646  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
647  if (ok) {
649  }
650 }
651 
652 
653 void
655  myAmInTLLogicMode = true;
656  bool ok = true;
657  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
658  TrafficLightType type;
659  std::string typeS = attrs.get<std::string>(SUMO_ATTR_TYPE, 0, ok);
660  if (SUMOXMLDefinitions::TrafficLightTypes.hasString(typeS)) {
662  } else {
663  WRITE_ERROR("Traffic light '" + id + "' has unknown type '" + typeS + "'");
664  return;
665  }
666  //
667  SUMOTime offset = attrs.getOptSUMOTimeReporting(SUMO_ATTR_OFFSET, id.c_str(), ok, 0);
668  if (!ok) {
669  return;
670  }
671  std::string programID = attrs.getOpt<std::string>(SUMO_ATTR_PROGRAMID, id.c_str(), ok, "<unknown>");
672  myJunctionControlBuilder.initTrafficLightLogic(id, programID, type, offset);
673 }
674 
675 
676 void
678  // try to get the phase definition
679  bool ok = true;
680  std::string state = attrs.get<std::string>(SUMO_ATTR_STATE, 0, ok);
681  if (!ok) {
682  return;
683  }
684  // try to get the phase duration
686  if (duration == 0) {
687  WRITE_ERROR("Duration of tls-logic '" + myJunctionControlBuilder.getActiveKey() + "/" + myJunctionControlBuilder.getActiveSubKey() + "' is zero.");
688  return;
689  }
690  // if the traffic light is an actuated traffic light, try to get
691  // the minimum and maximum durations
692  SUMOTime minDuration = attrs.getOptSUMOTimeReporting(
694  SUMOTime maxDuration = attrs.getOptSUMOTimeReporting(
696  myJunctionControlBuilder.addPhase(duration, state, minDuration, maxDuration);
697 }
698 
699 
700 void
702  bool ok = true;
703  // get the id, report an error if not given or empty...
704  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
705  if (!ok) {
706  return;
707  }
708  const SUMOTime frequency = attrs.getSUMOTimeReporting(SUMO_ATTR_FREQUENCY, id.c_str(), ok);
709  const SUMOReal position = attrs.get<SUMOReal>(SUMO_ATTR_POSITION, id.c_str(), ok);
710  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, id.c_str(), ok, false);
711  const bool splitByType = attrs.getOpt<bool>(SUMO_ATTR_SPLIT_VTYPE, id.c_str(), ok, false);
712  const std::string lane = attrs.get<std::string>(SUMO_ATTR_LANE, id.c_str(), ok);
713  const std::string file = attrs.get<std::string>(SUMO_ATTR_FILE, id.c_str(), ok);
714  if (!ok) {
715  return;
716  }
717  try {
718  myDetectorBuilder.buildInductLoop(id, lane, position, frequency,
720  friendlyPos, splitByType);
721  } catch (InvalidArgument& e) {
722  WRITE_ERROR(e.what());
723  } catch (IOError& e) {
724  WRITE_ERROR(e.what());
725  }
726 }
727 
728 
729 void
731  bool ok = true;
732  // get the id, report an error if not given or empty...
733  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
734  if (!ok) {
735  return;
736  }
737  const SUMOReal position = attrs.get<SUMOReal>(SUMO_ATTR_POSITION, id.c_str(), ok);
738  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, id.c_str(), ok, false);
739  const std::string lane = attrs.get<std::string>(SUMO_ATTR_LANE, id.c_str(), ok);
740  const std::string file = attrs.get<std::string>(SUMO_ATTR_FILE, id.c_str(), ok);
741  if (!ok) {
742  return;
743  }
744  try {
745  myDetectorBuilder.buildInstantInductLoop(id, lane, position, FileHelpers::checkForRelativity(file, getFileName()), friendlyPos);
746  } catch (InvalidArgument& e) {
747  WRITE_ERROR(e.what());
748  } catch (IOError& e) {
749  WRITE_ERROR(e.what());
750  }
751 }
752 
753 
754 void
756  bool ok = true;
757  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
758  SUMOTime frequency = attrs.getSUMOTimeReporting(SUMO_ATTR_FREQUENCY, id.c_str(), ok);
759  std::string type = attrs.getStringSecure(SUMO_ATTR_TYPE, "");
760  std::string file = attrs.get<std::string>(SUMO_ATTR_FILE, id.c_str(), ok);
761  if (!ok) {
762  return;
763  }
764  try {
766  } catch (InvalidArgument& e) {
767  WRITE_ERROR(e.what());
768  } catch (IOError& e) {
769  WRITE_ERROR(e.what());
770  }
771 }
772 
773 
774 void
776  bool ok = true;
777  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
778  SUMOTime frequency = attrs.getSUMOTimeReporting(SUMO_ATTR_FREQUENCY, id.c_str(), ok);
779  SUMOTime begin = attrs.getOptSUMOTimeReporting(SUMO_ATTR_BEGIN, id.c_str(), ok, -1);
780  std::string edge = attrs.get<std::string>(SUMO_ATTR_EDGE, id.c_str(), ok);
781  std::string file = attrs.get<std::string>(SUMO_ATTR_FILE, id.c_str(), ok);
782  if (!ok) {
783  return;
784  }
785  try {
786  myDetectorBuilder.buildRouteProbe(id, edge, frequency, begin,
788  } catch (InvalidArgument& e) {
789  WRITE_ERROR(e.what());
790  } catch (IOError& e) {
791  WRITE_ERROR(e.what());
792  }
793 }
794 
795 
796 
797 void
799  // check whether this is a detector connected to a tls an optionally to a link
800  bool ok = true;
801  const std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
802  const std::string lsaid = attrs.getOpt<std::string>(SUMO_ATTR_TLID, id.c_str(), ok, "<invalid>");
803  const std::string toLane = attrs.getOpt<std::string>(SUMO_ATTR_TO, id.c_str(), ok, "<invalid>");
804  const SUMOTime haltingTimeThreshold = attrs.getOptSUMOTimeReporting(SUMO_ATTR_HALTING_TIME_THRESHOLD, id.c_str(), ok, TIME2STEPS(1));
805  const SUMOReal haltingSpeedThreshold = attrs.getOpt<SUMOReal>(SUMO_ATTR_HALTING_SPEED_THRESHOLD, id.c_str(), ok, 5.0f / 3.6f);
806  const SUMOReal jamDistThreshold = attrs.getOpt<SUMOReal>(SUMO_ATTR_JAM_DIST_THRESHOLD, id.c_str(), ok, 10.0f);
807  const SUMOReal position = attrs.get<SUMOReal>(SUMO_ATTR_POSITION, id.c_str(), ok);
808  const SUMOReal length = attrs.get<SUMOReal>(SUMO_ATTR_LENGTH, id.c_str(), ok);
809  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, id.c_str(), ok, false);
810  const bool cont = attrs.getOpt<bool>(SUMO_ATTR_CONT, id.c_str(), ok, false);
811  const std::string lane = attrs.get<std::string>(SUMO_ATTR_LANE, id.c_str(), ok);
812  const std::string file = attrs.get<std::string>(SUMO_ATTR_FILE, id.c_str(), ok);
813  if (!ok) {
814  return;
815  }
816  try {
817  if (lsaid != "<invalid>") {
818  if (toLane == "<invalid>") {
819  myDetectorBuilder.buildE2Detector(id, lane, position, length, cont,
822  haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold,
823  friendlyPos);
824  } else {
825  myDetectorBuilder.buildE2Detector(id, lane, position, length, cont,
826  myJunctionControlBuilder.getTLLogic(lsaid), toLane,
828  haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold,
829  friendlyPos);
830  }
831  } else {
832  bool ok = true;
833  SUMOTime frequency = attrs.getSUMOTimeReporting(SUMO_ATTR_FREQUENCY, id.c_str(), ok);
834  if (!ok) {
835  return;
836  }
837  myDetectorBuilder.buildE2Detector(id, lane, position, length, cont, frequency,
839  haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold,
840  friendlyPos);
841  }
842  } catch (InvalidArgument& e) {
843  WRITE_ERROR(e.what());
844  } catch (IOError& e) {
845  WRITE_ERROR(e.what());
846  }
847 }
848 
849 
850 void
852  bool ok = true;
853  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
854  const SUMOTime frequency = attrs.getSUMOTimeReporting(SUMO_ATTR_FREQUENCY, id.c_str(), ok);
855  const SUMOTime haltingTimeThreshold = attrs.getOptSUMOTimeReporting(SUMO_ATTR_HALTING_TIME_THRESHOLD, id.c_str(), ok, TIME2STEPS(1));
856  const SUMOReal haltingSpeedThreshold = attrs.getOpt<SUMOReal>(SUMO_ATTR_HALTING_SPEED_THRESHOLD, id.c_str(), ok, 5.0f / 3.6f);
857  const std::string file = attrs.get<std::string>(SUMO_ATTR_FILE, id.c_str(), ok);
858  if (!ok) {
859  return;
860  }
861  try {
864  frequency, haltingSpeedThreshold, haltingTimeThreshold);
865  } catch (InvalidArgument& e) {
866  WRITE_ERROR(e.what());
867  } catch (IOError& e) {
868  WRITE_ERROR(e.what());
869  }
870 }
871 
872 
873 void
875  bool ok = true;
876  const SUMOReal position = attrs.get<SUMOReal>(SUMO_ATTR_POSITION, myDetectorBuilder.getCurrentE3ID().c_str(), ok);
877  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, myDetectorBuilder.getCurrentE3ID().c_str(), ok, false);
878  const std::string lane = attrs.get<std::string>(SUMO_ATTR_LANE, myDetectorBuilder.getCurrentE3ID().c_str(), ok);
879  if (!ok) {
880  return;
881  }
882  myDetectorBuilder.addE3Entry(lane, position, friendlyPos);
883 }
884 
885 
886 void
888  bool ok = true;
889  const SUMOReal position = attrs.get<SUMOReal>(SUMO_ATTR_POSITION, myDetectorBuilder.getCurrentE3ID().c_str(), ok);
890  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, myDetectorBuilder.getCurrentE3ID().c_str(), ok, false);
891  const std::string lane = attrs.get<std::string>(SUMO_ATTR_LANE, myDetectorBuilder.getCurrentE3ID().c_str(), ok);
892  if (!ok) {
893  return;
894  }
895  myDetectorBuilder.addE3Exit(lane, position, friendlyPos);
896 }
897 
898 
899 void
900 NLHandler::addEdgeLaneMeanData(const SUMOSAXAttributes& attrs, int objecttype) {
901  bool ok = true;
902  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
903  const SUMOReal maxTravelTime = attrs.getOpt<SUMOReal>(SUMO_ATTR_MAX_TRAVELTIME, id.c_str(), ok, 100000);
904  const SUMOReal minSamples = attrs.getOpt<SUMOReal>(SUMO_ATTR_MIN_SAMPLES, id.c_str(), ok, 0);
905  const SUMOReal haltingSpeedThreshold = attrs.getOpt<SUMOReal>(SUMO_ATTR_HALTING_SPEED_THRESHOLD, id.c_str(), ok, POSITION_EPS);
906  const std::string excludeEmpty = attrs.getOpt<std::string>(SUMO_ATTR_EXCLUDE_EMPTY, id.c_str(), ok, "false");
907  const bool withInternal = attrs.getOpt<bool>(SUMO_ATTR_WITH_INTERNAL, id.c_str(), ok, false);
908  const bool trackVehicles = attrs.getOpt<bool>(SUMO_ATTR_TRACK_VEHICLES, id.c_str(), ok, false);
909  const std::string file = attrs.get<std::string>(SUMO_ATTR_FILE, id.c_str(), ok);
910  const std::string type = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok, "performance");
911  std::string vtypes = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id.c_str(), ok, "");
912  const SUMOTime frequency = attrs.getOptSUMOTimeReporting(SUMO_ATTR_FREQUENCY, id.c_str(), ok, -1);
913  const SUMOTime begin = attrs.getOptSUMOTimeReporting(SUMO_ATTR_BEGIN, id.c_str(), ok, string2time(OptionsCont::getOptions().getString("begin")));
914  const SUMOTime end = attrs.getOptSUMOTimeReporting(SUMO_ATTR_END, id.c_str(), ok, string2time(OptionsCont::getOptions().getString("end")));
915  if (!ok) {
916  return;
917  }
918  try {
919  myDetectorBuilder.createEdgeLaneMeanData(id, frequency, begin, end,
920  type, objecttype == SUMO_TAG_MEANDATA_LANE,
921  // equivalent to TplConvert::_2bool used in SUMOSAXAttributes::getBool
922  excludeEmpty[0] != 't' && excludeEmpty[0] != 'T' && excludeEmpty[0] != '1' && excludeEmpty[0] != 'x',
923  excludeEmpty == "defaults", withInternal, trackVehicles,
924  maxTravelTime, minSamples, haltingSpeedThreshold, vtypes,
926  } catch (InvalidArgument& e) {
927  WRITE_ERROR(e.what());
928  } catch (IOError& e) {
929  WRITE_ERROR(e.what());
930  }
931 }
932 
933 
934 void
936  bool ok = true;
937  std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, 0, ok);
938  if (!MSGlobals::gUsingInternalLanes && fromID[0] == ':') {
939  return;
940  }
941 
942  try {
943  bool ok = true;
944  const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, 0, ok);
945  const int fromLaneIdx = attrs.get<int>(SUMO_ATTR_FROM_LANE, 0, ok);
946  const int toLaneIdx = attrs.get<int>(SUMO_ATTR_TO_LANE, 0, ok);
947  LinkDirection dir = parseLinkDir(attrs.get<std::string>(SUMO_ATTR_DIR, 0, ok));
948  LinkState state = parseLinkState(attrs.get<std::string>(SUMO_ATTR_STATE, 0, ok));
949  std::string tlID = attrs.getOpt<std::string>(SUMO_ATTR_TLID, 0, ok, "");
950 #ifdef HAVE_INTERNAL_LANES
951  std::string viaID = attrs.getOpt<std::string>(SUMO_ATTR_VIA, 0, ok, "");
952 #endif
953 
954  MSEdge* from = MSEdge::dictionary(fromID);
955  if (from == 0) {
956  WRITE_ERROR("Unknown from-edge '" + fromID + "' in connection");
957  return;
958  }
959  MSEdge* to = MSEdge::dictionary(toID);
960  if (to == 0) {
961  WRITE_ERROR("Unknown to-edge '" + toID + "' in connection");
962  return;
963  }
964  if (fromLaneIdx < 0 || static_cast<unsigned int>(fromLaneIdx) >= from->getLanes().size() ||
965  toLaneIdx < 0 || static_cast<unsigned int>(toLaneIdx) >= to->getLanes().size()) {
966  WRITE_ERROR("Invalid lane index in connection from '" + from->getID() + "' to '" + to->getID() + "'.");
967  return;
968  }
969  MSLane* fromLane = from->getLanes()[fromLaneIdx];
970  MSLane* toLane = to->getLanes()[toLaneIdx];
971  assert(fromLane);
972  assert(toLane);
973 
974  int tlLinkIdx = -1;
975  if (tlID != "") {
976  tlLinkIdx = attrs.get<int>(SUMO_ATTR_TLLINKINDEX, 0, ok);
977  // make sure that the index is in range
979  if (tlLinkIdx < 0 || tlLinkIdx >= (int)logic->getCurrentPhaseDef().getState().size()) {
980  WRITE_ERROR("Invalid " + toString(SUMO_ATTR_TLLINKINDEX) + " '" + toString(tlLinkIdx) +
981  "' in connection controlled by '" + tlID + "'");
982  return;
983  }
984  if (!ok) {
985  return;
986  }
987  }
988  SUMOReal length = fromLane->getShape()[-1].distanceTo(toLane->getShape()[0]);
989  MSLink* link = 0;
990 
991  // build the link
992 #ifdef HAVE_INTERNAL_LANES
993  MSLane* via = 0;
994  if (viaID != "" && MSGlobals::gUsingInternalLanes) {
995  via = MSLane::dictionary(viaID);
996  if (via == 0) {
997  WRITE_ERROR("An unknown lane ('" + viaID +
998  "') should be set as a via-lane for lane '" + toLane->getID() + "'.");
999  return;
1000  }
1001  length = via->getLength();
1002  }
1003  link = new MSLink(toLane, via, dir, state, length);
1004  if (via != 0) {
1005  via->addIncomingLane(fromLane, link);
1006  } else {
1007  toLane->addIncomingLane(fromLane, link);
1008  }
1009 #else
1010  link = new MSLink(toLane, dir, state, length);
1011  toLane->addIncomingLane(fromLane, link);
1012 #endif
1013  toLane->addApproachingLane(fromLane);
1014 
1015  // if a traffic light is responsible for it, inform the traffic light
1016  // check whether this link is controlled by a traffic light
1017  if (tlID != "") {
1018  myJunctionControlBuilder.getTLLogic(tlID).addLink(link, fromLane, tlLinkIdx);
1019  }
1020  // add the link
1021  fromLane->addLink(link);
1022 
1023  } catch (InvalidArgument& e) {
1024  WRITE_ERROR(e.what());
1025  }
1026 }
1027 
1028 
1030 NLHandler::parseLinkDir(const std::string& dir) {
1031  if (SUMOXMLDefinitions::LinkDirections.hasString(dir)) {
1033  } else {
1034  throw InvalidArgument("Unrecognised link direction '" + dir + "'.");
1035  }
1036 }
1037 
1038 
1039 LinkState
1040 NLHandler::parseLinkState(const std::string& state) {
1041  if (SUMOXMLDefinitions::LinkStates.hasString(state)) {
1042  return SUMOXMLDefinitions::LinkStates.get(state);
1043  } else {
1044  if (state == "t") { // legacy networks
1045  // WRITE_WARNING("Obsolete link state 't'. Use 'o' instead");
1047  } else {
1048  throw InvalidArgument("Unrecognised link state '" + state + "'.");
1049  }
1050  }
1051 }
1052 
1053 
1054 // ----------------------------------
1055 void
1057  bool ok = true;
1059  Boundary convBoundary = attrs.get<Boundary>(SUMO_ATTR_CONV_BOUNDARY, 0, ok);
1060  Boundary origBoundary = attrs.get<Boundary>(SUMO_ATTR_ORIG_BOUNDARY, 0, ok);
1061  std::string proj = attrs.get<std::string>(SUMO_ATTR_ORIG_PROJ, 0, ok);
1062  if (ok) {
1063  Position networkOffset = s[0];
1064  GeoConvHelper::init(proj, networkOffset, origBoundary, convBoundary);
1065  if (OptionsCont::getOptions().getBool("fcd-output.geo") && !GeoConvHelper::getFinal().usingGeoProjection()) {
1066  WRITE_WARNING("no valid geo projection loaded from network. fcd-output.geo will not work");
1067  }
1068  }
1069 }
1070 
1071 
1072 void
1074  bool ok = true;
1075  myCurrentIsBroken = false;
1076  // get the id, report an error if not given or empty...
1077  myCurrentDistrictID = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
1078  if (!ok) {
1079  myCurrentIsBroken = true;
1080  return;
1081  }
1082  try {
1084  if (!MSEdge::dictionary(myCurrentDistrictID + "-sink", sink)) {
1085  delete sink;
1086  throw InvalidArgument("Another edge with the id '" + myCurrentDistrictID + "-sink' exists.");
1087  }
1088  sink->initialize(new std::vector<MSLane*>());
1090  if (!MSEdge::dictionary(myCurrentDistrictID + "-source", source)) {
1091  delete source;
1092  throw InvalidArgument("Another edge with the id '" + myCurrentDistrictID + "-source' exists.");
1093  }
1094  source->initialize(new std::vector<MSLane*>());
1095  if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
1096  std::vector<std::string> desc = attrs.getStringVector(SUMO_ATTR_EDGES);
1097  for (std::vector<std::string>::const_iterator i = desc.begin(); i != desc.end(); ++i) {
1098  MSEdge* edge = MSEdge::dictionary(*i);
1099  // check whether the edge exists
1100  if (edge == 0) {
1101  throw InvalidArgument("The edge '" + *i + "' within district '" + myCurrentDistrictID + "' is not known.");
1102  }
1103  source->addFollower(edge);
1104  edge->addFollower(sink);
1105  }
1106  }
1107  } catch (InvalidArgument& e) {
1108  WRITE_ERROR(e.what());
1109  myCurrentIsBroken = true;
1110  }
1111 }
1112 
1113 
1114 void
1115 NLHandler::addDistrictEdge(const SUMOSAXAttributes& attrs, bool isSource) {
1116  if (myCurrentIsBroken) {
1117  // earlier error
1118  return;
1119  }
1120  bool ok = true;
1121  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, myCurrentDistrictID.c_str(), ok);
1122  MSEdge* succ = MSEdge::dictionary(id);
1123  if (succ != 0) {
1124  // connect edge
1125  if (isSource) {
1126  MSEdge::dictionary(myCurrentDistrictID + "-source")->addFollower(succ);
1127  } else {
1128  succ->addFollower(MSEdge::dictionary(myCurrentDistrictID + "-sink"));
1129  }
1130  } else {
1131  WRITE_ERROR("At district '" + myCurrentDistrictID + "': succeeding edge '" + id + "' does not exist.");
1132  }
1133 }
1134 
1135 
1136 // ----------------------------------
1137 void
1139  try {
1141  } catch (InvalidArgument& e) {
1142  WRITE_ERROR(e.what());
1143  }
1144 }
1145 
1146 
1147 void
1149  if (!myCurrentIsBroken) {
1150  try {
1152  } catch (InvalidArgument& e) {
1153  WRITE_ERROR(e.what());
1154  myCurrentIsBroken = true;
1155  }
1156  }
1157  myCurrentWAUTID = "";
1158 }
1159 
1160 
1161 /****************************************************************************/