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>
29 #include <mesosim/MELoop.h>
33 #include <microsim/MSLane.h>
34 #include <microsim/MSEdge.h>
35 #include <microsim/MSGlobals.h>
36 #include <microsim/MSParkingArea.h>
49 #include <utils/common/RGBColor.h>
52 #include <utils/xml/XMLSubSys.h>
53 #include "NLHandler.h"
54 #include "NLTriggerBuilder.h"
55 
56 
57 // ===========================================================================
58 // method definitions
59 // ===========================================================================
61  : myHandler(nullptr), myParkingArea(nullptr), myCurrentStop(nullptr) {}
62 
63 
65 
66 void
68  myHandler = handler;
69 }
70 
71 
72 void
74  WRITE_WARNING(TL("Vaporizers are deprecated. Use rerouters instead."));
75  bool ok = true;
76  // get the id, throw if not given or empty...
77  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
78  if (!ok) {
79  return;
80  }
81  MSEdge* e = MSEdge::dictionary(id);
82  if (e == nullptr) {
83  WRITE_ERRORF(TL("Unknown edge ('%') referenced in a vaporizer."), id);
84  return;
85  }
86  SUMOTime begin = attrs.getSUMOTimeReporting(SUMO_ATTR_BEGIN, nullptr, ok);
87  SUMOTime end = attrs.getSUMOTimeReporting(SUMO_ATTR_END, nullptr, ok);
88  if (!ok) {
89  return;
90  }
91  if (begin < 0) {
92  WRITE_ERRORF(TL("A vaporization begin time is negative (edge id='%')."), id);
93  return;
94  }
95  if (begin >= end) {
96  WRITE_ERRORF(TL("A vaporization ends before it starts (edge id='%')."), id);
97  return;
98  }
99  if (end >= string2time(OptionsCont::getOptions().getString("begin"))) {
104  }
105 }
106 
107 
108 void
110  const std::string& base) {
111  // get the id, throw if not given or empty...
112  bool ok = true;
113  // get the id, throw if not given or empty...
114  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
115  if (!ok) {
116  return;
117  }
118  // get the file name to read further definitions from
119  std::string file = getFileName(attrs, base, true);
120  std::string objectid = attrs.get<std::string>(SUMO_ATTR_LANES, id.c_str(), ok);
121  std::vector<MSLane*> lanes;
122  for (const std::string& laneID : attrs.get<std::vector<std::string> >(SUMO_ATTR_LANES, id.c_str(), ok)) {
123  MSLane* lane = MSLane::dictionary(laneID);
124  if (lane == nullptr) {
125  throw InvalidArgument("The lane '" + laneID + "' to use within MSLaneSpeedTrigger '" + id + "' is not known.");
126  }
127  lanes.push_back(lane);
128  }
129  if (!ok) {
130  throw InvalidArgument("The lanes to use within MSLaneSpeedTrigger '" + id + "' are not known.");
131  }
132  if (lanes.size() == 0) {
133  throw InvalidArgument("No lane defined for MSLaneSpeedTrigger '" + id + "'.");
134  }
135  try {
136  MSLaneSpeedTrigger* trigger = buildLaneSpeedTrigger(net, id, lanes, file);
137  if (file == "") {
139  }
140  } catch (ProcessError& e) {
141  throw InvalidArgument(e.what());
142  }
143 }
144 
145 
146 void
148  bool ok = true;
149 
150  // get the id, throw if not given or empty...
151  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
152  if (!ok) {
153  throw ProcessError();
154  }
155 
156  MSLane* const lane = getLane(attrs, "chargingStation", id);
157  double frompos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, id.c_str(), ok, 0);
158  double topos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, id.c_str(), ok, lane->getLength());
159  const double chargingPower = attrs.getOpt<double>(SUMO_ATTR_CHARGINGPOWER, id.c_str(), ok, 22000);
160  const double efficiency = attrs.getOpt<double>(SUMO_ATTR_EFFICIENCY, id.c_str(), ok, 0.95);
161  const bool chargeInTransit = attrs.getOpt<bool>(SUMO_ATTR_CHARGEINTRANSIT, id.c_str(), ok, 0);
162  const SUMOTime chargeDelay = attrs.getOptSUMOTimeReporting(SUMO_ATTR_CHARGEDELAY, id.c_str(), ok, 0);
163  const std::string chargeType = attrs.getOpt<std::string>(SUMO_ATTR_CHARGETYPE, id.c_str(), ok, "normal");
164  const SUMOTime waitingTime = attrs.getOptSUMOTimeReporting(SUMO_ATTR_WAITINGTIME, id.c_str(), ok, 900);
165  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, id.c_str(), ok, false);
166  const std::string name = attrs.getOpt<std::string>(SUMO_ATTR_NAME, id.c_str(), ok, "");
167  MSParkingArea* parkingArea = getParkingArea(attrs, "parkingArea", id);
168 
169  // check charge type
170  if ((chargeType != "normal") && (chargeType != "electric") && (chargeType != "fuel")) {
171  throw InvalidArgument("The chargeType to use within MSLaneSpeedTrigger '" + id + "' is invalid.");
172  }
173 
174  if (!ok || (myHandler->checkStopPos(frompos, topos, lane->getLength(), POSITION_EPS, friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID)) {
175  throw InvalidArgument("Invalid position for charging station '" + id + "'.");
176  }
177 
178  buildChargingStation(net, id, lane, frompos, topos, name, chargingPower, efficiency, chargeInTransit, chargeDelay, chargeType, waitingTime, parkingArea);
179 }
180 
181 
182 void
184  bool ok = true;
185 
186  // get the id, throw if not given or empty...
187  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
188  if (!ok) {
189  throw ProcessError();
190  }
191 
192  /* The following call may either throw InvalidArgument exeption or return NULL:
193  NULL is returned in case when the overhead wire segment should be built over an already
194  ignored internal lane of an intersection, the exeption is thrown in case that
195  the overhead wire segment references a non-existent lane. */
196  MSLane* const lane = getLane(attrs, "overheadWireSegment", id);
197  if (lane == nullptr) {
198  WRITE_MESSAGEF(TL("The overheadWireSegment '%' was not created as it is attached to internal lane. It will be build automatically."), id);
199  return;
200  }
201 
202  if (lane->isInternal()) {
203  WRITE_MESSAGEF(TL("The overheadWireSegment '%' not built as it is attached to internal lane. It will be build automatically."), id);
204  return;
205  }
206 
207  double frompos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, id.c_str(), ok, 0);
208  double topos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, id.c_str(), ok, lane->getLength());
209  const bool voltageSource = attrs.getOpt<bool>(SUMO_ATTR_VOLTAGESOURCE, id.c_str(), ok, false);
210  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, id.c_str(), ok, false);
211 
212  if (!ok || myHandler->checkStopPos(frompos, topos, lane->getLength(), POSITION_EPS, friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID) {
213  frompos = 0;
214  topos = lane->getLength();
215  WRITE_MESSAGEF(TL("The overheadWireSegment '%' has wrong position. Automatically set from 0 to the length of the lane."), id);
216  //throw InvalidArgument("Invalid position for overheadWireSegment'" + id + "'.");
217  }
218 
219  buildOverheadWireSegment(net, id, lane, frompos, topos, voltageSource);
220 #ifndef HAVE_EIGEN
222  myHaveWarnedAboutEigen = true;
223  WRITE_WARNING(TL("Overhead wire solver (Eigen) not compiled in, expect errors in overhead wire simulation"))
224  }
225 #endif // !HAVE_EIGEN
226 }
227 
228 void
230  bool ok = true;
231  std::string substationId = attrs.get<std::string>(SUMO_ATTR_SUBSTATIONID, 0, ok);
232  if (!ok) {
233  throw ProcessError();
234  }
235 
236  MSTractionSubstation* substation = MSNet::getInstance()->findTractionSubstation(substationId);
237  if (substation == nullptr) {
238  throw InvalidArgument("Traction substation '" + substationId + "' refereced by an OverheadWire Section is not known.");
239  } else if (substation->isAnySectionPreviouslyDefined()) {
240  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).");
241  }
242 
243  // @todo This may be a relict of older approach to processing the attributes ...
244  std::string segmentStrings = attrs.get<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENTS, substationId.c_str(), ok);
245  if (!ok) {
246  throw InvalidArgument("Segments referenced by Traction substation '" + substationId + "' are not declared .");
247  }
248 
249  // process forbidden internal lanes
250  const std::vector<std::string>& forbiddenInnerLanesIDs = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN, substationId.c_str(), ok);
252  for (const std::string& laneID : forbiddenInnerLanesIDs) {
253  MSLane* lane = MSLane::dictionary(laneID);
254  if (lane != nullptr) {
255  substation->addForbiddenLane(lane);
256  } else {
257  throw InvalidArgument("Unknown lane '" + laneID + "' in Traction substation '" + substationId + "'.");
258  }
259  }
260 
261  // @todo Check this as well ...
262  // Original version from 2018
263  // std::vector<std::string> segmentIDs;
264  // SUMOSAXAttributes::parseStringVector(segmentStrings, segmentIDs);
265  const std::vector<std::string>& segmentIDs = attrs.get<std::vector<std::string> >(SUMO_ATTR_OVERHEAD_WIRE_SEGMENTS, substationId.c_str(), ok);
266  std::vector<MSOverheadWire*> segments;
267 
268  // ----------------------------------------------
269  // Add overhead wire segments over internal lanes
270  // ----------------------------------------------
271 
272  // Adding internal overhead wire segments (segments on neighboring inner lanes if a connection between two regular lane with overhead wire segment exists)
273  for (const std::string& segmentID : segmentIDs) {
274  const MSLane* connection = nullptr;
276  std::string neigboringOvrhdSegmentID;
277  MSOverheadWire* neigboringOvrhdSegment;
278  MSTractionSubstation* neigboringOvrhdSegmentTractionSubstation;
279  if (ovrhdSegment == nullptr) {
280  throw InvalidArgument("The OverheadWireSegment with id='" + segmentID + "' referenced by OverheadWireSegment for substation '" + substationId + "' was not defined.");
281  }
282 
283  MSTractionSubstation* ts = ovrhdSegment->getTractionSubstation();
284  if (!(ts == substation || ts == nullptr)) {
285  std::string tsName = ts->getID();
286  throw InvalidArgument("The OverheadWireSegment '" + segmentID + "' referenced by OverheadWireSegment for substation '" + substationId + "' is already assigned to substation '" + tsName + "'.");
287  }
288  ovrhdSegment->setTractionSubstation(substation);
289 
290  const MSLane* lane = &(ovrhdSegment->getLane());
291 
292  /* in version before SUMO 1.0.1 the function getOutgoingLanes() returning MSLane* exists,
293  in new version of SUMO the funciton getOutgoingViaLanes() returning MSLane* and MSEdge* pair exists */
294  const std::vector<std::pair<const MSLane*, const MSEdge*> > outgoingLanesAndEdges = lane->getOutgoingViaLanes();
295  std::vector<const MSLane*> neigboringInnerLanes;
296  neigboringInnerLanes.reserve(outgoingLanesAndEdges.size());
297  for (size_t it = 0; it < outgoingLanesAndEdges.size(); ++it) {
298  neigboringInnerLanes.push_back(outgoingLanesAndEdges[it].first);
299  }
300 
301  // Check if an outgoing lane has an overhead wire segment. If not, do nothing, otherwise find connnecting internal lanes and
302  // add overhead wire segments over all detected internal lanes
303  for (std::vector<const MSLane*>::iterator it = neigboringInnerLanes.begin(); it != neigboringInnerLanes.end(); ++it) {
304  // If the overhead wire segment is over the outgoing (not internal) lane
305  neigboringOvrhdSegmentID = MSNet::getInstance()->getStoppingPlaceID(*it, NUMERICAL_EPS, SUMO_TAG_OVERHEAD_WIRE_SEGMENT);
306  if (neigboringOvrhdSegmentID != "") {
307  neigboringOvrhdSegment = dynamic_cast<MSOverheadWire*>(MSNet::getInstance()->getStoppingPlace(neigboringOvrhdSegmentID, SUMO_TAG_OVERHEAD_WIRE_SEGMENT));
308  neigboringOvrhdSegmentTractionSubstation = neigboringOvrhdSegment->getTractionSubstation();
309  } else {
310  neigboringOvrhdSegment = nullptr;
311  neigboringOvrhdSegmentTractionSubstation = nullptr;
312  }
313 
314  if (neigboringOvrhdSegmentTractionSubstation == substation && !(*it)->isInternal()) {
315  connection = lane->getInternalFollowingLane(*it);
316  if (connection != nullptr) {
317  //is connection forbidden?
318  if (!(substation->isForbidden(connection) || substation->isForbidden(lane->getInternalFollowingLane(connection)) || substation->isForbidden(connection->getInternalFollowingLane(*it)))) {
319  buildInnerOverheadWireSegments(net, connection, lane->getInternalFollowingLane(connection), connection->getInternalFollowingLane(*it));
320  }
321  }
322  }
323  }
324 
325  // Check if an incoming lane has an overhead wire segment. If not, do nothing, otherwise find connnecting internal lanes and
326  // add overhead wire segments over all detected internal lanes
327  neigboringInnerLanes = lane->getNormalIncomingLanes();
328  for (std::vector<const MSLane*>::iterator it = neigboringInnerLanes.begin(); it != neigboringInnerLanes.end(); ++it) {
329  // If the overhead wire segment is over the incoming (not internal) lane
330  neigboringOvrhdSegmentID = MSNet::getInstance()->getStoppingPlaceID(*it, (*it)->getLength() - NUMERICAL_EPS, SUMO_TAG_OVERHEAD_WIRE_SEGMENT);
331  if (neigboringOvrhdSegmentID != "") {
332  neigboringOvrhdSegment = dynamic_cast<MSOverheadWire*>(MSNet::getInstance()->getStoppingPlace(neigboringOvrhdSegmentID, SUMO_TAG_OVERHEAD_WIRE_SEGMENT));
333  neigboringOvrhdSegmentTractionSubstation = neigboringOvrhdSegment->getTractionSubstation();
334  } else {
335  neigboringOvrhdSegment = nullptr;
336  neigboringOvrhdSegmentTractionSubstation = nullptr;
337  }
338 
339  if (neigboringOvrhdSegmentTractionSubstation == substation && !(*it)->isInternal()) {
340  connection = (*it)->getInternalFollowingLane(lane);
341  if (connection != nullptr) {
342  //is connection forbidden?
343  if (!(substation->isForbidden(connection) || substation->isForbidden((*it)->getInternalFollowingLane(connection)) || substation->isForbidden(connection->getInternalFollowingLane(lane)))) {
344  buildInnerOverheadWireSegments(net, connection, (*it)->getInternalFollowingLane(connection), connection->getInternalFollowingLane(lane));
345  }
346  }
347  }
348  }
349  }
350 
351 
352  // ----- *** adding segments into the electric circuit*** -----
353 
354  // setting nullptr for substation (a fragment from old version of adding segments into the circuit)
355  for (const std::string& segmentID : segmentIDs) {
357  ovrhdSegment->setTractionSubstation(nullptr);
358  }
359 
360  for (const std::string& segmentID : segmentIDs) {
361  if (segmentID == "") {
362  continue;
363  }
365  substation->addOverheadWireSegmentToCircuit(ovrhdSegment);
366  segments.push_back(ovrhdSegment);
367  }
368 
369  // adding overhead wire clamp
370  std::string clampsString = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_CLAMPS, nullptr, ok, "");
371  if (clampsString != "" && MSGlobals::gOverheadWireSolver) {
372 #ifdef HAVE_EIGEN
373  const std::vector<std::string>& clampIDs = attrs.get<std::vector<std::string> >(SUMO_ATTR_OVERHEAD_WIRE_CLAMPS, nullptr, ok);
374  for (const std::string& clampID : clampIDs) {
375  MSTractionSubstation::OverheadWireClamp* clamp = substation->findClamp(clampID);
376  if (clamp != nullptr) {
377  if (clamp->start->getTractionSubstation() == substation && clamp->end->getTractionSubstation() == substation) {
378  substation->addOverheadWireClampToCircuit(clamp->id, clamp->start, clamp->end);
379  buildOverheadWireClamp(net, clamp->id, const_cast<MSLane*>(&clamp->start->getLane()), const_cast<MSLane*>(&clamp->end->getLane()));
380  clamp->usage = true;
381  } else {
382  if (clamp->start->getTractionSubstation() != substation) {
383  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);
384  } else {
385  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);
386  }
387  }
388  } else {
389  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);
390  }
391  }
392 #else
393  WRITE_WARNING(TL("Overhead circuit solver requested, but solver support (Eigen) not compiled in."));
394 #endif
395  }
396 
397  if (segments.size() == 0) {
398  throw InvalidArgument("No segments found for overHeadWireSection '" + substationId + "'.");
399  } else if (MSGlobals::gOverheadWireSolver) {
400 #ifdef HAVE_EIGEN
401  // check that the electric circuit makes sense
402  segments[0]->getCircuit()->checkCircuit(substationId);
403 #else
404  WRITE_WARNING(TL("Cannot check circuit, overhead circuit solver support (Eigen) not compiled in."));
405 #endif
406  }
407 }
408 
409 void
411  bool ok = true;
412 
413  // get the id, throw if not given or empty...
414  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
415  if (!ok) {
416  throw ProcessError();
417  }
418 
419  // RICE_TODO Limits are fixed, change them to some predefined constants ...
420  const double voltage = attrs.getOpt<double>(SUMO_ATTR_VOLTAGE, id.c_str(), ok, 600);
421  const double currentLimit = attrs.getOpt<double>(SUMO_ATTR_CURRENTLIMIT, id.c_str(), ok, 400);
422  buildTractionSubstation(net, id, voltage, currentLimit);
423 }
424 
425 void
428 #ifdef HAVE_EIGEN
429  bool ok = true;
430  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
431  if (!ok) {
432  throw ProcessError();
433  }
434 
435  std::string substationId = attrs.get<std::string>(SUMO_ATTR_SUBSTATIONID, 0, ok);
436  if (!ok) {
437  throw ProcessError();
438  }
439  MSTractionSubstation* substation = MSNet::getInstance()->findTractionSubstation(substationId);
440  if (substation == nullptr) {
441  throw InvalidArgument("Traction substation '" + substationId + "' using within an overheadWireClamp '" + id + "' is not known.");
442  }
443 
444  std::string overhead_fromItsStart = attrs.get<std::string>(SUMO_ATTR_OVERHEAD_WIRE_CLAMP_START, 0, ok);
445  if (!ok) {
446  throw ProcessError();
447  }
448  MSOverheadWire* ovrhdSegment_fromItsStart = dynamic_cast<MSOverheadWire*>(MSNet::getInstance()->getStoppingPlace(overhead_fromItsStart, SUMO_TAG_OVERHEAD_WIRE_SEGMENT));
449  if (ovrhdSegment_fromItsStart == nullptr) {
450  throw InvalidArgument("The overheadWireSegment '" + overhead_fromItsStart + "' to use within overheadWireClamp '" + id + "' is not known.");
451  }
452  /*if (ovrhdSegment_fromItsStart->getTractionSubstation() != substation) {
453  throw InvalidArgument("The overheadWireSegment '" + overhead_fromItsStart + "' to use within overheadWireClamp is assign to a different overhead wire section or substation.");
454  }
455  */
456  std::string overhead_fromItsEnd = attrs.get<std::string>(SUMO_ATTR_OVERHEAD_WIRE_CLAMP_END, 0, ok);
457  if (!ok) {
458  throw ProcessError();
459  }
460  MSOverheadWire* ovrhdSegment_fromItsEnd = dynamic_cast<MSOverheadWire*>(MSNet::getInstance()->getStoppingPlace(overhead_fromItsEnd, SUMO_TAG_OVERHEAD_WIRE_SEGMENT));
461  if (ovrhdSegment_fromItsEnd == nullptr) {
462  throw InvalidArgument("The overheadWireSegment '" + overhead_fromItsEnd + "' to use within overheadWireClamp '" + id + "' is not known.");
463  }
464  /*
465  if (ovrhdSegment_fromItsEnd->getTractionSubstation() != substation) {
466  throw InvalidArgument("The overheadWireSegment '" + overhead_fromItsEnd + "' to use within overheadWireClamp is assign to a different overhead wire section or substation.");
467  }
468  */
469  if (substation->findClamp(id) == nullptr) {
470  substation->addClamp(id, ovrhdSegment_fromItsStart, ovrhdSegment_fromItsEnd);
471  } else {
472  WRITE_ERROR("The overhead wire clamp '" + id + "' is probably declared twice.")
473  }
474 #else
475  UNUSED_PARAMETER(attrs);
476  WRITE_WARNING(TL("Not building overhead wire clamps, overhead wire solver support (Eigen) not compiled in."));
477 #endif
478  } else {
479  WRITE_WARNING(TL("Ignoring overhead wire clamps, they make no sense when overhead wire circuit solver is off."));
480  }
481 }
482 
483 
484 void
486  bool ok = true;
487  // get the id, throw if not given or empty...
488  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
489  if (!ok) {
490  throw ProcessError();
491  }
492 
493  //get the name, leave blank if not given
494  const std::string ptStopName = attrs.getOpt<std::string>(SUMO_ATTR_NAME, id.c_str(), ok, "");
495 
496  //get the color, use default if not given
497  // default color, copy from GUIVisualizationStoppingPlaceSettings::busStopColor / containerStopColor
498  RGBColor color = attrs.getOpt<RGBColor>(SUMO_ATTR_COLOR, id.c_str(), ok, RGBColor::INVISIBLE);
499 
500  MSLane* lane = getLane(attrs, toString(element), id);
501  // get the positions
502  double frompos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, id.c_str(), ok, 0.);
503  double topos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, id.c_str(), ok, lane->getLength());
504  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, id.c_str(), ok, false);
505  if (!ok || (myHandler->checkStopPos(frompos, topos, lane->getLength(), POSITION_EPS, friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID)) {
506  throw InvalidArgument("Invalid position for " + toString(element) + " '" + id + "'.");
507  }
508  const std::vector<std::string>& lines = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_LINES, id.c_str(), ok);
509  int defaultCapacity;
510  SumoXMLAttr capacityAttr;
511  if (element != SUMO_TAG_CONTAINER_STOP) {
512  defaultCapacity = MAX2(MSStoppingPlace::getTransportablesAbreast(topos - frompos, element) * 3, 6);
513  capacityAttr = SUMO_ATTR_PERSON_CAPACITY;
514  } else {
515  defaultCapacity = MSStoppingPlace::getTransportablesAbreast(topos - frompos, element);
516  capacityAttr = SUMO_ATTR_CONTAINER_CAPACITY;
517  }
518  const int transportableCapacity = attrs.getOpt<int>(capacityAttr, id.c_str(), ok, defaultCapacity);
519  const double parkingLength = attrs.getOpt<double>(SUMO_ATTR_PARKING_LENGTH, id.c_str(), ok, 0);
520  // build the bus stop
521  buildStoppingPlace(net, id, lines, lane, frompos, topos, element, ptStopName, transportableCapacity, parkingLength, color);
522 }
523 
524 
525 void
527  if (myCurrentStop == nullptr) {
528  throw InvalidArgument("Could not add access outside a stopping place.");
529  }
530  // get the lane
531  MSLane* lane = getLane(attrs, "access", myCurrentStop->getID());
532  if (!lane->allowsVehicleClass(SVC_PEDESTRIAN)) {
533  WRITE_WARNINGF(TL("Ignoring invalid access from non-pedestrian lane '%' in busStop '%'."), lane->getID(), myCurrentStop->getID());
534  return;
535  }
536  // get the positions
537  bool ok = true;
538  const std::string accessPos = attrs.getOpt<std::string>(SUMO_ATTR_POSITION, "access", ok);
539  const bool random = accessPos == "random";
541  if (accessPos == "doors") {
543  } else if (accessPos == "carriage") {
545  }
546  double startPos = random || exit != MSStoppingPlace::AccessExit::PLATFORM ? 0. : attrs.getOpt<double>(SUMO_ATTR_POSITION, "access", ok, 0);
547  double endPos = random || exit != MSStoppingPlace::AccessExit::PLATFORM ? lane->getLength() : startPos;
548  const double length = attrs.getOpt<double>(SUMO_ATTR_LENGTH, "access", ok, -1);
549  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, "access", ok, false);
550  if (!ok || (myHandler->checkStopPos(startPos, endPos, lane->getLength(), 0, friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID)) {
551  throw InvalidArgument("Invalid position " + attrs.getString(SUMO_ATTR_POSITION) + " for access on lane '" + lane->getID() + "' in stop '" + myCurrentStop->getID() + "'.");
552  }
553  // add bus stop access
554  if (!myCurrentStop->addAccess(lane, startPos, endPos, length, exit)) {
555  throw InvalidArgument("Duplicate access on lane '" + lane->getID() + "' for stop '" + myCurrentStop->getID() + "'");
556  }
557 }
558 
559 
560 void
562  bool ok = true;
563  // get the id, throw if not given or empty...
564  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
565  if (!ok) {
566  throw ProcessError();
567  }
568  // get the lane
569  MSLane* lane = getLane(attrs, "parkingArea", id);
570  // get the positions
571  double frompos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, id.c_str(), ok, 0);
572  double topos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, id.c_str(), ok, lane->getLength());
573  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, id.c_str(), ok, false);
574  unsigned int capacity = attrs.getOpt<int>(SUMO_ATTR_ROADSIDE_CAPACITY, id.c_str(), ok, 0);
576  bool onRoad = attrs.getOpt<bool>(SUMO_ATTR_ONROAD, id.c_str(), ok, false);
577  double width = attrs.getOpt<double>(SUMO_ATTR_WIDTH, id.c_str(), ok, 0);
578  double length = attrs.getOpt<double>(SUMO_ATTR_LENGTH, id.c_str(), ok, 0);
579  double angle = attrs.getOpt<double>(SUMO_ATTR_ANGLE, id.c_str(), ok, 0);
580  const std::string name = attrs.getOpt<std::string>(SUMO_ATTR_NAME, id.c_str(), ok);
581  const std::string departPos = attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS, id.c_str(), ok);
582  bool lefthand = attrs.getOpt<bool>(SUMO_ATTR_LEFTHAND, id.c_str(), ok, false);
583  const std::vector<std::string>& acceptedBadges = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_ACCEPTED_BADGES, id.c_str(), ok);
584 
585  if (!ok || (myHandler->checkStopPos(frompos, topos, lane->getLength(), POSITION_EPS, friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID)) {
586  throw InvalidArgument("Invalid position for parking area '" + id + "'.");
587  }
588  const std::vector<std::string>& lines = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_LINES, id.c_str(), ok);
589  // build the parking area
590  beginParkingArea(net, id, lines, acceptedBadges, lane, frompos, topos, capacity, width, length, angle, name, onRoad, departPos, lefthand);
591 }
592 
593 
594 
595 void
597  bool ok = true;
598  // Check for open parking area
599  if (myParkingArea == nullptr) {
600  throw ProcessError();
601  }
602  // get the positions
603  double x = attrs.get<double>(SUMO_ATTR_X, "", ok);
604  if (!ok) {
605  throw InvalidArgument("Invalid x position for lot entry.");
606  }
607  double y = attrs.get<double>(SUMO_ATTR_Y, "", ok);
608  if (!ok) {
609  throw InvalidArgument("Invalid y position for lot entry.");
610  }
611  double z = attrs.getOpt<double>(SUMO_ATTR_Z, "", ok, 0.);
612  double width = attrs.getOpt<double>(SUMO_ATTR_WIDTH, "", ok, myParkingArea->getWidth());
613  double length = attrs.getOpt<double>(SUMO_ATTR_LENGTH, "", ok, myParkingArea->getLength());
614  double angle = attrs.getOpt<double>(SUMO_ATTR_ANGLE, "", ok, myParkingArea->getAngle());
615  double slope = attrs.getOpt<double>(SUMO_ATTR_SLOPE, "", ok, 0.);
616  // add the lot entry
617  addLotEntry(x, y, z, width, length, angle, slope);
618 }
619 
620 
621 void
623  const std::string& base) {
624  bool ok = true;
625  // get the id, throw if not given or empty...
626  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
627  if (!ok) {
628  throw ProcessError();
629  }
630  MSLane* lane = nullptr;
631  MSEdge* edge = nullptr;
632  MSJunction* node = nullptr;
633  if (attrs.hasAttribute(SUMO_ATTR_NODE)) {
635  throw InvalidArgument("The node calibrator '" + id + "' cannot define an edge or lane as well.");
636  }
637  const std::string nodeID = attrs.get<std::string>(SUMO_ATTR_NODE, id.c_str(), ok);
638  node = net.getJunctionControl().get(nodeID);
639  if (node == nullptr) {
640  throw InvalidArgument("The node " + nodeID + " to use within the calibrator '" + id + "' is not known.");
641  }
642  } else {
643  if (attrs.hasAttribute(SUMO_ATTR_EDGE)) {
644  const std::string edgeID = attrs.get<std::string>(SUMO_ATTR_EDGE, id.c_str(), ok);
645  edge = MSEdge::dictionary(edgeID);
646  if (edge == nullptr) {
647  throw InvalidArgument("The edge " + edgeID + " to use within the calibrator '" + id + "' is not known.");
648  }
649  if (attrs.hasAttribute(SUMO_ATTR_LANE)) {
650  lane = getLane(attrs, "calibrator", id);
651  if (&lane->getEdge() != edge) {
652  throw InvalidArgument("The edge " + edgeID + " to use within the calibrator '" + id
653  + "' does not match the calibrator lane '" + lane->getID() + ".");
654  }
655  }
656  } else {
657  lane = getLane(attrs, "calibrator", id);
658  edge = &lane->getEdge();
659  }
660  }
661  const double pos = node != nullptr ? 0 : getPosition(attrs, lane, "calibrator", id, edge);
662  const SUMOTime period = attrs.getOptPeriod(id.c_str(), ok, DELTA_T); // !!! no error handling
663  const std::string vTypes = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id.c_str(), ok, "");
664  const std::string file = getFileName(attrs, base, true);
665  const std::string outfile = attrs.getOpt<std::string>(SUMO_ATTR_OUTPUT, id.c_str(), ok, "");
666  const std::string routeProbe = attrs.getOpt<std::string>(SUMO_ATTR_ROUTEPROBE, id.c_str(), ok, "");
667  // differing defaults for backward compatibility, values are dimensionless
668  const double invalidJamThreshold = attrs.getOpt<double>(SUMO_ATTR_JAM_DIST_THRESHOLD, id.c_str(), ok, MSGlobals::gUseMesoSim ? 0.8 : 0.5);
669  const bool local = attrs.getOpt<bool>(SUMO_ATTR_LOCAL, id.c_str(), ok, false);
670  MSRouteProbe* probe = nullptr;
671  if (routeProbe != "") {
672  probe = dynamic_cast<MSRouteProbe*>(net.getDetectorControl().getTypedDetectors(SUMO_TAG_ROUTEPROBE).get(routeProbe));
673  if (probe == nullptr) {
674  throw InvalidArgument("The routeProbe '" + routeProbe + "' to use within the calibrator '" + id + "' is not known.");
675  }
676  }
678  if (lane != nullptr && edge->getLanes().size() > 1) {
679  WRITE_WARNING("Meso calibrator '" + id
680  + "' defined for lane '" + lane->getID()
681  + "' will collect data for all lanes of edge '" + edge->getID() + "'.");
682  }
683  METriggeredCalibrator* trigger = buildMECalibrator(id, edge, pos, file, outfile, period, probe, invalidJamThreshold, vTypes);
684  if (file == "") {
686  }
687  } else {
688  MSCalibrator* trigger = buildCalibrator(id, edge, lane, node, pos, file, outfile, period, probe, invalidJamThreshold, vTypes, local);
689  if (file == "") {
691  }
692  }
693 }
694 
695 
696 void
698  bool ok = true;
699  // get the id, throw if not given or empty...
700  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
701  if (!ok) {
702  throw ProcessError();
703  }
704  if (MSTriggeredRerouter::getInstances().count(id) > 0) {
705  throw InvalidArgument("Could not build rerouter '" + id + "'; probably declared twice.");
706  }
707  MSEdgeVector edges;
708  for (const std::string& edgeID : attrs.get<std::vector<std::string> >(SUMO_ATTR_EDGES, id.c_str(), ok)) {
709  MSEdge* edge = MSEdge::dictionary(edgeID);
710  if (edge == nullptr) {
711  throw InvalidArgument("The edge '" + edgeID + "' to use within rerouter '" + id + "' is not known.");
712  }
713  edges.push_back(edge);
714  }
715  if (!ok) {
716  throw InvalidArgument("The edge to use within rerouter '" + id + "' is not known.");
717  }
718  if (edges.size() == 0) {
719  throw InvalidArgument("No edges found for rerouter '" + id + "'.");
720  }
721  const double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, id.c_str(), ok, 1);
722  const bool off = attrs.getOpt<bool>(SUMO_ATTR_OFF, id.c_str(), ok, false);
723  const bool optional = attrs.getOpt<bool>(SUMO_ATTR_OPTIONAL, id.c_str(), ok, false);
724  const SUMOTime timeThreshold = TIME2STEPS(attrs.getOpt<double>(SUMO_ATTR_HALTING_TIME_THRESHOLD, id.c_str(), ok, 0));
725  const std::string vTypes = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id.c_str(), ok, "");
726  const std::string pos = attrs.getOpt<std::string>(SUMO_ATTR_POSITION, id.c_str(), ok, "");
728  if (pos != "") {
729  const std::vector<std::string> posSplit = StringTokenizer(pos, ",").getVector();
730  if (posSplit.size() == 1) {
731  p = edges.front()->getLanes()[0]->geometryPositionAtOffset(StringUtils::toDouble(posSplit[0]));
732  } else if (posSplit.size() == 2) {
733  p = Position(StringUtils::toDouble(posSplit[0]), StringUtils::toDouble(posSplit[1]));
734  } else if (posSplit.size() == 3) {
735  p = Position(StringUtils::toDouble(posSplit[0]), StringUtils::toDouble(posSplit[1]), StringUtils::toDouble(posSplit[2]));
736  } else {
737  throw InvalidArgument("Invalid position for rerouter '" + id + "'.");
738  }
739  }
740  if (!ok) {
741  throw InvalidArgument("Could not parse rerouter '" + id + "'.");
742  }
743  MSTriggeredRerouter* trigger = buildRerouter(net, id, edges, prob, off, optional, timeThreshold, vTypes, p);
744  // read in the trigger description
746 }
747 
748 
749 // -------------------------
750 
751 
753 NLTriggerBuilder::buildLaneSpeedTrigger(MSNet& /*net*/, const std::string& id,
754  const std::vector<MSLane*>& destLanes,
755  const std::string& file) {
756  return new MSLaneSpeedTrigger(id, destLanes, file);
757 }
758 
759 
762  MSEdge* edge,
763  double pos,
764  const std::string& file,
765  const std::string& outfile,
766  const SUMOTime freq,
767  MSRouteProbe* probe,
768  const double invalidJamThreshold,
769  const std::string& vTypes) {
770  return new METriggeredCalibrator(id, edge, pos, file, outfile, freq,
771  edge == nullptr ? 0. : MSGlobals::gMesoNet->getSegmentForEdge(*edge, pos)->getLength(),
772  probe, invalidJamThreshold, vTypes);
773 }
774 
775 
777 NLTriggerBuilder::buildCalibrator(const std::string& id,
778  MSEdge* edge,
779  MSLane* lane,
780  MSJunction* node,
781  double pos,
782  const std::string& file,
783  const std::string& outfile,
784  const SUMOTime freq,
785  const MSRouteProbe* probe,
786  const double invalidJamThreshold,
787  const std::string& vTypes,
788  const bool local) {
789  return new MSCalibrator(id, edge, lane, node, pos, file, outfile, freq,
790  edge == nullptr ? 0. : edge->getLength(),
791  probe, invalidJamThreshold, vTypes, local, true);
792 }
793 
794 
796 NLTriggerBuilder::buildRerouter(MSNet&, const std::string& id,
797  MSEdgeVector& edges, double prob, bool off, bool optional,
798  SUMOTime timeThreshold, const std::string& vTypes, const Position& pos) {
799  return new MSTriggeredRerouter(id, edges, prob, off, optional, timeThreshold, vTypes, pos);
800 }
801 
802 
803 void
804 NLTriggerBuilder::buildStoppingPlace(MSNet& net, std::string id, std::vector<std::string> lines, MSLane* lane,
805  double frompos, double topos, const SumoXMLTag element, std::string ptStopName,
806  int personCapacity, double parkingLength, RGBColor& color) {
807  myCurrentStop = new MSStoppingPlace(id, element, lines, *lane, frompos, topos, ptStopName, personCapacity, parkingLength, color);
808  if (!net.addStoppingPlace(element, myCurrentStop)) {
809  delete myCurrentStop;
810  myCurrentStop = nullptr;
811  throw InvalidArgument("Could not build " + toString(element) + " '" + id + "'; probably declared twice.");
812  }
813 }
814 
815 
816 void
817 NLTriggerBuilder::beginParkingArea(MSNet& net, const std::string& id,
818  const std::vector<std::string>& lines,
819  const std::vector<std::string>& badges,
820  MSLane* lane, double frompos, double topos,
821  unsigned int capacity,
822  double width, double length, double angle, const std::string& name,
823  bool onRoad,
824  const std::string& departPos,
825  bool lefthand) {
826  // Close previous parking area if there are no lots inside
827  MSParkingArea* stop = new MSParkingArea(id, lines, badges, *lane, frompos, topos, capacity, width, length, angle, name, onRoad, departPos, lefthand);
828  if (!net.addStoppingPlace(SUMO_TAG_PARKING_AREA, stop)) {
829  delete stop;
830  throw InvalidArgument("Could not build parking area '" + id + "'; probably declared twice.");
831  } else {
832  myParkingArea = stop;
833  }
834 }
835 
836 
837 void
838 NLTriggerBuilder::addLotEntry(double x, double y, double z,
839  double width, double length,
840  double angle, double slope) {
841  if (myParkingArea != nullptr) {
842  if (!myParkingArea->parkOnRoad()) {
843  myParkingArea->addLotEntry(x, y, z, width, length, angle, slope);
845  } else {
846  throw InvalidArgument("Cannot not add lot entry to on-road parking area.");
847  }
848  } else {
849  throw InvalidArgument("Could not add lot entry outside a parking area.");
850  }
851 }
852 
853 
854 void
856  if (myParkingArea != nullptr) {
857  myParkingArea = nullptr;
858  myParkingAreaCapacitySet = false;
859  } else {
860  throw InvalidArgument("Could not end a parking area that is not opened.");
861  }
862 }
863 
864 
865 void
867  if (myCurrentStop != nullptr) {
868  myCurrentStop = nullptr;
869  } else {
870  throw InvalidArgument("Could not end a stopping place that is not opened.");
871  }
872 }
873 
874 
875 void
876 NLTriggerBuilder::buildChargingStation(MSNet& net, const std::string& id, MSLane* lane, double frompos, double topos,
877  const std::string& name, double chargingPower, double efficiency, bool chargeInTransit,
878  SUMOTime chargeDelay, std::string chargeType, SUMOTime waitingTime, MSParkingArea* parkingArea) {
879  MSChargingStation* chargingStation = (parkingArea == nullptr) ? new MSChargingStation(id, *lane, frompos, topos, name, chargingPower, efficiency,
880  chargeInTransit, chargeDelay, chargeType, waitingTime) : new MSChargingStation(id, parkingArea, name, chargingPower, efficiency,
881  chargeInTransit, chargeDelay, chargeType, waitingTime);
882  if (!net.addStoppingPlace(SUMO_TAG_CHARGING_STATION, chargingStation)) {
883  delete chargingStation;
884  throw InvalidArgument("Could not build charging station '" + id + "'; probably declared twice.");
885  }
886  myCurrentStop = chargingStation;
887 }
888 
889 
890 void
891 NLTriggerBuilder::buildOverheadWireSegment(MSNet& net, const std::string& id, MSLane* lane, double frompos, double topos,
892  bool voltageSource) {
893  MSOverheadWire* overheadWireSegment = new MSOverheadWire(id, *lane, frompos, topos, voltageSource);
894  if (!net.addStoppingPlace(SUMO_TAG_OVERHEAD_WIRE_SEGMENT, overheadWireSegment)) {
895  delete overheadWireSegment;
896  throw InvalidArgument("Could not build overheadWireSegment '" + id + "'; probably declared twice.");
897  }
898 }
899 
900 void
901 NLTriggerBuilder::buildInnerOverheadWireSegments(MSNet& net, const MSLane* connection, const MSLane* frontConnection, const MSLane* behindConnection) {
902  if (frontConnection == NULL && behindConnection == NULL) {
903  buildOverheadWireSegment(net, "ovrhd_inner_" + connection->getID(), const_cast<MSLane*>(connection), 0, connection->getLength(), false);
904  } else if (frontConnection != NULL && behindConnection == NULL) {
905  buildOverheadWireSegment(net, "ovrhd_inner_" + frontConnection->getID(), const_cast<MSLane*>(frontConnection), 0, frontConnection->getLength(), false);
906  buildOverheadWireSegment(net, "ovrhd_inner_" + connection->getID(), const_cast<MSLane*>(connection), 0, connection->getLength(), false);
907  } else if (frontConnection == NULL && behindConnection != NULL) {
908  buildOverheadWireSegment(net, "ovrhd_inner_" + behindConnection->getID(), const_cast<MSLane*>(behindConnection), 0, behindConnection->getLength(), false);
909  buildOverheadWireSegment(net, "ovrhd_inner_" + connection->getID(), const_cast<MSLane*>(connection), 0, connection->getLength(), false);
910  } else if (frontConnection != NULL && behindConnection != NULL) {
911  buildOverheadWireSegment(net, "ovrhd_inner_" + frontConnection->getID(), const_cast<MSLane*>(frontConnection), 0, frontConnection->getLength(), false);
912  buildOverheadWireSegment(net, "ovrhd_inner_" + behindConnection->getID(), const_cast<MSLane*>(behindConnection), 0, behindConnection->getLength(), false);
913  buildOverheadWireSegment(net, "ovrhd_inner_" + connection->getID(), const_cast<MSLane*>(connection), 0, connection->getLength(), false);
914  }
915 }
916 
917 void
918 NLTriggerBuilder::buildTractionSubstation(MSNet& net, std::string id, double voltage, double currentLimit) {
919  MSTractionSubstation* myTractionSubstation = new MSTractionSubstation(id, voltage, currentLimit);
920  if (!net.addTractionSubstation(myTractionSubstation)) {
921  delete myTractionSubstation;
922  throw InvalidArgument("Could not build traction substation '" + id + "'; probably declared twice.");
923  }
924 }
925 
926 void
927 NLTriggerBuilder::buildOverheadWireClamp(MSNet& /*net*/, const std::string& /*id*/, MSLane* /*lane_start*/, MSLane* /*lane_end*/) {
928 }
929 
930 std::string
932  const std::string& base,
933  const bool allowEmpty) {
934  // get the file name to read further definitions from
935  bool ok = true;
936  std::string file = attrs.getOpt<std::string>(SUMO_ATTR_FILE, nullptr, ok, "");
937  if (file == "") {
938  if (allowEmpty) {
939  return file;
940  }
941  throw InvalidArgument("No filename given.");
942  }
943  // check whether absolute or relative filenames are given
944  if (!FileHelpers::isAbsolute(file)) {
945  return FileHelpers::getConfigurationRelative(base, file);
946  }
947  return file;
948 }
949 
950 
951 MSLane*
953  const std::string& tt,
954  const std::string& tid) {
955  bool ok = true;
956  std::string objectid = attrs.get<std::string>(SUMO_ATTR_LANE, tid.c_str(), ok);
957  MSLane* lane = MSLane::dictionary(objectid);
958  if (lane == nullptr) {
959  // Either a lane that is non-existent/broken, or a lane that is internal and has been ignored.
960  // We assume that internal lane names start with ':'.
961  if (objectid[0] == ':' && !MSGlobals::gUsingInternalLanes) {
962  return nullptr;
963  }
964  // Throw the exception only in case that the lane really does not exist in the network file
965  // or it is broken.
966  throw InvalidArgument("The lane " + objectid + " to use within the " + tt + " '" + tid + "' is not known.");
967  }
968  return lane;
969 }
970 
971 
973 NLTriggerBuilder::getParkingArea(const SUMOSAXAttributes& attrs, const std::string& tt, const std::string& tid) {
974  bool ok = true;
975  std::string objectID = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, tid.c_str(), ok);
976  if (!ok || objectID.size() == 0) {
977  return nullptr;
978  }
980  if (pa == nullptr) {
981  // Throw the exception only in case that the lane really does not exist in the network file
982  // or it is broken.
983  throw InvalidArgument("The parkingArea " + objectID + " to use within the " + tt + " '" + tid + "' is not known.");
984  }
985  return pa;
986 }
987 
988 
989 double
991  MSLane* lane,
992  const std::string& tt, const std::string& tid,
993  MSEdge* edge) {
994  assert(lane != nullptr || edge != nullptr);
995  const double length = lane != nullptr ? lane->getLength() : edge->getLength();
996  bool ok = true;
997  double pos = attrs.get<double>(SUMO_ATTR_POSITION, nullptr, ok);
998  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, false);
999  if (!ok) {
1000  throw InvalidArgument("Error on parsing a position information.");
1001  }
1002  if (pos < 0) {
1003  pos = length + pos;
1004  }
1005  if (pos > length) {
1006  if (friendlyPos) {
1007  pos = length - (double) 0.1;
1008  } else {
1009  if (lane != nullptr) {
1010  throw InvalidArgument("The position of " + tt + " '" + tid + "' lies beyond the lane's '" + lane->getID() + "' length.");
1011  } else {
1012  throw InvalidArgument("The position of " + tt + " '" + tid + "' lies beyond the edge's '" + edge->getID() + "' length.");
1013  }
1014  }
1015  }
1016  return pos;
1017 }
1018 
1019 
1020 void
1022  if (myParkingArea != nullptr && !myParkingAreaCapacitySet) {
1024  }
1025 }
1026 
1027 
1030  return myParkingArea == nullptr ? myCurrentStop : myParkingArea;
1031 }
1032 
1033 
1034 /****************************************************************************/
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_NODE
@ 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_LOCAL
@ 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:519
double getLength() const
return the length of the edge
Definition: MSEdge.h:670
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:995
SUMOTime incVaporization(SUMOTime t)
Enables vaporization.
Definition: MSEdge.cpp:512
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
The base class for an intersection.
Definition: MSJunction.h:58
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:2661
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:3228
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition: MSLane.cpp:2395
bool isInternal() const
Definition: MSLane.cpp:2526
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:3238
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:1357
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:184
MSDetectorControl & getDetectorControl()
Returns the detector control.
Definition: MSNet.h:441
bool addTractionSubstation(MSTractionSubstation *substation)
Adds a traction substation.
Definition: MSNet.cpp:1363
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:1394
MSJunctionControl & getJunctionControl()
Returns the junctions control.
Definition: MSNet.h:461
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition: MSNet.cpp:1373
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:1465
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
void setRoadsideCapacity(int capactity)
overwrite the capacity (caution: will delete ANY previous parking space definitions)
Writes routes of vehicles passing a certain edge.
Definition: MSRouteProbe.h:58
A lane area vehicles can halt at.
int getTransportablesAbreast() const
const MSLane & getLane() const
Returns the lane this stop is located at.
virtual bool addAccess(MSLane *const lane, const double startPos, const double endPos, double length, const MSStoppingPlace::AccessExit exit)
adds an access point to this stop
Traction substation 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
void updateParkingAreaDefaultCapacity()
updates the parkingArea default capacity
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 ~NLTriggerBuilder()
Destructor.
void buildTractionSubstation(MSNet &net, std::string id, double voltage, double currentLimit)
Builds a traction substation.
virtual METriggeredCalibrator * buildMECalibrator(const std::string &id, 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
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 MSCalibrator * buildCalibrator(const std::string &id, MSEdge *edge, MSLane *lane, MSJunction *node, double pos, const std::string &file, const std::string &outfile, const SUMOTime freq, const MSRouteProbe *probe, const double invalidJamThreshold, const std::string &vTypes, const bool local)
builds a microscopic 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:322
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.