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-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>
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  case SUMO_TAG_CALIBRATOR:
160  break;
161  case SUMO_TAG_REROUTER:
163  break;
164  case SUMO_TAG_BUS_STOP:
166  break;
167  case SUMO_TAG_VTYPEPROBE:
168  addVTypeProbeDetector(attrs);
169  break;
170  case SUMO_TAG_ROUTEPROBE:
171  addRouteProbeDetector(attrs);
172  break;
175  break;
178  break;
179  case SUMO_TAG_TIMEDEVENT:
181  break;
182  case SUMO_TAG_VAPORIZER:
184  break;
185  case SUMO_TAG_LOCATION:
186  setLocation(attrs);
187  break;
188  case SUMO_TAG_TAZ:
189  addDistrict(attrs);
190  break;
191  case SUMO_TAG_TAZSOURCE:
192  addDistrictEdge(attrs, true);
193  break;
194  case SUMO_TAG_TAZSINK:
195  addDistrictEdge(attrs, false);
196  break;
197  default:
198  break;
199  }
200  } catch (InvalidArgument& e) {
201  WRITE_ERROR(e.what());
202  }
203  MSRouteHandler::myStartElement(element, attrs);
204  if (element == SUMO_TAG_PARAM) {
205  addParam(attrs);
206  }
207 }
208 
209 
210 void
212  switch (element) {
213  case SUMO_TAG_EDGE:
214  closeEdge();
215  break;
216  case SUMO_TAG_JUNCTION:
217  if (!myCurrentIsBroken) {
218  try {
221  } catch (InvalidArgument& e) {
222  WRITE_ERROR(e.what());
223  }
224  }
225  break;
226  case SUMO_TAG_TLLOGIC:
227  try {
229  } catch (InvalidArgument& e) {
230  WRITE_ERROR(e.what());
231  }
232  myAmInTLLogicMode = false;
233  break;
234  case SUMO_TAG_WAUT:
235  closeWAUT();
236  break;
237  case SUMO_TAG_E3DETECTOR:
239  endE3Detector();
240  break;
241  case SUMO_TAG_NET:
243  break;
244  default:
245  break;
246  }
248  if (element != SUMO_TAG_PARAM) {
250  }
251 }
252 
253 
254 
255 // ---- the root/edge - element
256 void
258  bool ok = true;
259  myCurrentIsBroken = false;
260  // get the id, report an error if not given or empty...
261  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
262  if (!ok) {
263  myCurrentIsBroken = true;
264  return;
265  }
266  // omit internal edges if not wished
267  if (!MSGlobals::gUsingInternalLanes && id[0] == ':') {
269  return;
270  }
272  // parse the function
273  const SumoXMLEdgeFunc func = attrs.getEdgeFunc(ok);
274  if (!ok) {
275  WRITE_ERROR("Edge '" + id + "' has an invalid type.");
276  myCurrentIsBroken = true;
277  return;
278  }
279  // interpret the function
281  switch (func) {
282  case EDGEFUNC_NORMAL:
283  funcEnum = MSEdge::EDGEFUNCTION_NORMAL;
284  break;
285  case EDGEFUNC_CONNECTOR:
286  case EDGEFUNC_SINK:
287  case EDGEFUNC_SOURCE:
289  break;
290  case EDGEFUNC_INTERNAL:
292  break;
293  }
294  // get the street name
295  std::string streetName = attrs.getOpt<std::string>(SUMO_ATTR_NAME, id.c_str(), ok, "");
296  if (!ok) {
297  myCurrentIsBroken = true;
298  return;
299  }
300  //
301  try {
302  myEdgeControlBuilder.beginEdgeParsing(id, funcEnum, streetName);
303  } catch (InvalidArgument& e) {
304  WRITE_ERROR(e.what());
305  myCurrentIsBroken = true;
306  }
307 }
308 
309 
310 void
312  // omit internal edges if not wished and broken edges
314  return;
315  }
316  try {
318  MSEdge::dictionary(e->getID(), e);
319  } catch (InvalidArgument& e) {
320  WRITE_ERROR(e.what());
321  }
322 }
323 
324 
325 // ---- the root/edge/lanes/lane - element
326 void
328  // omit internal edges if not wished and broken edges
330  return;
331  }
332  bool ok = true;
333  // get the id, report an error if not given or empty...
334  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
335  if (!ok) {
336  myCurrentIsBroken = true;
337  return;
338  }
339  SUMOReal maxSpeed = attrs.get<SUMOReal>(SUMO_ATTR_SPEED, id.c_str(), ok);
340  SUMOReal length = attrs.get<SUMOReal>(SUMO_ATTR_LENGTH, id.c_str(), ok);
341  std::string allow;
342  try {
343  bool dummy;
344  allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, id.c_str(), dummy, "", false);
345  } catch (EmptyData e) {
346  // !!! deprecated
347  }
348  std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, id.c_str(), ok, "");
349  SUMOReal width = attrs.getOpt<SUMOReal>(SUMO_ATTR_WIDTH, id.c_str(), ok, SUMO_const_laneWidth);
350  PositionVector shape = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok);
351  if (shape.size() < 2) {
352  WRITE_ERROR("Shape of lane '" + id + "' is broken.\n Can not build according edge.");
353  myCurrentIsBroken = true;
354  return;
355  }
356  SVCPermissions permissions = parseVehicleClasses(allow, disallow);
357  myCurrentIsBroken |= !ok;
358  if (!myCurrentIsBroken) {
359  try {
360  MSLane* lane = myEdgeControlBuilder.addLane(id, maxSpeed, length, shape, width, permissions);
361  // insert the lane into the lane-dictionary, checking
362  if (!MSLane::dictionary(id, lane)) {
363  delete lane;
364  WRITE_ERROR("Another lane with the id '" + id + "' exists.");
365  myCurrentIsBroken = true;
366  }
367  myLastParameterised = lane;
368  } catch (InvalidArgument& e) {
369  WRITE_ERROR(e.what());
370  }
371  }
372 }
373 
374 
375 // ---- the root/junction - element
376 void
378  myCurrentIsBroken = false;
379  bool ok = true;
380  // get the id, report an error if not given or empty...
381  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
382  if (!ok) {
383  myCurrentIsBroken = true;
384  return;
385  }
386  PositionVector shape;
387  if (attrs.hasAttribute(SUMO_ATTR_SHAPE)) {
388  // inner junctions have no shape
389  shape = attrs.getOpt<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok, PositionVector());
390  }
391  SUMOReal x = attrs.get<SUMOReal>(SUMO_ATTR_X, id.c_str(), ok);
392  SUMOReal y = attrs.get<SUMOReal>(SUMO_ATTR_Y, id.c_str(), ok);
393  bool typeOK = true;
394  SumoXMLNodeType type = attrs.getNodeType(typeOK);
395  if (!typeOK) {
396  WRITE_ERROR("An unknown or invalid junction type occured in junction '" + id + "'.");
397  ok = false;
398  }
399  std::string key = attrs.getOpt<std::string>(SUMO_ATTR_KEY, id.c_str(), ok, "");
400  // incoming lanes
401  std::vector<MSLane*> incomingLanes;
402  parseLanes(id, attrs.getStringSecure(SUMO_ATTR_INCLANES, ""), incomingLanes, ok);
403  // internal lanes
404  std::vector<MSLane*> internalLanes;
405 #ifdef HAVE_INTERNAL_LANES
407  parseLanes(id, attrs.getStringSecure(SUMO_ATTR_INTLANES, ""), internalLanes, ok);
408  }
409 #endif
410  if (!ok) {
411  myCurrentIsBroken = true;
412  } else {
413  try {
414  myJunctionControlBuilder.openJunction(id, key, type, x, y, shape, incomingLanes, internalLanes);
415  } catch (InvalidArgument& e) {
416  WRITE_ERROR(e.what() + std::string("\n Can not build according junction."));
417  myCurrentIsBroken = true;
418  }
419  }
420 }
421 
422 
423 void
424 NLHandler::parseLanes(const std::string& junctionID,
425  const std::string& def, std::vector<MSLane*>& into, bool& ok) {
426  StringTokenizer st(def);
427  while (ok && st.hasNext()) {
428  std::string laneID = st.next();
429  MSLane* lane = MSLane::dictionary(laneID);
430  if (!MSGlobals::gUsingInternalLanes && laneID[0] == ':') {
431  continue;
432  }
433  if (lane == 0) {
434  WRITE_ERROR("An unknown lane ('" + laneID + "') was tried to be set as incoming to junction '" + junctionID + "'.");
435  ok = false;
436  continue;
437  }
438  into.push_back(lane);
439  }
440 }
441 // ----
442 
443 void
445  bool ok = true;
446  std::string key = attrs.get<std::string>(SUMO_ATTR_KEY, 0, ok);
447  std::string val = attrs.get<std::string>(SUMO_ATTR_VALUE, 0, ok);
448  if (myLastParameterised != 0) {
450  }
451  // set
452  if (ok && myAmInTLLogicMode) {
453  assert(key != "");
454  assert(val != "");
456  }
457 }
458 
459 
460 void
462  myCurrentIsBroken = false;
463  bool ok = true;
464  // get the id, report an error if not given or empty...
465  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
466  if (!ok) {
467  myCurrentIsBroken = true;
468  return;
469  }
470  SUMOTime t = attrs.getOptSUMOTimeReporting(SUMO_ATTR_REF_TIME, id.c_str(), ok, 0);
471  std::string pro = attrs.get<std::string>(SUMO_ATTR_START_PROG, id.c_str(), ok);
472  if (!ok) {
473  myCurrentIsBroken = true;
474  }
475  if (!myCurrentIsBroken) {
476  myCurrentWAUTID = id;
477  try {
479  } catch (InvalidArgument& e) {
480  WRITE_ERROR(e.what());
481  myCurrentIsBroken = true;
482  }
483  }
484 }
485 
486 
487 void
489  bool ok = true;
491  std::string to = attrs.get<std::string>(SUMO_ATTR_TO, myCurrentWAUTID.c_str(), ok);
492  if (!ok) {
493  myCurrentIsBroken = true;
494  }
495  if (!myCurrentIsBroken) {
496  try {
498  } catch (InvalidArgument& e) {
499  WRITE_ERROR(e.what());
500  myCurrentIsBroken = true;
501  }
502  }
503 }
504 
505 
506 void
508  bool ok = true;
509  std::string wautID = attrs.get<std::string>(SUMO_ATTR_WAUT_ID, 0, ok);
510  std::string junctionID = attrs.get<std::string>(SUMO_ATTR_JUNCTION_ID, 0, ok);
511  std::string procedure = attrs.getOpt<std::string>(SUMO_ATTR_PROCEDURE, 0, ok, "");
512  bool synchron = attrs.getOpt<bool>(SUMO_ATTR_SYNCHRON, 0, ok, false);
513  if (!ok) {
514  myCurrentIsBroken = true;
515  }
516  try {
517  if (!myCurrentIsBroken) {
518  myJunctionControlBuilder.getTLLogicControlToUse().addWAUTJunction(wautID, junctionID, procedure, synchron);
519  }
520  } catch (InvalidArgument& e) {
521  WRITE_ERROR(e.what());
522  myCurrentIsBroken = true;
523  }
524 }
525 
526 
527 
528 
529 
530 
531 
532 void
534  bool ok = true;
535  const SUMOReal INVALID_POSITION(-1000000);
536  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
537  SUMOReal x = attrs.getOpt<SUMOReal>(SUMO_ATTR_X, id.c_str(), ok, INVALID_POSITION);
538  SUMOReal y = attrs.getOpt<SUMOReal>(SUMO_ATTR_Y, id.c_str(), ok, INVALID_POSITION);
539  SUMOReal lon = attrs.getOpt<SUMOReal>(SUMO_ATTR_LON, id.c_str(), ok, INVALID_POSITION);
540  SUMOReal lat = attrs.getOpt<SUMOReal>(SUMO_ATTR_LAT, id.c_str(), ok, INVALID_POSITION);
541  SUMOReal lanePos = attrs.getOpt<SUMOReal>(SUMO_ATTR_POSITION, id.c_str(), ok, INVALID_POSITION);
542  SUMOReal layer = attrs.getOpt<SUMOReal>(SUMO_ATTR_LAYER, id.c_str(), ok, (SUMOReal)GLO_POI);
543  std::string type = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok, "");
544  std::string laneID = attrs.getOpt<std::string>(SUMO_ATTR_LANE, id.c_str(), ok, "");
545  RGBColor color = attrs.hasAttribute(SUMO_ATTR_COLOR) ? attrs.get<RGBColor>(SUMO_ATTR_COLOR, id.c_str(), ok) : RGBColor::RED;
546  SUMOReal angle = attrs.getOpt<SUMOReal>(SUMO_ATTR_ANGLE, id.c_str(), ok, Shape::DEFAULT_ANGLE);
547  std::string imgFile = attrs.getOpt<std::string>(SUMO_ATTR_IMGFILE, id.c_str(), ok, Shape::DEFAULT_IMG_FILE);
548  if (imgFile != "" && !FileHelpers::isAbsolute(imgFile)) {
550  }
551  SUMOReal width = attrs.getOpt<SUMOReal>(SUMO_ATTR_WIDTH, id.c_str(), ok, Shape::DEFAULT_IMG_WIDTH);
552  SUMOReal height = attrs.getOpt<SUMOReal>(SUMO_ATTR_HEIGHT, id.c_str(), ok, Shape::DEFAULT_IMG_HEIGHT);
553  if (!ok) {
554  return;
555  }
556  Position pos(x, y);
557  if (x == INVALID_POSITION || y == INVALID_POSITION) {
558  // try computing x,y from lane,pos
559  if (laneID != "") {
560  MSLane* lane = MSLane::dictionary(laneID);
561  if (lane == 0) {
562  WRITE_ERROR("Lane '" + laneID + "' to place a poi '" + id + "'on is not known.");
563  return;
564  }
565  if (lanePos < 0) {
566  lanePos = lane->getLength() + lanePos;
567  }
568  pos = lane->getShape().positionAtOffset(lanePos);
569  } else {
570  // try computing x,y from lon,lat
571  if (lat == INVALID_POSITION || lon == INVALID_POSITION) {
572  WRITE_ERROR("Either (x,y), (lon,lat) or (lane,pos) must be specified for poi '" + id + "'.");
573  return;
574  } else if (!GeoConvHelper::getFinal().usingGeoProjection()) {
575  WRITE_ERROR("(lon, lat) is specified for poi '" + id + "' but no geo-conversion is specified for the network.");
576  return;
577  }
578  pos.set(lon, lat);
580  }
581  }
582  if (!myNet.getShapeContainer().addPOI(id, type, color, layer, angle, imgFile, pos, width, height)) {
583  WRITE_ERROR("PoI '" + id + "' already exists.");
584  }
585 }
586 
587 
588 void
590  bool ok = true;
591  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
592  // get the id, report an error if not given or empty...
593  if (!ok) {
594  return;
595  }
596  SUMOReal layer = attrs.getOpt<SUMOReal>(SUMO_ATTR_LAYER, id.c_str(), ok, (SUMOReal)GLO_POLYGON);
597  bool fill = attrs.getOpt<bool>(SUMO_ATTR_FILL, id.c_str(), ok, false);
598  std::string type = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok, "");
599  std::string colorStr = attrs.get<std::string>(SUMO_ATTR_COLOR, id.c_str(), ok);
600  RGBColor color = attrs.get<RGBColor>(SUMO_ATTR_COLOR, id.c_str(), ok);
601  PositionVector shape = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok);
602  SUMOReal angle = attrs.getOpt<SUMOReal>(SUMO_ATTR_ANGLE, id.c_str(), ok, Shape::DEFAULT_ANGLE);
603  std::string imgFile = attrs.getOpt<std::string>(SUMO_ATTR_IMGFILE, id.c_str(), ok, Shape::DEFAULT_IMG_FILE);
604  if (imgFile != "" && !FileHelpers::isAbsolute(imgFile)) {
606  }
607  if (shape.size() != 0) {
608  if (!myNet.getShapeContainer().addPolygon(id, type, color, layer, angle, imgFile, shape, fill)) {
609  WRITE_ERROR("Polygon '" + id + "' already exists.");
610  }
611  }
612 }
613 
614 
615 void
617  if (myCurrentIsBroken) {
618  return;
619  }
620  bool ok = true;
621  int request = attrs.get<int>(SUMO_ATTR_INDEX, 0, ok);
622  bool cont = false;
623 #ifdef HAVE_INTERNAL_LANES
624  cont = attrs.getOpt<bool>(SUMO_ATTR_CONT, 0, ok, false);
625 #endif
626  std::string response = attrs.get<std::string>(SUMO_ATTR_RESPONSE, 0, ok);
627  std::string foes = attrs.get<std::string>(SUMO_ATTR_FOES, 0, ok);
628  if (!ok) {
629  return;
630  }
631  // store received information
632  if (request >= 0 && response.length() > 0) {
633  try {
634  myJunctionControlBuilder.addLogicItem(request, response, foes, cont);
635  } catch (InvalidArgument& e) {
636  WRITE_ERROR(e.what());
637  }
638  }
639 }
640 
641 
642 void
644  if (myCurrentIsBroken) {
645  return;
646  }
647  bool ok = true;
648  // we either a have a junction or a legacy network with ROWLogic
649  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
650  if (ok) {
652  }
653 }
654 
655 
656 void
658  myAmInTLLogicMode = true;
659  bool ok = true;
660  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
661  TrafficLightType type;
662  std::string typeS = attrs.get<std::string>(SUMO_ATTR_TYPE, 0, ok);
663  if (SUMOXMLDefinitions::TrafficLightTypes.hasString(typeS)) {
665  } else {
666  WRITE_ERROR("Traffic light '" + id + "' has unknown type '" + typeS + "'");
667  return;
668  }
669  //
670  SUMOTime offset = attrs.getOptSUMOTimeReporting(SUMO_ATTR_OFFSET, id.c_str(), ok, 0);
671  if (!ok) {
672  return;
673  }
674  std::string programID = attrs.getOpt<std::string>(SUMO_ATTR_PROGRAMID, id.c_str(), ok, "<unknown>");
675  myJunctionControlBuilder.initTrafficLightLogic(id, programID, type, offset);
676 }
677 
678 
679 void
681  // try to get the phase definition
682  bool ok = true;
683  std::string state = attrs.get<std::string>(SUMO_ATTR_STATE, 0, ok);
684  if (!ok) {
685  return;
686  }
687  // try to get the phase duration
689  if (duration == 0) {
690  WRITE_ERROR("Duration of tls-logic '" + myJunctionControlBuilder.getActiveKey() + "/" + myJunctionControlBuilder.getActiveSubKey() + "' is zero.");
691  return;
692  }
693  // if the traffic light is an actuated traffic light, try to get
694  // the minimum and maximum durations
695  SUMOTime minDuration = attrs.getOptSUMOTimeReporting(
697  SUMOTime maxDuration = attrs.getOptSUMOTimeReporting(
699  myJunctionControlBuilder.addPhase(duration, state, minDuration, maxDuration);
700 }
701 
702 
703 #ifdef _MESSAGES
704 void
705 NLHandler::addMsgEmitter(const SUMOSAXAttributes& attrs) {
706  bool ok = true;
707  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
708  std::string file = attrs.getOpt<std::string>(SUMO_ATTR_FILE, 0, ok, "");
709  // if no file given, use stdout
710  if (file == "") {
711  file = "-";
712  }
713  SUMOTime step = attrs.getOptSUMOTimeReporting(SUMO_ATTR_STEP, id.c_str(), ok, 1);
714  bool reverse = attrs.getOpt<bool>(SUMO_ATTR_REVERSE, 0, ok, false);
715  bool table = attrs.getOpt<bool>(SUMO_ATTR_TABLE, 0, ok, false);
716  bool xycoord = attrs.getOpt<bool>(SUMO_ATTR_XY, 0, ok, false);
717  std::string whatemit = attrs.get<std::string>(SUMO_ATTR_EVENTS, 0, ok);
718  if (!ok) {
719  return;
720  }
721  myNet.createMsgEmitter(id, file, getFileName(), whatemit, reverse, table, xycoord, step);
722 }
723 #endif
724 
725 
726 void
728  bool ok = true;
729  // get the id, report an error if not given or empty...
730  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
731  if (!ok) {
732  return;
733  }
734  const SUMOTime frequency = attrs.getSUMOTimeReporting(SUMO_ATTR_FREQUENCY, id.c_str(), ok);
735  const SUMOReal position = attrs.get<SUMOReal>(SUMO_ATTR_POSITION, id.c_str(), ok);
736  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, id.c_str(), ok, false);
737  const bool splitByType = attrs.getOpt<bool>(SUMO_ATTR_SPLIT_VTYPE, id.c_str(), ok, false);
738  const std::string lane = attrs.get<std::string>(SUMO_ATTR_LANE, id.c_str(), ok);
739  const std::string file = attrs.get<std::string>(SUMO_ATTR_FILE, id.c_str(), ok);
740  if (!ok) {
741  return;
742  }
743  try {
744  myDetectorBuilder.buildInductLoop(id, lane, position, frequency,
746  friendlyPos, splitByType);
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  // get the id, report an error if not given or empty...
759  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
760  if (!ok) {
761  return;
762  }
763  const SUMOReal position = attrs.get<SUMOReal>(SUMO_ATTR_POSITION, id.c_str(), ok);
764  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, id.c_str(), ok, false);
765  const std::string lane = attrs.get<std::string>(SUMO_ATTR_LANE, id.c_str(), ok);
766  const std::string file = attrs.get<std::string>(SUMO_ATTR_FILE, id.c_str(), ok);
767  if (!ok) {
768  return;
769  }
770  try {
771  myDetectorBuilder.buildInstantInductLoop(id, lane, position, FileHelpers::checkForRelativity(file, getFileName()), friendlyPos);
772  } catch (InvalidArgument& e) {
773  WRITE_ERROR(e.what());
774  } catch (IOError& e) {
775  WRITE_ERROR(e.what());
776  }
777 }
778 
779 
780 void
782  bool ok = true;
783  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
784  SUMOTime frequency = attrs.getSUMOTimeReporting(SUMO_ATTR_FREQUENCY, id.c_str(), ok);
785  std::string type = attrs.getStringSecure(SUMO_ATTR_TYPE, "");
786  std::string file = attrs.get<std::string>(SUMO_ATTR_FILE, id.c_str(), ok);
787  if (!ok) {
788  return;
789  }
790  try {
792  } catch (InvalidArgument& e) {
793  WRITE_ERROR(e.what());
794  } catch (IOError& e) {
795  WRITE_ERROR(e.what());
796  }
797 }
798 
799 
800 void
802  bool ok = true;
803  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
804  SUMOTime frequency = attrs.getSUMOTimeReporting(SUMO_ATTR_FREQUENCY, id.c_str(), ok);
805  SUMOTime begin = attrs.getOptSUMOTimeReporting(SUMO_ATTR_BEGIN, id.c_str(), ok, -1);
806  std::string edge = attrs.get<std::string>(SUMO_ATTR_EDGE, id.c_str(), ok);
807  std::string file = attrs.get<std::string>(SUMO_ATTR_FILE, id.c_str(), ok);
808  if (!ok) {
809  return;
810  }
811  try {
812  myDetectorBuilder.buildRouteProbe(id, edge, frequency, begin,
814  } catch (InvalidArgument& e) {
815  WRITE_ERROR(e.what());
816  } catch (IOError& e) {
817  WRITE_ERROR(e.what());
818  }
819 }
820 
821 
822 
823 void
825  // check whether this is a detector connected to a tls an optionally to a link
826  bool ok = true;
827  const std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
828  const std::string lsaid = attrs.getOpt<std::string>(SUMO_ATTR_TLID, id.c_str(), ok, "<invalid>");
829  const std::string toLane = attrs.getOpt<std::string>(SUMO_ATTR_TO, id.c_str(), ok, "<invalid>");
830  const SUMOTime haltingTimeThreshold = attrs.getOptSUMOTimeReporting(SUMO_ATTR_HALTING_TIME_THRESHOLD, id.c_str(), ok, TIME2STEPS(1));
831  const SUMOReal haltingSpeedThreshold = attrs.getOpt<SUMOReal>(SUMO_ATTR_HALTING_SPEED_THRESHOLD, id.c_str(), ok, 5.0f / 3.6f);
832  const SUMOReal jamDistThreshold = attrs.getOpt<SUMOReal>(SUMO_ATTR_JAM_DIST_THRESHOLD, id.c_str(), ok, 10.0f);
833  const SUMOReal position = attrs.get<SUMOReal>(SUMO_ATTR_POSITION, id.c_str(), ok);
834  const SUMOReal length = attrs.get<SUMOReal>(SUMO_ATTR_LENGTH, id.c_str(), ok);
835  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, id.c_str(), ok, false);
836  const bool cont = attrs.getOpt<bool>(SUMO_ATTR_CONT, id.c_str(), ok, false);
837  const std::string lane = attrs.get<std::string>(SUMO_ATTR_LANE, id.c_str(), ok);
838  const std::string file = attrs.get<std::string>(SUMO_ATTR_FILE, id.c_str(), ok);
839  if (!ok) {
840  return;
841  }
842  try {
843  if (lsaid != "<invalid>") {
844  if (toLane == "<invalid>") {
845  myDetectorBuilder.buildE2Detector(id, lane, position, length, cont,
848  haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold,
849  friendlyPos);
850  } else {
851  myDetectorBuilder.buildE2Detector(id, lane, position, length, cont,
852  myJunctionControlBuilder.getTLLogic(lsaid), toLane,
854  haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold,
855  friendlyPos);
856  }
857  } else {
858  bool ok = true;
859  SUMOTime frequency = attrs.getSUMOTimeReporting(SUMO_ATTR_FREQUENCY, id.c_str(), ok);
860  if (!ok) {
861  return;
862  }
863  myDetectorBuilder.buildE2Detector(id, lane, position, length, cont, frequency,
865  haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold,
866  friendlyPos);
867  }
868  } catch (InvalidArgument& e) {
869  WRITE_ERROR(e.what());
870  } catch (IOError& e) {
871  WRITE_ERROR(e.what());
872  }
873 }
874 
875 
876 void
878  bool ok = true;
879  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
880  const SUMOTime frequency = attrs.getSUMOTimeReporting(SUMO_ATTR_FREQUENCY, id.c_str(), ok);
881  const SUMOTime haltingTimeThreshold = attrs.getOptSUMOTimeReporting(SUMO_ATTR_HALTING_TIME_THRESHOLD, id.c_str(), ok, TIME2STEPS(1));
882  const SUMOReal haltingSpeedThreshold = attrs.getOpt<SUMOReal>(SUMO_ATTR_HALTING_SPEED_THRESHOLD, id.c_str(), ok, 5.0f / 3.6f);
883  const std::string file = attrs.get<std::string>(SUMO_ATTR_FILE, id.c_str(), ok);
884  if (!ok) {
885  return;
886  }
887  try {
890  frequency, haltingSpeedThreshold, haltingTimeThreshold);
891  } catch (InvalidArgument& e) {
892  WRITE_ERROR(e.what());
893  } catch (IOError& e) {
894  WRITE_ERROR(e.what());
895  }
896 }
897 
898 
899 void
901  bool ok = true;
902  const SUMOReal position = attrs.get<SUMOReal>(SUMO_ATTR_POSITION, myDetectorBuilder.getCurrentE3ID().c_str(), ok);
903  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, myDetectorBuilder.getCurrentE3ID().c_str(), ok, false);
904  const std::string lane = attrs.get<std::string>(SUMO_ATTR_LANE, myDetectorBuilder.getCurrentE3ID().c_str(), ok);
905  if (!ok) {
906  return;
907  }
908  myDetectorBuilder.addE3Entry(lane, position, friendlyPos);
909 }
910 
911 
912 void
914  bool ok = true;
915  const SUMOReal position = attrs.get<SUMOReal>(SUMO_ATTR_POSITION, myDetectorBuilder.getCurrentE3ID().c_str(), ok);
916  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, myDetectorBuilder.getCurrentE3ID().c_str(), ok, false);
917  const std::string lane = attrs.get<std::string>(SUMO_ATTR_LANE, myDetectorBuilder.getCurrentE3ID().c_str(), ok);
918  if (!ok) {
919  return;
920  }
921  myDetectorBuilder.addE3Exit(lane, position, friendlyPos);
922 }
923 
924 
925 void
926 NLHandler::addEdgeLaneMeanData(const SUMOSAXAttributes& attrs, int objecttype) {
927  bool ok = true;
928  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
929  const SUMOReal maxTravelTime = attrs.getOpt<SUMOReal>(SUMO_ATTR_MAX_TRAVELTIME, id.c_str(), ok, 100000);
930  const SUMOReal minSamples = attrs.getOpt<SUMOReal>(SUMO_ATTR_MIN_SAMPLES, id.c_str(), ok, 0);
931  const SUMOReal haltingSpeedThreshold = attrs.getOpt<SUMOReal>(SUMO_ATTR_HALTING_SPEED_THRESHOLD, id.c_str(), ok, POSITION_EPS);
932  const std::string excludeEmpty = attrs.getOpt<std::string>(SUMO_ATTR_EXCLUDE_EMPTY, id.c_str(), ok, "false");
933  const bool withInternal = attrs.getOpt<bool>(SUMO_ATTR_WITH_INTERNAL, id.c_str(), ok, false);
934  const bool trackVehicles = attrs.getOpt<bool>(SUMO_ATTR_TRACK_VEHICLES, id.c_str(), ok, false);
935  const std::string file = attrs.get<std::string>(SUMO_ATTR_FILE, id.c_str(), ok);
936  const std::string type = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok, "performance");
937  std::string vtypes = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id.c_str(), ok, "");
938  const SUMOTime frequency = attrs.getOptSUMOTimeReporting(SUMO_ATTR_FREQUENCY, id.c_str(), ok, -1);
939  const SUMOTime begin = attrs.getOptSUMOTimeReporting(SUMO_ATTR_BEGIN, id.c_str(), ok, string2time(OptionsCont::getOptions().getString("begin")));
940  const SUMOTime end = attrs.getOptSUMOTimeReporting(SUMO_ATTR_END, id.c_str(), ok, string2time(OptionsCont::getOptions().getString("end")));
941  if (!ok) {
942  return;
943  }
944  try {
945  myDetectorBuilder.createEdgeLaneMeanData(id, frequency, begin, end,
946  type, objecttype == SUMO_TAG_MEANDATA_LANE,
947  // equivalent to TplConvert::_2bool used in SUMOSAXAttributes::getBool
948  excludeEmpty[0] != 't' && excludeEmpty[0] != 'T' && excludeEmpty[0] != '1' && excludeEmpty[0] != 'x',
949  excludeEmpty == "defaults", withInternal, trackVehicles,
950  maxTravelTime, minSamples, haltingSpeedThreshold, vtypes,
952  } catch (InvalidArgument& e) {
953  WRITE_ERROR(e.what());
954  } catch (IOError& e) {
955  WRITE_ERROR(e.what());
956  }
957 }
958 
959 
960 void
962  bool ok = true;
963  std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, 0, ok);
964  if (!MSGlobals::gUsingInternalLanes && fromID[0] == ':') {
965  return;
966  }
967 
968  try {
969  bool ok = true;
970  const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, 0, ok);
971  const int fromLaneIdx = attrs.get<int>(SUMO_ATTR_FROM_LANE, 0, ok);
972  const int toLaneIdx = attrs.get<int>(SUMO_ATTR_TO_LANE, 0, ok);
973  LinkDirection dir = parseLinkDir(attrs.get<std::string>(SUMO_ATTR_DIR, 0, ok));
974  LinkState state = parseLinkState(attrs.get<std::string>(SUMO_ATTR_STATE, 0, ok));
975  std::string tlID = attrs.getOpt<std::string>(SUMO_ATTR_TLID, 0, ok, "");
976 #ifdef HAVE_INTERNAL_LANES
977  std::string viaID = attrs.getOpt<std::string>(SUMO_ATTR_VIA, 0, ok, "");
978 #endif
979 
980  MSEdge* from = MSEdge::dictionary(fromID);
981  if (from == 0) {
982  WRITE_ERROR("Unknown from-edge '" + fromID + "' in connection");
983  return;
984  }
985  MSEdge* to = MSEdge::dictionary(toID);
986  if (to == 0) {
987  WRITE_ERROR("Unknown to-edge '" + toID + "' in connection");
988  return;
989  }
990  if (fromLaneIdx < 0 || static_cast<unsigned int>(fromLaneIdx) >= from->getLanes().size() ||
991  toLaneIdx < 0 || static_cast<unsigned int>(toLaneIdx) >= to->getLanes().size()) {
992  WRITE_ERROR("Invalid lane index in connection from '" + from->getID() + "' to '" + to->getID() + "'.");
993  return;
994  }
995  MSLane* fromLane = from->getLanes()[fromLaneIdx];
996  MSLane* toLane = to->getLanes()[toLaneIdx];
997  assert(fromLane);
998  assert(toLane);
999 
1000  int tlLinkIdx = -1;
1001  if (tlID != "") {
1002  tlLinkIdx = attrs.get<int>(SUMO_ATTR_TLLINKINDEX, 0, ok);
1003  // make sure that the index is in range
1005  if (tlLinkIdx < 0 || tlLinkIdx >= (int)logic->getCurrentPhaseDef().getState().size()) {
1006  WRITE_ERROR("Invalid " + toString(SUMO_ATTR_TLLINKINDEX) + " '" + toString(tlLinkIdx) +
1007  "' in connection controlled by '" + tlID + "'");
1008  return;
1009  }
1010  if (!ok) {
1011  return;
1012  }
1013  }
1014  SUMOReal length = fromLane->getShape()[-1].distanceTo(toLane->getShape()[0]);
1015  MSLink* link = 0;
1016 
1017  // build the link
1018 #ifdef HAVE_INTERNAL_LANES
1019  MSLane* via = 0;
1020  if (viaID != "" && MSGlobals::gUsingInternalLanes) {
1021  via = MSLane::dictionary(viaID);
1022  if (via == 0) {
1023  WRITE_ERROR("An unknown lane ('" + viaID +
1024  "') should be set as a via-lane for lane '" + toLane->getID() + "'.");
1025  return;
1026  }
1027  length = via->getLength();
1028  }
1029  link = new MSLink(toLane, via, dir, state, length);
1030  if (via != 0) {
1031  via->addIncomingLane(fromLane, link);
1032  } else {
1033  toLane->addIncomingLane(fromLane, link);
1034  }
1035 #else
1036  link = new MSLink(toLane, dir, state, length);
1037  toLane->addIncomingLane(fromLane, link);
1038 #endif
1039  toLane->addApproachingLane(fromLane);
1040 
1041  // if a traffic light is responsible for it, inform the traffic light
1042  // check whether this link is controlled by a traffic light
1043  if (tlID != "") {
1044  myJunctionControlBuilder.getTLLogic(tlID).addLink(link, fromLane, tlLinkIdx);
1045  }
1046  // add the link
1047  fromLane->addLink(link);
1048 
1049  } catch (InvalidArgument& e) {
1050  WRITE_ERROR(e.what());
1051  }
1052 }
1053 
1054 
1056 NLHandler::parseLinkDir(const std::string& dir) {
1057  if (SUMOXMLDefinitions::LinkDirections.hasString(dir)) {
1059  } else {
1060  throw InvalidArgument("Unrecognised link direction '" + dir + "'.");
1061  }
1062 }
1063 
1064 
1065 LinkState
1066 NLHandler::parseLinkState(const std::string& state) {
1067  if (SUMOXMLDefinitions::LinkStates.hasString(state)) {
1068  return SUMOXMLDefinitions::LinkStates.get(state);
1069  } else {
1070  if (state == "t") { // legacy networks
1071  // WRITE_WARNING("Obsolete link state 't'. Use 'o' instead");
1073  } else {
1074  throw InvalidArgument("Unrecognised link state '" + state + "'.");
1075  }
1076  }
1077 }
1078 
1079 
1080 // ----------------------------------
1081 void
1083  bool ok = true;
1085  Boundary convBoundary = attrs.get<Boundary>(SUMO_ATTR_CONV_BOUNDARY, 0, ok);
1086  Boundary origBoundary = attrs.get<Boundary>(SUMO_ATTR_ORIG_BOUNDARY, 0, ok);
1087  std::string proj = attrs.get<std::string>(SUMO_ATTR_ORIG_PROJ, 0, ok);
1088  if (ok) {
1089  Position networkOffset = s[0];
1090  GeoConvHelper::init(proj, networkOffset, origBoundary, convBoundary);
1091  if (OptionsCont::getOptions().getBool("fcd-output.geo") && !GeoConvHelper::getFinal().usingGeoProjection()) {
1092  WRITE_WARNING("no valid geo projection loaded from network. fcd-output.geo will not work");
1093  }
1094  }
1095 }
1096 
1097 
1098 void
1100  bool ok = true;
1101  myCurrentIsBroken = false;
1102  // get the id, report an error if not given or empty...
1103  myCurrentDistrictID = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
1104  if (!ok) {
1105  myCurrentIsBroken = true;
1106  return;
1107  }
1108  try {
1110  if (!MSEdge::dictionary(myCurrentDistrictID + "-sink", sink)) {
1111  delete sink;
1112  throw InvalidArgument("Another edge with the id '" + myCurrentDistrictID + "-sink' exists.");
1113  }
1114  sink->initialize(new std::vector<MSLane*>());
1116  if (!MSEdge::dictionary(myCurrentDistrictID + "-source", source)) {
1117  delete source;
1118  throw InvalidArgument("Another edge with the id '" + myCurrentDistrictID + "-source' exists.");
1119  }
1120  source->initialize(new std::vector<MSLane*>());
1121  if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
1122  std::vector<std::string> desc = attrs.getStringVector(SUMO_ATTR_EDGES);
1123  for (std::vector<std::string>::const_iterator i = desc.begin(); i != desc.end(); ++i) {
1124  MSEdge* edge = MSEdge::dictionary(*i);
1125  // check whether the edge exists
1126  if (edge == 0) {
1127  throw InvalidArgument("The edge '" + *i + "' within district '" + myCurrentDistrictID + "' is not known.");
1128  }
1129  source->addFollower(edge);
1130  edge->addFollower(sink);
1131  }
1132  }
1133  } catch (InvalidArgument& e) {
1134  WRITE_ERROR(e.what());
1135  myCurrentIsBroken = true;
1136  }
1137 }
1138 
1139 
1140 void
1141 NLHandler::addDistrictEdge(const SUMOSAXAttributes& attrs, bool isSource) {
1142  if (myCurrentIsBroken) {
1143  // earlier error
1144  return;
1145  }
1146  bool ok = true;
1147  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, myCurrentDistrictID.c_str(), ok);
1148  MSEdge* succ = MSEdge::dictionary(id);
1149  if (succ != 0) {
1150  // connect edge
1151  if (isSource) {
1152  MSEdge::dictionary(myCurrentDistrictID + "-source")->addFollower(succ);
1153  } else {
1154  succ->addFollower(MSEdge::dictionary(myCurrentDistrictID + "-sink"));
1155  }
1156  } else {
1157  WRITE_ERROR("At district '" + myCurrentDistrictID + "': succeeding edge '" + id + "' does not exist.");
1158  }
1159 }
1160 
1161 
1162 // ----------------------------------
1163 void
1165  try {
1167  } catch (InvalidArgument& e) {
1168  WRITE_ERROR(e.what());
1169  }
1170 }
1171 
1172 
1173 void
1175  if (!myCurrentIsBroken) {
1176  try {
1178  } catch (InvalidArgument& e) {
1179  WRITE_ERROR(e.what());
1180  myCurrentIsBroken = true;
1181  }
1182  }
1183  myCurrentWAUTID = "";
1184 }
1185 
1186 
1187 /****************************************************************************/