Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSTriggeredRerouter.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/****************************************************************************/
22// Reroutes vehicles passing an edge
23/****************************************************************************/
24#include <config.h>
25
26#include <string>
27#include <algorithm>
28#ifdef HAVE_FOX
30#endif
43#include <microsim/MSLane.h>
44#include <microsim/MSLink.h>
45#include <microsim/MSVehicle.h>
47#include <microsim/MSRoute.h>
48#include <microsim/MSEdge.h>
50#include <microsim/MSNet.h>
52#include <microsim/MSGlobals.h>
54#include <microsim/MSStop.h>
60#include "MSTriggeredRerouter.h"
61
62#include <mesosim/MELoop.h>
63#include <mesosim/MESegment.h>
64
65//#define DEBUG_REROUTER
66//#define DEBUG_OVERTAKING
67#define DEBUGCOND(veh) (veh.isSelected())
68//#define DEBUGCOND(veh) (true)
69//#define DEBUGCOND(veh) (veh.getID() == "")
70
72#define DEFAULT_PRIO_OVERTAKER 1
73#define DEFAULT_PRIO_OVERTAKEN 0.001
74
75// ===========================================================================
76// static member definition
77// ===========================================================================
78MSEdge MSTriggeredRerouter::mySpecialDest_keepDestination("MSTriggeredRerouter_keepDestination", -1, SumoXMLEdgeFunc::UNKNOWN, "", "", "", -1, 0);
79MSEdge MSTriggeredRerouter::mySpecialDest_terminateRoute("MSTriggeredRerouter_terminateRoute", -1, SumoXMLEdgeFunc::UNKNOWN, "", "", "", -1, 0);
81std::map<std::string, MSTriggeredRerouter*> MSTriggeredRerouter::myInstances;
82
83
84// ===========================================================================
85// method definitions
86// ===========================================================================
88 const MSEdgeVector& edges, double prob, bool off, bool optional,
89 SUMOTime timeThreshold, const std::string& vTypes, const Position& pos, const double radius) :
90 Named(id),
92 MSStoppingPlaceRerouter("parking"),
93 myEdges(edges),
94 myProbability(prob),
95 myUserProbability(prob),
96 myAmInUserMode(false),
97 myAmOptional(optional),
98 myPosition(pos),
99 myRadius(radius),
100 myTimeThreshold(timeThreshold),
101 myHaveParkProbs(false) {
102 myInstances[id] = this;
103 // build actors
104 for (const MSEdge* const e : edges) {
107 }
108 for (MSLane* const lane : e->getLanes()) {
109 lane->addMoveReminder(this);
110 }
111 }
112 if (off) {
113 setUserMode(true);
115 }
116 const std::vector<std::string> vt = StringTokenizer(vTypes).getVector();
117 myVehicleTypes.insert(vt.begin(), vt.end());
119 myPosition = edges.front()->getLanes()[0]->getShape()[0];
120 }
121}
122
123
127
128
129// ------------ loading begin
130void
132 const SUMOSAXAttributes& attrs) {
133 if (element == SUMO_TAG_INTERVAL) {
134 bool ok = true;
139 throw ProcessError(TLF("rerouter '%': interval end % is not after begin %.", getID(),
142 }
143 }
144 if (element == SUMO_TAG_DEST_PROB_REROUTE) {
145 // by giving probabilities of new destinations
146 // get the destination edge
147 std::string dest = attrs.getStringSecure(SUMO_ATTR_ID, "");
148 if (dest == "") {
149 throw ProcessError(TLF("rerouter '%': destProbReroute has no destination edge id.", getID()));
150 }
151 MSEdge* to = MSEdge::dictionary(dest);
152 if (to == nullptr) {
153 if (dest == "keepDestination") {
155 } else if (dest == "terminateRoute") {
157 } else {
158 throw ProcessError(TLF("rerouter '%': Destination edge '%' is not known.", getID(), dest));
159 }
160 }
161 // get the probability to reroute
162 bool ok = true;
163 double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
164 if (!ok) {
165 throw ProcessError();
166 }
167 if (prob < 0) {
168 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for destination '%' is negative (must not).", getID(), dest));
169 }
170 // add
172 }
173
174 if (element == SUMO_TAG_CLOSING_REROUTE) {
175 // by closing edge
176 const std::string& closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
177 MSEdge* const closedEdge = MSEdge::dictionary(closed_id);
178 if (closedEdge == nullptr) {
179 throw ProcessError(TLF("rerouter '%': Edge '%' to close is not known.", getID(), closed_id));
180 }
181 bool ok;
182 const std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, getID().c_str(), ok, "", false);
183 const std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, getID().c_str(), ok, "");
184 const SUMOTime until = attrs.getOptSUMOTimeReporting(SUMO_ATTR_UNTIL, nullptr, ok, TIME2STEPS(-1));
185 SVCPermissions permissions = parseVehicleClasses(allow, disallow);
186 myParsedRerouteInterval.closed[closedEdge] = std::make_pair(permissions, STEPS2TIME(until));
187 }
188
189 if (element == SUMO_TAG_CLOSING_LANE_REROUTE) {
190 // by closing lane
191 std::string closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
192 MSLane* closedLane = MSLane::dictionary(closed_id);
193 if (closedLane == nullptr) {
194 throw ProcessError(TLF("rerouter '%': Lane '%' to close is not known.", getID(), closed_id));
195 }
196 bool ok;
197 SVCPermissions permissions = SVC_AUTHORITY;
199 const std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, getID().c_str(), ok, "", false);
200 const std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, getID().c_str(), ok, "");
201 permissions = parseVehicleClasses(allow, disallow);
202 }
203 myParsedRerouteInterval.closedLanes[closedLane] = permissions;
204 }
205
206 if (element == SUMO_TAG_ROUTE_PROB_REROUTE) {
207 // by explicit rerouting using routes
208 // check if route exists
209 std::string routeStr = attrs.getStringSecure(SUMO_ATTR_ID, "");
210 if (routeStr == "") {
211 throw ProcessError(TLF("rerouter '%': routeProbReroute has no alternative route id.", getID()));
212 }
213 ConstMSRoutePtr route = MSRoute::dictionary(routeStr);
214 if (route == nullptr) {
215 throw ProcessError(TLF("rerouter '%': Alternative route '%' does not exist.", getID(), routeStr));
216 }
217
218 // get the probability to reroute
219 bool ok = true;
220 double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
221 if (!ok) {
222 throw ProcessError();
223 }
224 if (prob < 0) {
225 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for alternative route '%' is negative (must not).", getID(), routeStr));
226 }
227 // add
229 }
230
231 if (element == SUMO_TAG_PARKING_AREA_REROUTE) {
232 std::string parkingarea = attrs.getStringSecure(SUMO_ATTR_ID, "");
233 if (parkingarea == "") {
234 throw ProcessError(TLF("rerouter '%': parkingAreaReroute requires a parkingArea id.", getID()));
235 }
237 if (pa == nullptr) {
238 throw ProcessError(TLF("rerouter '%': parkingArea '%' is not known.", getID(), parkingarea));
239 }
240 // get the probability to reroute
241 bool ok = true;
242 const double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
243 if (!ok) {
244 throw ProcessError();
245 }
246 if (prob < 0) {
247 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for parkingArea '%' is negative (must not).", getID(), parkingarea));
248 }
249 const bool visible = attrs.getOpt<bool>(SUMO_ATTR_VISIBLE, getID().c_str(), ok, false);
250 // add
251 myParsedRerouteInterval.parkProbs.add(std::make_pair(pa, visible), prob);
252 myHaveParkProbs = true;
253 }
254
255 if (element == SUMO_TAG_VIA_PROB_REROUTE) {
256 // by giving probabilities of vias
257 std::string viaID = attrs.getStringSecure(SUMO_ATTR_ID, "");
258 if (viaID == "") {
259 throw ProcessError(TLF("rerouter '%': No via edge id given.", getID()));
260 }
261 MSEdge* const via = MSEdge::dictionary(viaID);
262 if (via == nullptr) {
263 throw ProcessError(TLF("rerouter '%': Via Edge '%' is not known.", getID(), viaID));
264 }
265 // get the probability to reroute
266 bool ok = true;
267 double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
268 if (!ok) {
269 throw ProcessError();
270 }
271 if (prob < 0) {
272 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for via '%' is negative (must not).", getID(), viaID));
273 }
274 // add
277 }
278 if (element == SUMO_TAG_OVERTAKING_REROUTE) {
279 // for letting a slow train use a siding to be overtaken by a fast train
280 OvertakeLocation oloc;
281 bool ok = true;
282 for (const std::string& edgeID : attrs.get<std::vector<std::string> >(SUMO_ATTR_MAIN, getID().c_str(), ok)) {
283 MSEdge* edge = MSEdge::dictionary(edgeID);
284 if (edge == nullptr) {
285 throw InvalidArgument(TLF("The main edge '%' to use within rerouter '%' is not known.", edgeID, getID()));
286 }
287 oloc.main.push_back(edge);
288 oloc.cMain.push_back(edge);
289 }
290 for (const std::string& edgeID : attrs.get<std::vector<std::string> >(SUMO_ATTR_SIDING, getID().c_str(), ok)) {
291 MSEdge* edge = MSEdge::dictionary(edgeID);
292 if (edge == nullptr) {
293 throw InvalidArgument(TLF("The siding edge '%' to use within rerouter '%' is not known.", edgeID, getID()));
294 }
295 oloc.siding.push_back(edge);
296 oloc.cSiding.push_back(edge);
297 }
298 oloc.sidingExit = findSignal(oloc.cSiding.begin(), oloc.cSiding.end());
299 if (oloc.sidingExit == nullptr) {
300 throw InvalidArgument(TLF("The siding within rerouter '%' does not have a rail signal.", getID()));
301 }
302 for (auto it = oloc.cSiding.begin(); it != oloc.cSiding.end(); it++) {
303 oloc.sidingLength += (*it)->getLength();
304 if ((*it)->getToJunction()->getID() == oloc.sidingExit->getID()) {
305 break;
306 }
307 }
308 oloc.minSaving = attrs.getOpt<double>(SUMO_ATTR_MINSAVING, getID().c_str(), ok, 300);
309 const bool hasAlternatives = myParsedRerouteInterval.overtakeLocations.size() > 0;
310 oloc.defer = attrs.getOpt<bool>(SUMO_ATTR_DEFER, getID().c_str(), ok, hasAlternatives);
312 }
313 if (element == SUMO_TAG_STATION_REROUTE) {
314 // for letting a train switch it's stopping place in case of conflict
315 const std::string stopID = attrs.getStringSecure(SUMO_ATTR_ID, "");
316 if (stopID == "") {
317 throw ProcessError(TLF("rerouter '%': stationReroute requires a stopping place id.", getID()));
318 }
320 if (stop == nullptr) {
321 throw ProcessError(TLF("rerouter '%': stopping place '%' is not known.", getID(), stopID));
322 }
323 myParsedRerouteInterval.stopAlternatives.push_back(std::make_pair(stop, true));
324 }
325}
326
327
328void
330 if (element == SUMO_TAG_INTERVAL) {
331 // precompute permissionsAllowAll
332 bool allowAll = true;
333 for (const auto& entry : myParsedRerouteInterval.closed) {
334 allowAll = allowAll && entry.second.first == SVCAll;
335 if (!allowAll) {
336 break;
337 }
338 }
340
341 for (auto paVi : myParsedRerouteInterval.parkProbs.getVals()) {
342 dynamic_cast<MSParkingArea*>(paVi.first)->setNumAlternatives((int)myParsedRerouteInterval.parkProbs.getVals().size() - 1);
343 }
344 if (myParsedRerouteInterval.closedLanes.size() > 0) {
345 // collect edges that are affect by a closed lane
346 std::set<MSEdge*> affected;
347 for (std::pair<MSLane*, SVCPermissions> settings : myParsedRerouteInterval.closedLanes) {
348 affected.insert(&settings.first->getEdge());
349 }
351 }
352 const SUMOTime closingBegin = myParsedRerouteInterval.begin;
353 const SUMOTime simBegin = string2time(OptionsCont::getOptions().getString("begin"));
354 if (closingBegin < simBegin && myParsedRerouteInterval.end > simBegin) {
355 // interval started before simulation begin but is still active at
356 // the start of the simulation
358 }
360 myIntervals.back().id = (long long int)&myIntervals.back();
364 }
365 }
366}
367
368
369// ------------ loading end
370
371
374 bool updateVehicles = false;
375 for (const RerouteInterval& i : myIntervals) {
376 if (i.begin == currentTime && !(i.closed.empty() && i.closedLanes.empty()) /*&& i.permissions != SVCAll*/) {
377 for (const auto& settings : i.closed) {
378 for (MSLane* lane : settings.first->getLanes()) {
379 //std::cout << SIMTIME << " closing: intervalID=" << i.id << " lane=" << lane->getID() << " prevPerm=" << getVehicleClassNames(lane->getPermissions()) << " new=" << getVehicleClassNames(i.permissions) << "\n";
380 lane->setPermissions(settings.second.first, i.id);
381 }
382 settings.first->rebuildAllowedLanes();
383 updateVehicles = true;
384 }
385 for (std::pair<MSLane*, SVCPermissions> settings : i.closedLanes) {
386 settings.first->setPermissions(settings.second, i.id);
387 settings.first->getEdge().rebuildAllowedLanes();
388 updateVehicles = true;
389 }
392 }
393 if (i.end == currentTime && !(i.closed.empty() && i.closedLanes.empty()) /*&& i.permissions != SVCAll*/) {
394 for (auto settings : i.closed) {
395 for (MSLane* lane : settings.first->getLanes()) {
396 lane->resetPermissions(i.id);
397 //std::cout << SIMTIME << " opening: intervalID=" << i.id << " lane=" << lane->getID() << " restore prevPerm=" << getVehicleClassNames(lane->getPermissions()) << "\n";
398 }
399 settings.first->rebuildAllowedLanes();
400 updateVehicles = true;
401 }
402 for (std::pair<MSLane*, SVCPermissions> settings : i.closedLanes) {
403 settings.first->resetPermissions(i.id);
404 settings.first->getEdge().rebuildAllowedLanes();
405 updateVehicles = true;
406 }
407 }
408 }
409 if (updateVehicles) {
410 // only vehicles on the affected lanes had their bestlanes updated so far
411 for (MSEdge* e : myEdges) {
412 // also updates vehicles
413 e->rebuildAllowedTargets();
414 }
415 }
416 return 0;
417}
418
419
422 for (const RerouteInterval& ri : myIntervals) {
423 if (ri.begin <= time && ri.end > time) {
424 if (
425 // destProbReroute
426 ri.edgeProbs.getOverallProb() > 0 ||
427 // routeProbReroute
428 ri.routeProbs.getOverallProb() > 0 ||
429 // parkingZoneReroute
430 ri.parkProbs.getOverallProb() > 0 ||
431 // stationReroute
432 ri.stopAlternatives.size() > 0) {
433 return &ri;
434 }
435 if (!ri.closed.empty() || !ri.closedLanesAffected.empty() || !ri.overtakeLocations.empty()) {
436 const std::set<SUMOTrafficObject::NumericalID>& edgeIndices = obj.getUpcomingEdgeIDs();
437 if (affected(edgeIndices, ri.getClosedEdges())
438 || affected(edgeIndices, ri.closedLanesAffected)) {
439 return &ri;
440 }
441 for (const OvertakeLocation& oloc : ri.overtakeLocations) {
442 if (affected(edgeIndices, oloc.main)) {
443 return &ri;
444 }
445 }
446
447 }
448 }
449 }
450 return nullptr;
451}
452
453
456 for (const RerouteInterval& ri : myIntervals) {
457 if (ri.begin <= time && ri.end > time) {
458 if (ri.edgeProbs.getOverallProb() != 0 || ri.routeProbs.getOverallProb() != 0 || ri.parkProbs.getOverallProb() != 0
459 || !ri.closed.empty() || !ri.closedLanesAffected.empty() || !ri.overtakeLocations.empty()) {
460 return &ri;
461 }
462 }
463 }
464 return nullptr;
465}
466
467
468bool
470 if (myAmOptional || myRadius != std::numeric_limits<double>::max()) {
471 return true;
472 }
473 return triggerRouting(tObject, reason);
474}
475
476
477bool
479 double /*newPos*/, double /*newSpeed*/) {
481}
482
483
484bool
486 MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
487 return reason == NOTIFICATION_LANE_CHANGE;
488}
489
490
491bool
493 if (!applies(tObject)) {
494 return false;
495 }
496 if (myRadius != std::numeric_limits<double>::max() && tObject.getPosition().distanceTo(myPosition) > myRadius) {
497 return true;
498 }
499 // check whether the vehicle shall be rerouted
501 const MSTriggeredRerouter::RerouteInterval* const rerouteDef = getCurrentReroute(now, tObject);
502 if (rerouteDef == nullptr) {
503 return true; // an active interval could appear later
504 }
505 const double prob = myAmInUserMode ? myUserProbability : myProbability;
506 if (prob < 1 && RandHelper::rand(tObject.getRNG()) > prob) {
507 return false; // XXX another interval could appear later but we would have to track whether the current interval was already tried
508 }
509 if (myTimeThreshold > 0 && MAX2(tObject.getWaitingTime(), tObject.getWaitingTime(true)) < myTimeThreshold) {
510 return true; // waiting time may be reached later
511 }
512 if (reason == NOTIFICATION_LANE_CHANGE) {
513 return false;
514 }
515 // if we have a closingLaneReroute, only vehicles with a rerouting device can profit from rerouting (otherwise, edge weights will not reflect local jamming)
516 const bool hasReroutingDevice = tObject.getDevice(typeid(MSDevice_Routing)) != nullptr;
517 if (rerouteDef->closedLanes.size() > 0 && !hasReroutingDevice) {
518 return true; // an active interval could appear later
519 }
520 const MSEdge* lastEdge = tObject.getRerouteDestination();
521#ifdef DEBUG_REROUTER
522 if (DEBUGCOND(tObject)) {
523 std::cout << SIMTIME << " veh=" << tObject.getID() << " check rerouter " << getID() << " lane=" << Named::getIDSecure(tObject.getLane()) << " edge=" << tObject.getEdge()->getID() << " finalEdge=" << lastEdge->getID() /*<< " arrivalPos=" << tObject.getArrivalPos()*/ << "\n";
524 }
525#endif
526
527 if (rerouteDef->parkProbs.getOverallProb() > 0) {
528#ifdef HAVE_FOX
529 ScopedLocker<> lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
530#endif
531 if (!tObject.isVehicle()) {
532 return false;
533 }
534 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
535 bool newDestination = false;
536 ConstMSEdgeVector newRoute;
537 MSParkingArea* oldParkingArea = veh.getNextParkingArea();
538 MSParkingArea* newParkingArea = rerouteParkingArea(rerouteDef, veh, newDestination, newRoute);
539 if (newParkingArea != nullptr) {
540 // adapt plans of any riders
541 for (MSTransportable* p : veh.getPersons()) {
542 p->rerouteParkingArea(oldParkingArea, newParkingArea);
543 }
544
545 if (newDestination && veh.getParameter().arrivalPosProcedure != ArrivalPosDefinition::DEFAULT) {
546 // update arrival parameters
547 SUMOVehicleParameter* newParameter = new SUMOVehicleParameter();
548 *newParameter = veh.getParameter();
550 newParameter->arrivalPos = newParkingArea->getEndLanePosition();
551 veh.replaceParameter(newParameter);
552 }
553
554 SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = hasReroutingDevice
555 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), rerouteDef->getClosed())
556 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), rerouteDef->getClosed());
557 const double routeCost = router.recomputeCosts(newRoute, &veh, MSNet::getInstance()->getCurrentTimeStep());
558 ConstMSEdgeVector prevEdges(veh.getCurrentRouteEdge(), veh.getRoute().end());
559 resetClosedEdges(hasReroutingDevice, veh);
560 const double previousCost = router.recomputeCosts(prevEdges, &veh, MSNet::getInstance()->getCurrentTimeStep());
561 const double savings = previousCost - routeCost;
562 //if (getID() == "ego") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
563 // << " prevEdges=" << toString(prevEdges)
564 // << " newEdges=" << toString(edges)
565 // << "\n";
566
567 std::string errorMsg;
568 if (veh.replaceParkingArea(newParkingArea, errorMsg)) {
569 veh.replaceRouteEdges(newRoute, routeCost, savings, getID() + ":" + toString(SUMO_TAG_PARKING_AREA_REROUTE), false, false, false);
570 if (oldParkingArea->isReservable()) {
571 oldParkingArea->removeSpaceReservation(&veh);
572 }
573 if (newParkingArea->isReservable()) {
574 newParkingArea->addSpaceReservation(&veh);
575 }
576 } else {
577 WRITE_WARNING("Vehicle '" + veh.getID() + "' at rerouter '" + getID()
578 + "' could not reroute to new parkingArea '" + newParkingArea->getID()
579 + "' reason=" + errorMsg + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
580 }
581 } else {
582 if (oldParkingArea && oldParkingArea->isReservable()) {
583 oldParkingArea->addSpaceReservation(&veh);
584 }
585 }
586 return false;
587 }
588 if (rerouteDef->overtakeLocations.size() > 0) {
589 if (!tObject.isVehicle()) {
590 return false;
591 }
592 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
593 const ConstMSEdgeVector& oldEdges = veh.getRoute().getEdges();
594 double bestSavings = -std::numeric_limits<double>::max();
595 double netSaving;
596 int bestIndex = -1;
597 MSRouteIterator bestMainStart = oldEdges.end();
598 std::pair<const SUMOVehicle*, MSRailSignal*> best_overtaker_signal(nullptr, nullptr);
599 int index = -1;
600 // sort locations by descending distance to vehicle
601 std::vector<std::pair<int, int> > sortedLocs;
602 for (const OvertakeLocation& oloc : rerouteDef->overtakeLocations) {
603 index++;
604 if (veh.getLength() > oloc.sidingLength) {
605 continue;
606 }
607 auto mainStart = std::find(veh.getCurrentRouteEdge(), oldEdges.end(), oloc.main.front());
608 if (mainStart == oldEdges.end()
609 // exit main within
610 || ConstMSEdgeVector(mainStart, mainStart + oloc.main.size()) != oloc.cMain
611 // stop in main
612 || (veh.hasStops() && veh.getNextStop().edge < (mainStart + oloc.main.size()))) {
613 //std::cout << SIMTIME << " veh=" << veh.getID() << " wrong route or stop\n";
614 continue;
615 }
616 // negated iterator distance for descending order
617 sortedLocs.push_back(std::make_pair(-(int)(mainStart - veh.getCurrentRouteEdge()), index));
618 }
619 std::sort(sortedLocs.begin(), sortedLocs.end());
620 for (const auto& item : sortedLocs) {
621 index = item.second;
622 const OvertakeLocation& oloc = rerouteDef->overtakeLocations[index];
623 auto mainStart = veh.getCurrentRouteEdge() - item.first; // subtracting negative difference
624 std::pair<const SUMOVehicle*, MSRailSignal*> overtaker_signal = overtakingTrain(veh, mainStart, oloc, netSaving);
625 if (overtaker_signal.first != nullptr && netSaving > bestSavings) {
626 bestSavings = netSaving;
627 bestIndex = index;
628 best_overtaker_signal = overtaker_signal;
629 bestMainStart = mainStart;
630#ifdef DEBUG_OVERTAKING
631 std::cout << " newBest index=" << bestIndex << " saving=" << bestSavings << "\n";
632#endif
633 }
634 }
635 if (bestIndex >= 0) {
636 const OvertakeLocation& oloc = rerouteDef->overtakeLocations[bestIndex];
637 if (oloc.defer) {
638 return false;
639 }
640 SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = hasReroutingDevice
641 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), rerouteDef->getClosed())
642 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), rerouteDef->getClosed());
643 ConstMSEdgeVector newEdges(veh.getCurrentRouteEdge(), bestMainStart);
644 newEdges.insert(newEdges.end(), oloc.siding.begin(), oloc.siding.end());
645 newEdges.insert(newEdges.end(), bestMainStart + oloc.main.size(), oldEdges.end());
646 const double routeCost = router.recomputeCosts(newEdges, &veh, MSNet::getInstance()->getCurrentTimeStep());
647 const double savings = (router.recomputeCosts(oloc.cMain, &veh, MSNet::getInstance()->getCurrentTimeStep())
649 const std::string info = getID() + ":" + toString(SUMO_TAG_OVERTAKING_REROUTE) + ":" + best_overtaker_signal.first->getID();
650 veh.replaceRouteEdges(newEdges, routeCost, savings, info, false, false, false);
652 MSRailSignalConstraint::PREDECESSOR, best_overtaker_signal.second, best_overtaker_signal.first->getID(), 100, true));
653 resetClosedEdges(hasReroutingDevice, veh);
654 }
655 return false;
656 }
657 if (rerouteDef->stopAlternatives.size() > 0) {
658 // somewhat similar to parkProbs but taking into account public transport schedule
659 if (!tObject.isVehicle()) {
660 return false;
661 }
662 checkStopSwitch(static_cast<MSBaseVehicle&>(tObject), rerouteDef);
663 }
664 // get rerouting params
665 ConstMSRoutePtr newRoute = rerouteDef->routeProbs.getOverallProb() > 0 ? rerouteDef->routeProbs.get() : nullptr;
666 // we will use the route if given rather than calling our own dijsktra...
667 if (newRoute != nullptr) {
668#ifdef DEBUG_REROUTER
669 if (DEBUGCOND(tObject)) {
670 std::cout << " replacedRoute from routeDist " << newRoute->getID() << "\n";
671 }
672#endif
673 tObject.replaceRoute(newRoute, getID());
674 return false; // XXX another interval could appear later but we would have to track whether the currenty interval was already used
675 }
676 const MSEdge* newEdge = lastEdge;
677 // ok, try using a new destination
678 double newArrivalPos = -1;
679 const MSEdgeVector closedEdges = rerouteDef->getClosedEdges();
680 const bool destUnreachable = std::find(closedEdges.begin(), closedEdges.end(), lastEdge) != closedEdges.end();
681 bool keepDestination = false;
682 // if we have a closingReroute, only assign new destinations to vehicles which cannot reach their original destination
683 // if we have a closingLaneReroute, no new destinations should be assigned
684 if (closedEdges.empty() || destUnreachable || rerouteDef->isVia) {
685 newEdge = rerouteDef->edgeProbs.getOverallProb() > 0 ? rerouteDef->edgeProbs.get() : lastEdge;
686 assert(newEdge != nullptr);
687 if (newEdge == &mySpecialDest_terminateRoute) {
688 keepDestination = true;
689 newEdge = tObject.getEdge();
690 newArrivalPos = tObject.getPositionOnLane(); // instant arrival
691 } else if (newEdge == &mySpecialDest_keepDestination || newEdge == lastEdge) {
692 if (destUnreachable && rerouteDef->permissionsAllowAll) {
693 // if permissions aren't set vehicles will simply drive through
694 // the closing unless terminated. If the permissions are specified, assume that the user wants
695 // vehicles to stand and wait until the closing ends
696 WRITE_WARNINGF(TL("Cannot keep destination edge '%' for vehicle '%' due to closed edges. Terminating route."), lastEdge->getID(), tObject.getID());
697 newEdge = tObject.getEdge();
698 } else {
699 newEdge = lastEdge;
700 }
701 }
702 }
703 ConstMSEdgeVector edges;
704 std::vector<MSTransportableRouter::TripItem> items;
705 // we have a new destination, let's replace the route (if it is affected)
706 MSEdgeVector closed = rerouteDef->getClosedEdges();
707 Prohibitions prohibited = rerouteDef->getClosed();
708 if (rerouteDef->closed.empty() || destUnreachable || rerouteDef->isVia || affected(tObject.getUpcomingEdgeIDs(), closed)) {
709 if (tObject.isVehicle()) {
710 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
711 ConstMSEdgeVector prevEdges = veh.getRoute().getEdges();
712 const bool canChangeDest = rerouteDef->edgeProbs.getOverallProb() > 0;
713 MSVehicleRouter& router = hasReroutingDevice
714 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), prohibited)
715 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), prohibited);
716 bool ok = false;
717 try {
718 ok = veh.reroute(now, getID(), router, false, false, canChangeDest, newEdge);
719 } catch (ProcessError&) {}
720 if (!ok && !keepDestination && canChangeDest) {
721 // destination unreachable due to closed intermediate edges. pick among alternative targets
722 RandomDistributor<MSEdge*> edgeProbs2 = rerouteDef->edgeProbs;
723 edgeProbs2.remove(const_cast<MSEdge*>(newEdge));
724 while (!ok && edgeProbs2.getVals().size() > 0) {
725 newEdge = edgeProbs2.get();
726 edgeProbs2.remove(const_cast<MSEdge*>(newEdge));
727 if (newEdge == &mySpecialDest_terminateRoute) {
728 newEdge = veh.getEdge();
729 newArrivalPos = veh.getPositionOnLane(); // instant arrival
730 while (veh.hasStops()) {
731 veh.abortNextStop();
732 }
733 }
734 if (newEdge == &mySpecialDest_keepDestination && !rerouteDef->permissionsAllowAll) {
735 newEdge = lastEdge;
736 break;
737 }
738 try {
739 ok = veh.reroute(now, getID(), router, false, false, true, newEdge);
740 } catch (ProcessError&) {}
741 }
742 }
743 resetClosedEdges(hasReroutingDevice, tObject);
744 if (ok) {
745 // since the old route was closed, savings would be infinite. This isn't useful
746 const double previousCost = router.recomputeCosts(prevEdges, &veh, MSNet::getInstance()->getCurrentTimeStep());
747 const double savings = previousCost - veh.getRoute().getCosts();
748 const_cast<MSRoute&>(veh.getRoute()).setSavings(savings);
749 }
750 if (!rerouteDef->isVia) {
751#ifdef DEBUG_REROUTER
752 if (DEBUGCOND(tObject)) std::cout << " rerouting: newDest=" << newEdge->getID()
753 << " newEdges=" << toString(edges)
754 << " newArrivalPos=" << newArrivalPos << " numClosed=" << rerouteDef->closed.size()
755 << " destUnreachable=" << destUnreachable << " containsClosed=" << veh.getRoute().containsAnyOf(rerouteDef->getClosedEdges()) << "\n";
756#endif
757 if (ok && newArrivalPos != -1) {
758 // must be called here because replaceRouteEdges may also set the arrivalPos
759 veh.setArrivalPos(newArrivalPos);
760 }
761
762 }
763 } else {
764 // person rerouting here
765 MSTransportableRouter& router = hasReroutingDevice
767 : MSNet::getInstance()->getIntermodalRouter(tObject.getRNGIndex(), 0, prohibited);
768 const bool success = router.compute(tObject.getEdge(), newEdge, tObject.getPositionOnLane(), "",
769 rerouteDef->isVia ? newEdge->getLength() / 2. : tObject.getParameter().arrivalPos, "",
770 tObject.getMaxSpeed(), nullptr, tObject.getVTypeParameter(), 0, now, items);
771 if (!rerouteDef->isVia) {
772 if (success) {
773 for (const MSTransportableRouter::TripItem& it : items) {
774 if (!it.edges.empty() && !edges.empty() && edges.back() == it.edges.front()) {
775 edges.pop_back();
776 }
777 edges.insert(edges.end(), std::make_move_iterator(it.edges.begin()), std::make_move_iterator(it.edges.end()));
778 if (!edges.empty()) {
779 static_cast<MSPerson&>(tObject).replaceWalk(edges, tObject.getPositionOnLane(), 0, 1);
780 }
781 }
782 } else {
783 // maybe the pedestrian model still finds a way (JuPedSim)
784 static_cast<MSPerson&>(tObject).replaceWalk({tObject.getEdge(), newEdge}, tObject.getPositionOnLane(), 0, 1);
785 }
786 }
787 }
788 if (!prohibited.empty()) {
789 resetClosedEdges(hasReroutingDevice, tObject);
790 }
791 }
792 // it was only a via so calculate the remaining part
793 if (rerouteDef->isVia) {
794 if (tObject.isVehicle()) {
795 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
796 if (!edges.empty()) {
797 edges.pop_back();
798 }
799 MSVehicleRouter& router = hasReroutingDevice
800 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), prohibited)
801 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), prohibited);
802 router.compute(newEdge, lastEdge, &veh, now, edges);
803 const double routeCost = router.recomputeCosts(edges, &veh, now);
804 hasReroutingDevice
806 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex()); // reset closed edges
807 const bool useNewRoute = veh.replaceRouteEdges(edges, routeCost, 0, getID());
808#ifdef DEBUG_REROUTER
809 if (DEBUGCOND(tObject)) std::cout << " rerouting: newDest=" << newEdge->getID()
810 << " newEdges=" << toString(edges)
811 << " useNewRoute=" << useNewRoute << " newArrivalPos=" << newArrivalPos << " numClosed=" << rerouteDef->closed.size()
812 << " destUnreachable=" << destUnreachable << " containsClosed=" << veh.getRoute().containsAnyOf(rerouteDef->getClosedEdges()) << "\n";
813#endif
814 if (useNewRoute && newArrivalPos != -1) {
815 // must be called here because replaceRouteEdges may also set the arrivalPos
816 veh.setArrivalPos(newArrivalPos);
817 }
818 } else {
819 // person rerouting here
820 bool success = !items.empty();
821 if (success) {
822 MSTransportableRouter& router = hasReroutingDevice
824 : MSNet::getInstance()->getIntermodalRouter(tObject.getRNGIndex(), 0, prohibited);
825 success = router.compute(newEdge, lastEdge, newEdge->getLength() / 2., "",
826 tObject.getParameter().arrivalPos, "",
827 tObject.getMaxSpeed(), nullptr, tObject.getVTypeParameter(), 0, now, items);
828 }
829 if (success) {
830 for (const MSTransportableRouter::TripItem& it : items) {
831 if (!it.edges.empty() && !edges.empty() && edges.back() == it.edges.front()) {
832 edges.pop_back();
833 }
834 edges.insert(edges.end(), std::make_move_iterator(it.edges.begin()), std::make_move_iterator(it.edges.end()));
835 }
836 if (!edges.empty()) {
837 static_cast<MSPerson&>(tObject).replaceWalk(edges, tObject.getPositionOnLane(), 0, 1);
838 }
839 } else {
840 // maybe the pedestrian model still finds a way (JuPedSim)
841 static_cast<MSPerson&>(tObject).replaceWalk({tObject.getEdge(), newEdge, lastEdge}, tObject.getPositionOnLane(), 0, 1);
842 }
843 }
844 if (!prohibited.empty()) {
845 resetClosedEdges(hasReroutingDevice, tObject);
846 }
847 }
848 return false; // XXX another interval could appear later but we would have to track whether the currenty interval was already used
849}
850
851
852void
856
857
858void
862
863
864bool
868
869
870double
874
875
876double
880
881
882double
884 return (sp->getElement() == SUMO_TAG_PARKING_AREA
885 ? (double)dynamic_cast<MSParkingArea*>(sp)->getOccupancyIncludingRemoteReservations(veh)
886 : (double)sp->getStoppedVehicles().size());
887}
888
889
890double
896
897
898double
900 if (myBlockedStoppingPlaces.count(sp) == 0) {
901 return (double)(sp->getElement() == SUMO_TAG_PARKING_AREA
902 ? dynamic_cast<MSParkingArea*>(sp)->getCapacity()
903 // assume only one vehicle at a time (for stationReroute)
904 : 1.);
905 } else {
906 return 0.;
907 }
908}
909
910
911void
913 veh.rememberBlockedParkingArea(parkingArea, blocked);
914}
915
916
917void
919 veh.rememberParkingAreaScore(parkingArea, score);
920}
921
922
923void
927
928
931 return veh.sawBlockedParkingArea(parkingArea, local);
932}
933
934
935int
939
940
941void
945
946
949 SUMOVehicle& veh, bool& newDestination, ConstMSEdgeVector& newRoute) {
950 MSStoppingPlace* destStoppingPlace = veh.getNextParkingArea();
951 if (destStoppingPlace == nullptr) {
952 // not driving towards the right type of stop
953 return nullptr;
954 }
955 std::vector<StoppingPlaceVisible> parks;
956 for (auto cand : rerouteDef->parkProbs.getVals()) {
957 if (cand.first->accepts(&veh)) {
958 parks.push_back(cand);
959 }
960 }
961 StoppingPlaceParamMap_t addInput = {};
962 return dynamic_cast<MSParkingArea*>(rerouteStoppingPlace(destStoppingPlace, parks, rerouteDef->parkProbs.getProbs(), veh, newDestination, newRoute, addInput, rerouteDef->getClosed()));
963}
964
965
966std::pair<const SUMOVehicle*, MSRailSignal*>
968 ConstMSEdgeVector::const_iterator mainStart,
969 const OvertakeLocation& oloc,
970 double& netSaving) {
971 const ConstMSEdgeVector& route = veh.getRoute().getEdges();
972 const MSEdgeVector& main = oloc.main;
973 const double vMax = veh.getMaxSpeed();
974 const double prio = veh.getFloatParam(toString(SUMO_TAG_OVERTAKING_REROUTE) + ".prio", false, DEFAULT_PRIO_OVERTAKEN, false);
976 for (MSVehicleControl::constVehIt it_veh = c.loadedVehBegin(); it_veh != c.loadedVehEnd(); ++it_veh) {
977 const MSBaseVehicle* veh2 = dynamic_cast<const MSBaseVehicle*>((*it_veh).second);
978 if (veh2->isOnRoad() && veh2->getMaxSpeed() > vMax) {
979 const double arrivalDelay = veh2->getStopArrivalDelay();
980 const double delay = MAX2(veh2->getStopDelay(), arrivalDelay == INVALID_DOUBLE ? 0 : arrivalDelay);
981 if (delay > veh2->getFloatParam(toString(SUMO_TAG_OVERTAKING_REROUTE) + ".maxDelay", false, DEFAULT_MAXDELAY, false)) {
982 continue;
983 }
984 const ConstMSEdgeVector& route2 = veh2->getRoute().getEdges();
985 auto itOnMain2 = route2.end();
986 int mainIndex = 0;
987 for (const MSEdge* m : main) {
988 itOnMain2 = std::find(veh2->getCurrentRouteEdge(), route2.end(), m);
989 if (itOnMain2 != route2.end()) {
990 break;
991 }
992 mainIndex++;
993 }
994 if (itOnMain2 != route2.end() && itOnMain2 > veh2->getCurrentRouteEdge()) {
995 auto itOnMain = mainStart + mainIndex;
996 double timeToMain = 0;
997 for (auto it = veh.getCurrentRouteEdge(); it != itOnMain; it++) {
998 timeToMain += (*it)->getMinimumTravelTime(&veh);
999 }
1000 // veh2 may be anywhere on the current edge so we have to discount
1001 double timeToMain2 = -veh2->getEdge()->getMinimumTravelTime(veh2) * veh2->getPositionOnLane() / veh2->getEdge()->getLength();
1002 double timeToLastSignal2 = timeToMain2;
1003 for (auto it = veh2->getCurrentRouteEdge(); it != itOnMain2; it++) {
1004 timeToMain2 += (*it)->getMinimumTravelTime(veh2);
1005 auto signal = getRailSignal(*it);
1006 if (signal) {
1007 timeToLastSignal2 = timeToMain2;
1008#ifdef DEBUG_OVERTAKING
1009 std::cout << " lastBeforeMain2 " << signal->getID() << "\n";
1010#endif
1011 }
1012 }
1013 double exitMainTime = timeToMain;
1014 double exitMainBlockTime2 = timeToMain2;
1015 double commonTime = 0;
1016 double commonTime2 = 0;
1017 int nCommon = 0;
1018 auto exitMain2 = itOnMain2;
1019 const MSRailSignal* firstAfterMain = nullptr;
1020 const MSEdge* common = nullptr;
1021 double vMinCommon = (*itOnMain)->getVehicleMaxSpeed(&veh);
1022 double vMinCommon2 = (*itOnMain2)->getVehicleMaxSpeed(veh2);
1023 while (itOnMain2 != route2.end()
1024 && itOnMain != route.end()
1025 && *itOnMain == *itOnMain2) {
1026 common = *itOnMain;
1027 commonTime += common->getMinimumTravelTime(&veh);
1028 commonTime2 += common->getMinimumTravelTime(veh2);
1029 vMinCommon = MIN2(vMinCommon, common->getVehicleMaxSpeed(&veh));
1030 vMinCommon2 = MIN2(vMinCommon2, common->getVehicleMaxSpeed(veh2));
1031 const bool onMain = nCommon < (int)main.size() - mainIndex;
1032 if (onMain) {
1033 exitMainTime = timeToMain + commonTime;
1034 }
1035 if (firstAfterMain == nullptr) {
1036 exitMainBlockTime2 = timeToMain2 + commonTime2;
1037 }
1038 auto signal = getRailSignal(common);
1039 if (signal) {
1040 if (!onMain && firstAfterMain == nullptr) {
1041 firstAfterMain = signal;
1042#ifdef DEBUG_OVERTAKING
1043 std::cout << " firstAfterMain " << signal->getID() << "\n";
1044#endif
1045 }
1046 }
1047 nCommon++;
1048 itOnMain++;
1049 itOnMain2++;
1050 }
1051 const double vMaxLast = common->getVehicleMaxSpeed(&veh);
1052 const double vMaxLast2 = common->getVehicleMaxSpeed(veh2);
1053 commonTime += veh.getLength() / vMaxLast;
1054 exitMainBlockTime2 += veh2->getLength() / vMaxLast2;
1055 exitMain2 += MIN2(nCommon, (int)main.size() - mainIndex);
1056 double timeLoss2 = MAX2(0.0, timeToMain + veh.getLength() / oloc.siding.front()->getVehicleMaxSpeed(&veh) - timeToLastSignal2);
1057 const double saving = timeToMain + commonTime - (timeToMain2 + commonTime2) - timeLoss2;
1058 const double loss = exitMainBlockTime2 - exitMainTime;
1059 const double prio2 = veh2->getFloatParam(toString(SUMO_TAG_OVERTAKING_REROUTE) + ".prio", false, DEFAULT_PRIO_OVERTAKER, false);
1060 // losses from acceleration after stopping at a signal
1061 const double accelTimeLoss = loss > 0 ? 0.5 * vMinCommon / veh.getVehicleType().getCarFollowModel().getMaxAccel() : 0;
1062 const double accelTimeLoss2 = timeLoss2 > 0 ? 0.5 * vMinCommon2 / veh2->getVehicleType().getCarFollowModel().getMaxAccel() : 0;
1063 netSaving = prio2 * (saving - accelTimeLoss2) - prio * (loss + accelTimeLoss);
1064#ifdef DEBUG_OVERTAKING
1065 std::cout << SIMTIME << " veh=" << veh.getID() << " veh2=" << veh2->getID()
1066 << " sidingStart=" << oloc.siding.front()->getID()
1067 << " ttm=" << timeToMain << " ttm2=" << timeToMain2
1068 << " nCommon=" << nCommon << " cT=" << commonTime << " cT2=" << commonTime2
1069 << " em=" << exitMainTime << " emb2=" << exitMainBlockTime2
1070 << " ttls2=" << timeToLastSignal2
1071 << " saving=" << saving << " loss=" << loss
1072 << " atl=" << accelTimeLoss << " atl2=" << accelTimeLoss2 << " tl2=" << timeLoss2
1073 << " prio=" << prio << " prio2=" << prio2 << " netSaving=" << netSaving << "\n";
1074#endif
1075 if (netSaving > oloc.minSaving) {
1076 MSRailSignal* s = findSignal(veh2->getCurrentRouteEdge(), exitMain2);
1077 if (s != nullptr) {
1078 return std::make_pair(veh2, s);
1079 }
1080 }
1081 }
1082 }
1083 }
1084 return std::make_pair(nullptr, nullptr);
1085}
1086
1087
1088void
1091#ifdef DEBUG_REROUTER
1092 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << "\n";
1093#endif
1094 if (!ego.hasStops()) {
1095 return;
1096 }
1097 const MSStop& stop = ego.getNextStop();
1098 if (stop.reached || stop.joinTriggered || (stop.pars.arrival < 0 && stop.pars.until < 0)) {
1099 return;
1100 }
1101 MSStoppingPlace* cur = nullptr;
1102 for (MSStoppingPlace* sp : stop.getPlaces()) {
1103 for (auto item : def->stopAlternatives) {
1104 if (sp == item.first) {
1105 cur = sp;
1106 break;
1107 }
1108 }
1109 }
1110 if (cur == nullptr) {
1111 return;
1112 }
1113 std::vector<const SUMOVehicle*> stopped = cur->getStoppedVehicles();
1114#ifdef DEBUG_REROUTER
1115 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << " stopped=" << toString(stopped) << "\n";
1116#endif
1117 SUMOTime stoppedDuration = -1;
1118 if (stopped.empty()) {
1120 const MSLane& stopLane = cur->getLane();
1122 for (MSVehicleControl::constVehIt it_veh = c.loadedVehBegin(); it_veh != c.loadedVehEnd(); ++it_veh) {
1123 const MSBaseVehicle* veh = dynamic_cast<const MSBaseVehicle*>((*it_veh).second);
1124 if (veh->isOnRoad() && veh->hasStops()) {
1125 const MSStop& vehStop = veh->getNextStop();
1126 if (vehStop.pars.lane == stopLane.getID()) {
1127 myBlockedStoppingPlaces.insert(cur);
1128 if (veh->isStopped()) {
1129 // stopped somewhere else on the same lane
1130 stoppedDuration = MAX3((SUMOTime)0, stoppedDuration, veh->getStopDuration());
1131 } else {
1132 std::pair<double, double> timeDist = veh->estimateTimeToNextStop();
1133 SUMOTime timeTo = TIME2STEPS(timeDist.first);
1134 stoppedDuration = MAX3((SUMOTime)0, stoppedDuration, timeTo + vehStop.getMinDuration(SIMSTEP + timeTo));
1135 }
1136 }
1137 }
1138 }
1139 } else {
1140 stoppedDuration = 0;
1141 for (const SUMOVehicle* veh : cur->getStoppedVehicles()) {
1142 stoppedDuration = MAX2(stoppedDuration, veh->getStopDuration());
1143 }
1144 }
1145 if (stoppedDuration < 0) {
1146 return;
1147 }
1149 const SUMOTime stopFree = SIMSTEP + stoppedDuration;
1150 const SUMOTime scheduledArrival = stop.pars.arrival >= 0 ? stop.pars.arrival : stop.pars.until - stop.pars.duration;
1151#ifdef DEBUG_REROUTER
1152 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << " stopFree=" << stopFree << " scheduledArrival=" << time2string(scheduledArrival) << "\n";
1153#endif
1154 if (stopFree < scheduledArrival) {
1155 // no conflict according to the schedule
1156 return;
1157 }
1158 const SUMOTime estimatedArrival = SIMSTEP + (stop.pars.arrival >= 0
1160 : TIME2STEPS(ego.getStopDelay()) - stop.pars.duration);
1161#ifdef DEBUG_REROUTER
1162 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << " stopFree=" << stopFree << " estimatedArrival=" << time2string(estimatedArrival) << "\n";
1163#endif
1164 if (stopFree < estimatedArrival) {
1165 // no conflict when considering current delay
1166 return;
1167 }
1168 const std::vector<double> probs(def->stopAlternatives.size(), 1.);
1169 StoppingPlaceParamMap_t scores = {};
1170 bool newDestination;
1171 ConstMSEdgeVector newRoute;
1172 // @todo: consider future conflicts caused by rerouting
1173 // @todo: reject alternatives with large detour
1174 const MSStoppingPlace* alternative = rerouteStoppingPlace(nullptr, def->stopAlternatives, probs, ego, newDestination, newRoute, scores);
1175#ifdef DEBUG_REROUTER
1176 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << " alternative=" << Named::getIDSecure(alternative) << "\n";
1177#endif
1178 if (alternative != nullptr) {
1179 // @todo adapt plans of any riders
1180 //for (MSTransportable* p : ego.getPersons()) {
1181 // p->rerouteParkingArea(ego.getNextParkingArea(), newParkingArea);
1182 //}
1183
1184 if (newDestination && ego.getParameter().arrivalPosProcedure != ArrivalPosDefinition::DEFAULT) {
1185 // update arrival parameters
1186 SUMOVehicleParameter* newParameter = new SUMOVehicleParameter();
1187 *newParameter = ego.getParameter();
1189 newParameter->arrivalPos = alternative->getEndLanePosition();
1190 ego.replaceParameter(newParameter);
1191 }
1192
1193 SUMOVehicleParameter::Stop newStop = stop.pars;
1194 newStop.lane = alternative->getLane().getID();
1195 newStop.startPos = alternative->getBeginLanePosition();
1196 newStop.endPos = alternative->getEndLanePosition();
1197 switch (alternative->getElement()) {
1199 newStop.parkingarea = alternative->getID();
1200 break;
1202 newStop.containerstop = alternative->getID();
1203 break;
1205 newStop.chargingStation = alternative->getID();
1206 break;
1208 newStop.overheadWireSegment = alternative->getID();
1209 break;
1210 case SUMO_TAG_BUS_STOP:
1212 default:
1213 newStop.busstop = alternative->getID();
1214 }
1215 std::string errorMsg;
1216 if (!ego.replaceStop(0, newStop, getID() + ":" + toString(SUMO_TAG_STATION_REROUTE), false, errorMsg)) {
1217 WRITE_WARNING("Vehicle '" + ego.getID() + "' at rerouter '" + getID()
1218 + "' could not perform stationReroute to '" + alternative->getID()
1219 + "' reason=" + errorMsg + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1220 }
1221 }
1222}
1223
1224
1226MSTriggeredRerouter::findSignal(ConstMSEdgeVector::const_iterator begin, ConstMSEdgeVector::const_iterator end) {
1227 auto it = end;
1228 do {
1229 it--;
1230 auto signal = getRailSignal(*it);
1231 if (signal != nullptr) {
1232 return signal;
1233 }
1234 } while (it != begin);
1235 return nullptr;
1236}
1237
1238
1242 for (const MSLink* link : edge->getLanes().front()->getLinkCont()) {
1243 if (link->getTLLogic() != nullptr) {
1244 return dynamic_cast<MSRailSignal*>(const_cast<MSTrafficLightLogic*>(link->getTLLogic()));
1245 }
1246 }
1247 }
1248 return nullptr;
1249}
1250
1251bool
1253 if (myVehicleTypes.empty() || myVehicleTypes.count(obj.getVehicleType().getOriginalID()) > 0) {
1254 return true;
1255 } else {
1257 for (auto vTypeDist : vTypeDists) {
1258 if (myVehicleTypes.count(vTypeDist) > 0) {
1259 return true;
1260 }
1261 }
1262 return false;
1263 }
1264}
1265
1266
1267bool
1268MSTriggeredRerouter::affected(const std::set<SUMOTrafficObject::NumericalID>& edgeIndices, const MSEdgeVector& closed) {
1269 for (const MSEdge* const e : closed) {
1270 if (edgeIndices.count(e->getNumericalID()) > 0) {
1271 return true;
1272 }
1273 }
1274 return false;
1275}
1276
1277
1278void
1280 // if a parkingArea is a rerouting target, it should generally have a
1281 // rerouter on its edge or vehicles will be stuck there once it's full.
1282 // The user should receive a Warning in this case
1283 std::set<MSEdge*> parkingRerouterEdges;
1284 std::map<MSParkingArea*, std::string, ComparatorIdLess> targetedParkingArea; // paID -> targetingRerouter
1285 for (const auto& rr : myInstances) {
1286 bool hasParkingReroute = false;
1287 for (const RerouteInterval& interval : rr.second->myIntervals) {
1288 if (interval.parkProbs.getOverallProb() > 0) {
1289 hasParkingReroute = true;
1290 for (const StoppingPlaceVisible& pav : interval.parkProbs.getVals()) {
1291 targetedParkingArea[dynamic_cast<MSParkingArea*>(pav.first)] = rr.first;
1292 }
1293 }
1294 }
1295 if (hasParkingReroute) {
1296 parkingRerouterEdges.insert(rr.second->myEdges.begin(), rr.second->myEdges.end());
1297 }
1298 }
1299 for (const auto& item : targetedParkingArea) {
1300 if (parkingRerouterEdges.count(&item.first->getLane().getEdge()) == 0) {
1301 WRITE_WARNINGF(TL("ParkingArea '%' is targeted by rerouter '%' but doesn't have its own rerouter. This may cause parking search to abort."),
1302 item.first->getID(), item.second);
1303 }
1304 }
1305}
1306
1307
1308void
1310 // getRouterTT without prohibitions removes previous prohibitions
1311 if (o.isVehicle()) {
1312 hasReroutingDevice
1315 } else {
1316 hasReroutingDevice
1319 }
1320}
1321
1322/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
std::vector< const MSEdge * > ConstMSEdgeVector
Definition MSEdge.h:74
std::vector< MSEdge * > MSEdgeVector
Definition MSEdge.h:73
#define DEBUGCOND(PED)
ConstMSEdgeVector::const_iterator MSRouteIterator
Definition MSRoute.h:57
#define DEFAULT_PRIO_OVERTAKEN
#define DEFAULT_PRIO_OVERTAKER
assume that a faster train has more priority and a slower train doesn't matter
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition Route.h:32
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition SUMOTime.cpp:46
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:91
#define STEPS2TIME(x)
Definition SUMOTime.h:58
#define SIMSTEP
Definition SUMOTime.h:64
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define SIMTIME
Definition SUMOTime.h:65
#define TIME2STEPS(x)
Definition SUMOTime.h:60
const SVCPermissions SVCAll
all VClasses are allowed
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ SVC_AUTHORITY
authorities vehicles
@ GIVEN
The arrival position is given.
@ DEFAULT
No information given; use default.
@ SUMO_TAG_INTERVAL
an aggreagated-output interval
@ SUMO_TAG_CLOSING_REROUTE
reroute of type closing
@ SUMO_TAG_CHARGING_STATION
A Charging Station.
@ SUMO_TAG_CONTAINER_STOP
A container stop.
@ SUMO_TAG_PARKING_AREA_REROUTE
entry for an alternative parking zone
@ SUMO_TAG_BUS_STOP
A bus stop.
@ SUMO_TAG_PARKING_AREA
A parking area.
@ SUMO_TAG_ROUTE_PROB_REROUTE
probability of route of a reroute
@ SUMO_TAG_VIA_PROB_REROUTE
probability of a via reroute
@ SUMO_TAG_TRAIN_STOP
A train stop (alias for bus stop)
@ SUMO_TAG_OVERHEAD_WIRE_SEGMENT
An overhead wire segment.
@ SUMO_TAG_DEST_PROB_REROUTE
probability of destination of a reroute
@ SUMO_TAG_OVERTAKING_REROUTE
decision point for rerouting to be overtaken
@ SUMO_TAG_CLOSING_LANE_REROUTE
lane of a reroute of type closing
@ SUMO_TAG_STATION_REROUTE
decision point for switching trainStop/busStop within a station
@ SUMO_ATTR_DISALLOW
@ SUMO_ATTR_ALLOW
@ SUMO_ATTR_MAIN
@ SUMO_ATTR_DEFER
@ SUMO_ATTR_BEGIN
weights: time range begin
@ SUMO_ATTR_MINSAVING
@ SUMO_ATTR_END
weights: time range end
@ SUMO_ATTR_PROB
@ SUMO_ATTR_SIDING
@ SUMO_ATTR_ID
@ SUMO_ATTR_VISIBLE
@ SUMO_ATTR_UNTIL
const double INVALID_DOUBLE
invalid double
Definition StdDefs.h:68
T MIN2(T a, T b)
Definition StdDefs.h:80
T MAX2(T a, T b)
Definition StdDefs.h:86
T MAX3(T a, T b, T c)
Definition StdDefs.h:100
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:49
int main(int argc, char *argv[])
bool compute(const E *from, const E *to, const double departPos, const std::string &originStopID, const double arrivalPos, const std::string &stopID, const double speed, const V *const vehicle, const SUMOVTypeParameter &pars, const SVCPermissions modeSet, const SUMOTime msTime, std::vector< TripItem > &into, const double externalFactor=0.)
Builds the route between the given edges using the minimum effort at the given time The definition of...
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition MELoop.cpp:339
void addDetector(MSMoveReminder *data, int queueIndex=-1)
Adds a data collector for a detector to this segment.
The base class for microscopic and mesoscopic vehicles.
double getMaxSpeed() const
Returns the maximum speed (the minimum of desired and technical maximum speed)
bool replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string &info, bool teleport, std::string &errorMsg)
virtual double getStopDelay() const
Returns the estimated public transport stop (departure) delay in seconds.
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
void replaceParameter(const SUMOVehicleParameter *newParameter)
replace the vehicle parameter (deleting the old one)
const MSRouteIterator & getCurrentRouteEdge() const
Returns an iterator pointing to the current edge in this vehicles route.
double getLength() const
Returns the vehicle's length.
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
virtual std::pair< double, double > estimateTimeToNextStop() const
return time (s) and distance to the next stop
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
const MSStop & getNextStop() const
virtual double getStopArrivalDelay() const
Returns the estimated public transport stop arrival delay in seconds.
SUMOTime getStopDuration() const
get remaining stop duration or 0 if the vehicle isn't stopped
const MSRoute & getRoute() const
Returns the current route.
virtual bool isOnRoad() const
Returns the information whether the vehicle is on a road (is simulated)
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
bool isStopped() const
Returns whether the vehicle is at a stop.
double getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
Definition MSCFModel.h:277
A device that performs vehicle rerouting based on current edge speeds.
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
const MSJunction * getToJunction() const
Definition MSEdge.h:427
double getLength() const
return the length of the edge
Definition MSEdge.h:694
double getMinimumTravelTime(const SUMOVehicle *const veh) const
returns the minimum travel time for the given vehicle
Definition MSEdge.h:485
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:1081
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the maximum speed the vehicle may use on this edge.
Definition MSEdge.cpp:1204
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static bool gUseMesoSim
Definition MSGlobals.h:106
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition MSGlobals.h:115
static int gNumSimThreads
how many threads to use for simulation
Definition MSGlobals.h:149
SumoXMLNodeType getType() const
return the type of this Junction
Definition MSJunction.h:133
Representation of a lane in the micro simulation.
Definition MSLane.h:84
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2521
Something on a lane to be noticed about vehicle movement.
Notification
Definition of a vehicle state.
@ NOTIFICATION_LANE_CHANGE
The vehicle changes lanes (micro only)
@ NOTIFICATION_JUNCTION
The vehicle arrived at a junction.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:199
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:495
MSTransportableRouter & getIntermodalRouter(int rngIndex, const int routingMode=0, const Prohibitions &prohibited={}) const
Definition MSNet.cpp:1675
MSVehicleRouter & getRouterTT(int rngIndex, const Prohibitions &prohibited={}) const
Definition MSNet.cpp:1628
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition MSNet.cpp:1496
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:402
A lane area vehicles can halt at.
int getLastStepOccupancyIncludingRemoteReservations(const SUMOVehicle *forVehicle) const
bool isReservable() const
whether vehicles may reserve a slot for this parkingArea
void addSpaceReservation(const SUMOVehicle *veh)
api for reserving spaces at this parkingArea
int getOccupancyIncludingRemoteReservations(const SUMOVehicle *forVehicle) const
void removeSpaceReservation(const SUMOVehicle *veh)
A signal for rails.
void addConstraint(const std::string &tripId, MSRailSignalConstraint *constraint)
register constraint for signal switching
const ConstMSEdgeVector & getEdges() const
Definition MSRoute.h:128
MSRouteIterator end() const
Returns the end of the list of edges to pass.
Definition MSRoute.cpp:79
bool containsAnyOf(const MSEdgeVector &edgelist) const
Definition MSRoute.cpp:250
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition MSRoute.cpp:116
double getCosts() const
Returns the costs of the route.
Definition MSRoute.h:178
static MSVehicleRouter & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const Prohibitions &prohibited={})
return the vehicle router instance
static MSTransportableRouter & getIntermodalRouterTT(const int rngIndex, const Prohibitions &prohibited={})
return the person router instance
std::vector< MSStoppingPlace * > getPlaces() const
return all stoppingPlaces associated with this stop
Definition MSStop.cpp:225
bool joinTriggered
whether coupling another vehicle (train) the vehicle continue
Definition MSStop.h:73
SUMOTime getMinDuration(SUMOTime time) const
return minimum stop duration when starting stop at time
Definition MSStop.cpp:171
bool reached
Information whether the stop has been reached.
Definition MSStop.h:75
MSRouteIterator edge
The edge in the route to stop at.
Definition MSStop.h:48
const SUMOVehicleParameter::Stop pars
The stop parameter.
Definition MSStop.h:65
A lane area vehicles can halt at.
std::vector< const SUMOVehicle * > getStoppedVehicles() const
get list of vehicles waiting at this stop
double getBeginLanePosition() const
Returns the begin position of this stop.
SumoXMLTag getElement() const
return the type of this stopping place
double getEndLanePosition() const
Returns the end position of this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
std::map< std::string, double > StoppingPlaceParamMap_t
MSStoppingPlace * rerouteStoppingPlace(MSStoppingPlace *destStoppingPlace, const std::vector< StoppingPlaceVisible > &stoppingPlaceCandidates, const std::vector< double > &probs, SUMOVehicle &veh, bool &newDestination, ConstMSEdgeVector &newRoute, StoppingPlaceParamMap_t &scores, const Prohibitions &closedEdges={}, const int insertStopIndex=0, const bool keepCurrentStop=true)
main method to trigger the rerouting to the "best" StoppingPlace according to the custom evaluation f...
std::pair< MSStoppingPlace *, bool > StoppingPlaceVisible
The parent class for traffic light logics.
SUMOTime setPermissions(const SUMOTime currentTime)
Sets the edge permission if there are any defined in the closingEdge.
bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Tries to reroute the vehicle.
int getNumberStoppingPlaceReroutes(SUMOVehicle &veh)
ask how many times already the vehicle has been rerouted to another stopping place
bool notifyMove(SUMOTrafficObject &veh, double oldPos, double newPos, double newSpeed)
Triggers rerouting (once) for vehicles that are already on the edge when the rerouter activates.
static MSRailSignal * findSignal(ConstMSEdgeVector::const_iterator begin, ConstMSEdgeVector::const_iterator end)
find the last downstream signal on the given route
bool notifyLeave(SUMOTrafficObject &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Removes the reminder.
MSTriggeredRerouter(const std::string &id, const MSEdgeVector &edges, double prob, bool off, bool optional, SUMOTime timeThreshold, const std::string &vTypes, const Position &pos, const double radius)
Constructor.
double getStoppingPlaceOccupancy(MSStoppingPlace *sp, const SUMOVehicle *veh)
Return the number of occupied places of the stopping place.
double getUserProbability() const
Returns the rerouting probability given by the user.
static const double DEFAULT_MAXDELAY
MSParkingArea * rerouteParkingArea(const MSTriggeredRerouter::RerouteInterval *rerouteDef, SUMOVehicle &veh, bool &newDestination, ConstMSEdgeVector &newRoute)
search for an alternative ParkingArea
bool myHaveParkProbs
whether this rerouter has loaded parkingReroute definitions
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
bool myAmOptional
Information whether the rerouting will only take place on request.
static bool affected(const std::set< SUMOTrafficObject::NumericalID > &edgeIndices, const MSEdgeVector &closed)
void setUserUsageProbability(double prob)
Sets the probability with which a vehicle is rerouted given by the user.
Position myPosition
Where are we located in the network.
std::pair< const SUMOVehicle *, MSRailSignal * > overtakingTrain(const SUMOVehicle &veh, ConstMSEdgeVector::const_iterator mainStart, const OvertakeLocation &oloc, double &netSaving)
determine whether veh should switch from main to siding to be overtaken and return the overtaking veh...
void rememberStoppingPlaceScore(SUMOVehicle &veh, MSStoppingPlace *parkingArea, const std::string &score)
store the score of the ParkingArea in the vehicle
void rememberBlockedStoppingPlace(SUMOVehicle &veh, const MSStoppingPlace *parkingArea, bool blocked)
store the blocked ParkingArea in the vehicle
static MSEdge mySpecialDest_terminateRoute
virtual void myEndElement(int element)
Called when a closing tag occurs.
void checkStopSwitch(MSBaseVehicle &veh, const MSTriggeredRerouter::RerouteInterval *def)
consider switching the location of the upcoming stop
void resetClosedEdges(bool hasReroutingDevice, const SUMOTrafficObject &o)
reset router after closing edges
bool triggerRouting(SUMOTrafficObject &veh, MSMoveReminder::Notification reason)
double myRadius
At which distance are we activated.
void resetStoppingPlaceScores(SUMOVehicle &veh)
reset all stored ParkingArea scores for this vehicle
double myProbability
The probability and the user-given probability.
SUMOTime sawBlockedStoppingPlace(SUMOVehicle &veh, MSStoppingPlace *parkingArea, bool local)
get the time the ParkingArea was considered full from this vehicle
virtual ~MSTriggeredRerouter()
Destructor.
bool inUserMode() const
Returns whether the user is setting the rerouting probability.
void setNumberStoppingPlaceReroutes(SUMOVehicle &veh, int value)
update the number of reroutes for the vehicle
std::set< const MSStoppingPlace * > myBlockedStoppingPlaces
double getStoppingPlaceCapacity(MSStoppingPlace *sp)
Return the number of places the stopping place provides.
std::set< std::string > myVehicleTypes
The vehicle types to look for (empty means all)
const RerouteInterval * getCurrentReroute(SUMOTime time, SUMOTrafficObject &obj) const
Returns the rerouting definition valid for the given time and object, nullptr if none.
static void checkParkingRerouteConsistency()
issues warning for incomplete parkingReroute relationships
static std::map< std::string, MSTriggeredRerouter * > myInstances
bool applies(const SUMOTrafficObject &obj) const
Checks whether the detector measures objects of the given type.
bool myAmInUserMode
Information whether the current rerouting probability is the user-given.
static MSRailSignal * getRailSignal(const MSEdge *edge)
return railsignal at that edge or nullptr
const MSEdgeVector myEdges
edges where vehicles are notified
std::map< const MSEdge *, RouterProhibition > Prohibitions
static MSEdge mySpecialDest_keepDestination
special destination values
RerouteInterval myParsedRerouteInterval
used during loading
double getProbability() const
Returns the rerouting probability.
std::vector< RerouteInterval > myIntervals
List of rerouting definition intervals.
double getLastStepStoppingPlaceOccupancy(MSStoppingPlace *sp, const SUMOVehicle *veh)
Return the number of occupied places of the stopping place from the previous time step.
void setUserMode(bool val)
Sets whether the process is currently steered by the user.
The class responsible for building and deletion of vehicles.
std::map< std::string, SUMOVehicle * >::const_iterator constVehIt
Definition of the internal vehicles map iterator.
constVehIt loadedVehBegin() const
Returns the begin of the internal vehicle map.
constVehIt loadedVehEnd() const
Returns the end of the internal vehicle map.
const std::set< std::string > getVTypeDistributionMembership(const std::string &id) const
Return the distribution IDs the vehicle type is a member of.
const MSCFModel & getCarFollowModel() const
Returns the vehicle type's car following model definition (const version)
const std::string & getOriginalID() const
Returns the id of the original vehicle type if this is a vehicle specific type, the id otherwise.
Base class for objects which have an id.
Definition Named.h:54
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition Named.h:67
const std::string & getID() const
Returns the id.
Definition Named.h:74
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
double distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimensions
Definition Position.h:263
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Represents a generic random distribution.
double getOverallProb() const
Return the sum of the probabilites assigned to the members.
T get(SumoRNG *which=nullptr) const
Draw a sample of the distribution.
bool add(T val, double prob, bool checkDuplicates=true)
Adds a value with an assigned probability to the distribution.
const std::vector< T > & getVals() const
Returns the members of the distribution.
bool remove(T val)
Removes a value with an assigned probability from the distribution.
const std::vector< double > & getProbs() const
Returns the probabilities assigned to the members of the distribution.
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
virtual double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const
Encapsulated SAX-Attributes.
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.
virtual std::string getStringSecure(int id, const std::string &def) const =0
Returns the string-value of the named (by its enum-value) attribute.
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.
Representation of a vehicle, person, or container.
virtual bool isVehicle() const
Whether it is a vehicle.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual const MSLane * getLane() const =0
Returns the lane the object is currently at.
virtual const SUMOVTypeParameter & getVTypeParameter() const =0
Returns the object's "vehicle" type parameter.
virtual int getRNGIndex() const =0
virtual MSDevice * getDevice(const std::type_info &type) const =0
Returns a device of the given type if it exists or nullptr if not.
virtual bool replaceRoute(ConstMSRoutePtr route, const std::string &info, bool onInit=false, int offset=0, bool addStops=true, bool removeStops=true, std::string *msgReturn=nullptr)=0
Replaces the current route by the given one.
virtual SUMOTime getWaitingTime(const bool accumulated=false) const =0
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
virtual double getMaxSpeed() const =0
Returns the object's maximum speed (minimum of technical and desired maximum speed)
virtual SUMOVehicleClass getVClass() const =0
Returns the object's access class.
virtual SumoRNG * getRNG() const =0
Returns the associated RNG for this object.
virtual Position getPosition(const double offset=0) const =0
Return current position (x/y, cartesian)
double getFloatParam(const std::string &paramName, const bool required=false, const double deflt=INVALID_DOUBLE, bool checkDist=true) const
Retrieve a floating point parameter for the traffic object.
virtual const std::set< NumericalID > getUpcomingEdgeIDs() const =0
returns the numerical IDs of edges to be used (possibly of future stages)
virtual const MSEdge * getEdge() const =0
Returns the (normal) route edge the object is currently at.
virtual const MSEdge * getRerouteDestination() const =0
Returns the end point for reroutes (usually the last edge of the route)
virtual double getPositionOnLane() const =0
Get the object's position along the lane.
Representation of a vehicle.
Definition SUMOVehicle.h:63
virtual bool reroute(SUMOTime t, const std::string &info, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, const bool onInit=false, const bool withTaz=false, const bool silent=false, const MSEdge *sink=nullptr)=0
Performs a rerouting using the given router.
virtual SUMOTime sawBlockedParkingArea(const MSStoppingPlace *pa, bool local) const =0
virtual bool replaceRouteEdges(ConstMSEdgeVector &edges, double cost, double savings, const std::string &info, bool onInit=false, bool check=false, bool removeStops=true, std::string *msgReturn=nullptr)=0
Replaces the current route by the given edges.
virtual bool replaceParkingArea(MSParkingArea *parkingArea, std::string &errorMsg)=0
Replaces a stop.
virtual bool hasStops() const =0
Returns whether the vehicle has to stop somewhere.
virtual MSParkingArea * getNextParkingArea()=0
virtual void rememberParkingAreaScore(const MSStoppingPlace *pa, const std::string &score)=0
virtual void rememberBlockedParkingArea(const MSStoppingPlace *pa, bool local)=0
virtual double getLength() const =0
Returns the vehicles's length.
virtual int getNumberParkingReroutes() const =0
virtual const std::vector< MSTransportable * > & getPersons() const =0
retrieve riding persons
virtual void replaceParameter(const SUMOVehicleParameter *newParameter)=0
Replaces the vehicle's parameter.
virtual void resetParkingAreaScores()=0
virtual const MSStop & getNextStop() const =0
virtual void setArrivalPos(double arrivalPos)=0
Sets this vehicle's desired arrivalPos for its current route.
virtual const ConstMSEdgeVector::const_iterator & getCurrentRouteEdge() const =0
Returns an iterator pointing to the current edge in this vehicles route.
virtual void setNumberParkingReroutes(int value)=0
virtual const MSRoute & getRoute() const =0
Returns the current route.
virtual bool abortNextStop(int nextStopIndex=0)=0
deletes the next stop at the given index if it exists
Definition of vehicle stop (position and duration)
std::string lane
The lane to stop at.
std::string parkingarea
(Optional) parking area if one is assigned to the stop
double startPos
The stopping position start.
std::string chargingStation
(Optional) charging station if one is assigned to the stop
std::string overheadWireSegment
(Optional) overhead line segment if one is assigned to the stop
SUMOTime until
The time at which the vehicle may continue its journey.
double endPos
The stopping position end.
std::string busstop
(Optional) bus stop if one is assigned to the stop
std::string containerstop
(Optional) container stop if one is assigned to the stop
SUMOTime arrival
The (expected) time at which the vehicle reaches the stop.
SUMOTime duration
The stopping duration.
Structure representing possible vehicle parameter.
double arrivalPos
(optional) The position the vehicle shall arrive on
ArrivalPosDefinition arrivalPosProcedure
Information how the vehicle shall choose the arrival position.
A scoped lock which only triggers on condition.
std::vector< std::string > getVector()
return vector of strings
A wrapper for a Command function.
double sidingLength
The usable length of the siding.
MSEdgeVector main
The list of main edges (const and non-const for different usage)
bool defer
whether the decision to use this siding should be deferred
double minSaving
The threshold in savings for triggering reroute.
MSEdgeVector siding
The list of siding edges.
MSRailSignal * sidingExit
The rail signal at the end of the siding.
SUMOTime begin
The begin time these definitions are valid.
RandomDistributor< MSStoppingPlaceRerouter::StoppingPlaceVisible > parkProbs
The distributions of new parking areas to use as destinations.
std::vector< MSStoppingPlaceRerouter::StoppingPlaceVisible > stopAlternatives
RandomDistributor< ConstMSRoutePtr > routeProbs
The distributions of new routes to use.
SUMOTime end
The end time these definitions are valid.
RandomDistributor< MSEdge * > edgeProbs
The distributions of new destinations or vias to use.
std::map< MSLane *, SVCPermissions > closedLanes
The list of closed lanes to their permissions.
bool isVia
The edge probs are vias and not destinations.
MSEdgeVector closedLanesAffected
The list of edges that are affected by closed lanes.
bool permissionsAllowAll
The permissions are all SVCAll.
std::map< MSEdge *, std::pair< SVCPermissions, double > > closed
The map of closed edges to their permissions and expected end of closing.
std::vector< OvertakeLocation > overtakeLocations