Eclipse SUMO - Simulation of Urban MObility
NLTriggerBuilder.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
24 // Builds trigger objects for microsim
25 /****************************************************************************/
26 #include <config.h>
27 
28 #include <string>
30 #include <microsim/MSLane.h>
31 #include <microsim/MSEdge.h>
32 #include <microsim/MSGlobals.h>
33 #include <microsim/MSParkingArea.h>
46 #include <utils/common/RGBColor.h>
48 #include "NLHandler.h"
49 #include "NLTriggerBuilder.h"
51 #include <utils/xml/XMLSubSys.h>
52 
53 
54 #include <mesosim/MELoop.h>
56 
57 
58 // ===========================================================================
59 // method definitions
60 // ===========================================================================
62  : myHandler(nullptr), myParkingArea(nullptr), myCurrentStop(nullptr) {}
63 
64 
66 
67 void
69  myHandler = handler;
70 }
71 
72 
73 void
75  WRITE_WARNING(TL("Vaporizers are deprecated. Use rerouters instead."));
76  bool ok = true;
77  // get the id, throw if not given or empty...
78  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
79  if (!ok) {
80  return;
81  }
82  MSEdge* e = MSEdge::dictionary(id);
83  if (e == nullptr) {
84  WRITE_ERRORF(TL("Unknown edge ('%') referenced in a vaporizer."), id);
85  return;
86  }
87  SUMOTime begin = attrs.getSUMOTimeReporting(SUMO_ATTR_BEGIN, nullptr, ok);
88  SUMOTime end = attrs.getSUMOTimeReporting(SUMO_ATTR_END, nullptr, ok);
89  if (!ok) {
90  return;
91  }
92  if (begin < 0) {
93  WRITE_ERRORF(TL("A vaporization begin time is negative (edge id='%')."), id);
94  return;
95  }
96  if (begin >= end) {
97  WRITE_ERRORF(TL("A vaporization ends before it starts (edge id='%')."), id);
98  return;
99  }
100  if (end >= string2time(OptionsCont::getOptions().getString("begin"))) {
105  }
106 }
107 
108 
109 void
111  const std::string& base) {
112  // get the id, throw if not given or empty...
113  bool ok = true;
114  // get the id, throw if not given or empty...
115  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
116  if (!ok) {
117  return;
118  }
119  // get the file name to read further definitions from
120  std::string file = getFileName(attrs, base, true);
121  std::string objectid = attrs.get<std::string>(SUMO_ATTR_LANES, id.c_str(), ok);
122  std::vector<MSLane*> lanes;
123  for (const std::string& laneID : attrs.get<std::vector<std::string> >(SUMO_ATTR_LANES, id.c_str(), ok)) {
124  MSLane* lane = MSLane::dictionary(laneID);
125  if (lane == nullptr) {
126  throw InvalidArgument("The lane '" + laneID + "' to use within MSLaneSpeedTrigger '" + id + "' is not known.");
127  }
128  lanes.push_back(lane);
129  }
130  if (!ok) {
131  throw InvalidArgument("The lanes to use within MSLaneSpeedTrigger '" + id + "' are not known.");
132  }
133  if (lanes.size() == 0) {
134  throw InvalidArgument("No lane defined for MSLaneSpeedTrigger '" + id + "'.");
135  }
136  try {
137  MSLaneSpeedTrigger* trigger = buildLaneSpeedTrigger(net, id, lanes, file);
138  if (file == "") {
140  }
141  } catch (ProcessError& e) {
142  throw InvalidArgument(e.what());
143  }
144 }
145 
146 
147 void
149  bool ok = true;
150 
151  // get the id, throw if not given or empty...
152  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
153  if (!ok) {
154  throw ProcessError();
155  }
156 
157  MSLane* const lane = getLane(attrs, "chargingStation", id);
158  double frompos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, id.c_str(), ok, 0);
159  double topos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, id.c_str(), ok, lane->getLength());
160  const double chargingPower = attrs.getOpt<double>(SUMO_ATTR_CHARGINGPOWER, id.c_str(), ok, 0);
161  const double efficiency = attrs.getOpt<double>(SUMO_ATTR_EFFICIENCY, id.c_str(), ok, 0.95);
162  const bool chargeInTransit = attrs.getOpt<bool>(SUMO_ATTR_CHARGEINTRANSIT, id.c_str(), ok, 0);
163  const SUMOTime chargeDelay = attrs.getOptSUMOTimeReporting(SUMO_ATTR_CHARGEDELAY, id.c_str(), ok, 0);
164  const std::string chargeType = attrs.getOpt<std::string>(SUMO_ATTR_CHARGETYPE, id.c_str(), ok, "normal");
165  const SUMOTime waitingTime = attrs.getOptSUMOTimeReporting(SUMO_ATTR_WAITINGTIME, id.c_str(), ok, 900);
166  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, id.c_str(), ok, false);
167  const std::string name = attrs.getOpt<std::string>(SUMO_ATTR_NAME, id.c_str(), ok, "");
168  MSParkingArea* parkingArea = getParkingArea(attrs, "parkingArea", id);
169 
170  // check charge type
171  if ((chargeType != "normal") && (chargeType != "electric") && (chargeType != "fuel")) {
172  throw InvalidArgument("The chargeType to use within MSLaneSpeedTrigger '" + id + "' is invalid.");
173  }
174 
175  if (!ok || (myHandler->checkStopPos(frompos, topos, lane->getLength(), POSITION_EPS, friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID)) {
176  throw InvalidArgument("Invalid position for charging station '" + id + "'.");
177  }
178 
179  buildChargingStation(net, id, lane, frompos, topos, name, chargingPower, efficiency, chargeInTransit, chargeDelay, chargeType, waitingTime, parkingArea);
180 }
181 
182 
183 void
185  bool ok = true;
186 
187  // get the id, throw if not given or empty...
188  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
189  if (!ok) {
190  throw ProcessError();
191  }
192 
193  /* The following call may either throw InvalidArgument exeption or return NULL:
194  NULL is returned in case when the overhead wire segment should be built over an already
195  ignored internal lane of an intersection, the exeption is thrown in case that
196  the overhead wire segment references a non-existent lane. */
197  MSLane* const lane = getLane(attrs, "overheadWireSegment", id);
198  if (lane == nullptr) {
199  WRITE_MESSAGEF(TL("The overheadWireSegment '%' was not created as it is attached to internal lane. It will be build automatically."), id);
200  return;
201  }
202 
203  if (lane->isInternal()) {
204  WRITE_MESSAGEF(TL("The overheadWireSegment '%' not built as it is attached to internal lane. It will be build automatically."), id);
205  return;
206  }
207 
208  double frompos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, id.c_str(), ok, 0);
209  double topos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, id.c_str(), ok, lane->getLength());
210  const bool voltageSource = attrs.getOpt<bool>(SUMO_ATTR_VOLTAGESOURCE, id.c_str(), ok, false);
211  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, id.c_str(), ok, false);
212 
213  if (!ok || myHandler->checkStopPos(frompos, topos, lane->getLength(), POSITION_EPS, friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID) {
214  frompos = 0;
215  topos = lane->getLength();
216  WRITE_MESSAGEF(TL("The overheadWireSegment '%' has wrong position. Automatically set from 0 to the length of the lane."), id);
217  //throw InvalidArgument("Invalid position for overheadWireSegment'" + id + "'.");
218  }
219 
220  buildOverheadWireSegment(net, id, lane, frompos, topos, voltageSource);
221 #ifndef HAVE_EIGEN
223  myHaveWarnedAboutEigen = true;
224  WRITE_WARNING(TL("Overhead wire solver (Eigen) not compiled in, expect errors in overhead wire simulation"))
225  }
226 #endif // !HAVE_EIGEN
227 }
228 
229 void
231  bool ok = true;
232  std::string substationId = attrs.get<std::string>(SUMO_ATTR_SUBSTATIONID, 0, ok);
233  if (!ok) {
234  throw ProcessError();
235  }
236 
237  MSTractionSubstation* substation = MSNet::getInstance()->findTractionSubstation(substationId);
238  if (substation == nullptr) {
239  throw InvalidArgument("Traction substation '" + substationId + "' refereced by an OverheadWire Section is not known.");
240  } else if (substation->isAnySectionPreviouslyDefined()) {
241  throw InvalidArgument("Traction substation '" + substationId + "' refereced by an OverheadWire Section is probably referenced twice (a known limitation of the actual version of overhead wire simulation).");
242  }
243 
244  // @todo This may be a relict of older approach to processing the attributes ...
245  std::string segmentStrings = attrs.get<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENTS, substationId.c_str(), ok);
246  if (!ok) {
247  throw InvalidArgument("Segments referenced by Traction substation '" + substationId + "' are not declared .");
248  }
249 
250  // process forbidden internal lanes
251  const std::vector<std::string>& forbiddenInnerLanesIDs = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN, substationId.c_str(), ok);
253  for (const std::string& laneID : forbiddenInnerLanesIDs) {
254  MSLane* lane = MSLane::dictionary(laneID);
255  if (lane != nullptr) {
256  substation->addForbiddenLane(lane);
257  } else {
258  throw InvalidArgument("Unknown lane '" + laneID + "' in Traction substation '" + substationId + "'.");
259  }
260  }
261 
262  // @todo Check this as well ...
263  // Original version from 2018
264  // std::vector<std::string> segmentIDs;
265  // SUMOSAXAttributes::parseStringVector(segmentStrings, segmentIDs);
266  const std::vector<std::string>& segmentIDs = attrs.get<std::vector<std::string> >(SUMO_ATTR_OVERHEAD_WIRE_SEGMENTS, substationId.c_str(), ok);
267  std::vector<MSOverheadWire*> segments;
268 
269  // ----------------------------------------------
270  // Add overhead wire segments over internal lanes
271  // ----------------------------------------------
272 
273  // Adding internal overhead wire segments (segments on neighboring inner lanes if a connection between two regular lane with overhead wire segment exists)
274  for (const std::string& segmentID : segmentIDs) {
275  const MSLane* connection = nullptr;
277  std::string neigboringOvrhdSegmentID;
278  MSOverheadWire* neigboringOvrhdSegment;
279  MSTractionSubstation* neigboringOvrhdSegmentTractionSubstation;
280  if (ovrhdSegment == nullptr) {
281  throw InvalidArgument("The OverheadWireSegment with id='" + segmentID + "' referenced by OverheadWireSegment for substation '" + substationId + "' was not defined.");
282  }
283 
284  MSTractionSubstation* ts = ovrhdSegment->getTractionSubstation();
285  if (!(ts == substation || ts == nullptr)) {
286  std::string tsName = ts->getID();
287  throw InvalidArgument("The OverheadWireSegment '" + segmentID + "' referenced by OverheadWireSegment for substation '" + substationId + "' is already assigned to substation '" + tsName + "'.");
288  }
289  ovrhdSegment->setTractionSubstation(substation);
290 
291  const MSLane* lane = &(ovrhdSegment->getLane());
292 
293  /* in version before SUMO 1.0.1 the function getOutgoingLanes() returning MSLane* exists,
294  in new version of SUMO the funciton getOutgoingViaLanes() returning MSLane* and MSEdge* pair exists */
295  const std::vector<std::pair<const MSLane*, const MSEdge*> > outgoingLanesAndEdges = lane->getOutgoingViaLanes();
296  std::vector<const MSLane*> neigboringInnerLanes;
297  neigboringInnerLanes.reserve(outgoingLanesAndEdges.size());
298  for (size_t it = 0; it < outgoingLanesAndEdges.size(); ++it) {
299  neigboringInnerLanes.push_back(outgoingLanesAndEdges[it].first);
300  }
301 
302  // Check if an outgoing lane has an overhead wire segment. If not, do nothing, otherwise find connnecting internal lanes and
303  // add overhead wire segments over all detected internal lanes
304  for (std::vector<const MSLane*>::iterator it = neigboringInnerLanes.begin(); it != neigboringInnerLanes.end(); ++it) {
305  // If the overhead wire segment is over the outgoing (not internal) lane
306  neigboringOvrhdSegmentID = MSNet::getInstance()->getStoppingPlaceID(*it, NUMERICAL_EPS, SUMO_TAG_OVERHEAD_WIRE_SEGMENT);
307  if (neigboringOvrhdSegmentID != "") {
308  neigboringOvrhdSegment = dynamic_cast<MSOverheadWire*>(MSNet::getInstance()->getStoppingPlace(neigboringOvrhdSegmentID, SUMO_TAG_OVERHEAD_WIRE_SEGMENT));
309  neigboringOvrhdSegmentTractionSubstation = neigboringOvrhdSegment->getTractionSubstation();
310  } else {
311  neigboringOvrhdSegment = nullptr;
312  neigboringOvrhdSegmentTractionSubstation = nullptr;
313  }
314 
315  if (neigboringOvrhdSegmentTractionSubstation == substation && !(*it)->isInternal()) {
316  connection = lane->getInternalFollowingLane(*it);
317  if (connection != nullptr) {
318  //is connection forbidden?
319  if (!(substation->isForbidden(connection) || substation->isForbidden(lane->getInternalFollowingLane(connection)) || substation->isForbidden(connection->getInternalFollowingLane(*it)))) {
320  buildInnerOverheadWireSegments(net, connection, lane->getInternalFollowingLane(connection), connection->getInternalFollowingLane(*it));
321  }
322  }
323  }
324  }
325 
326  // Check if an incoming lane has an overhead wire segment. If not, do nothing, otherwise find connnecting internal lanes and
327  // add overhead wire segments over all detected internal lanes
328  neigboringInnerLanes = lane->getNormalIncomingLanes();
329  for (std::vector<const MSLane*>::iterator it = neigboringInnerLanes.begin(); it != neigboringInnerLanes.end(); ++it) {
330  // If the overhead wire segment is over the incoming (not internal) lane
331  neigboringOvrhdSegmentID = MSNet::getInstance()->getStoppingPlaceID(*it, (*it)->getLength() - NUMERICAL_EPS, SUMO_TAG_OVERHEAD_WIRE_SEGMENT);
332  if (neigboringOvrhdSegmentID != "") {
333  neigboringOvrhdSegment = dynamic_cast<MSOverheadWire*>(MSNet::getInstance()->getStoppingPlace(neigboringOvrhdSegmentID, SUMO_TAG_OVERHEAD_WIRE_SEGMENT));
334  neigboringOvrhdSegmentTractionSubstation = neigboringOvrhdSegment->getTractionSubstation();
335  } else {
336  neigboringOvrhdSegment = nullptr;
337  neigboringOvrhdSegmentTractionSubstation = nullptr;
338  }
339 
340  if (neigboringOvrhdSegmentTractionSubstation == substation && !(*it)->isInternal()) {
341  connection = (*it)->getInternalFollowingLane(lane);
342  if (connection != nullptr) {
343  //is connection forbidden?
344  if (!(substation->isForbidden(connection) || substation->isForbidden((*it)->getInternalFollowingLane(connection)) || substation->isForbidden(connection->getInternalFollowingLane(lane)))) {
345  buildInnerOverheadWireSegments(net, connection, (*it)->getInternalFollowingLane(connection), connection->getInternalFollowingLane(lane));
346  }
347  }
348  }
349  }
350  }
351 
352 
353  // ----- *** adding segments into the electric circuit*** -----
354 
355  // setting nullptr for substation (a fragment from old version of adding segments into the circuit)
356  for (const std::string& segmentID : segmentIDs) {
358  ovrhdSegment->setTractionSubstation(nullptr);
359  }
360 
361  for (const std::string& segmentID : segmentIDs) {
362  if (segmentID == "") {
363  continue;
364  }
366  substation->addOverheadWireSegmentToCircuit(ovrhdSegment);
367  segments.push_back(ovrhdSegment);
368  }
369 
370  // adding overhead wire clamp
371  std::string clampsString = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_CLAMPS, nullptr, ok, "");
372  if (clampsString != "" && MSGlobals::gOverheadWireSolver) {
373 #ifdef HAVE_EIGEN
374  const std::vector<std::string>& clampIDs = attrs.get<std::vector<std::string> >(SUMO_ATTR_OVERHEAD_WIRE_CLAMPS, nullptr, ok);
375  for (const std::string& clampID : clampIDs) {
376  MSTractionSubstation::OverheadWireClamp* clamp = substation->findClamp(clampID);
377  if (clamp != nullptr) {
378  if (clamp->start->getTractionSubstation() == substation && clamp->end->getTractionSubstation() == substation) {
379  substation->addOverheadWireClampToCircuit(clamp->id, clamp->start, clamp->end);
380  buildOverheadWireClamp(net, clamp->id, const_cast<MSLane*>(&clamp->start->getLane()), const_cast<MSLane*>(&clamp->end->getLane()));
381  clamp->usage = true;
382  } else {
383  if (clamp->start->getTractionSubstation() != substation) {
384  WRITE_WARNINGF(TL("A connecting overhead wire start segment '%' defined for overhead wire clamp '%' is not assigned to the traction substation '%'."), clamp->start->getID(), clampID, substationId);
385  } else {
386  WRITE_WARNINGF(TL("A connecting overhead wire end segment '%' defined for overhead wire clamp '%' is not assigned to the traction substation '%'."), clamp->end->getID(), clampID, substationId);
387  }
388  }
389  } else {
390  WRITE_WARNINGF(TL("The overhead wire clamp '%' defined in an overhead wire section was not assigned to the substation '%'. Please define proper <overheadWireClamp .../> in additional files before defining overhead wire section."), clampID, substationId);
391  }
392  }
393 #else
394  WRITE_WARNING(TL("Overhead circuit solver requested, but solver support (Eigen) not compiled in."));
395 #endif
396  }
397 
398  if (segments.size() == 0) {
399  throw InvalidArgument("No segments found for overHeadWireSection '" + substationId + "'.");
400  } else if (MSGlobals::gOverheadWireSolver) {
401 #ifdef HAVE_EIGEN
402  // check that the electric circuit makes sense
403  segments[0]->getCircuit()->checkCircuit(substationId);
404 #else
405  WRITE_WARNING(TL("Cannot check circuit, overhead circuit solver support (Eigen) not compiled in."));
406 #endif
407  }
408 }
409 
410 void
412  bool ok = true;
413 
414  // get the id, throw if not given or empty...
415  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
416  if (!ok) {
417  throw ProcessError();
418  }
419 
420  // RICE_TODO Limits are fixed, change them to some predefined constants ...
421  const double voltage = attrs.getOpt<double>(SUMO_ATTR_VOLTAGE, id.c_str(), ok, 600);
422  const double currentLimit = attrs.getOpt<double>(SUMO_ATTR_CURRENTLIMIT, id.c_str(), ok, 400);
423  buildTractionSubstation(net, id, voltage, currentLimit);
424 }
425 
426 void
429 #ifdef HAVE_EIGEN
430  bool ok = true;
431  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
432  if (!ok) {
433  throw ProcessError();
434  }
435 
436  std::string substationId = attrs.get<std::string>(SUMO_ATTR_SUBSTATIONID, 0, ok);
437  if (!ok) {
438  throw ProcessError();
439  }
440  MSTractionSubstation* substation = MSNet::getInstance()->findTractionSubstation(substationId);
441  if (substation == nullptr) {
442  throw InvalidArgument("Traction substation '" + substationId + "' using within an overheadWireClamp '" + id + "' is not known.");
443  }
444 
445  std::string overhead_fromItsStart = attrs.get<std::string>(SUMO_ATTR_OVERHEAD_WIRE_CLAMP_START, 0, ok);
446  if (!ok) {
447  throw ProcessError();
448  }
449  MSOverheadWire* ovrhdSegment_fromItsStart = dynamic_cast<MSOverheadWire*>(MSNet::getInstance()->getStoppingPlace(overhead_fromItsStart, SUMO_TAG_OVERHEAD_WIRE_SEGMENT));
450  if (ovrhdSegment_fromItsStart == nullptr) {
451  throw InvalidArgument("The overheadWireSegment '" + overhead_fromItsStart + "' to use within overheadWireClamp '" + id + "' is not known.");
452  }
453  /*if (ovrhdSegment_fromItsStart->getTractionSubstation() != substation) {
454  throw InvalidArgument("The overheadWireSegment '" + overhead_fromItsStart + "' to use within overheadWireClamp is assign to a different overhead wire section or substation.");
455  }
456  */
457  std::string overhead_fromItsEnd = attrs.get<std::string>(SUMO_ATTR_OVERHEAD_WIRE_CLAMP_END, 0, ok);
458  if (!ok) {
459  throw ProcessError();
460  }
461  MSOverheadWire* ovrhdSegment_fromItsEnd = dynamic_cast<MSOverheadWire*>(MSNet::getInstance()->getStoppingPlace(overhead_fromItsEnd, SUMO_TAG_OVERHEAD_WIRE_SEGMENT));
462  if (ovrhdSegment_fromItsEnd == nullptr) {
463  throw InvalidArgument("The overheadWireSegment '" + overhead_fromItsEnd + "' to use within overheadWireClamp '" + id + "' is not known.");
464  }
465  /*
466  if (ovrhdSegment_fromItsEnd->getTractionSubstation() != substation) {
467  throw InvalidArgument("The overheadWireSegment '" + overhead_fromItsEnd + "' to use within overheadWireClamp is assign to a different overhead wire section or substation.");
468  }
469  */
470  if (substation->findClamp(id) == nullptr) {
471  substation->addClamp(id, ovrhdSegment_fromItsStart, ovrhdSegment_fromItsEnd);
472  } else {
473  WRITE_ERROR("The overhead wire clamp '" + id + "' is probably declared twice.")
474  }
475 #else
476  UNUSED_PARAMETER(attrs);
477  WRITE_WARNING(TL("Not building overhead wire clamps, overhead wire solver support (Eigen) not compiled in."));
478 #endif
479  } else {
480  WRITE_WARNING(TL("Ignoring overhead wire clamps, they make no sense when overhead wire circuit solver is off."));
481  }
482 }
483 
484 
485 void
487  bool ok = true;
488  // get the id, throw if not given or empty...
489  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
490  if (!ok) {
491  throw ProcessError();
492  }
493 
494  //get the name, leave blank if not given
495  const std::string ptStopName = attrs.getOpt<std::string>(SUMO_ATTR_NAME, id.c_str(), ok, "");
496 
497  //get the color, use default if not given
498  // default color, copy from GUIVisualizationStoppingPlaceSettings::busStopColor / containerStopColor
499  RGBColor color = attrs.getOpt<RGBColor>(SUMO_ATTR_COLOR, id.c_str(), ok, RGBColor::INVISIBLE);
500 
501  MSLane* lane = getLane(attrs, toString(element), id);
502  // get the positions
503  double frompos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, id.c_str(), ok, 0.);
504  double topos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, id.c_str(), ok, lane->getLength());
505  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, id.c_str(), ok, false);
506  if (!ok || (myHandler->checkStopPos(frompos, topos, lane->getLength(), POSITION_EPS, friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID)) {
507  throw InvalidArgument("Invalid position for " + toString(element) + " '" + id + "'.");
508  }
509  const std::vector<std::string>& lines = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_LINES, id.c_str(), ok);
510  int defaultCapacity;
511  SumoXMLAttr capacityAttr;
512  if (element != SUMO_TAG_CONTAINER_STOP) {
513  defaultCapacity = MAX2(MSStoppingPlace::getTransportablesAbreast(topos - frompos, element) * 3, 6);
514  capacityAttr = SUMO_ATTR_PERSON_CAPACITY;
515  } else {
516  defaultCapacity = MSStoppingPlace::getTransportablesAbreast(topos - frompos, element);
517  capacityAttr = SUMO_ATTR_CONTAINER_CAPACITY;
518  }
519  const int transportableCapacity = attrs.getOpt<int>(capacityAttr, id.c_str(), ok, defaultCapacity);
520  const double parkingLength = attrs.getOpt<double>(SUMO_ATTR_PARKING_LENGTH, id.c_str(), ok, 0);
521  // build the bus stop
522  buildStoppingPlace(net, id, lines, lane, frompos, topos, element, ptStopName, transportableCapacity, parkingLength, color);
523 }
524 
525 
526 void
528  if (myCurrentStop == nullptr) {
529  throw InvalidArgument("Could not add access outside a stopping place.");
530  }
531  // get the lane
532  MSLane* lane = getLane(attrs, "access", myCurrentStop->getID());
533  if (!lane->allowsVehicleClass(SVC_PEDESTRIAN)) {
534  WRITE_WARNINGF(TL("Ignoring invalid access from non-pedestrian lane '%' in busStop '%'."), lane->getID(), myCurrentStop->getID());
535  return;
536  }
537  // get the positions
538  bool ok = true;
539  const bool random = attrs.getOpt<std::string>(SUMO_ATTR_POSITION, "access", ok) == "random";
540  const bool useDoors = attrs.getOpt<std::string>(SUMO_ATTR_POSITION, "access", ok) == "doors";
541  double startPos = random || useDoors ? 0. : attrs.getOpt<double>(SUMO_ATTR_POSITION, "access", ok, 0);
542  double endPos = random || useDoors ? lane->getLength() : startPos;
543  const double length = attrs.getOpt<double>(SUMO_ATTR_LENGTH, "access", ok, -1);
544  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, "access", ok, false);
545  if (!ok || (myHandler->checkStopPos(startPos, endPos, lane->getLength(), 0, friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID)) {
546  throw InvalidArgument("Invalid position " + attrs.getString(SUMO_ATTR_POSITION) + " for access on lane '" + lane->getID() + "' in stop '" + myCurrentStop->getID() + "'.");
547  }
548  // add bus stop access
549  if (!myCurrentStop->addAccess(lane, startPos, endPos, length, useDoors)) {
550  throw InvalidArgument("Duplicate access on lane '" + lane->getID() + "' for stop '" + myCurrentStop->getID() + "'");
551  }
552 }
553 
554 
555 void
557  bool ok = true;
558  // get the id, throw if not given or empty...
559  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
560  if (!ok) {
561  throw ProcessError();
562  }
563  // get the lane
564  MSLane* lane = getLane(attrs, "parkingArea", id);
565  // get the positions
566  double frompos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, id.c_str(), ok, 0);
567  double topos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, id.c_str(), ok, lane->getLength());
568  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, id.c_str(), ok, false);
569  unsigned int capacity = attrs.getOpt<int>(SUMO_ATTR_ROADSIDE_CAPACITY, id.c_str(), ok, 0);
570  bool onRoad = attrs.getOpt<bool>(SUMO_ATTR_ONROAD, id.c_str(), ok, false);
571  double width = attrs.getOpt<double>(SUMO_ATTR_WIDTH, id.c_str(), ok, 0);
572  double length = attrs.getOpt<double>(SUMO_ATTR_LENGTH, id.c_str(), ok, 0);
573  double angle = attrs.getOpt<double>(SUMO_ATTR_ANGLE, id.c_str(), ok, 0);
574  const std::string name = attrs.getOpt<std::string>(SUMO_ATTR_NAME, id.c_str(), ok);
575  const std::string departPos = attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS, id.c_str(), ok);
576  bool lefthand = attrs.getOpt<bool>(SUMO_ATTR_LEFTHAND, id.c_str(), ok, false);
577  const std::vector<std::string>& acceptedBadges = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_ACCEPTED_BADGES, id.c_str(), ok);
578 
579  if (!ok || (myHandler->checkStopPos(frompos, topos, lane->getLength(), POSITION_EPS, friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID)) {
580  throw InvalidArgument("Invalid position for parking area '" + id + "'.");
581  }
582  const std::vector<std::string>& lines = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_LINES, id.c_str(), ok);
583  // build the parking area
584  beginParkingArea(net, id, lines, acceptedBadges, lane, frompos, topos, capacity, width, length, angle, name, onRoad, departPos, lefthand);
585 }
586 
587 
588 
589 void
591  bool ok = true;
592  // Check for open parking area
593  if (myParkingArea == nullptr) {
594  throw ProcessError();
595  }
596  // get the positions
597  double x = attrs.get<double>(SUMO_ATTR_X, "", ok);
598  if (!ok) {
599  throw InvalidArgument("Invalid x position for lot entry.");
600  }
601  double y = attrs.get<double>(SUMO_ATTR_Y, "", ok);
602  if (!ok) {
603  throw InvalidArgument("Invalid y position for lot entry.");
604  }
605  double z = attrs.getOpt<double>(SUMO_ATTR_Z, "", ok, 0.);
606  double width = attrs.getOpt<double>(SUMO_ATTR_WIDTH, "", ok, myParkingArea->getWidth());
607  double length = attrs.getOpt<double>(SUMO_ATTR_LENGTH, "", ok, myParkingArea->getLength());
608  double angle = attrs.getOpt<double>(SUMO_ATTR_ANGLE, "", ok, myParkingArea->getAngle());
609  double slope = attrs.getOpt<double>(SUMO_ATTR_SLOPE, "", ok, 0.);
610  // add the lot entry
611  addLotEntry(x, y, z, width, length, angle, slope);
612 }
613 
614 
615 void
617  const std::string& base) {
618  bool ok = true;
619  // get the id, throw if not given or empty...
620  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
621  if (!ok) {
622  throw ProcessError();
623  }
624  MSLane* lane = nullptr;
625  MSEdge* edge = nullptr;
626  // get the file name to read further definitions from
627  if (attrs.hasAttribute(SUMO_ATTR_EDGE)) {
628  std::string edgeID = attrs.get<std::string>(SUMO_ATTR_EDGE, id.c_str(), ok);
629  edge = MSEdge::dictionary(edgeID);
630  if (edge == nullptr) {
631  throw InvalidArgument("The edge " + edgeID + " to use within the calibrator '" + id + "' is not known.");
632  }
633  if (attrs.hasAttribute(SUMO_ATTR_LANE)) {
634  lane = getLane(attrs, "calibrator", id);
635  if (&lane->getEdge() != edge) {
636  throw InvalidArgument("The edge " + edgeID + " to use within the calibrator '" + id
637  + "' does not match the calibrator lane '" + lane->getID() + ".");
638  }
639  }
640  } else {
641  lane = getLane(attrs, "calibrator", id);
642  edge = &lane->getEdge();
643  }
644  const double pos = getPosition(attrs, lane, "calibrator", id, edge);
645  const SUMOTime period = attrs.getOptPeriod(id.c_str(), ok, DELTA_T); // !!! no error handling
646  const std::string vTypes = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id.c_str(), ok, "");
647  std::string file = getFileName(attrs, base, true);
648  std::string outfile = attrs.getOpt<std::string>(SUMO_ATTR_OUTPUT, id.c_str(), ok, "");
649  std::string routeProbe = attrs.getOpt<std::string>(SUMO_ATTR_ROUTEPROBE, id.c_str(), ok, "");
650  // differing defaults for backward compatibility, values are dimensionless
651  double invalidJamThreshold = attrs.getOpt<double>(SUMO_ATTR_JAM_DIST_THRESHOLD, id.c_str(), ok, MSGlobals::gUseMesoSim ? 0.8 : 0.5);
652  MSRouteProbe* probe = nullptr;
653  if (routeProbe != "") {
654  probe = dynamic_cast<MSRouteProbe*>(net.getDetectorControl().getTypedDetectors(SUMO_TAG_ROUTEPROBE).get(routeProbe));
655  if (probe == nullptr) {
656  throw InvalidArgument("The routeProbe '" + routeProbe + "' to use within the calibrator '" + id + "' is not known.");
657  }
658  }
660  if (lane != nullptr && edge->getLanes().size() > 1) {
661  WRITE_WARNING("Meso calibrator '" + id
662  + "' defined for lane '" + lane->getID()
663  + "' will collect data for all lanes of edge '" + edge->getID() + "'.");
664  }
665  METriggeredCalibrator* trigger = buildMECalibrator(net, id, edge, pos, file, outfile, period, probe, invalidJamThreshold, vTypes);
666  if (file == "") {
668  }
669  } else {
670  MSCalibrator* trigger = buildCalibrator(net, id, edge, lane, pos, file, outfile, period, probe, invalidJamThreshold, vTypes);
671  if (file == "") {
673  }
674  }
675 }
676 
677 
678 void
680  bool ok = true;
681  // get the id, throw if not given or empty...
682  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
683  if (!ok) {
684  throw ProcessError();
685  }
686  if (MSTriggeredRerouter::getInstances().count(id) > 0) {
687  throw InvalidArgument("Could not build rerouter '" + id + "'; probably declared twice.");
688  }
689  MSEdgeVector edges;
690  for (const std::string& edgeID : attrs.get<std::vector<std::string> >(SUMO_ATTR_EDGES, id.c_str(), ok)) {
691  MSEdge* edge = MSEdge::dictionary(edgeID);
692  if (edge == nullptr) {
693  throw InvalidArgument("The edge '" + edgeID + "' to use within rerouter '" + id + "' is not known.");
694  }
695  edges.push_back(edge);
696  }
697  if (!ok) {
698  throw InvalidArgument("The edge to use within rerouter '" + id + "' is not known.");
699  }
700  if (edges.size() == 0) {
701  throw InvalidArgument("No edges found for rerouter '" + id + "'.");
702  }
703  const double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, id.c_str(), ok, 1);
704  const bool off = attrs.getOpt<bool>(SUMO_ATTR_OFF, id.c_str(), ok, false);
705  const bool optional = attrs.getOpt<bool>(SUMO_ATTR_OPTIONAL, id.c_str(), ok, false);
706  const SUMOTime timeThreshold = TIME2STEPS(attrs.getOpt<double>(SUMO_ATTR_HALTING_TIME_THRESHOLD, id.c_str(), ok, 0));
707  const std::string vTypes = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id.c_str(), ok, "");
708  const std::string pos = attrs.getOpt<std::string>(SUMO_ATTR_POSITION, id.c_str(), ok, "");
710  if (pos != "") {
711  const std::vector<std::string> posSplit = StringTokenizer(pos, ",").getVector();
712  if (posSplit.size() == 1) {
713  p = edges.front()->getLanes()[0]->geometryPositionAtOffset(StringUtils::toDouble(posSplit[0]));
714  } else if (posSplit.size() == 2) {
715  p = Position(StringUtils::toDouble(posSplit[0]), StringUtils::toDouble(posSplit[1]));
716  } else if (posSplit.size() == 3) {
717  p = Position(StringUtils::toDouble(posSplit[0]), StringUtils::toDouble(posSplit[1]), StringUtils::toDouble(posSplit[2]));
718  } else {
719  throw InvalidArgument("Invalid position for rerouter '" + id + "'.");
720  }
721  }
722  if (!ok) {
723  throw InvalidArgument("Could not parse rerouter '" + id + "'.");
724  }
725  MSTriggeredRerouter* trigger = buildRerouter(net, id, edges, prob, off, optional, timeThreshold, vTypes, p);
726  // read in the trigger description
728 }
729 
730 
731 // -------------------------
732 
733 
735 NLTriggerBuilder::buildLaneSpeedTrigger(MSNet& /*net*/, const std::string& id,
736  const std::vector<MSLane*>& destLanes,
737  const std::string& file) {
738  return new MSLaneSpeedTrigger(id, destLanes, file);
739 }
740 
741 
743 NLTriggerBuilder::buildMECalibrator(MSNet& /*net*/, const std::string& id,
744  const MSEdge* edge,
745  double pos,
746  const std::string& file,
747  const std::string& outfile,
748  const SUMOTime freq,
749  MSRouteProbe* probe,
750  const double invalidJamThreshold,
751  const std::string& vTypes) {
752  return new METriggeredCalibrator(id, edge, pos, file, outfile, freq, MSGlobals::gMesoNet->getSegmentForEdge(*edge, pos)->getLength(), probe, invalidJamThreshold, vTypes);
753 }
754 
755 
757 NLTriggerBuilder::buildCalibrator(MSNet& /*net*/, const std::string& id,
758  MSEdge* edge,
759  MSLane* lane,
760  double pos,
761  const std::string& file,
762  const std::string& outfile,
763  const SUMOTime freq,
764  const MSRouteProbe* probe,
765  const double invalidJamThreshold,
766  const std::string& vTypes) {
767  return new MSCalibrator(id, edge, lane, pos, file, outfile, freq, edge->getLength(), probe, invalidJamThreshold, vTypes);
768 }
769 
770 
772 NLTriggerBuilder::buildRerouter(MSNet&, const std::string& id,
773  MSEdgeVector& edges, double prob, bool off, bool optional,
774  SUMOTime timeThreshold, const std::string& vTypes, const Position& pos) {
775  return new MSTriggeredRerouter(id, edges, prob, off, optional, timeThreshold, vTypes, pos);
776 }
777 
778 
779 void
780 NLTriggerBuilder::buildStoppingPlace(MSNet& net, std::string id, std::vector<std::string> lines, MSLane* lane,
781  double frompos, double topos, const SumoXMLTag element, std::string ptStopName,
782  int personCapacity, double parkingLength, RGBColor& color) {
783  myCurrentStop = new MSStoppingPlace(id, element, lines, *lane, frompos, topos, ptStopName, personCapacity, parkingLength, color);
784  if (!net.addStoppingPlace(element, myCurrentStop)) {
785  delete myCurrentStop;
786  myCurrentStop = nullptr;
787  throw InvalidArgument("Could not build " + toString(element) + " '" + id + "'; probably declared twice.");
788  }
789 }
790 
791 
792 void
793 NLTriggerBuilder::beginParkingArea(MSNet& net, const std::string& id,
794  const std::vector<std::string>& lines,
795  const std::vector<std::string>& badges,
796  MSLane* lane, double frompos, double topos,
797  unsigned int capacity,
798  double width, double length, double angle, const std::string& name,
799  bool onRoad,
800  const std::string& departPos,
801  bool lefthand) {
802  // Close previous parking area if there are no lots inside
803  MSParkingArea* stop = new MSParkingArea(id, lines, badges, *lane, frompos, topos, capacity, width, length, angle, name, onRoad, departPos, lefthand);
804  if (!net.addStoppingPlace(SUMO_TAG_PARKING_AREA, stop)) {
805  delete stop;
806  throw InvalidArgument("Could not build parking area '" + id + "'; probably declared twice.");
807  } else {
808  myParkingArea = stop;
809  }
810 }
811 
812 
813 void
814 NLTriggerBuilder::addLotEntry(double x, double y, double z,
815  double width, double length,
816  double angle, double slope) {
817  if (myParkingArea != nullptr) {
818  if (!myParkingArea->parkOnRoad()) {
819  myParkingArea->addLotEntry(x, y, z, width, length, angle, slope);
820  } else {
821  throw InvalidArgument("Cannot not add lot entry to on-road parking area.");
822  }
823  } else {
824  throw InvalidArgument("Could not add lot entry outside a parking area.");
825  }
826 }
827 
828 
829 void
831  if (myParkingArea != nullptr) {
832  myParkingArea = nullptr;
833  } else {
834  throw InvalidArgument("Could not end a parking area that is not opened.");
835  }
836 }
837 
838 
839 void
841  if (myCurrentStop != nullptr) {
842  myCurrentStop = nullptr;
843  } else {
844  throw InvalidArgument("Could not end a stopping place that is not opened.");
845  }
846 }
847 
848 
849 void
850 NLTriggerBuilder::buildChargingStation(MSNet& net, const std::string& id, MSLane* lane, double frompos, double topos,
851  const std::string& name, double chargingPower, double efficiency, bool chargeInTransit,
852  SUMOTime chargeDelay, std::string chargeType, SUMOTime waitingTime, MSParkingArea* parkingArea) {
853  MSChargingStation* chargingStation = (parkingArea == nullptr) ? new MSChargingStation(id, *lane, frompos, topos, name, chargingPower, efficiency,
854  chargeInTransit, chargeDelay, chargeType, waitingTime) : new MSChargingStation(id, parkingArea, name, chargingPower, efficiency,
855  chargeInTransit, chargeDelay, chargeType, waitingTime);
856  if (!net.addStoppingPlace(SUMO_TAG_CHARGING_STATION, chargingStation)) {
857  delete chargingStation;
858  throw InvalidArgument("Could not build charging station '" + id + "'; probably declared twice.");
859  }
860  myCurrentStop = chargingStation;
861 }
862 
863 
864 void
865 NLTriggerBuilder::buildOverheadWireSegment(MSNet& net, const std::string& id, MSLane* lane, double frompos, double topos,
866  bool voltageSource) {
867  MSOverheadWire* overheadWireSegment = new MSOverheadWire(id, *lane, frompos, topos, voltageSource);
868  if (!net.addStoppingPlace(SUMO_TAG_OVERHEAD_WIRE_SEGMENT, overheadWireSegment)) {
869  delete overheadWireSegment;
870  throw InvalidArgument("Could not build overheadWireSegment '" + id + "'; probably declared twice.");
871  }
872 }
873 
874 void
875 NLTriggerBuilder::buildInnerOverheadWireSegments(MSNet& net, const MSLane* connection, const MSLane* frontConnection, const MSLane* behindConnection) {
876  if (frontConnection == NULL && behindConnection == NULL) {
877  buildOverheadWireSegment(net, "ovrhd_inner_" + connection->getID(), const_cast<MSLane*>(connection), 0, connection->getLength(), false);
878  } else if (frontConnection != NULL && behindConnection == NULL) {
879  buildOverheadWireSegment(net, "ovrhd_inner_" + frontConnection->getID(), const_cast<MSLane*>(frontConnection), 0, frontConnection->getLength(), false);
880  buildOverheadWireSegment(net, "ovrhd_inner_" + connection->getID(), const_cast<MSLane*>(connection), 0, connection->getLength(), false);
881  } else if (frontConnection == NULL && behindConnection != NULL) {
882  buildOverheadWireSegment(net, "ovrhd_inner_" + behindConnection->getID(), const_cast<MSLane*>(behindConnection), 0, behindConnection->getLength(), false);
883  buildOverheadWireSegment(net, "ovrhd_inner_" + connection->getID(), const_cast<MSLane*>(connection), 0, connection->getLength(), false);
884  } else if (frontConnection != NULL && behindConnection != NULL) {
885  buildOverheadWireSegment(net, "ovrhd_inner_" + frontConnection->getID(), const_cast<MSLane*>(frontConnection), 0, frontConnection->getLength(), false);
886  buildOverheadWireSegment(net, "ovrhd_inner_" + behindConnection->getID(), const_cast<MSLane*>(behindConnection), 0, behindConnection->getLength(), false);
887  buildOverheadWireSegment(net, "ovrhd_inner_" + connection->getID(), const_cast<MSLane*>(connection), 0, connection->getLength(), false);
888  }
889 }
890 
891 void
892 NLTriggerBuilder::buildTractionSubstation(MSNet& net, std::string id, double voltage, double currentLimit) {
893  MSTractionSubstation* myTractionSubstation = new MSTractionSubstation(id, voltage, currentLimit);
894  if (!net.addTractionSubstation(myTractionSubstation)) {
895  delete myTractionSubstation;
896  throw InvalidArgument("Could not build traction substation '" + id + "'; probably declared twice.");
897  }
898 }
899 
900 void
901 NLTriggerBuilder::buildOverheadWireClamp(MSNet& /*net*/, const std::string& /*id*/, MSLane* /*lane_start*/, MSLane* /*lane_end*/) {
902 }
903 
904 std::string
906  const std::string& base,
907  const bool allowEmpty) {
908  // get the file name to read further definitions from
909  bool ok = true;
910  std::string file = attrs.getOpt<std::string>(SUMO_ATTR_FILE, nullptr, ok, "");
911  if (file == "") {
912  if (allowEmpty) {
913  return file;
914  }
915  throw InvalidArgument("No filename given.");
916  }
917  // check whether absolute or relative filenames are given
918  if (!FileHelpers::isAbsolute(file)) {
919  return FileHelpers::getConfigurationRelative(base, file);
920  }
921  return file;
922 }
923 
924 
925 MSLane*
927  const std::string& tt,
928  const std::string& tid) {
929  bool ok = true;
930  std::string objectid = attrs.get<std::string>(SUMO_ATTR_LANE, tid.c_str(), ok);
931  MSLane* lane = MSLane::dictionary(objectid);
932  if (lane == nullptr) {
933  // Either a lane that is non-existent/broken, or a lane that is internal and has been ignored.
934  // We assume that internal lane names start with ':'.
935  if (objectid[0] == ':' && !MSGlobals::gUsingInternalLanes) {
936  return nullptr;
937  }
938  // Throw the exception only in case that the lane really does not exist in the network file
939  // or it is broken.
940  throw InvalidArgument("The lane " + objectid + " to use within the " + tt + " '" + tid + "' is not known.");
941  }
942  return lane;
943 }
944 
945 
947 NLTriggerBuilder::getParkingArea(const SUMOSAXAttributes& attrs, const std::string& tt, const std::string& tid) {
948  bool ok = true;
949  std::string objectID = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, tid.c_str(), ok);
950  if (!ok || objectID.size() == 0) {
951  return nullptr;
952  }
954  if (pa == nullptr) {
955  // Throw the exception only in case that the lane really does not exist in the network file
956  // or it is broken.
957  throw InvalidArgument("The parkingArea " + objectID + " to use within the " + tt + " '" + tid + "' is not known.");
958  }
959  return pa;
960 }
961 
962 
963 double
965  MSLane* lane,
966  const std::string& tt, const std::string& tid,
967  MSEdge* edge) {
968  assert(lane != 0 || edge != 0);
969  const double length = lane != nullptr ? lane->getLength() : edge->getLength();
970  bool ok = true;
971  double pos = attrs.get<double>(SUMO_ATTR_POSITION, nullptr, ok);
972  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, false);
973  if (!ok) {
974  throw InvalidArgument("Error on parsing a position information.");
975  }
976  if (pos < 0) {
977  pos = length + pos;
978  }
979  if (pos > length) {
980  if (friendlyPos) {
981  pos = length - (double) 0.1;
982  } else {
983  if (lane != nullptr) {
984  throw InvalidArgument("The position of " + tt + " '" + tid + "' lies beyond the lane's '" + lane->getID() + "' length.");
985  } else {
986  throw InvalidArgument("The position of " + tt + " '" + tid + "' lies beyond the edges's '" + edge->getID() + "' length.");
987  }
988  }
989  }
990  return pos;
991 }
992 
995  return myParkingArea == nullptr ? myCurrentStop : myParkingArea;
996 }
997 
998 
999 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
std::vector< MSEdge * > MSEdgeVector
Definition: MSEdge.h:73
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define WRITE_MESSAGEF(...)
Definition: MsgHandler.h:298
#define WRITE_ERRORF(...)
Definition: MsgHandler.h:305
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:304
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TL(string)
Definition: MsgHandler.h:315
SUMOTime DELTA_T
Definition: SUMOTime.cpp:38
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition: SUMOTime.cpp:46
#define TIME2STEPS(x)
Definition: SUMOTime.h:57
@ SVC_PEDESTRIAN
pedestrian
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_REROUTER
A rerouter.
@ SUMO_TAG_ROUTEPROBE
a routeprobe detector
@ SUMO_TAG_CHARGING_STATION
A Charging Station.
@ SUMO_TAG_CONTAINER_STOP
A container stop.
@ SUMO_TAG_PARKING_AREA
A parking area.
@ SUMO_TAG_OVERHEAD_WIRE_SEGMENT
An overhead wire segment.
@ SUMO_TAG_CALIBRATOR
A calibrator placed over edge.
@ SUMO_TAG_VSS
A variable speed sign.
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_STARTPOS
@ SUMO_ATTR_LINES
@ SUMO_ATTR_LANE
@ SUMO_ATTR_ACCEPTED_BADGES
@ SUMO_ATTR_WAITINGTIME
@ SUMO_ATTR_FILE
@ SUMO_ATTR_PARKING_AREA
@ SUMO_ATTR_Y
@ SUMO_ATTR_SUBSTATIONID
id of a traction substation substation
@ SUMO_ATTR_Z
@ SUMO_ATTR_EDGE
@ SUMO_ATTR_JAM_DIST_THRESHOLD
@ SUMO_ATTR_CHARGETYPE
Charge type (fuel or electric)
@ SUMO_ATTR_PARKING_LENGTH
@ SUMO_ATTR_ENDPOS
@ SUMO_ATTR_VOLTAGE
voltage of the traction substation [V]
@ SUMO_ATTR_X
@ SUMO_ATTR_BEGIN
weights: time range begin
@ SUMO_ATTR_EDGES
the edges of a route
@ SUMO_ATTR_OFF
@ SUMO_ATTR_ROUTEPROBE
@ SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN
forbidden lanes for overhead wire segment
@ SUMO_ATTR_HALTING_TIME_THRESHOLD
@ SUMO_ATTR_OVERHEAD_WIRE_CLAMP_END
id of the overhead wire segment, to the end of which the overhead wire clamp is connected
@ SUMO_ATTR_LANES
@ SUMO_ATTR_VTYPES
@ SUMO_ATTR_DEPARTPOS
@ SUMO_ATTR_LEFTHAND
@ SUMO_ATTR_CHARGEINTRANSIT
Allow/disallow charge in transit in Charging Stations.
@ SUMO_ATTR_CONTAINER_CAPACITY
@ SUMO_ATTR_NAME
@ SUMO_ATTR_SLOPE
@ SUMO_ATTR_ANGLE
@ SUMO_ATTR_OVERHEAD_WIRE_CLAMPS
overhead wire clamps for overhead wire segment
@ SUMO_ATTR_END
weights: time range end
@ SUMO_ATTR_ROADSIDE_CAPACITY
@ SUMO_ATTR_CURRENTLIMIT
current limit of the traction substation [A]
@ SUMO_ATTR_OPTIONAL
@ SUMO_ATTR_OUTPUT
@ SUMO_ATTR_CHARGINGPOWER
@ SUMO_ATTR_PROB
@ SUMO_ATTR_FRIENDLY_POS
@ SUMO_ATTR_ONROAD
@ SUMO_ATTR_OVERHEAD_WIRE_CLAMP_START
id of the overhead wire segment, to the start of which the overhead wire clamp is connected
@ SUMO_ATTR_LENGTH
@ SUMO_ATTR_COLOR
A color information.
@ SUMO_ATTR_EFFICIENCY
Eficiency of the charge in Charging Stations.
@ SUMO_ATTR_ID
@ SUMO_ATTR_VOLTAGESOURCE
a voltage source on the overhead wire segment [bool]
@ SUMO_ATTR_WIDTH
@ SUMO_ATTR_PERSON_CAPACITY
@ SUMO_ATTR_OVERHEAD_WIRE_SEGMENTS
@ SUMO_ATTR_POSITION
@ SUMO_ATTR_CHARGEDELAY
Delay in the charge of charging stations (different of waiting time)
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
Base (microsim) event class.
Definition: Command.h:50
static bool isAbsolute(const std::string &path)
Returns the information whether the given path is absolute.
static std::string getConfigurationRelative(const std::string &configPath, const std::string &path)
Returns the second path as a relative path to the first file.
void registerParent(const int tag, GenericSAXHandler *handler)
Assigning a parent handler which is enabled when the specified tag is closed.
Calibrates the flow on a segment to a specified one.
Calibrates the flow on a segment to a specified one.
Definition: MSCalibrator.h:47
const NamedObjectCont< MSDetectorFileOutput * > & getTypedDetectors(SumoXMLTag type) const
Returns the list of detectors of the given type.
A road/street connecting two junctions.
Definition: MSEdge.h:77
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:168
SUMOTime decVaporization(SUMOTime t)
Disables vaporization.
Definition: MSEdge.cpp:514
double getLength() const
return the length of the edge
Definition: MSEdge.h:662
static bool dictionary(const std::string &id, MSEdge *edge)
Inserts edge into the static dictionary Returns true if the key id isn't already in the dictionary....
Definition: MSEdge.cpp:983
SUMOTime incVaporization(SUMOTime t)
Enables vaporization.
Definition: MSEdge.cpp:507
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static bool gUseMesoSim
Definition: MSGlobals.h:103
static bool gOverheadWireSolver
Definition: MSGlobals.h:118
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition: MSGlobals.h:109
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:78
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
double getLength() const
Returns the lane's length.
Definition: MSLane.h:598
const MSLane * getInternalFollowingLane(const MSLane *const) const
returns the internal lane leading to the given lane or nullptr, if there is none
Definition: MSLane.cpp:2651
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition: MSLane.h:917
const std::vector< std::pair< const MSLane *, const MSEdge * > > getOutgoingViaLanes() const
get the list of outgoing lanes
Definition: MSLane.cpp:3207
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition: MSLane.cpp:2385
bool isInternal() const
Definition: MSLane.cpp:2516
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:756
std::vector< const MSLane * > getNormalIncomingLanes() const
get the list of all direct (disregarding internal predecessors) non-internal predecessor lanes of thi...
Definition: MSLane.cpp:3217
Changes the speed allowed on a set of lanes.
The simulated network and simulation perfomer.
Definition: MSNet.h:89
bool addStoppingPlace(const SumoXMLTag category, MSStoppingPlace *stop)
Adds a stopping place.
Definition: MSNet.cpp:1348
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:182
MSDetectorControl & getDetectorControl()
Returns the detector control.
Definition: MSNet.h:441
bool addTractionSubstation(MSTractionSubstation *substation)
Adds a traction substation.
Definition: MSNet.cpp:1354
std::string getStoppingPlaceID(const MSLane *lane, const double pos, const SumoXMLTag category) const
Returns the stop of the given category close to the given position.
Definition: MSNet.cpp:1373
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition: MSNet.cpp:1364
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition: MSNet.h:471
MSTractionSubstation * findTractionSubstation(const std::string &substationId)
find electrical substation by its id
Definition: MSNet.cpp:1444
Definition of overhead wire segment.
MSTractionSubstation * getTractionSubstation() const
void setTractionSubstation(MSTractionSubstation *substation)
A lane area vehicles can halt at.
Definition: MSParkingArea.h:60
double getAngle() const
Returns the lot rectangle angle.
double getLength() const
Returns the lot rectangle length.
virtual void addLotEntry(double x, double y, double z, double width, double length, double angle, double slope)
Add a lot entry to parking area.
double getWidth() const
Returns the lot rectangle width.
bool parkOnRoad() const
whether vehicles park on the road
Writes routes of vehicles passing a certain edge.
Definition: MSRouteProbe.h:58
A lane area vehicles can halt at.
int getTransportablesAbreast() const
virtual bool addAccess(MSLane *const lane, const double startPos, const double endPos, double length, const bool doors)
adds an access point to this stop
const MSLane & getLane() const
Returns the lane this stop is located at.
Traction substaction powering one or more overhead wire sections.
void addOverheadWireClampToCircuit(const std::string id, MSOverheadWire *startSegment, MSOverheadWire *endSegment)
void addClamp(const std::string &id, MSOverheadWire *startPos, MSOverheadWire *endPos)
bool isForbidden(const MSLane *lane)
void addOverheadWireSegmentToCircuit(MSOverheadWire *newOverheadWireSegment)
OverheadWireClamp * findClamp(std::string id)
Find an overhead wire clamp by its ID.
void addForbiddenLane(MSLane *lane)
Reroutes traffic objects passing an edge.
static const std::map< std::string, MSTriggeredRerouter * > & getInstances()
return all rerouter instances
The XML-Handler for network loading.
Definition: NLHandler.h:79
MSParkingArea * getParkingArea(const SUMOSAXAttributes &attrs, const std::string &tt, const std::string &tid)
Returns the parking area defined by attribute "parkingArea".
NLTriggerBuilder()
Constructor.
virtual void buildOverheadWireClamp(MSNet &net, const std::string &id, MSLane *lane_start, MSLane *lane_end)
MSParkingArea * myParkingArea
definition of the currently parsed parking area
void parseAndBuildTractionSubstation(MSNet &net, const SUMOSAXAttributes &attrs)
Parses its values and builds a traction substation.
void addAccess(MSNet &net, const SUMOSAXAttributes &attrs)
Parses the values and adds an access point to the currently parsed stopping place.
void parseAndBuildOverheadWireSegment(MSNet &net, const SUMOSAXAttributes &attrs)
Parses its values and builds an overhead wire segment.
void parseAndBuildCalibrator(MSNet &net, const SUMOSAXAttributes &attrs, const std::string &base)
Parses his values and builds a mesoscopic or microscopic calibrator.
double getPosition(const SUMOSAXAttributes &attrs, MSLane *lane, const std::string &tt, const std::string &tid, MSEdge *edge=0)
returns the position on the lane checking it
void buildInnerOverheadWireSegments(MSNet &net, const MSLane *connection, const MSLane *frontConnection, const MSLane *behindConnection)
Builds an overhead wire inner segments.
virtual MSLaneSpeedTrigger * buildLaneSpeedTrigger(MSNet &net, const std::string &id, const std::vector< MSLane * > &destLanes, const std::string &file)
Builds a lane speed trigger.
virtual void buildChargingStation(MSNet &net, const std::string &id, MSLane *lane, double frompos, double topos, const std::string &name, double chargingPower, double efficiency, bool chargeInTransit, SUMOTime chargeDelay, std::string chargeType, SUMOTime waitingTime, MSParkingArea *parkingArea)
Builds a charging station.
virtual void endParkingArea()
End a parking area.
void parseAndBuildLaneSpeedTrigger(MSNet &net, const SUMOSAXAttributes &attrs, const std::string &base)
Parses his values and builds a lane speed trigger.
void parseAndAddLotEntry(const SUMOSAXAttributes &attrs)
Parses his values and adds a lot entry to current parking area.
virtual MSTriggeredRerouter * buildRerouter(MSNet &net, const std::string &id, MSEdgeVector &edges, double prob, bool off, bool optional, SUMOTime timeThreshold, const std::string &vTypes, const Position &pos)
builds an rerouter
NLHandler * myHandler
The parent handler to set for subhandlers.
MSLane * getLane(const SUMOSAXAttributes &attrs, const std::string &tt, const std::string &tid)
Returns the lane defined by attribute "lane".
void buildVaporizer(const SUMOSAXAttributes &attrs)
Builds a vaporization.
void parseAndBuildRerouter(MSNet &net, const SUMOSAXAttributes &attrs)
Parses his values and builds a rerouter.
void parseAndBuildOverheadWireSection(MSNet &net, const SUMOSAXAttributes &attrs)
Parses its values and builds an overhead wire section.
virtual void beginParkingArea(MSNet &net, const std::string &id, const std::vector< std::string > &lines, const std::vector< std::string > &badges, MSLane *lane, double frompos, double topos, unsigned int capacity, double width, double length, double angle, const std::string &name, bool onRoad, const std::string &departPos, bool lefthand)
Begin a parking area.
void setHandler(NLHandler *handler)
Sets the parent handler to use for nested parsing.
virtual MSCalibrator * buildCalibrator(MSNet &net, const std::string &id, MSEdge *edge, MSLane *lane, double pos, const std::string &file, const std::string &outfile, const SUMOTime freq, const MSRouteProbe *probe, const double invalidJamThreshold, const std::string &vTypes)
builds a microscopic calibrator
virtual ~NLTriggerBuilder()
Destructor.
void buildTractionSubstation(MSNet &net, std::string id, double voltage, double currentLimit)
Builds a traction substation.
void addLotEntry(double x, double y, double z, double width, double length, double angle, double slope)
Add a lot entry to current parking area.
void parseAndBuildChargingStation(MSNet &net, const SUMOSAXAttributes &attrs)
Parses his values and builds a charging station.
void parseAndBuildOverheadWireClamp(MSNet &net, const SUMOSAXAttributes &attrs)
Parses its values and builds an overhead wire clamp.
virtual void endStoppingPlace()
End a stopping place.
virtual void buildOverheadWireSegment(MSNet &net, const std::string &id, MSLane *lane, double frompos, double topos, bool voltageSource)
Builds an overhead wire segment.
MSStoppingPlace * myCurrentStop
The currently parsed stop to add access points to.
MSStoppingPlace * getCurrentStop()
virtual METriggeredCalibrator * buildMECalibrator(MSNet &net, const std::string &id, const MSEdge *edge, double pos, const std::string &file, const std::string &outfile, const SUMOTime freq, MSRouteProbe *probe, const double invalidJamThreshold, const std::string &vTypes)
builds a mesoscopic calibrator
virtual void buildStoppingPlace(MSNet &net, std::string id, std::vector< std::string > lines, MSLane *lane, double frompos, double topos, const SumoXMLTag element, std::string string, int personCapacity, double parkingLength, RGBColor &color)
Builds a stopping place.
void parseAndBuildStoppingPlace(MSNet &net, const SUMOSAXAttributes &attrs, const SumoXMLTag element)
Parses the values and builds a stopping places for busses, trains or container vehicles.
void parseAndBeginParkingArea(MSNet &net, const SUMOSAXAttributes &attrs)
Parses his values and builds a parking area.
std::string getFileName(const SUMOSAXAttributes &attrs, const std::string &base, const bool allowEmpty=false)
Helper method to obtain the filename.
const std::string & getID() const
Returns the id.
Definition: Named.h:74
T get(const std::string &id) const
Retrieves an item.
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:60
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:317
static const RGBColor INVISIBLE
Definition: RGBColor.h:195
static StopPos checkStopPos(double &startPos, double &endPos, const double laneLength, const double minLength, const bool friendlyPos)
check start and end position of a stop
Encapsulated SAX-Attributes.
virtual std::string getString(int id, bool *isPresent=nullptr) const =0
Returns the string-value of the named (by its enum-value) attribute.
SUMOTime getOptPeriod(const char *objectid, bool &ok, SUMOTime defaultValue, bool report=true) const
Tries to read the SUMOTime 'period' attribute.
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue=T(), bool report=true) const
Tries to read given attribute assuming it is an int.
SUMOTime getOptSUMOTimeReporting(int attr, const char *objectid, bool &ok, SUMOTime defaultValue, bool report=true) const
Tries to read given attribute assuming it is a SUMOTime.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
SUMOTime getSUMOTimeReporting(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is a SUMOTime.
std::vector< std::string > getVector()
return vector of strings
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
A wrapper for a Command function.