Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
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-2026 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>
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
66void
68 myHandler = handler;
69}
70
71
72void
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 }
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
108void
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
146void
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 totalPower = attrs.getOpt<double>(SUMO_ATTR_TOTALPOWER, id.c_str(), ok, -1);
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 != "battery-exchange") && (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, totalPower, efficiency, chargeInTransit, chargeDelay, chargeType, waitingTime, parkingArea);
180}
181
182
183void
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
224 WRITE_WARNING(TL("Overhead wire solver (Eigen) not compiled in, expect errors in overhead wire simulation"))
225 }
226#endif // !HAVE_EIGEN
227}
228
229void
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
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 + "'.");
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
410void
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
426void
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 }
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
485void
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 double angle = attrs.getOpt<double>(SUMO_ATTR_ANGLE, id.c_str(), ok, 90);
506 const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, id.c_str(), ok, false);
507 if (!ok || (myHandler->checkStopPos(frompos, topos, lane->getLength(), POSITION_EPS, friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID)) {
508 throw InvalidArgument("Invalid position for " + toString(element) + " '" + id + "'.");
509 }
510 const std::vector<std::string>& lines = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_LINES, id.c_str(), ok);
511 int defaultCapacity;
512 SumoXMLAttr capacityAttr;
513 if (element != SUMO_TAG_CONTAINER_STOP) {
514 defaultCapacity = MAX2(MSStoppingPlace::getDefaultTransportablesAbreast(topos - frompos, element) * 3, 6);
515 capacityAttr = SUMO_ATTR_PERSON_CAPACITY;
516 } else {
517 defaultCapacity = MSStoppingPlace::getDefaultTransportablesAbreast(topos - frompos, element);
518 capacityAttr = SUMO_ATTR_CONTAINER_CAPACITY;
519 }
520 const int transportableCapacity = attrs.getOpt<int>(capacityAttr, id.c_str(), ok, defaultCapacity);
521 const double parkingLength = attrs.getOpt<double>(SUMO_ATTR_PARKING_LENGTH, id.c_str(), ok, 0);
522 // build the bus stop
523 buildStoppingPlace(net, id, lines, lane, frompos, topos, element, ptStopName, transportableCapacity, parkingLength, color, angle);
524}
525
526
527void
529 if (myCurrentStop == nullptr) {
530 throw InvalidArgument("Could not add access outside a stopping place.");
531 }
532 // get the lane
533 MSLane* lane = getLane(attrs, "access", myCurrentStop->getID());
535 WRITE_WARNINGF(TL("Ignoring invalid access from non-pedestrian lane '%' in busStop '%'."), lane->getID(), myCurrentStop->getID());
536 return;
537 }
538 // get the positions
539 bool ok = true;
540 const std::string accessPos = attrs.getOpt<std::string>(SUMO_ATTR_POSITION, "access", ok);
541 const bool random = accessPos == "random";
543 if (accessPos == "doors") {
545 } else if (accessPos == "carriage") {
547 }
548 double startPos = random || exit != MSStoppingPlace::AccessExit::PLATFORM ? 0. : attrs.getOpt<double>(SUMO_ATTR_POSITION, "access", ok, 0);
549 double endPos = random || exit != MSStoppingPlace::AccessExit::PLATFORM ? lane->getLength() : startPos;
550 const double length = attrs.getOpt<double>(SUMO_ATTR_LENGTH, "access", ok, -1);
551 const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, "access", ok, false);
552 if (!ok || (myHandler->checkStopPos(startPos, endPos, lane->getLength(), 0, friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID)) {
553 throw InvalidArgument("Invalid position " + attrs.getString(SUMO_ATTR_POSITION) + " for access on lane '" + lane->getID() + "' in stop '" + myCurrentStop->getID() + "'.");
554 }
555 // add bus stop access
556 if (!myCurrentStop->addAccess(lane, startPos, endPos, length, exit)) {
557 throw InvalidArgument("Duplicate access on lane '" + lane->getID() + "' for stop '" + myCurrentStop->getID() + "'");
558 }
559}
560
561
562void
564 bool ok = true;
565 // get the id, throw if not given or empty...
566 std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
567 if (!ok) {
568 throw ProcessError();
569 }
570 // get the lane
571 MSLane* lane = getLane(attrs, "parkingArea", id);
572 // get the positions
573 double frompos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, id.c_str(), ok, 0);
574 double topos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, id.c_str(), ok, lane->getLength());
575 const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, id.c_str(), ok, false);
576 unsigned int capacity = attrs.getOpt<int>(SUMO_ATTR_ROADSIDE_CAPACITY, id.c_str(), ok, 0);
578 bool onRoad = attrs.getOpt<bool>(SUMO_ATTR_ONROAD, id.c_str(), ok, false);
579 double width = attrs.getOpt<double>(SUMO_ATTR_WIDTH, id.c_str(), ok, 0);
580 double length = attrs.getOpt<double>(SUMO_ATTR_LENGTH, id.c_str(), ok, 0);
581 double angle = attrs.getOpt<double>(SUMO_ATTR_ANGLE, id.c_str(), ok, 0);
582 const std::string name = attrs.getOpt<std::string>(SUMO_ATTR_NAME, id.c_str(), ok);
583 const std::string departPos = attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS, id.c_str(), ok);
584 bool lefthand = attrs.getOpt<bool>(SUMO_ATTR_LEFTHAND, id.c_str(), ok, false);
585 const std::vector<std::string>& acceptedBadges = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_ACCEPTED_BADGES, id.c_str(), ok);
586 const bool reservable = attrs.getOpt<bool>(SUMO_ATTR_RESERVABLE, id.c_str(), ok, false);
587
588 if (!ok || (myHandler->checkStopPos(frompos, topos, lane->getLength(), POSITION_EPS, friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID)) {
589 throw InvalidArgument("Invalid position for parking area '" + id + "'.");
590 }
591 const std::vector<std::string>& lines = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_LINES, id.c_str(), ok);
592 // build the parking area
593 beginParkingArea(net, id, lines, acceptedBadges, lane, frompos, topos, capacity, width, length, angle, name, onRoad, departPos, lefthand, reservable);
594}
595
596
597
598void
600 bool ok = true;
601 // Check for open parking area
602 if (myParkingArea == nullptr) {
603 throw ProcessError();
604 }
605 // get the positions
606 double x = attrs.get<double>(SUMO_ATTR_X, "", ok);
607 if (!ok) {
608 throw InvalidArgument("Invalid x position for lot entry.");
609 }
610 double y = attrs.get<double>(SUMO_ATTR_Y, "", ok);
611 if (!ok) {
612 throw InvalidArgument("Invalid y position for lot entry.");
613 }
614 double z = attrs.getOpt<double>(SUMO_ATTR_Z, "", ok, 0.);
615 double width = attrs.getOpt<double>(SUMO_ATTR_WIDTH, "", ok, myParkingArea->getWidth());
616 double length = attrs.getOpt<double>(SUMO_ATTR_LENGTH, "", ok, myParkingArea->getLength());
617 double angle = attrs.getOpt<double>(SUMO_ATTR_ANGLE, "", ok, myParkingArea->getAngle());
618 double slope = attrs.getOpt<double>(SUMO_ATTR_SLOPE, "", ok, 0.);
619 // add the lot entry
620 addLotEntry(x, y, z, width, length, angle, slope);
621}
622
623
624void
626 const std::string& base) {
627 bool ok = true;
628 // get the id, throw if not given or empty...
629 std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
630 if (!ok) {
631 throw ProcessError();
632 }
633 MSLane* lane = nullptr;
634 MSEdge* edge = nullptr;
635 MSJunction* node = nullptr;
636 if (attrs.hasAttribute(SUMO_ATTR_NODE)) {
638 throw InvalidArgument("The node calibrator '" + id + "' cannot define an edge or lane as well.");
639 }
640 const std::string nodeID = attrs.get<std::string>(SUMO_ATTR_NODE, id.c_str(), ok);
641 node = net.getJunctionControl().get(nodeID);
642 if (node == nullptr) {
643 throw InvalidArgument("The node " + nodeID + " to use within the calibrator '" + id + "' is not known.");
644 }
645 } else {
646 if (attrs.hasAttribute(SUMO_ATTR_EDGE)) {
647 const std::string edgeID = attrs.get<std::string>(SUMO_ATTR_EDGE, id.c_str(), ok);
648 edge = MSEdge::dictionary(edgeID);
649 if (edge == nullptr) {
650 throw InvalidArgument("The edge " + edgeID + " to use within the calibrator '" + id + "' is not known.");
651 }
652 if (attrs.hasAttribute(SUMO_ATTR_LANE)) {
653 lane = getLane(attrs, "calibrator", id);
654 if (&lane->getEdge() != edge) {
655 throw InvalidArgument("The edge " + edgeID + " to use within the calibrator '" + id
656 + "' does not match the calibrator lane '" + lane->getID() + ".");
657 }
658 }
659 } else {
660 lane = getLane(attrs, "calibrator", id);
661 edge = &lane->getEdge();
662 }
663 }
664 const double pos = node != nullptr ? 0 : getPosition(attrs, lane, "calibrator", id, edge);
665 SUMOTime period = attrs.getOptPeriod(id.c_str(), ok, DELTA_T); // !!! no error handling
666 if (period > TIME2STEPS(1)) {
667 WRITE_WARNINGF("Reducing period to 1 for calibrator '%'", id);
668 period = TIME2STEPS(1);
669 }
670 const std::string vTypes = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id.c_str(), ok, "");
671 const std::string file = getFileName(attrs, base, true);
672 const std::string outfile = attrs.getOpt<std::string>(SUMO_ATTR_OUTPUT, id.c_str(), ok, "");
673 const std::string routeProbe = attrs.getOpt<std::string>(SUMO_ATTR_ROUTEPROBE, id.c_str(), ok, "");
674 // differing defaults for backward compatibility, values are dimensionless
675 const double invalidJamThreshold = attrs.getOpt<double>(SUMO_ATTR_JAM_DIST_THRESHOLD, id.c_str(), ok, MSGlobals::gUseMesoSim ? 0.8 : 0.5);
676 const bool local = attrs.getOpt<bool>(SUMO_ATTR_LOCAL, id.c_str(), ok, false);
677 MSRouteProbe* probe = nullptr;
678 if (routeProbe != "") {
679 probe = dynamic_cast<MSRouteProbe*>(net.getDetectorControl().getTypedDetectors(SUMO_TAG_ROUTEPROBE).get(routeProbe));
680 if (probe == nullptr) {
681 throw InvalidArgument("The routeProbe '" + routeProbe + "' to use within the calibrator '" + id + "' is not known.");
682 }
683 }
685 if (lane != nullptr && edge->getLanes().size() > 1) {
686 WRITE_WARNING("Meso calibrator '" + id
687 + "' defined for lane '" + lane->getID()
688 + "' will collect data for all lanes of edge '" + edge->getID() + "'.");
689 }
690 METriggeredCalibrator* trigger = buildMECalibrator(id, edge, pos, file, outfile, period, probe, invalidJamThreshold, vTypes);
691 if (file == "") {
693 }
694 } else {
695 MSCalibrator* trigger = buildCalibrator(id, edge, lane, node, pos, file, outfile, period, probe, invalidJamThreshold, vTypes, local);
696 if (file == "") {
698 }
699 }
700}
701
702
703void
705 bool ok = true;
706 // get the id, throw if not given or empty...
707 std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
708 if (!ok) {
709 throw ProcessError();
710 }
711 if (MSTriggeredRerouter::getInstances().count(id) > 0) {
712 throw InvalidArgument("Could not build rerouter '" + id + "'; probably declared twice.");
713 }
714 MSEdgeVector edges;
715 for (const std::string& edgeID : attrs.get<std::vector<std::string> >(SUMO_ATTR_EDGES, id.c_str(), ok)) {
716 MSEdge* edge = MSEdge::dictionary(edgeID);
717 if (edge == nullptr) {
718 throw InvalidArgument("The edge '" + edgeID + "' to use within rerouter '" + id + "' is not known.");
719 }
720 edges.push_back(edge);
721 }
722 if (!ok) {
723 throw InvalidArgument("The edge to use within rerouter '" + id + "' is not known.");
724 }
725 if (edges.size() == 0) {
726 throw InvalidArgument("No edges found for rerouter '" + id + "'.");
727 }
728 const double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, id.c_str(), ok, 1);
729 const bool off = attrs.getOpt<bool>(SUMO_ATTR_OFF, id.c_str(), ok, false);
730 const bool optional = attrs.getOpt<bool>(SUMO_ATTR_OPTIONAL, id.c_str(), ok, false);
731 const SUMOTime timeThreshold = TIME2STEPS(attrs.getOpt<double>(SUMO_ATTR_HALTING_TIME_THRESHOLD, id.c_str(), ok, 0));
732 const std::string vTypes = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id.c_str(), ok, "");
733 const std::string pos = attrs.getOpt<std::string>(SUMO_ATTR_POSITION, id.c_str(), ok, "");
734 const double radius = attrs.getOpt<double>(SUMO_ATTR_RADIUS, id.c_str(), ok, std::numeric_limits<double>::max());
736 WRITE_WARNINGF(TL("It is strongly advisable to give an explicit position when using radius in the definition of rerouter '%'."), id)
737 }
739 if (pos != "") {
740 const std::vector<std::string> posSplit = StringTokenizer(pos, ",").getVector();
741 if (posSplit.size() == 1) {
742 double lanePos = StringUtils::toDouble(pos);
743 if (lanePos < 0) {
744 lanePos += edges.front()->getLanes()[0]->getLength();
745 }
746 p = edges.front()->getLanes()[0]->geometryPositionAtOffset(lanePos);
747 } else if (posSplit.size() == 2) {
748 p = Position(StringUtils::toDouble(posSplit[0]), StringUtils::toDouble(posSplit[1]));
749 } else if (posSplit.size() == 3) {
750 p = Position(StringUtils::toDouble(posSplit[0]), StringUtils::toDouble(posSplit[1]), StringUtils::toDouble(posSplit[2]));
751 } else {
752 throw InvalidArgument("Invalid position for rerouter '" + id + "'.");
753 }
754 }
755 if (!ok) {
756 throw InvalidArgument("Could not parse rerouter '" + id + "'.");
757 }
758 MSTriggeredRerouter* trigger = buildRerouter(net, id, edges, prob, off, optional, timeThreshold, vTypes, p, radius);
759 // read in the trigger description
761}
762
763
764// -------------------------
765
766
768NLTriggerBuilder::buildLaneSpeedTrigger(MSNet& /*net*/, const std::string& id,
769 const std::vector<MSLane*>& destLanes,
770 const std::string& file) {
771 return new MSLaneSpeedTrigger(id, destLanes, file);
772}
773
774
777 MSEdge* edge,
778 double pos,
779 const std::string& file,
780 const std::string& outfile,
781 const SUMOTime freq,
782 MSRouteProbe* probe,
783 const double invalidJamThreshold,
784 const std::string& vTypes) {
785 return new METriggeredCalibrator(id, edge, pos, file, outfile, freq,
786 edge == nullptr ? 0. : MSGlobals::gMesoNet->getSegmentForEdge(*edge, pos)->getLength(),
787 probe, invalidJamThreshold, vTypes);
788}
789
790
793 MSEdge* edge,
794 MSLane* lane,
795 MSJunction* node,
796 double pos,
797 const std::string& file,
798 const std::string& outfile,
799 const SUMOTime freq,
800 const MSRouteProbe* probe,
801 const double invalidJamThreshold,
802 const std::string& vTypes,
803 const bool local) {
804 return new MSCalibrator(id, edge, lane, node, pos, file, outfile, freq,
805 edge == nullptr ? 0. : edge->getLength(),
806 probe, invalidJamThreshold, vTypes, local, true);
807}
808
809
812 MSEdgeVector& edges, double prob, bool off, bool optional,
813 SUMOTime timeThreshold, const std::string& vTypes, const Position& pos, const double radius) {
814 return new MSTriggeredRerouter(id, edges, prob, off, optional, timeThreshold, vTypes, pos, radius);
815}
816
817
818void
819NLTriggerBuilder::buildStoppingPlace(MSNet& net, std::string id, std::vector<std::string> lines, MSLane* lane,
820 double frompos, double topos, const SumoXMLTag element, std::string ptStopName,
821 int personCapacity, double parkingLength, RGBColor& color, double angle) {
822 myCurrentStop = new MSStoppingPlace(id, element, lines, *lane, frompos, topos, ptStopName, personCapacity, parkingLength, color, angle);
823 if (!net.addStoppingPlace(element, myCurrentStop)) {
824 delete myCurrentStop;
825 myCurrentStop = nullptr;
826 throw InvalidArgument("Could not build " + toString(element) + " '" + id + "'; probably declared twice.");
827 }
828}
829
830
831void
832NLTriggerBuilder::beginParkingArea(MSNet& net, const std::string& id,
833 const std::vector<std::string>& lines,
834 const std::vector<std::string>& badges,
835 MSLane* lane, double frompos, double topos,
836 unsigned int capacity,
837 double width, double length, double angle, const std::string& name,
838 bool onRoad,
839 const std::string& departPos,
840 bool lefthand, bool reservable) {
841 // Close previous parking area if there are no lots inside
842 MSParkingArea* stop = new MSParkingArea(id, lines, badges, *lane, frompos, topos, capacity, width, length, angle, name, onRoad, departPos, lefthand, reservable);
843 if (!net.addStoppingPlace(SUMO_TAG_PARKING_AREA, stop)) {
844 delete stop;
845 throw InvalidArgument("Could not build parking area '" + id + "'; probably declared twice.");
846 } else {
847 myParkingArea = stop;
848 }
849}
850
851
852void
853NLTriggerBuilder::addLotEntry(double x, double y, double z,
854 double width, double length,
855 double angle, double slope) {
856 if (myParkingArea != nullptr) {
857 if (!myParkingArea->parkOnRoad()) {
858 myParkingArea->addLotEntry(x, y, z, width, length, angle, slope);
860 } else {
861 throw InvalidArgument("Cannot not add lot entry to on-road parking area.");
862 }
863 } else {
864 throw InvalidArgument("Could not add lot entry outside a parking area.");
865 }
866}
867
868
869void
871 if (myParkingArea != nullptr) {
872 myParkingArea = nullptr;
874 } else {
875 throw InvalidArgument("Could not end a parking area that is not opened.");
876 }
877}
878
879
880void
882 if (myCurrentStop != nullptr) {
884 myCurrentStop = nullptr;
885 } else {
886 throw InvalidArgument("Could not end a stopping place that is not opened.");
887 }
888}
889
890
891void
892NLTriggerBuilder::buildChargingStation(MSNet& net, const std::string& id, MSLane* lane, double frompos, double topos,
893 const std::string& name, double chargingPower, double totalPower, double efficiency,
894 bool chargeInTransit, SUMOTime chargeDelay, std::string chargeType, SUMOTime waitingTime, MSParkingArea* parkingArea) {
895 MSChargingStation* chargingStation = (parkingArea == nullptr) ? new MSChargingStation(id, *lane, frompos, topos, name, chargingPower, totalPower, efficiency,
896 chargeInTransit, chargeDelay, chargeType, waitingTime) : new MSChargingStation(id, parkingArea, name, chargingPower, totalPower, efficiency,
897 chargeInTransit, chargeDelay, chargeType, waitingTime);
898 if (!net.addStoppingPlace(SUMO_TAG_CHARGING_STATION, chargingStation)) {
899 delete chargingStation;
900 throw InvalidArgument("Could not build charging station '" + id + "'; probably declared twice.");
901 }
902 myCurrentStop = chargingStation;
903}
904
905
906void
907NLTriggerBuilder::buildOverheadWireSegment(MSNet& net, const std::string& id, MSLane* lane, double frompos, double topos,
908 bool voltageSource) {
909 MSOverheadWire* overheadWireSegment = new MSOverheadWire(id, *lane, frompos, topos, voltageSource);
910 if (!net.addStoppingPlace(SUMO_TAG_OVERHEAD_WIRE_SEGMENT, overheadWireSegment)) {
911 delete overheadWireSegment;
912 throw InvalidArgument("Could not build overheadWireSegment '" + id + "'; probably declared twice.");
913 }
914}
915
916void
917NLTriggerBuilder::buildInnerOverheadWireSegments(MSNet& net, const MSLane* connection, const MSLane* frontConnection, const MSLane* behindConnection) {
918 if (frontConnection == NULL && behindConnection == NULL) {
919 buildOverheadWireSegment(net, "ovrhd_inner_" + connection->getID(), const_cast<MSLane*>(connection), 0, connection->getLength(), false);
920 } else if (frontConnection != NULL && behindConnection == NULL) {
921 buildOverheadWireSegment(net, "ovrhd_inner_" + frontConnection->getID(), const_cast<MSLane*>(frontConnection), 0, frontConnection->getLength(), false);
922 buildOverheadWireSegment(net, "ovrhd_inner_" + connection->getID(), const_cast<MSLane*>(connection), 0, connection->getLength(), false);
923 } else if (frontConnection == NULL && behindConnection != NULL) {
924 buildOverheadWireSegment(net, "ovrhd_inner_" + behindConnection->getID(), const_cast<MSLane*>(behindConnection), 0, behindConnection->getLength(), false);
925 buildOverheadWireSegment(net, "ovrhd_inner_" + connection->getID(), const_cast<MSLane*>(connection), 0, connection->getLength(), false);
926 } else if (frontConnection != NULL && behindConnection != NULL) {
927 buildOverheadWireSegment(net, "ovrhd_inner_" + frontConnection->getID(), const_cast<MSLane*>(frontConnection), 0, frontConnection->getLength(), false);
928 buildOverheadWireSegment(net, "ovrhd_inner_" + behindConnection->getID(), const_cast<MSLane*>(behindConnection), 0, behindConnection->getLength(), false);
929 buildOverheadWireSegment(net, "ovrhd_inner_" + connection->getID(), const_cast<MSLane*>(connection), 0, connection->getLength(), false);
930 }
931}
932
933void
934NLTriggerBuilder::buildTractionSubstation(MSNet& net, std::string id, double voltage, double currentLimit) {
935 MSTractionSubstation* myTractionSubstation = new MSTractionSubstation(id, voltage, currentLimit);
936 if (!net.addTractionSubstation(myTractionSubstation)) {
937 delete myTractionSubstation;
938 throw InvalidArgument("Could not build traction substation '" + id + "'; probably declared twice.");
939 }
940}
941
942void
943NLTriggerBuilder::buildOverheadWireClamp(MSNet& /*net*/, const std::string& /*id*/, MSLane* /*lane_start*/, MSLane* /*lane_end*/) {
944}
945
946std::string
948 const std::string& base,
949 const bool allowEmpty) {
950 // get the file name to read further definitions from
951 bool ok = true;
952 std::string file = attrs.getOpt<std::string>(SUMO_ATTR_FILE, nullptr, ok, "");
953 if (file == "") {
954 if (allowEmpty) {
955 return file;
956 }
957 throw InvalidArgument("No filename given.");
958 }
959 // check whether absolute or relative filenames are given
960 if (!FileHelpers::isAbsolute(file)) {
961 return FileHelpers::getConfigurationRelative(base, file);
962 }
963 return file;
964}
965
966
967MSLane*
969 const std::string& tt,
970 const std::string& tid) {
971 bool ok = true;
972 std::string objectid = attrs.get<std::string>(SUMO_ATTR_LANE, tid.c_str(), ok);
973 MSLane* lane = MSLane::dictionary(objectid);
974 if (lane == nullptr) {
975 // Either a lane that is non-existent/broken, or a lane that is internal and has been ignored.
976 // We assume that internal lane names start with ':'.
977 if (objectid[0] == ':' && !MSGlobals::gUsingInternalLanes) {
978 return nullptr;
979 }
980 // Throw the exception only in case that the lane really does not exist in the network file
981 // or it is broken.
982 throw InvalidArgument("The lane " + objectid + " to use within the " + tt + " '" + tid + "' is not known.");
983 }
984 return lane;
985}
986
987
989NLTriggerBuilder::getParkingArea(const SUMOSAXAttributes& attrs, const std::string& tt, const std::string& tid) {
990 bool ok = true;
991 std::string objectID = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, tid.c_str(), ok);
992 if (!ok || objectID.size() == 0) {
993 return nullptr;
994 }
996 if (pa == nullptr) {
997 // Throw the exception only in case that the lane really does not exist in the network file
998 // or it is broken.
999 throw InvalidArgument("The parkingArea " + objectID + " to use within the " + tt + " '" + tid + "' is not known.");
1000 }
1001 return pa;
1002}
1003
1004
1005double
1007 MSLane* lane,
1008 const std::string& tt, const std::string& tid,
1009 MSEdge* edge) {
1010 assert(lane != nullptr || edge != nullptr);
1011 const double length = lane != nullptr ? lane->getLength() : edge->getLength();
1012 bool ok = true;
1013 double pos = attrs.get<double>(SUMO_ATTR_POSITION, nullptr, ok);
1014 const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, false);
1015 if (!ok) {
1016 throw InvalidArgument("Error on parsing a position information.");
1017 }
1018 if (pos < 0) {
1019 pos = length + pos;
1020 }
1021 if (pos > length) {
1022 if (friendlyPos) {
1023 pos = length - (double) 0.1;
1024 } else {
1025 if (lane != nullptr) {
1026 throw InvalidArgument("The position of " + tt + " '" + tid + "' lies beyond the lane's '" + lane->getID() + "' length.");
1027 } else {
1028 throw InvalidArgument("The position of " + tt + " '" + tid + "' lies beyond the edge's '" + edge->getID() + "' length.");
1029 }
1030 }
1031 }
1032 return pos;
1033}
1034
1035
1036void
1042
1043
1048
1049
1050/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
std::vector< MSEdge * > MSEdgeVector
Definition MSEdge.h:73
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_MESSAGEF(...)
Definition MsgHandler.h:289
#define WRITE_ERRORF(...)
Definition MsgHandler.h:296
#define WRITE_ERROR(msg)
Definition MsgHandler.h:295
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
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:60
@ 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_RADIUS
The turning radius at an intersection in m.
@ 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_RESERVABLE
@ 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_TOTALPOWER
total charge in W/s of the Charging Stations
@ 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)
T MAX2(T a, T b)
Definition StdDefs.h:86
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.
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition MELoop.cpp:330
double getLength() const
Returns the length of the segment in meters.
Definition MESegment.h:246
Calibrates the flow on a segment to a specified one.
Calibrates the flow on a segment to a specified one.
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:540
double getLength() const
return the length of the edge
Definition MSEdge.h:694
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:1075
SUMOTime incVaporization(SUMOTime t)
Enables vaporization.
Definition MSEdge.cpp:533
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static bool gUseMesoSim
Definition MSGlobals.h:106
static bool gOverheadWireSolver
Definition MSGlobals.h:121
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition MSGlobals.h:112
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition MSGlobals.h:81
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:612
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:2771
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition MSLane.h:936
const std::vector< std::pair< const MSLane *, const MSEdge * > > getOutgoingViaLanes() const
get the list of outgoing lanes
Definition MSLane.cpp:3342
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2496
bool isInternal() const
Definition MSLane.cpp:2627
std::vector< const MSLane * > getNormalIncomingLanes() const
get the list of all direct (disregarding internal predecessors) non-internal predecessor lanes of thi...
Definition MSLane.cpp:3352
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:770
Changes the speed allowed on a set of lanes.
The simulated network and simulation perfomer.
Definition MSNet.h:89
MSDetectorControl & getDetectorControl()
Returns the detector control.
Definition MSNet.h:455
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:187
bool addStoppingPlace(SumoXMLTag category, MSStoppingPlace *stop)
Adds a stopping place.
Definition MSNet.cpp:1445
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:485
bool addTractionSubstation(MSTractionSubstation *substation)
Adds a traction substation.
Definition MSNet.cpp:1458
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:1489
MSJunctionControl & getJunctionControl()
Returns the junctions control.
Definition MSNet.h:475
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition MSNet.cpp:1468
MSTractionSubstation * findTractionSubstation(const std::string &substationId)
find electrical substation by its id
Definition MSNet.cpp:1589
Definition of overhead wire segment.
MSTractionSubstation * getTractionSubstation() const
void setTractionSubstation(MSTractionSubstation *substation)
A lane area vehicles can halt at.
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.
A lane area vehicles can halt at.
virtual void finishedLoading()
perform extra processing after element has been loaded
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
static int getDefaultTransportablesAbreast(double length, SumoXMLTag element)
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".
virtual void buildChargingStation(MSNet &net, const std::string &id, MSLane *lane, double frompos, double topos, const std::string &name, double chargingPower, double totalPower, double efficiency, bool chargeInTransit, SUMOTime chargeDelay, std::string chargeType, SUMOTime waitingTime, MSParkingArea *parkingArea)
Builds a charging station.
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 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, double angle)
Builds a stopping place.
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 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.
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.
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
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, bool reservable)
Begin a parking area.
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 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, const double radius)
builds an rerouter
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
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.
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:323
static const RGBColor INVISIBLE
Definition RGBColor.h:198
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.
#define UNUSED_PARAMETER(x)