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