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 SVCPermissions permissions = SVC_UNSPECIFIED;
184 const std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, getID().c_str(), ok, "", false);
185 const std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, getID().c_str(), ok, "");
186 permissions = parseVehicleClasses(allow, disallow);
187 }
188 const SUMOTime until = attrs.getOptSUMOTimeReporting(SUMO_ATTR_UNTIL, nullptr, ok, TIME2STEPS(-1));
189 myParsedRerouteInterval.closed[closedEdge] = std::make_pair(permissions, STEPS2TIME(until));
190 }
191
192 if (element == SUMO_TAG_CLOSING_LANE_REROUTE) {
193 // by closing lane
194 std::string closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
195 MSLane* closedLane = MSLane::dictionary(closed_id);
196 if (closedLane == nullptr) {
197 throw ProcessError(TLF("rerouter '%': Lane '%' to close is not known.", getID(), closed_id));
198 }
199 SVCPermissions permissions = SVC_AUTHORITY;
201 bool ok;
202 const std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, getID().c_str(), ok, "", false);
203 const std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, getID().c_str(), ok, "");
204 permissions = parseVehicleClasses(allow, disallow);
205 }
206 myParsedRerouteInterval.closedLanes[closedLane] = permissions;
207 }
208
209 if (element == SUMO_TAG_ROUTE_PROB_REROUTE) {
210 // by explicit rerouting using routes
211 // check if route exists
212 std::string routeStr = attrs.getStringSecure(SUMO_ATTR_ID, "");
213 if (routeStr == "") {
214 throw ProcessError(TLF("rerouter '%': routeProbReroute has no alternative route id.", getID()));
215 }
216 ConstMSRoutePtr route = MSRoute::dictionary(routeStr);
217 if (route == nullptr) {
218 throw ProcessError(TLF("rerouter '%': Alternative route '%' does not exist.", getID(), routeStr));
219 }
220
221 // get the probability to reroute
222 bool ok = true;
223 double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
224 if (!ok) {
225 throw ProcessError();
226 }
227 if (prob < 0) {
228 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for alternative route '%' is negative (must not).", getID(), routeStr));
229 }
230 // add
232 }
233
234 if (element == SUMO_TAG_PARKING_AREA_REROUTE) {
235 std::string parkingarea = attrs.getStringSecure(SUMO_ATTR_ID, "");
236 if (parkingarea == "") {
237 throw ProcessError(TLF("rerouter '%': parkingAreaReroute requires a parkingArea id.", getID()));
238 }
240 if (pa == nullptr) {
241 throw ProcessError(TLF("rerouter '%': parkingArea '%' is not known.", getID(), parkingarea));
242 }
243 // get the probability to reroute
244 bool ok = true;
245 const double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
246 if (!ok) {
247 throw ProcessError();
248 }
249 if (prob < 0) {
250 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for parkingArea '%' is negative (must not).", getID(), parkingarea));
251 }
252 const bool visible = attrs.getOpt<bool>(SUMO_ATTR_VISIBLE, getID().c_str(), ok, false);
253 // add
254 myParsedRerouteInterval.parkProbs.add(std::make_pair(pa, visible), prob);
255 myHaveParkProbs = true;
256 }
257
258 if (element == SUMO_TAG_VIA_PROB_REROUTE) {
259 // by giving probabilities of vias
260 std::string viaID = attrs.getStringSecure(SUMO_ATTR_ID, "");
261 if (viaID == "") {
262 throw ProcessError(TLF("rerouter '%': No via edge id given.", getID()));
263 }
264 MSEdge* const via = MSEdge::dictionary(viaID);
265 if (via == nullptr) {
266 throw ProcessError(TLF("rerouter '%': Via Edge '%' is not known.", getID(), viaID));
267 }
268 // get the probability to reroute
269 bool ok = true;
270 double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
271 if (!ok) {
272 throw ProcessError();
273 }
274 if (prob < 0) {
275 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for via '%' is negative (must not).", getID(), viaID));
276 }
277 // add
280 }
281 if (element == SUMO_TAG_OVERTAKING_REROUTE) {
282 // for letting a slow train use a siding to be overtaken by a fast train
283 OvertakeLocation oloc;
284 bool ok = true;
285 for (const std::string& edgeID : attrs.get<std::vector<std::string> >(SUMO_ATTR_MAIN, getID().c_str(), ok)) {
286 MSEdge* edge = MSEdge::dictionary(edgeID);
287 if (edge == nullptr) {
288 throw InvalidArgument(TLF("The main edge '%' to use within rerouter '%' is not known.", edgeID, getID()));
289 }
290 oloc.main.push_back(edge);
291 oloc.cMain.push_back(edge);
292 }
293 for (const std::string& edgeID : attrs.get<std::vector<std::string> >(SUMO_ATTR_SIDING, getID().c_str(), ok)) {
294 MSEdge* edge = MSEdge::dictionary(edgeID);
295 if (edge == nullptr) {
296 throw InvalidArgument(TLF("The siding edge '%' to use within rerouter '%' is not known.", edgeID, getID()));
297 }
298 oloc.siding.push_back(edge);
299 oloc.cSiding.push_back(edge);
300 }
301 oloc.sidingExit = findSignal(oloc.cSiding.begin(), oloc.cSiding.end());
302 if (oloc.sidingExit == nullptr) {
303 throw InvalidArgument(TLF("The siding within rerouter '%' does not have a rail signal.", getID()));
304 }
305 for (auto it = oloc.cSiding.begin(); it != oloc.cSiding.end(); it++) {
306 oloc.sidingLength += (*it)->getLength();
307 if ((*it)->getToJunction()->getID() == oloc.sidingExit->getID()) {
308 break;
309 }
310 }
311 oloc.minSaving = attrs.getOpt<double>(SUMO_ATTR_MINSAVING, getID().c_str(), ok, 300);
312 const bool hasAlternatives = myParsedRerouteInterval.overtakeLocations.size() > 0;
313 oloc.defer = attrs.getOpt<bool>(SUMO_ATTR_DEFER, getID().c_str(), ok, hasAlternatives);
315 }
316 if (element == SUMO_TAG_STATION_REROUTE) {
317 // for letting a train switch it's stopping place in case of conflict
318 const std::string stopID = attrs.getStringSecure(SUMO_ATTR_ID, "");
319 if (stopID == "") {
320 throw ProcessError(TLF("rerouter '%': stationReroute requires a stopping place id.", getID()));
321 }
323 if (stop == nullptr) {
324 throw ProcessError(TLF("rerouter '%': stopping place '%' is not known.", getID(), stopID));
325 }
326 myParsedRerouteInterval.stopAlternatives.push_back(std::make_pair(stop, true));
327 }
328}
329
330
331void
333 if (element == SUMO_TAG_INTERVAL) {
334 // precompute permissionsAllowAll
335 bool allowAll = true;
336 for (const auto& entry : myParsedRerouteInterval.closed) {
337 allowAll = allowAll && entry.second.first == SVC_UNSPECIFIED;
338 if (!allowAll) {
339 break;
340 }
341 }
343
344 for (auto paVi : myParsedRerouteInterval.parkProbs.getVals()) {
345 dynamic_cast<MSParkingArea*>(paVi.first)->setNumAlternatives((int)myParsedRerouteInterval.parkProbs.getVals().size() - 1);
346 }
347 if (myParsedRerouteInterval.closedLanes.size() > 0) {
348 // collect edges that are affect by a closed lane
349 std::set<MSEdge*> affected;
350 for (std::pair<MSLane*, SVCPermissions> settings : myParsedRerouteInterval.closedLanes) {
351 affected.insert(&settings.first->getEdge());
352 }
354 }
355 const SUMOTime closingBegin = myParsedRerouteInterval.begin;
356 const SUMOTime simBegin = string2time(OptionsCont::getOptions().getString("begin"));
357 if (closingBegin < simBegin && myParsedRerouteInterval.end > simBegin) {
358 // interval started before simulation begin but is still active at
359 // the start of the simulation
361 }
363 myIntervals.back().id = (long long int)&myIntervals.back();
367 }
368 }
369}
370
371
372// ------------ loading end
373
374
377 bool updateVehicles = false;
378 for (const RerouteInterval& i : myIntervals) {
379 if (i.begin == currentTime && !(i.closed.empty() && i.closedLanes.empty()) /*&& i.permissions != SVCAll*/) {
380 for (const auto& settings : i.closed) {
381 if (settings.second.first != SVC_UNSPECIFIED) {
382 for (MSLane* lane : settings.first->getLanes()) {
383 //std::cout << SIMTIME << " closing: intervalID=" << i.id << " lane=" << lane->getID() << " prevPerm=" << getVehicleClassNames(lane->getPermissions()) << " new=" << getVehicleClassNames(settings.second.first) << "\n";
384 lane->setPermissions(settings.second.first, i.id);
385 }
386 settings.first->rebuildAllowedLanes();
387 updateVehicles = true;
388 }
389 }
390 for (std::pair<MSLane*, SVCPermissions> settings : i.closedLanes) {
391 settings.first->setPermissions(settings.second, i.id);
392 settings.first->getEdge().rebuildAllowedLanes();
393 updateVehicles = true;
394 }
397 }
398 if (i.end == currentTime && !(i.closed.empty() && i.closedLanes.empty()) /*&& i.permissions != SVCAll*/) {
399 for (auto settings : i.closed) {
400 if (settings.second.first != SVC_UNSPECIFIED) {
401 for (MSLane* lane : settings.first->getLanes()) {
402 lane->resetPermissions(i.id);
403 //std::cout << SIMTIME << " opening: intervalID=" << i.id << " lane=" << lane->getID() << " restore prevPerm=" << getVehicleClassNames(lane->getPermissions()) << "\n";
404 }
405 settings.first->rebuildAllowedLanes();
406 updateVehicles = true;
407 }
408 }
409 for (std::pair<MSLane*, SVCPermissions> settings : i.closedLanes) {
410 settings.first->resetPermissions(i.id);
411 settings.first->getEdge().rebuildAllowedLanes();
412 updateVehicles = true;
413 }
414 }
415 }
416 if (updateVehicles) {
417 // only vehicles on the affected lanes had their bestlanes updated so far
418 for (MSEdge* e : myEdges) {
419 // also updates vehicles
420 e->rebuildAllowedTargets();
421 }
422 }
423 return 0;
424}
425
426
429 for (const RerouteInterval& ri : myIntervals) {
430 if (ri.begin <= time && ri.end > time) {
431 if (
432 // destProbReroute
433 ri.edgeProbs.getOverallProb() > 0 ||
434 // routeProbReroute
435 ri.routeProbs.getOverallProb() > 0 ||
436 // parkingZoneReroute
437 ri.parkProbs.getOverallProb() > 0 ||
438 // stationReroute
439 ri.stopAlternatives.size() > 0) {
440 return &ri;
441 }
442 if (!ri.closed.empty() || !ri.closedLanesAffected.empty() || !ri.overtakeLocations.empty()) {
443 const std::set<SUMOTrafficObject::NumericalID>& edgeIndices = obj.getUpcomingEdgeIDs();
444 if (affected(edgeIndices, ri.getClosedEdges())
445 || affected(edgeIndices, ri.closedLanesAffected)) {
446 return &ri;
447 }
448 for (const OvertakeLocation& oloc : ri.overtakeLocations) {
449 if (affected(edgeIndices, oloc.main)) {
450 return &ri;
451 }
452 }
453
454 }
455 }
456 }
457 return nullptr;
458}
459
460
463 for (const RerouteInterval& ri : myIntervals) {
464 if (ri.begin <= time && ri.end > time) {
465 if (ri.edgeProbs.getOverallProb() != 0 || ri.routeProbs.getOverallProb() != 0 || ri.parkProbs.getOverallProb() != 0
466 || !ri.closed.empty() || !ri.closedLanesAffected.empty() || !ri.overtakeLocations.empty()) {
467 return &ri;
468 }
469 }
470 }
471 return nullptr;
472}
473
474
475bool
477 if (myAmOptional || myRadius != std::numeric_limits<double>::max()) {
478 return true;
479 }
480 return triggerRouting(tObject, reason);
481}
482
483
484bool
486 double /*newPos*/, double /*newSpeed*/) {
488}
489
490
491bool
493 MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
494 return reason == NOTIFICATION_LANE_CHANGE;
495}
496
497
498bool
500 if (!applies(tObject)) {
501 return false;
502 }
503 if (myRadius != std::numeric_limits<double>::max() && tObject.getPosition().distanceTo(myPosition) > myRadius) {
504 return true;
505 }
506 // check whether the vehicle shall be rerouted
508 const MSTriggeredRerouter::RerouteInterval* const rerouteDef = getCurrentReroute(now, tObject);
509 if (rerouteDef == nullptr) {
510 return true; // an active interval could appear later
511 }
512 const double prob = myAmInUserMode ? myUserProbability : myProbability;
513 if (prob < 1 && RandHelper::rand(tObject.getRNG()) > prob) {
514 return false; // XXX another interval could appear later but we would have to track whether the current interval was already tried
515 }
516 if (myTimeThreshold > 0 && MAX2(tObject.getWaitingTime(), tObject.getWaitingTime(true)) < myTimeThreshold) {
517 return true; // waiting time may be reached later
518 }
519 if (reason == NOTIFICATION_LANE_CHANGE) {
520 return false;
521 }
522 // if we have a closingLaneReroute, only vehicles with a rerouting device can profit from rerouting (otherwise, edge weights will not reflect local jamming)
523 const bool hasReroutingDevice = tObject.getDevice(typeid(MSDevice_Routing)) != nullptr;
524 if (rerouteDef->closedLanes.size() > 0 && !hasReroutingDevice) {
525 return true; // an active interval could appear later
526 }
527 const MSEdge* lastEdge = tObject.getRerouteDestination();
528#ifdef DEBUG_REROUTER
529 if (DEBUGCOND(tObject)) {
530 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";
531 }
532#endif
533
534 if (rerouteDef->parkProbs.getOverallProb() > 0) {
535#ifdef HAVE_FOX
536 ScopedLocker<> lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
537#endif
538 if (!tObject.isVehicle()) {
539 return false;
540 }
541 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
542 bool newDestination = false;
543 ConstMSEdgeVector newRoute;
544 MSParkingArea* oldParkingArea = veh.getNextParkingArea();
545 MSParkingArea* newParkingArea = rerouteParkingArea(rerouteDef, veh, newDestination, newRoute);
546 if (newParkingArea != nullptr) {
547 // adapt plans of any riders
548 for (MSTransportable* p : veh.getPersons()) {
549 p->rerouteParkingArea(oldParkingArea, newParkingArea);
550 }
551
552 if (newDestination && veh.getParameter().arrivalPosProcedure != ArrivalPosDefinition::DEFAULT) {
553 // update arrival parameters
554 SUMOVehicleParameter* newParameter = new SUMOVehicleParameter();
555 *newParameter = veh.getParameter();
557 newParameter->arrivalPos = newParkingArea->getEndLanePosition();
558 veh.replaceParameter(newParameter);
559 }
560
561 SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = hasReroutingDevice
562 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), rerouteDef->getClosed())
563 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), rerouteDef->getClosed());
564 const double routeCost = router.recomputeCosts(newRoute, &veh, MSNet::getInstance()->getCurrentTimeStep());
565 ConstMSEdgeVector prevEdges(veh.getCurrentRouteEdge(), veh.getRoute().end());
566 resetClosedEdges(hasReroutingDevice, veh);
567 const double previousCost = router.recomputeCosts(prevEdges, &veh, MSNet::getInstance()->getCurrentTimeStep());
568 const double savings = previousCost - routeCost;
569 //if (getID() == "ego") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
570 // << " prevEdges=" << toString(prevEdges)
571 // << " newEdges=" << toString(edges)
572 // << "\n";
573
574 std::string errorMsg;
575 if (veh.replaceParkingArea(newParkingArea, errorMsg)) {
576 veh.replaceRouteEdges(newRoute, routeCost, savings, getID() + ":" + toString(SUMO_TAG_PARKING_AREA_REROUTE), false, false, false);
577 if (oldParkingArea->isReservable()) {
578 oldParkingArea->removeSpaceReservation(&veh);
579 }
580 if (newParkingArea->isReservable()) {
581 newParkingArea->addSpaceReservation(&veh);
582 }
583 } else {
584 WRITE_WARNING("Vehicle '" + veh.getID() + "' at rerouter '" + getID()
585 + "' could not reroute to new parkingArea '" + newParkingArea->getID()
586 + "' reason=" + errorMsg + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
587 }
588 } else {
589 if (oldParkingArea && oldParkingArea->isReservable()) {
590 oldParkingArea->addSpaceReservation(&veh);
591 }
592 }
593 return false;
594 }
595 if (rerouteDef->overtakeLocations.size() > 0) {
596 if (!tObject.isVehicle()) {
597 return false;
598 }
599 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
600 const ConstMSEdgeVector& oldEdges = veh.getRoute().getEdges();
601 double bestSavings = -std::numeric_limits<double>::max();
602 double netSaving;
603 int bestIndex = -1;
604 MSRouteIterator bestMainStart = oldEdges.end();
605 std::pair<const SUMOVehicle*, MSRailSignal*> best_overtaker_signal(nullptr, nullptr);
606 int index = -1;
607 // sort locations by descending distance to vehicle
608 std::vector<std::pair<int, int> > sortedLocs;
609 for (const OvertakeLocation& oloc : rerouteDef->overtakeLocations) {
610 index++;
611 if (veh.getLength() > oloc.sidingLength) {
612 continue;
613 }
614 auto mainStart = std::find(veh.getCurrentRouteEdge(), oldEdges.end(), oloc.main.front());
615 if (mainStart == oldEdges.end()
616 // exit main within
617 || ConstMSEdgeVector(mainStart, mainStart + oloc.main.size()) != oloc.cMain
618 // stop in main
619 || (veh.hasStops() && veh.getNextStop().edge < (mainStart + oloc.main.size()))) {
620 //std::cout << SIMTIME << " veh=" << veh.getID() << " wrong route or stop\n";
621 continue;
622 }
623 // negated iterator distance for descending order
624 sortedLocs.push_back(std::make_pair(-(int)(mainStart - veh.getCurrentRouteEdge()), index));
625 }
626 std::sort(sortedLocs.begin(), sortedLocs.end());
627 for (const auto& item : sortedLocs) {
628 index = item.second;
629 const OvertakeLocation& oloc = rerouteDef->overtakeLocations[index];
630 auto mainStart = veh.getCurrentRouteEdge() - item.first; // subtracting negative difference
631 std::pair<const SUMOVehicle*, MSRailSignal*> overtaker_signal = overtakingTrain(veh, mainStart, oloc, netSaving);
632 if (overtaker_signal.first != nullptr && netSaving > bestSavings) {
633 bestSavings = netSaving;
634 bestIndex = index;
635 best_overtaker_signal = overtaker_signal;
636 bestMainStart = mainStart;
637#ifdef DEBUG_OVERTAKING
638 std::cout << " newBest index=" << bestIndex << " saving=" << bestSavings << "\n";
639#endif
640 }
641 }
642 if (bestIndex >= 0) {
643 const OvertakeLocation& oloc = rerouteDef->overtakeLocations[bestIndex];
644 if (oloc.defer) {
645 return false;
646 }
647 SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = hasReroutingDevice
648 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), rerouteDef->getClosed())
649 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), rerouteDef->getClosed());
650 ConstMSEdgeVector newEdges(veh.getCurrentRouteEdge(), bestMainStart);
651 newEdges.insert(newEdges.end(), oloc.siding.begin(), oloc.siding.end());
652 newEdges.insert(newEdges.end(), bestMainStart + oloc.main.size(), oldEdges.end());
653 const double routeCost = router.recomputeCosts(newEdges, &veh, MSNet::getInstance()->getCurrentTimeStep());
654 const double savings = (router.recomputeCosts(oloc.cMain, &veh, MSNet::getInstance()->getCurrentTimeStep())
656 const std::string info = getID() + ":" + toString(SUMO_TAG_OVERTAKING_REROUTE) + ":" + best_overtaker_signal.first->getID();
657 veh.replaceRouteEdges(newEdges, routeCost, savings, info, false, false, false);
659 MSRailSignalConstraint::PREDECESSOR, best_overtaker_signal.second, best_overtaker_signal.first->getID(), 100, true));
660 resetClosedEdges(hasReroutingDevice, veh);
661 }
662 return false;
663 }
664 if (rerouteDef->stopAlternatives.size() > 0) {
665 // somewhat similar to parkProbs but taking into account public transport schedule
666 if (!tObject.isVehicle()) {
667 return false;
668 }
669 checkStopSwitch(static_cast<MSBaseVehicle&>(tObject), rerouteDef);
670 }
671 // get rerouting params
672 ConstMSRoutePtr newRoute = rerouteDef->routeProbs.getOverallProb() > 0 ? rerouteDef->routeProbs.get() : nullptr;
673 // we will use the route if given rather than calling our own dijsktra...
674 if (newRoute != nullptr) {
675#ifdef DEBUG_REROUTER
676 if (DEBUGCOND(tObject)) {
677 std::cout << " replacedRoute from routeDist " << newRoute->getID() << "\n";
678 }
679#endif
680 tObject.replaceRoute(newRoute, getID());
681 return false; // XXX another interval could appear later but we would have to track whether the currenty interval was already used
682 }
683 const MSEdge* newEdge = lastEdge;
684 // ok, try using a new destination
685 double newArrivalPos = -1;
686 const MSEdgeVector closedEdges = rerouteDef->getClosedEdges();
687 const bool destUnreachable = std::find(closedEdges.begin(), closedEdges.end(), lastEdge) != closedEdges.end();
688 bool keepDestination = false;
689 // if we have a closingReroute, only assign new destinations to vehicles which cannot reach their original destination
690 // if we have a closingLaneReroute, no new destinations should be assigned
691 if (closedEdges.empty() || destUnreachable || rerouteDef->isVia) {
692 newEdge = rerouteDef->edgeProbs.getOverallProb() > 0 ? rerouteDef->edgeProbs.get() : lastEdge;
693 assert(newEdge != nullptr);
694 if (newEdge == &mySpecialDest_terminateRoute) {
695 keepDestination = true;
696 newEdge = tObject.getEdge();
697 newArrivalPos = tObject.getPositionOnLane(); // instant arrival
698 } else if (newEdge == &mySpecialDest_keepDestination || newEdge == lastEdge) {
699 if (destUnreachable && rerouteDef->permissionsAllowAll) {
700 // if permissions aren't set vehicles will simply drive through
701 // the closing unless terminated. If the permissions are specified, assume that the user wants
702 // vehicles to stand and wait until the closing ends
703 WRITE_WARNINGF(TL("Cannot keep destination edge '%' for vehicle '%' due to closed edges. Terminating route."), lastEdge->getID(), tObject.getID());
704 newEdge = tObject.getEdge();
705 } else {
706 newEdge = lastEdge;
707 }
708 }
709 }
710 ConstMSEdgeVector edges;
711 std::vector<MSTransportableRouter::TripItem> items;
712 // we have a new destination, let's replace the route (if it is affected)
713 MSEdgeVector closed = rerouteDef->getClosedEdges();
714 Prohibitions prohibited = rerouteDef->getClosed();
715 if (rerouteDef->closed.empty() || destUnreachable || rerouteDef->isVia || affected(tObject.getUpcomingEdgeIDs(), closed)) {
716 if (tObject.isVehicle()) {
717 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
718 ConstMSEdgeVector prevEdges = veh.getRoute().getEdges();
719 const bool canChangeDest = rerouteDef->edgeProbs.getOverallProb() > 0;
720 MSVehicleRouter& router = hasReroutingDevice
721 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), prohibited)
722 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), prohibited);
723 bool ok = false;
724 try {
725 ok = veh.reroute(now, getID(), router, false, false, canChangeDest, newEdge);
726 } catch (ProcessError&) {}
727 if (!ok && !keepDestination && canChangeDest) {
728 // destination unreachable due to closed intermediate edges. pick among alternative targets
729 RandomDistributor<MSEdge*> edgeProbs2 = rerouteDef->edgeProbs;
730 edgeProbs2.remove(const_cast<MSEdge*>(newEdge));
731 while (!ok && edgeProbs2.getVals().size() > 0) {
732 newEdge = edgeProbs2.get();
733 edgeProbs2.remove(const_cast<MSEdge*>(newEdge));
734 if (newEdge == &mySpecialDest_terminateRoute) {
735 newEdge = veh.getEdge();
736 newArrivalPos = veh.getPositionOnLane(); // instant arrival
737 while (veh.hasStops()) {
738 veh.abortNextStop();
739 }
740 }
741 if (newEdge == &mySpecialDest_keepDestination && !rerouteDef->permissionsAllowAll) {
742 newEdge = lastEdge;
743 break;
744 }
745 try {
746 ok = veh.reroute(now, getID(), router, false, false, true, newEdge);
747 } catch (ProcessError&) {}
748 }
749 }
750 resetClosedEdges(hasReroutingDevice, tObject);
751 if (ok) {
752 // since the old route was closed, savings would be infinite. This isn't useful
753 const double previousCost = router.recomputeCosts(prevEdges, &veh, MSNet::getInstance()->getCurrentTimeStep());
754 const double savings = previousCost - veh.getRoute().getCosts();
755 const_cast<MSRoute&>(veh.getRoute()).setSavings(savings);
756 }
757 if (!rerouteDef->isVia) {
758#ifdef DEBUG_REROUTER
759 if (DEBUGCOND(tObject)) std::cout << " rerouting: newDest=" << newEdge->getID()
760 << " newEdges=" << toString(edges)
761 << " newArrivalPos=" << newArrivalPos << " numClosed=" << rerouteDef->closed.size()
762 << " destUnreachable=" << destUnreachable << " containsClosed=" << veh.getRoute().containsAnyOf(rerouteDef->getClosedEdges()) << "\n";
763#endif
764 if (ok && newArrivalPos != -1) {
765 // must be called here because replaceRouteEdges may also set the arrivalPos
766 veh.setArrivalPos(newArrivalPos);
767 }
768
769 }
770 } else {
771 // person rerouting here
772 MSTransportableRouter& router = hasReroutingDevice
774 : MSNet::getInstance()->getIntermodalRouter(tObject.getRNGIndex(), 0, prohibited);
775 const bool success = router.compute(tObject.getEdge(), newEdge, tObject.getPositionOnLane(), "",
776 rerouteDef->isVia ? newEdge->getLength() / 2. : tObject.getParameter().arrivalPos, "",
777 tObject.getMaxSpeed(), nullptr, tObject.getVTypeParameter(), 0, now, items);
778 if (!rerouteDef->isVia) {
779 if (success) {
780 for (const MSTransportableRouter::TripItem& it : items) {
781 if (!it.edges.empty() && !edges.empty() && edges.back() == it.edges.front()) {
782 edges.pop_back();
783 }
784 edges.insert(edges.end(), std::make_move_iterator(it.edges.begin()), std::make_move_iterator(it.edges.end()));
785 if (!edges.empty()) {
786 static_cast<MSPerson&>(tObject).replaceWalk(edges, tObject.getPositionOnLane(), 0, 1);
787 }
788 }
789 } else {
790 // maybe the pedestrian model still finds a way (JuPedSim)
791 static_cast<MSPerson&>(tObject).replaceWalk({tObject.getEdge(), newEdge}, tObject.getPositionOnLane(), 0, 1);
792 }
793 }
794 }
795 if (!prohibited.empty()) {
796 resetClosedEdges(hasReroutingDevice, tObject);
797 }
798 }
799 // it was only a via so calculate the remaining part
800 if (rerouteDef->isVia) {
801 if (tObject.isVehicle()) {
802 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
803 if (!edges.empty()) {
804 edges.pop_back();
805 }
806 MSVehicleRouter& router = hasReroutingDevice
807 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), prohibited)
808 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), prohibited);
809 router.compute(newEdge, lastEdge, &veh, now, edges);
810 const double routeCost = router.recomputeCosts(edges, &veh, now);
811 hasReroutingDevice
813 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex()); // reset closed edges
814 const bool useNewRoute = veh.replaceRouteEdges(edges, routeCost, 0, getID());
815#ifdef DEBUG_REROUTER
816 if (DEBUGCOND(tObject)) std::cout << " rerouting: newDest=" << newEdge->getID()
817 << " newEdges=" << toString(edges)
818 << " useNewRoute=" << useNewRoute << " newArrivalPos=" << newArrivalPos << " numClosed=" << rerouteDef->closed.size()
819 << " destUnreachable=" << destUnreachable << " containsClosed=" << veh.getRoute().containsAnyOf(rerouteDef->getClosedEdges()) << "\n";
820#endif
821 if (useNewRoute && newArrivalPos != -1) {
822 // must be called here because replaceRouteEdges may also set the arrivalPos
823 veh.setArrivalPos(newArrivalPos);
824 }
825 } else {
826 // person rerouting here
827 bool success = !items.empty();
828 if (success) {
829 MSTransportableRouter& router = hasReroutingDevice
831 : MSNet::getInstance()->getIntermodalRouter(tObject.getRNGIndex(), 0, prohibited);
832 success = router.compute(newEdge, lastEdge, newEdge->getLength() / 2., "",
833 tObject.getParameter().arrivalPos, "",
834 tObject.getMaxSpeed(), nullptr, tObject.getVTypeParameter(), 0, now, items);
835 }
836 if (success) {
837 for (const MSTransportableRouter::TripItem& it : items) {
838 if (!it.edges.empty() && !edges.empty() && edges.back() == it.edges.front()) {
839 edges.pop_back();
840 }
841 edges.insert(edges.end(), std::make_move_iterator(it.edges.begin()), std::make_move_iterator(it.edges.end()));
842 }
843 if (!edges.empty()) {
844 static_cast<MSPerson&>(tObject).replaceWalk(edges, tObject.getPositionOnLane(), 0, 1);
845 }
846 } else {
847 // maybe the pedestrian model still finds a way (JuPedSim)
848 static_cast<MSPerson&>(tObject).replaceWalk({tObject.getEdge(), newEdge, lastEdge}, tObject.getPositionOnLane(), 0, 1);
849 }
850 }
851 if (!prohibited.empty()) {
852 resetClosedEdges(hasReroutingDevice, tObject);
853 }
854 }
855 return false; // XXX another interval could appear later but we would have to track whether the currenty interval was already used
856}
857
858
859void
863
864
865void
869
870
871bool
875
876
877double
881
882
883double
887
888
889double
891 return (sp->getElement() == SUMO_TAG_PARKING_AREA
892 ? (double)dynamic_cast<MSParkingArea*>(sp)->getOccupancyIncludingRemoteReservations(veh)
893 : (double)sp->getStoppedVehicles().size());
894}
895
896
897double
903
904
905double
907 if (myBlockedStoppingPlaces.count(sp) == 0) {
908 return (double)(sp->getElement() == SUMO_TAG_PARKING_AREA
909 ? dynamic_cast<MSParkingArea*>(sp)->getCapacity()
910 // assume only one vehicle at a time (for stationReroute)
911 : 1.);
912 } else {
913 return 0.;
914 }
915}
916
917
918void
920 veh.rememberBlockedParkingArea(parkingArea, blocked);
921}
922
923
924void
926 veh.rememberParkingAreaScore(parkingArea, score);
927}
928
929
930void
934
935
938 return veh.sawBlockedParkingArea(parkingArea, local);
939}
940
941
942int
946
947
948void
952
953
956 SUMOVehicle& veh, bool& newDestination, ConstMSEdgeVector& newRoute) {
957 MSStoppingPlace* destStoppingPlace = veh.getNextParkingArea();
958 if (destStoppingPlace == nullptr) {
959 // not driving towards the right type of stop
960 return nullptr;
961 }
962 std::vector<StoppingPlaceVisible> parks;
963 for (auto cand : rerouteDef->parkProbs.getVals()) {
964 if (cand.first->accepts(&veh)) {
965 parks.push_back(cand);
966 }
967 }
968 StoppingPlaceParamMap_t addInput = {};
969 return dynamic_cast<MSParkingArea*>(rerouteStoppingPlace(destStoppingPlace, parks, rerouteDef->parkProbs.getProbs(), veh, newDestination, newRoute, addInput, rerouteDef->getClosed()));
970}
971
972
973std::pair<const SUMOVehicle*, MSRailSignal*>
975 ConstMSEdgeVector::const_iterator mainStart,
976 const OvertakeLocation& oloc,
977 double& netSaving) {
978 const ConstMSEdgeVector& route = veh.getRoute().getEdges();
979 const MSEdgeVector& main = oloc.main;
980 const double vMax = veh.getMaxSpeed();
981 const double prio = veh.getFloatParam(toString(SUMO_TAG_OVERTAKING_REROUTE) + ".prio", false, DEFAULT_PRIO_OVERTAKEN, false);
983 for (MSVehicleControl::constVehIt it_veh = c.loadedVehBegin(); it_veh != c.loadedVehEnd(); ++it_veh) {
984 const MSBaseVehicle* veh2 = dynamic_cast<const MSBaseVehicle*>((*it_veh).second);
985 if (veh2->isOnRoad() && veh2->getMaxSpeed() > vMax) {
986 const double arrivalDelay = veh2->getStopArrivalDelay();
987 const double delay = MAX2(veh2->getStopDelay(), arrivalDelay == INVALID_DOUBLE ? 0 : arrivalDelay);
988 if (delay > veh2->getFloatParam(toString(SUMO_TAG_OVERTAKING_REROUTE) + ".maxDelay", false, DEFAULT_MAXDELAY, false)) {
989 continue;
990 }
991 const ConstMSEdgeVector& route2 = veh2->getRoute().getEdges();
992 auto itOnMain2 = route2.end();
993 int mainIndex = 0;
994 for (const MSEdge* m : main) {
995 itOnMain2 = std::find(veh2->getCurrentRouteEdge(), route2.end(), m);
996 if (itOnMain2 != route2.end()) {
997 break;
998 }
999 mainIndex++;
1000 }
1001 if (itOnMain2 != route2.end() && itOnMain2 > veh2->getCurrentRouteEdge()) {
1002 auto itOnMain = mainStart + mainIndex;
1003 double timeToMain = 0;
1004 for (auto it = veh.getCurrentRouteEdge(); it != itOnMain; it++) {
1005 timeToMain += (*it)->getMinimumTravelTime(&veh);
1006 }
1007 // veh2 may be anywhere on the current edge so we have to discount
1008 double timeToMain2 = -veh2->getEdge()->getMinimumTravelTime(veh2) * veh2->getPositionOnLane() / veh2->getEdge()->getLength();
1009 double timeToLastSignal2 = timeToMain2;
1010 for (auto it = veh2->getCurrentRouteEdge(); it != itOnMain2; it++) {
1011 timeToMain2 += (*it)->getMinimumTravelTime(veh2);
1012 auto signal = getRailSignal(*it);
1013 if (signal) {
1014 timeToLastSignal2 = timeToMain2;
1015#ifdef DEBUG_OVERTAKING
1016 std::cout << " lastBeforeMain2 " << signal->getID() << "\n";
1017#endif
1018 }
1019 }
1020 double exitMainTime = timeToMain;
1021 double exitMainBlockTime2 = timeToMain2;
1022 double commonTime = 0;
1023 double commonTime2 = 0;
1024 int nCommon = 0;
1025 auto exitMain2 = itOnMain2;
1026 const MSRailSignal* firstAfterMain = nullptr;
1027 const MSEdge* common = nullptr;
1028 double vMinCommon = (*itOnMain)->getVehicleMaxSpeed(&veh);
1029 double vMinCommon2 = (*itOnMain2)->getVehicleMaxSpeed(veh2);
1030 while (itOnMain2 != route2.end()
1031 && itOnMain != route.end()
1032 && *itOnMain == *itOnMain2) {
1033 common = *itOnMain;
1034 commonTime += common->getMinimumTravelTime(&veh);
1035 commonTime2 += common->getMinimumTravelTime(veh2);
1036 vMinCommon = MIN2(vMinCommon, common->getVehicleMaxSpeed(&veh));
1037 vMinCommon2 = MIN2(vMinCommon2, common->getVehicleMaxSpeed(veh2));
1038 const bool onMain = nCommon < (int)main.size() - mainIndex;
1039 if (onMain) {
1040 exitMainTime = timeToMain + commonTime;
1041 }
1042 if (firstAfterMain == nullptr) {
1043 exitMainBlockTime2 = timeToMain2 + commonTime2;
1044 }
1045 auto signal = getRailSignal(common);
1046 if (signal) {
1047 if (!onMain && firstAfterMain == nullptr) {
1048 firstAfterMain = signal;
1049#ifdef DEBUG_OVERTAKING
1050 std::cout << " firstAfterMain " << signal->getID() << "\n";
1051#endif
1052 }
1053 }
1054 nCommon++;
1055 itOnMain++;
1056 itOnMain2++;
1057 }
1058 const double vMaxLast = common->getVehicleMaxSpeed(&veh);
1059 const double vMaxLast2 = common->getVehicleMaxSpeed(veh2);
1060 commonTime += veh.getLength() / vMaxLast;
1061 exitMainBlockTime2 += veh2->getLength() / vMaxLast2;
1062 exitMain2 += MIN2(nCommon, (int)main.size() - mainIndex);
1063 double timeLoss2 = MAX2(0.0, timeToMain + veh.getLength() / oloc.siding.front()->getVehicleMaxSpeed(&veh) - timeToLastSignal2);
1064 const double saving = timeToMain + commonTime - (timeToMain2 + commonTime2) - timeLoss2;
1065 const double loss = exitMainBlockTime2 - exitMainTime;
1066 const double prio2 = veh2->getFloatParam(toString(SUMO_TAG_OVERTAKING_REROUTE) + ".prio", false, DEFAULT_PRIO_OVERTAKER, false);
1067 // losses from acceleration after stopping at a signal
1068 const double accelTimeLoss = loss > 0 ? 0.5 * vMinCommon / veh.getVehicleType().getCarFollowModel().getMaxAccel() : 0;
1069 const double accelTimeLoss2 = timeLoss2 > 0 ? 0.5 * vMinCommon2 / veh2->getVehicleType().getCarFollowModel().getMaxAccel() : 0;
1070 netSaving = prio2 * (saving - accelTimeLoss2) - prio * (loss + accelTimeLoss);
1071#ifdef DEBUG_OVERTAKING
1072 std::cout << SIMTIME << " veh=" << veh.getID() << " veh2=" << veh2->getID()
1073 << " sidingStart=" << oloc.siding.front()->getID()
1074 << " ttm=" << timeToMain << " ttm2=" << timeToMain2
1075 << " nCommon=" << nCommon << " cT=" << commonTime << " cT2=" << commonTime2
1076 << " em=" << exitMainTime << " emb2=" << exitMainBlockTime2
1077 << " ttls2=" << timeToLastSignal2
1078 << " saving=" << saving << " loss=" << loss
1079 << " atl=" << accelTimeLoss << " atl2=" << accelTimeLoss2 << " tl2=" << timeLoss2
1080 << " prio=" << prio << " prio2=" << prio2 << " netSaving=" << netSaving << "\n";
1081#endif
1082 if (netSaving > oloc.minSaving) {
1083 MSRailSignal* s = findSignal(veh2->getCurrentRouteEdge(), exitMain2);
1084 if (s != nullptr) {
1085 return std::make_pair(veh2, s);
1086 }
1087 }
1088 }
1089 }
1090 }
1091 return std::make_pair(nullptr, nullptr);
1092}
1093
1094
1095void
1098#ifdef DEBUG_REROUTER
1099 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << "\n";
1100#endif
1101 if (!ego.hasStops()) {
1102 return;
1103 }
1104 const MSStop& stop = ego.getNextStop();
1105 if (stop.reached || stop.joinTriggered || (stop.pars.arrival < 0 && stop.pars.until < 0)) {
1106 return;
1107 }
1108 MSStoppingPlace* cur = nullptr;
1109 for (MSStoppingPlace* sp : stop.getPlaces()) {
1110 for (auto item : def->stopAlternatives) {
1111 if (sp == item.first) {
1112 cur = sp;
1113 break;
1114 }
1115 }
1116 }
1117 if (cur == nullptr) {
1118 return;
1119 }
1120 std::vector<const SUMOVehicle*> stopped = cur->getStoppedVehicles();
1121#ifdef DEBUG_REROUTER
1122 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << " stopped=" << toString(stopped) << "\n";
1123#endif
1124 SUMOTime stoppedDuration = -1;
1125 if (stopped.empty()) {
1127 const MSLane& stopLane = cur->getLane();
1129 for (MSVehicleControl::constVehIt it_veh = c.loadedVehBegin(); it_veh != c.loadedVehEnd(); ++it_veh) {
1130 const MSBaseVehicle* veh = dynamic_cast<const MSBaseVehicle*>((*it_veh).second);
1131 if (veh->isOnRoad() && veh->hasStops()) {
1132 const MSStop& vehStop = veh->getNextStop();
1133 if (vehStop.pars.lane == stopLane.getID()) {
1134 myBlockedStoppingPlaces.insert(cur);
1135 if (veh->isStopped()) {
1136 // stopped somewhere else on the same lane
1137 stoppedDuration = MAX3((SUMOTime)0, stoppedDuration, veh->getStopDuration());
1138 } else {
1139 std::pair<double, double> timeDist = veh->estimateTimeToNextStop();
1140 SUMOTime timeTo = TIME2STEPS(timeDist.first);
1141 stoppedDuration = MAX3((SUMOTime)0, stoppedDuration, timeTo + vehStop.getMinDuration(SIMSTEP + timeTo));
1142 }
1143 }
1144 }
1145 }
1146 } else {
1147 stoppedDuration = 0;
1148 for (const SUMOVehicle* veh : cur->getStoppedVehicles()) {
1149 stoppedDuration = MAX2(stoppedDuration, veh->getStopDuration());
1150 }
1151 }
1152 if (stoppedDuration < 0) {
1153 return;
1154 }
1156 const SUMOTime stopFree = SIMSTEP + stoppedDuration;
1157 const SUMOTime scheduledArrival = stop.pars.arrival >= 0 ? stop.pars.arrival : stop.pars.until - stop.pars.duration;
1158#ifdef DEBUG_REROUTER
1159 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << " stopFree=" << stopFree << " scheduledArrival=" << time2string(scheduledArrival) << "\n";
1160#endif
1161 if (stopFree < scheduledArrival) {
1162 // no conflict according to the schedule
1163 return;
1164 }
1165 const SUMOTime estimatedArrival = SIMSTEP + (stop.pars.arrival >= 0
1167 : TIME2STEPS(ego.getStopDelay()) - stop.pars.duration);
1168#ifdef DEBUG_REROUTER
1169 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << " stopFree=" << stopFree << " estimatedArrival=" << time2string(estimatedArrival) << "\n";
1170#endif
1171 if (stopFree < estimatedArrival) {
1172 // no conflict when considering current delay
1173 return;
1174 }
1175 const std::vector<double> probs(def->stopAlternatives.size(), 1.);
1176 StoppingPlaceParamMap_t scores = {};
1177 bool newDestination;
1178 ConstMSEdgeVector newRoute;
1179 // @todo: consider future conflicts caused by rerouting
1180 // @todo: reject alternatives with large detour
1181 const MSStoppingPlace* alternative = rerouteStoppingPlace(nullptr, def->stopAlternatives, probs, ego, newDestination, newRoute, scores);
1182#ifdef DEBUG_REROUTER
1183 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << " alternative=" << Named::getIDSecure(alternative) << "\n";
1184#endif
1185 if (alternative != nullptr) {
1186 // @todo adapt plans of any riders
1187 //for (MSTransportable* p : ego.getPersons()) {
1188 // p->rerouteParkingArea(ego.getNextParkingArea(), newParkingArea);
1189 //}
1190
1191 if (newDestination && ego.getParameter().arrivalPosProcedure != ArrivalPosDefinition::DEFAULT) {
1192 // update arrival parameters
1193 SUMOVehicleParameter* newParameter = new SUMOVehicleParameter();
1194 *newParameter = ego.getParameter();
1196 newParameter->arrivalPos = alternative->getEndLanePosition();
1197 ego.replaceParameter(newParameter);
1198 }
1199
1200 SUMOVehicleParameter::Stop newStop = stop.pars;
1201 newStop.lane = alternative->getLane().getID();
1202 newStop.startPos = alternative->getBeginLanePosition();
1203 newStop.endPos = alternative->getEndLanePosition();
1204 switch (alternative->getElement()) {
1206 newStop.parkingarea = alternative->getID();
1207 break;
1209 newStop.containerstop = alternative->getID();
1210 break;
1212 newStop.chargingStation = alternative->getID();
1213 break;
1215 newStop.overheadWireSegment = alternative->getID();
1216 break;
1217 case SUMO_TAG_BUS_STOP:
1219 default:
1220 newStop.busstop = alternative->getID();
1221 }
1222 std::string errorMsg;
1223 if (!ego.replaceStop(0, newStop, getID() + ":" + toString(SUMO_TAG_STATION_REROUTE), false, errorMsg)) {
1224 WRITE_WARNING("Vehicle '" + ego.getID() + "' at rerouter '" + getID()
1225 + "' could not perform stationReroute to '" + alternative->getID()
1226 + "' reason=" + errorMsg + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1227 }
1228 }
1229}
1230
1231
1233MSTriggeredRerouter::findSignal(ConstMSEdgeVector::const_iterator begin, ConstMSEdgeVector::const_iterator end) {
1234 auto it = end;
1235 do {
1236 it--;
1237 auto signal = getRailSignal(*it);
1238 if (signal != nullptr) {
1239 return signal;
1240 }
1241 } while (it != begin);
1242 return nullptr;
1243}
1244
1245
1249 for (const MSLink* link : edge->getLanes().front()->getLinkCont()) {
1250 if (link->getTLLogic() != nullptr) {
1251 return dynamic_cast<MSRailSignal*>(const_cast<MSTrafficLightLogic*>(link->getTLLogic()));
1252 }
1253 }
1254 }
1255 return nullptr;
1256}
1257
1258bool
1260 if (myVehicleTypes.empty() || myVehicleTypes.count(obj.getVehicleType().getOriginalID()) > 0) {
1261 return true;
1262 } else {
1264 for (auto vTypeDist : vTypeDists) {
1265 if (myVehicleTypes.count(vTypeDist) > 0) {
1266 return true;
1267 }
1268 }
1269 return false;
1270 }
1271}
1272
1273
1274bool
1275MSTriggeredRerouter::affected(const std::set<SUMOTrafficObject::NumericalID>& edgeIndices, const MSEdgeVector& closed) {
1276 for (const MSEdge* const e : closed) {
1277 if (edgeIndices.count(e->getNumericalID()) > 0) {
1278 return true;
1279 }
1280 }
1281 return false;
1282}
1283
1284
1285void
1287 // if a parkingArea is a rerouting target, it should generally have a
1288 // rerouter on its edge or vehicles will be stuck there once it's full.
1289 // The user should receive a Warning in this case
1290 std::set<MSEdge*> parkingRerouterEdges;
1291 std::map<MSParkingArea*, std::string, ComparatorIdLess> targetedParkingArea; // paID -> targetingRerouter
1292 for (const auto& rr : myInstances) {
1293 bool hasParkingReroute = false;
1294 for (const RerouteInterval& interval : rr.second->myIntervals) {
1295 if (interval.parkProbs.getOverallProb() > 0) {
1296 hasParkingReroute = true;
1297 for (const StoppingPlaceVisible& pav : interval.parkProbs.getVals()) {
1298 targetedParkingArea[dynamic_cast<MSParkingArea*>(pav.first)] = rr.first;
1299 }
1300 }
1301 }
1302 if (hasParkingReroute) {
1303 parkingRerouterEdges.insert(rr.second->myEdges.begin(), rr.second->myEdges.end());
1304 }
1305 }
1306 for (const auto& item : targetedParkingArea) {
1307 if (parkingRerouterEdges.count(&item.first->getLane().getEdge()) == 0) {
1308 WRITE_WARNINGF(TL("ParkingArea '%' is targeted by rerouter '%' but doesn't have its own rerouter. This may cause parking search to abort."),
1309 item.first->getID(), item.second);
1310 }
1311 }
1312}
1313
1314
1315void
1317 // getRouterTT without prohibitions removes previous prohibitions
1318 if (o.isVehicle()) {
1319 hasReroutingDevice
1322 } else {
1323 hasReroutingDevice
1326 }
1327}
1328
1329/****************************************************************************/
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 SVC_UNSPECIFIED
permissions not specified
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:344
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:1089
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the maximum speed the vehicle may use on this edge.
Definition MSEdge.cpp:1219
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:2528
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:1692
MSVehicleRouter & getRouterTT(int rngIndex, const Prohibitions &prohibited={}) const
Definition MSNet.cpp:1645
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:1513
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:53
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:66
const std::string & getID() const
Returns the id.
Definition Named.h:73
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