Eclipse SUMO - Simulation of Urban MObility
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
MSStoppingPlaceRerouter.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-2025 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/****************************************************************************/
18// The StoppingPlaceRerouter provides an interface to structure the rerouting
19// to the best StoppingPlace according to the evaluation components and
20// associated weights.
21/****************************************************************************/
23#include <microsim/MSEdge.h>
24#include <microsim/MSGlobals.h>
25#include <microsim/MSLane.h>
26#include <microsim/MSRoute.h>
32
33//#define DEBUG_STOPPINGPLACE
34#define DEBUGCOND (veh.isSelected())
35//#define DEBUGCOND (true)
36
37
39MSStoppingPlaceRerouter::MSStoppingPlaceRerouter(std::string paramPrefix, bool checkValidity, StoppingPlaceParamMap_t addEvalParams, StoppingPlaceParamSwitchMap_t addInvertParams) :
40 myParamPrefix(paramPrefix), myCheckValidity(checkValidity) {
41 myEvalParams = { {"probability", 0.}, {"capacity", 0.}, {"timefrom", 0.}, {"timeto", 0.}, {"distancefrom", 0.}, {"distanceto", 1.}, {"absfreespace", 0.}, {"relfreespace", 0.}, };
42 myInvertParams = { {"probability", false}, { "capacity", true }, { "timefrom", false }, { "timeto", false }, { "distancefrom", false }, { "distanceto", false }, { "absfreespace", true }, { "relfreespace", true } };
43 for (auto param : addEvalParams) {
44 myEvalParams[param.first] = param.second;
45 myInvertParams[param.first] = (addInvertParams.count(param.first) > 0) ? addInvertParams[param.first] : false;
46 }
47 for (auto param : myEvalParams) {
48 myNormParams.insert({param.first, param.first != "probability"});
49 }
50}
51
53MSStoppingPlaceRerouter::rerouteStoppingPlace(MSStoppingPlace* destStoppingPlace, const std::vector<StoppingPlaceVisible>& stoppingPlaceCandidates, const std::vector<double>& probs, SUMOVehicle& veh, bool& newDestination, ConstMSEdgeVector& newRoute, StoppingPlaceParamMap_t& scores,
54 const MSEdgeVector& closedEdges, const int insertStopIndex, const bool keepCurrentStop) {
55 // Reroute destination from initial stopping place to an alternative stopping place
56 // if the following conditions are met:
57 // - next stop target is a stopping place of the right type
58 // - target is included in the current alternative set
59 // - target is visibly full
60 // Any stopping places that are visibly full at the current location are
61 // committed to the stopping place memory corresponding to their type
62
63 MSStoppingPlace* nearStoppingPlace = nullptr;
64
65 // get vehicle params
66 bool destVisible = false;
67 if (destStoppingPlace != nullptr) {
68 destVisible = (&destStoppingPlace->getLane().getEdge() == veh.getEdge());
69 // if the vehicle is on the destination stop edge it is always visible
70 for (auto stoppingPlace : stoppingPlaceCandidates) {
71 if (stoppingPlace.first == destStoppingPlace && stoppingPlace.second) {
72 destVisible = true;
73 break;
74 }
75 }
76 }
77 const MSRoute& route = veh.getRoute();
78
79 MSStoppingPlace* onTheWay = nullptr;
80 const int stopAnywhere = (int)getWeight(veh, "anywhere", -1);
81 const bool ignoreDest = getWeight(veh, "ignoreDest", destStoppingPlace != nullptr ? 0 : 1) != 0;
82 // check whether we are ready to accept any free stopping place along the
83 // way to our destination
84 if (stopAnywhere < 0 || stopAnywhere > getNumberStoppingPlaceReroutes(veh)) {
85 if (!destVisible) {
86 // cannot determine destination occupancy, only register visibly full
87 for (const StoppingPlaceVisible& stoppingPlace : stoppingPlaceCandidates) {
88 if (stoppingPlace.second && getLastStepStoppingPlaceOccupancy(stoppingPlace.first) >= getStoppingPlaceCapacity(stoppingPlace.first)) {
89 rememberStoppingPlaceScore(veh, stoppingPlace.first, "occupied");
90 rememberBlockedStoppingPlace(veh, stoppingPlace.first, &stoppingPlace.first->getLane().getEdge() == veh.getEdge());
91 }
92 }
93#ifdef DEBUG_STOPPINGPLACE
94 if (DEBUGCOND) {
95 //std::cout << SIMTIME << " veh=" << veh.getID() << " dest=" << ((destStoppingPlace == nullptr)? "null" : destStoppingPlace->getID()) << " stopAnywhere=" << stopAnywhere << " reroutes=" << getNumberStoppingPlaceReroutes(veh) << " stay on original route\n";
96 }
97#endif
98 }
99 } else {
100 double bestDist = std::numeric_limits<double>::max();
101 const double brakeGap = veh.getBrakeGap(true);
102 for (const StoppingPlaceVisible& item : stoppingPlaceCandidates) {
103 if (item.second) {
104 if (&item.first->getLane().getEdge() == veh.getEdge()
105 && getLastStepStoppingPlaceOccupancy(item.first) < getStoppingPlaceCapacity(item.first)) {
106 const double distToStart = item.first->getBeginLanePosition() - veh.getPositionOnLane();
107 const double distToEnd = item.first->getEndLanePosition() - veh.getPositionOnLane();
108 if (distToEnd > brakeGap) {
109 rememberStoppingPlaceScore(veh, item.first, "dist=" + toString(distToStart));
110 if (distToStart < bestDist) {
111 bestDist = distToStart;
112 onTheWay = item.first;
113 }
114 } else {
115 rememberStoppingPlaceScore(veh, item.first, "tooClose");
116 }
117 }
118 }
119 }
120#ifdef DEBUG_STOPPINGPLACE
121 if (DEBUGCOND) {
122 std::cout << SIMTIME << " veh=" << veh.getID()
123 << " dest=" << ((destStoppingPlace == nullptr) ? "null" : destStoppingPlace->getID()) << " stopAnywhere=" << stopAnywhere << " reroutes=" << getNumberStoppingPlaceReroutes(veh) << " alongTheWay=" << Named::getIDSecure(onTheWay) << "\n";
124 }
125#endif
126 }
127 if (!ignoreDest && !destVisible && onTheWay == nullptr) {
128 return nullptr;
129 }
130
131 if (ignoreDest || getLastStepStoppingPlaceOccupancy(destStoppingPlace) >= getStoppingPlaceCapacity(destStoppingPlace) || onTheWay != nullptr) {
132 // if the current route ends at the stopping place, the new route will
133 // also end at the new stopping place
134 newDestination = (destStoppingPlace != nullptr && &destStoppingPlace->getLane().getEdge() == route.getLastEdge()
135 && veh.getArrivalPos() >= destStoppingPlace->getBeginLanePosition()
136 && veh.getArrivalPos() <= destStoppingPlace->getEndLanePosition()
137 && veh.getStops().size() == 1);
138
139#ifdef DEBUG_STOPPINGPLACE
140 if (DEBUGCOND) {
141 std::cout << SIMTIME << " veh=" << veh.getID()
142 << " newDest=" << newDestination
143 << " onTheWay=" << Named::getIDSecure(onTheWay)
144 << "\n";
145 }
146#endif
147 std::map<MSStoppingPlace*, ConstMSEdgeVector> newRoutes;
148 std::map<MSStoppingPlace*, ConstMSEdgeVector> stopApproaches;
149 StoppingPlaceParamMap_t weights = collectWeights(veh); // add option to patch values for interdependent values
150 StoppingPlaceParamMap_t maxValues;
151 for (auto param : weights) {
152 maxValues[param.first] = 0.;
153 }
154
155 // a map stores elegible stopping places
156 StoppingPlaceMap_t stoppingPlaces;
157 SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = getRouter(veh, closedEdges);
158 const double brakeGap = veh.getBrakeGap(true);
159
160 if (onTheWay != nullptr) {
161 // compute new route
162 if (newDestination) {
163 newRoute.push_back(veh.getEdge());
164 } else {
165 bool valid = evaluateDestination(veh, brakeGap, newDestination, onTheWay, getLastStepStoppingPlaceOccupancy(onTheWay), 1, router, stoppingPlaces, newRoutes, stopApproaches, maxValues, scores, insertStopIndex, keepCurrentStop);
166 if (!valid) {
167 WRITE_WARNINGF(TL("Stopping place '%' along the way cannot be used by vehicle '%' for unknown reason"), onTheWay->getID(), veh.getID());
168 return nullptr;
169 }
170 newRoute = newRoutes[onTheWay];
171 }
172 return onTheWay;
173 }
174 int numAlternatives = 0;
175 std::vector<std::tuple<SUMOTime, MSStoppingPlace*, int>> blockedTimes;
177
178 if (destStoppingPlace != nullptr) {
179 rememberStoppingPlaceScore(veh, destStoppingPlace, "occupied");
180 rememberBlockedStoppingPlace(veh, destStoppingPlace, &destStoppingPlace->getLane().getEdge() == veh.getEdge());
181 }
182 const SUMOTime stoppingPlaceMemory = TIME2STEPS(getWeight(veh, "memory", 600));
183 const double stoppingPlaceFrustration = getWeight(veh, "frustration", 100);
184 const double stoppingPlaceKnowledge = getWeight(veh, "knowledge", 0);
185
186 for (int i = 0; i < (int)stoppingPlaceCandidates.size(); ++i) {
187 // alternative occupancy is randomized (but never full) if invisible
188 // current destination must be visible at this point
189 if (!useStoppingPlace(stoppingPlaceCandidates[i].first)) {
190 continue;
191 }
192 const bool visible = stoppingPlaceCandidates[i].second || (stoppingPlaceCandidates[i].first == destStoppingPlace && destVisible);
193 double occupancy = getStoppingPlaceOccupancy(stoppingPlaceCandidates[i].first);
194 if (!visible && (stoppingPlaceKnowledge == 0 || stoppingPlaceKnowledge < RandHelper::rand(veh.getRNG()))) {
195 double capacity = getStoppingPlaceCapacity(stoppingPlaceCandidates[i].first);
196 const double minOccupancy = MIN2(capacity - NUMERICAL_EPS, (getNumberStoppingPlaceReroutes(veh) * capacity / stoppingPlaceFrustration));
197 occupancy = RandHelper::rand(minOccupancy, capacity);
198 // previously visited?
199 SUMOTime blockedTime = sawBlockedStoppingPlace(veh, stoppingPlaceCandidates[i].first, false);
200 if (blockedTime >= 0 && SIMSTEP - blockedTime < stoppingPlaceMemory) {
201 // assume it's still occupied
202 occupancy = capacity;
203 blockedTimes.push_back(std::make_tuple(blockedTime, stoppingPlaceCandidates[i].first, i));
204#ifdef DEBUG_STOPPINGPLACE
205 if (DEBUGCOND) {
206 std::cout << " altStoppingPlace=" << stoppingPlaceCandidates[i].first->getID() << " was blocked at " << time2string(blockedTime) << "\n";
207 }
208#endif
209 }
210 }
211 if (occupancy < getStoppingPlaceCapacity(stoppingPlaceCandidates[i].first)) {
212 if (evaluateDestination(veh, brakeGap, newDestination, stoppingPlaceCandidates[i].first, occupancy, probs[i], router, stoppingPlaces, newRoutes, stopApproaches, maxValues, scores, insertStopIndex, keepCurrentStop)) {
213 numAlternatives++;
214 }
215 } else if (visible) {
216 // might only be visible now (i.e. because it's on the other
217 // side of the street), so we should remember this for later.
218 rememberStoppingPlaceScore(veh, stoppingPlaceCandidates[i].first, "occupied");
219 rememberBlockedStoppingPlace(veh, stoppingPlaceCandidates[i].first, &stoppingPlaceCandidates[i].first->getLane().getEdge() == veh.getEdge());
220 }
221 }
222
223 if (numAlternatives == 0) {
224 // use parkingArea with lowest blockedTime
225 std::sort(blockedTimes.begin(), blockedTimes.end(),
226 [](std::tuple<SUMOTime, MSStoppingPlace*, int> const & t1, std::tuple<SUMOTime, MSStoppingPlace*, int> const & t2) {
227 if (std::get<0>(t1) < std::get<0>(t2)) {
228 return true;
229 }
230 if (std::get<0>(t1) == std::get<0>(t2)) {
231 if (std::get<1>(t1)->getID() < std::get<1>(t2)->getID()) {
232 return true;
233 }
234 if (std::get<1>(t1)->getID() == std::get<1>(t2)->getID()) {
235 return std::get<2>(t1) < std::get<2>(t2);
236 }
237 }
238 return false;
239 }
240 );
241 for (auto item : blockedTimes) {
242 MSStoppingPlace* sp = std::get<1>(item);
243 double prob = probs[std::get<2>(item)];
244 // all stopping places are occupied. We have no good basis for
245 // prefering one or the other based on estimated occupancy
246 double occupancy = RandHelper::rand(getStoppingPlaceCapacity(sp));
247 if (evaluateDestination(veh, brakeGap, newDestination, sp, occupancy, prob, router, stoppingPlaces, newRoutes, stopApproaches, maxValues, scores, insertStopIndex, keepCurrentStop)) {
248#ifdef DEBUG_STOPPINGPLACE
249 if (DEBUGCOND) {
250 std::cout << " altStoppingPlace=" << sp->getID() << " targeting occupied stopping place based on blockTime " << STEPS2TIME(std::get<0>(item)) << " among " << blockedTimes.size() << " alternatives\n";
251 }
252#endif
253 numAlternatives = 1;
254 break;
255 }
256 //std::cout << " candidate=" << item.second->getID() << " observed=" << time2string(item.first) << "\n";
257 }
258 if (numAlternatives == 0) {
259 // take any random target but prefer one that hasn't been visited yet
260 std::vector<std::pair<SUMOTime, MSStoppingPlace*>> candidates;
261 for (const StoppingPlaceVisible& stoppingPlaceCandidate : stoppingPlaceCandidates) {
262 if (stoppingPlaceCandidate.first == destStoppingPlace) {
263 continue;
264 }
265 SUMOTime dummy = sawBlockedStoppingPlace(veh, stoppingPlaceCandidate.first, true);
266 if (dummy < 0) {
267 // randomize among the unvisited
268 dummy = -RandHelper::rand(1000000);
269 }
270 candidates.push_back(std::make_pair(dummy, stoppingPlaceCandidate.first));
271 }
272 std::sort(candidates.begin(), candidates.end(),
273 [](std::tuple<SUMOTime, MSStoppingPlace*> const & t1, std::tuple<SUMOTime, MSStoppingPlace*> const & t2) {
274 return std::get<0>(t1) < std::get<0>(t2) || (std::get<0>(t1) == std::get<0>(t2) && std::get<1>(t1)->getID() < std::get<1>(t2)->getID());
275 }
276 );
277 for (auto item : candidates) {
278 if (evaluateDestination(veh, brakeGap, newDestination, item.second, 0, 1, router, stoppingPlaces, newRoutes, stopApproaches, maxValues, scores, insertStopIndex, keepCurrentStop)) {
279#ifdef DEBUG_STOPPINGPLACE
280 if (DEBUGCOND) {
281 std::cout << " altStoppingPlace=" << item.second->getID() << " targeting occupied stopping place (based on pure randomness) among " << candidates.size() << " alternatives\n";
282 }
283#endif
284 numAlternatives = 1;
285 break;
286 }
287 }
288 }
289 }
290 getRouter(veh); // reset closed edges
291
292#ifdef DEBUG_STOPPINGPLACE
293 if (DEBUGCOND) {
294 std::cout << " maxValues=" << joinToString(maxValues, " ", ":") << "\n";
295 }
296#endif
297
298 // minimum cost to get the parking area
299 double minStoppingPlaceCost = 0.0;
300
301 for (StoppingPlaceMap_t::iterator it = stoppingPlaces.begin(); it != stoppingPlaces.end(); ++it) {
302 // get the parking values
303 StoppingPlaceParamMap_t stoppingPlaceValues = it->second;
304
305 if (weights["probability"] > 0. && maxValues["probability"] > 0.) {
306 // random search should not drive past a usable parking area
307 bool dominated = false;
308 double endPos = it->first->getEndLanePosition();
309 const ConstMSEdgeVector& to1 = stopApproaches[it->first];
310 assert(to1.size() > 0);
311 for (auto altSp : stoppingPlaces) {
312 if (altSp.first == it->first) {
313 continue;
314 }
315 const ConstMSEdgeVector& to2 = stopApproaches[altSp.first];
316 assert(to2.size() > 0);
317 if (to1.size() > to2.size()) {
318 if (std::equal(to2.begin(), to2.end(), to1.begin())) {
319 // other target lies on the route to the current candidate
320 dominated = true;
321 //std::cout << SIMTIME << " rrP veh=" << veh.getID() << " full=" << destParkArea->getID() << " cand=" << it->first->getID() << " onTheWay=" << altPa.first->getID() << "\n";
322 break;
323 }
324 } else if (to1 == to2 && endPos > altSp.first->getEndLanePosition()) {
325 // other target is on the same edge but ahead of the current candidate
326 dominated = true;
327 //std::cout << SIMTIME << " rrP veh=" << veh.getID() << " full=" << destParkArea->getID() << " cand=" << it->first->getID() << " sameEdge=" << altPa.first->getID() << "\n";
328 break;
329 }
330 }
331 double prob = 0;
332 if (!dominated) {
333 prob = RandHelper::rand(stoppingPlaceValues["probability"], veh.getRNG());
334 stoppingPlaceValues["probability"] = 1.0 - prob / maxValues["probability"];
335 } else {
336 // worst probability score
337 stoppingPlaceValues["probability"] = 1.0;
338 }
339 } else {
340 // value takes no effect due to weight=0
341 stoppingPlaceValues["probability"] = 0;
342 }
343
344 // get the parking area cost
345 double stoppingPlaceCost = getTargetValue(stoppingPlaceValues, maxValues, weights, myNormParams, myInvertParams);
346 rememberStoppingPlaceScore(veh, it->first, toString(stoppingPlaceCost));
347
348 // get the parking area with minimum cost
349 if (nearStoppingPlace == nullptr || stoppingPlaceCost < minStoppingPlaceCost) {
350 minStoppingPlaceCost = stoppingPlaceCost;
351 nearStoppingPlace = it->first;
352 newRoute = newRoutes[nearStoppingPlace];
353 }
354#ifdef DEBUG_STOPPINGPLACE
355 if (DEBUGCOND) {
356 std::cout << " altStoppingPlace=" << it->first->getID() << " score=" << stoppingPlaceCost << " vals=" << joinToString(stoppingPlaceValues, " ", ":") << "\n";
357 }
358#endif
359 }
360 // expose the scores of the best solution
361 if (nearStoppingPlace != nullptr) {
362 for (auto component : stoppingPlaces[nearStoppingPlace]) {
363 scores[component.first] = component.second;
364 }
365 }
367 } else {
368#ifdef DEBUG_STOPPINGPLACE
369 if (DEBUGCOND) {
370 std::cout << SIMTIME << " veh=" << veh.getID() << " dest=" << destStoppingPlace->getID() << " sufficient space\n";
371 }
372#endif
373 }
374
375#ifdef DEBUG_STOPPINGPLACE
376 if (DEBUGCOND) {
377 std::cout << " stoppingPlaceResult=" << Named::getIDSecure(nearStoppingPlace) << "\n";
378 }
379#endif
380 return nearStoppingPlace;
381}
382
383
384bool
385MSStoppingPlaceRerouter::evaluateDestination(SUMOVehicle& veh, double brakeGap, bool newDestination, MSStoppingPlace* alternative,
386 double occupancy, double prob, SUMOAbstractRouter<MSEdge, SUMOVehicle>& router, StoppingPlaceMap_t& stoppingPlaces,
387 std::map<MSStoppingPlace*, ConstMSEdgeVector>& newRoutes, std::map<MSStoppingPlace*, ConstMSEdgeVector>& stoppingPlaceApproaches,
388 StoppingPlaceParamMap_t& maxValues, StoppingPlaceParamMap_t& addInput, const int insertStopIndex, const bool keepCurrentStop) {
389
390 // a map stores the stopping place values
391 StoppingPlaceParamMap_t stoppingPlaceValues;
392 const SUMOTime now = SIMSTEP;
393
394 const MSRoute& route = veh.getRoute();
395 const RGBColor& c = route.getColor();
396 const MSEdge* stoppingPlaceEdge = &(alternative->getLane().getEdge());
397
398 const bool includeInternalLengths = MSGlobals::gUsingInternalLanes && MSNet::getInstance()->hasInternalLinks();
399
400 // Compute the route from the current edge to the stopping place edge
401 ConstMSEdgeVector edgesToStop;
402 ConstMSEdgeVector edgesUpstream;
403 const double targetPos = alternative->getLastFreePos(veh);
404 MSRouteIterator rerouteOriginIt = determineRerouteOrigin(veh, insertStopIndex);
405 double posOnLane = veh.getPositionOnLane();
406 if (insertStopIndex > 0) {
407 posOnLane = 0.;
408 // determine preceding edges
409 for (MSRouteIterator it = veh.getCurrentRouteEdge(); it != rerouteOriginIt; ++it) {
410 if (it != rerouteOriginIt) {
411 edgesUpstream.push_back(*it);
412 }
413 }
414 }
415 const MSEdge* rerouteOrigin = *rerouteOriginIt;
416 router.compute(rerouteOrigin, posOnLane, stoppingPlaceEdge, targetPos, &veh, now, edgesToStop, true);
417 if (edgesToStop.size() > 0) {
418 // Compute the route from the stopping place edge to the end of the route
419 if (insertStopIndex == 0 && rerouteOrigin != veh.getEdge()) {
420 edgesToStop.insert(edgesToStop.begin(), veh.getEdge());
421 }
422 // prepend preceding edges
423 std::reverse(edgesUpstream.begin(), edgesUpstream.end());
424 for (auto edge : edgesUpstream) {
425 edgesToStop.insert(edgesToStop.begin(), edge);
426 }
427 ConstMSEdgeVector edgesFromStop;
428 stoppingPlaceApproaches[alternative] = edgesToStop;
429
430 const MSEdge* nextDestination = route.getLastEdge();
431 double nextPos = veh.getArrivalPos();
432 int nextDestinationIndex = route.size() - 1;
433 if (!newDestination) {
434 std::vector<std::pair<int, double> > stopIndices = veh.getStopIndices();
435 int nextDestStopIndex = 1 + insertStopIndex;
436 if (!keepCurrentStop) {
437 nextDestStopIndex++;
438 }
439 if ((int)stopIndices.size() > nextDestStopIndex) {
440 nextDestinationIndex = stopIndices[nextDestStopIndex].first;
441 nextDestination = route.getEdges()[nextDestinationIndex];
442 nextPos = stopIndices[nextDestStopIndex].second;
443 }
444 router.compute(stoppingPlaceEdge, targetPos, nextDestination, nextPos, &veh, now, edgesFromStop, true);
445 }
446 if (edgesFromStop.size() > 0 || newDestination) {
447 stoppingPlaceValues["probability"] = prob;
448 if (stoppingPlaceValues["probability"] > maxValues["probability"]) {
449 maxValues["probability"] = stoppingPlaceValues["probability"];
450 }
451 stoppingPlaceValues["capacity"] = getStoppingPlaceCapacity(alternative);
452 stoppingPlaceValues["absfreespace"] = stoppingPlaceValues["capacity"] - occupancy;
453 // if capacity = 0 then absfreespace and relfreespace are also 0
454 stoppingPlaceValues["relfreespace"] = stoppingPlaceValues["absfreespace"] / MAX2(1.0, stoppingPlaceValues["capacity"]);
455 MSRoute routeToPark(route.getID() + "!to" + myParamPrefix + "#1", edgesToStop, false,
456 &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), route.getStops());
457
458 // The distance from the current edge to the new parking area
459 double toPos = alternative->getBeginLanePosition();
460 if (&alternative->getLane().getEdge() == veh.getEdge()) {
461 toPos = MAX2(veh.getPositionOnLane(), toPos);
462 }
463 stoppingPlaceValues["distanceto"] = routeToPark.getDistanceBetween(veh.getPositionOnLane(), toPos,
464 routeToPark.begin(), routeToPark.end() - 1, includeInternalLengths);
465
466 if (stoppingPlaceValues["distanceto"] == std::numeric_limits<double>::max()) {
467 WRITE_WARNINGF(TL("Invalid distance computation for vehicle '%' to stopping place '%' at time=%."),
468 veh.getID(), alternative->getID(), time2string(now));
469 }
470 const double endPos = getStoppingPlaceOccupancy(alternative) == getStoppingPlaceCapacity(alternative)
471 ? alternative->getLastFreePos(veh, veh.getPositionOnLane() + brakeGap)
472 : alternative->getEndLanePosition();
473 const double distToEnd = stoppingPlaceValues["distanceto"] - toPos + endPos;
474
475 if (distToEnd < brakeGap) {
476 rememberStoppingPlaceScore(veh, alternative, "tooClose");
477 return false;
478 }
479
480 // The time to reach the new stopping place
481 const double correctionLastEdge = ((alternative->getLane().getLength() - alternative->getEndLanePosition()) / alternative->getLane().getVehicleMaxSpeed(&veh));
482 const double correctionFirstEdge = veh.getPositionOnLane() / edgesToStop.front()->getVehicleMaxSpeed(&veh);
483
484 stoppingPlaceValues["timeto"] = router.recomputeCosts(edgesToStop, &veh, SIMSTEP) - correctionLastEdge - correctionFirstEdge;
485 ConstMSEdgeVector newEdges = edgesToStop;
486 if (newDestination) {
487 stoppingPlaceValues["distancefrom"] = 0;
488 stoppingPlaceValues["timefrom"] = 0;
489 } else {
490 MSRoute routeFromPark(route.getID() + "!from" + myParamPrefix + "#1", edgesFromStop, false,
491 &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), route.getStops());
492 // The distance from the new parking area to the end of the route
493 stoppingPlaceValues["distancefrom"] = routeFromPark.getDistanceBetween(alternative->getBeginLanePosition(), routeFromPark.getLastEdge()->getLength(),
494 routeFromPark.begin(), routeFromPark.end() - 1, includeInternalLengths);
495 if (stoppingPlaceValues["distancefrom"] == std::numeric_limits<double>::max()) {
496 WRITE_WARNINGF(TL("Invalid distance computation for vehicle '%' from stopping place '%' at time=%."),
497 veh.getID(), alternative->getID(), time2string(SIMSTEP));
498 }
499 // The time to reach this area
500 stoppingPlaceValues["timefrom"] = router.recomputeCosts(edgesFromStop, &veh, SIMSTEP) - (alternative->getEndLanePosition() / alternative->getLane().getSpeedLimit());
501 newEdges.insert(newEdges.end(), edgesFromStop.begin() + 1, edgesFromStop.end());
502 newEdges.insert(newEdges.end(), route.begin() + nextDestinationIndex + 1, route.end());
503 }
504
505 // add some additional/custom target function components
506 if (!evaluateCustomComponents(veh, brakeGap, newDestination, alternative, occupancy, prob, router, stoppingPlaceValues, stoppingPlaceApproaches[alternative], newEdges, maxValues, addInput)) {
507 return false;
508 }
509 if (!myCheckValidity || validComponentValues(stoppingPlaceValues)) {
510 updateMaxValues(stoppingPlaceValues, maxValues);
511 stoppingPlaces[alternative] = stoppingPlaceValues;
512 newRoutes[alternative] = newEdges;
513 return true;
514 } else {
515 return false;
516 }
517 } else {
518 rememberStoppingPlaceScore(veh, alternative, "unreachable");
519 }
520 } else {
521 rememberStoppingPlaceScore(veh, alternative, "unreachable");
522 }
523 // unreachable
524 return false;
525}
526
527
528bool
529MSStoppingPlaceRerouter::evaluateCustomComponents(SUMOVehicle& /*veh*/, double /*brakeGap*/, bool /*newDestination*/,
530 MSStoppingPlace* /*alternative*/, double /*occupancy*/, double /*prob*/, SUMOAbstractRouter<MSEdge, SUMOVehicle>& /*router*/,
531 StoppingPlaceParamMap_t& /*stoppingPlaceValues*/, ConstMSEdgeVector& /*newRoute*/, ConstMSEdgeVector& /*stoppingPlaceApproach*/,
532 StoppingPlaceParamMap_t& /*maxValues*/, StoppingPlaceParamMap_t& /*addInput*/) {
533 return true;
534}
535
536
537bool
539 return true;
540}
541
542
543bool
545 return true;
546}
547
548
551 return MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), prohibited);
552}
553
554
558 myEvalParams["distanceto"] = getWeight(veh, "distance.weight", myEvalParams["distanceto"]);
559 for (auto evalParam : myEvalParams) {
560 result[evalParam.first] = getWeight(veh, evalParam.first + ".weight", evalParam.second);
561 }
562 result["probability"] = getWeight(veh, "probability.weight", 0.);
563 return result;
564}
565
566
567double
568MSStoppingPlaceRerouter::getWeight(SUMOVehicle& veh, const std::string param, const double defaultWeight, const bool warn) {
569 // get custom vehicle parameter
570 const std::string key = myParamPrefix + "." + param;
571 if (veh.getParameter().hasParameter(key)) {
572 try {
573 return StringUtils::toDouble(veh.getParameter().getParameter(key, "-1"));
574 } catch (...) {
575 WRITE_WARNINGF(TL("Invalid value '%' for vehicle parameter '%'"), veh.getParameter().getParameter(key, "-1"), key);
576 }
577 } else {
578 // get custom vType parameter
579 if (veh.getVehicleType().getParameter().hasParameter(key)) {
580 try {
582 } catch (...) {
583 WRITE_WARNINGF(TL("Invalid value '%' for vType parameter '%'"), veh.getVehicleType().getParameter().getParameter(key, "-1"), key);
584 }
585 }
586 }
587 if (warn) {
588 WRITE_MESSAGEF("Vehicle '%' does not supply vehicle parameter '%'. Using default of %\n", veh.getID(), key, toString(defaultWeight));
589 }
590 return defaultWeight;
591}
592
593
594void
596 for (auto it = maxValues.begin(); it != maxValues.end(); ++it) {
597 if (stoppingPlaceValues[it->first] > it->second) {
598 it->second = stoppingPlaceValues[it->first];
599 }
600 }
601}
602
603
604double
606 double cost = 0.;
607 for (StoppingPlaceParamMap_t::const_iterator sc = absValues.begin(); sc != absValues.end(); ++sc) {
608 double weight = weights.at(sc->first);
609 double val = sc->second;
610 if (norm.at(sc->first) && maxValues.at(sc->first) > 0.) {
611 val /= maxValues.at(sc->first);
612 }
613 cost += (invert.at(sc->first)) ? weight * (1. - val) : weight * val;
614 }
615 return cost;
616}
617
618
619/****************************************************************************/
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 DEBUGCOND
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:288
#define WRITE_MESSAGEF(...)
Definition MsgHandler.h:290
#define TL(string)
Definition MsgHandler.h:305
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:55
#define SIMSTEP
Definition SUMOTime.h:61
#define SIMTIME
Definition SUMOTime.h:62
#define TIME2STEPS(x)
Definition SUMOTime.h:57
T MIN2(T a, T b)
Definition StdDefs.h:76
T MAX2(T a, T b)
Definition StdDefs.h:82
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition ToString.h:283
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
A road/street connecting two junctions.
Definition MSEdge.h:77
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition MSGlobals.h:81
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition MSLane.h:592
double getLength() const
Returns the lane's length.
Definition MSLane.h:606
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Definition MSLane.h:574
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:764
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:186
MSVehicleRouter & getRouterTT(int rngIndex, const MSEdgeVector &prohibited=MSEdgeVector()) const
Definition MSNet.cpp:1531
bool hasInternalLinks() const
return whether the network contains internal links
Definition MSNet.h:785
int size() const
Returns the number of edges to pass.
Definition MSRoute.cpp:85
const ConstMSEdgeVector & getEdges() const
Definition MSRoute.h:125
const std::vector< SUMOVehicleParameter::Stop > & getStops() const
Returns the stops.
Definition MSRoute.cpp:404
MSRouteIterator end() const
Returns the end of the list of edges to pass.
Definition MSRoute.cpp:79
const MSEdge * getLastEdge() const
returns the destination edge
Definition MSRoute.cpp:91
const RGBColor & getColor() const
Returns the color.
Definition MSRoute.cpp:395
MSRouteIterator begin() const
Returns the begin of the list of edges to pass.
Definition MSRoute.cpp:73
double getDistanceBetween(double fromPos, double toPos, const MSLane *fromLane, const MSLane *toLane, int routePosition=0) const
Compute the distance between 2 given edges on this route, optionally including the length of internal...
Definition MSRoute.cpp:311
A lane area vehicles can halt at.
double getBeginLanePosition() const
Returns the begin position of this stop.
double getEndLanePosition() const
Returns the end position of this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
virtual double getLastFreePos(const SUMOVehicle &forVehicle, double brakePos=0) const
Returns the last free position on this stop.
virtual bool useStoppingPlace(MSStoppingPlace *stoppingPlace)
Whether the stopping place should be included in the search (can be used to add an additional filter)
virtual void rememberBlockedStoppingPlace(SUMOVehicle &veh, const MSStoppingPlace *stoppingPlace, bool blocked)=0
store the blocked stopping place in the vehicle
virtual SUMOTime sawBlockedStoppingPlace(SUMOVehicle &veh, MSStoppingPlace *place, bool local)=0
ask the vehicle when it has seen the stopping place
StoppingPlaceParamSwitchMap_t myNormParams
std::map< std::string, bool > StoppingPlaceParamSwitchMap_t
std::map< std::string, double > StoppingPlaceParamMap_t
static void updateMaxValues(StoppingPlaceParamMap_t &stoppingPlaceValues, StoppingPlaceParamMap_t &maxValues)
keep track of the maximum values of each component
virtual SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouter(SUMOVehicle &veh, const MSEdgeVector &prohibited={})
Provide the router to use (MSNet::getRouterTT or MSRoutingEngine)
std::map< MSStoppingPlace *, StoppingPlaceParamMap_t, ComparatorIdLess > StoppingPlaceMap_t
virtual int getNumberStoppingPlaceReroutes(SUMOVehicle &veh)=0
ask how many times already the vehicle has been rerouted to another stopping place
virtual double getStoppingPlaceCapacity(MSStoppingPlace *stoppingPlace)=0
Return the number of places the StoppingPlace provides.
static double getTargetValue(const StoppingPlaceParamMap_t &absValues, const StoppingPlaceParamMap_t &maxValues, const StoppingPlaceParamMap_t &weights, const StoppingPlaceParamSwitchMap_t &norm, const StoppingPlaceParamSwitchMap_t &invert)
compute the scalar target function value by means of a linear combination of all components/weights a...
const MSRouteIterator determineRerouteOrigin(SUMOVehicle &veh, int insertStopIndex)
Determine the rerouting origin edge (not necessarily the current edge of the vehicle!...
virtual double getStoppingPlaceOccupancy(MSStoppingPlace *stoppingPlace)=0
Return the number of occupied places of the StoppingPlace.
double getWeight(SUMOVehicle &veh, const std::string param, const double defaultWeight, const bool warn=false)
read the value of a stopping place search param, e.g. a component weight factor
virtual StoppingPlaceParamMap_t collectWeights(SUMOVehicle &veh)
read target function weights for this vehicle
StoppingPlaceParamMap_t myEvalParams
MSStoppingPlace * rerouteStoppingPlace(MSStoppingPlace *destStoppingPlace, const std::vector< StoppingPlaceVisible > &stoppingPlaceCandidates, const std::vector< double > &probs, SUMOVehicle &veh, bool &newDestination, ConstMSEdgeVector &newRoute, StoppingPlaceParamMap_t &scores, const MSEdgeVector &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...
StoppingPlaceParamSwitchMap_t myInvertParams
virtual void rememberStoppingPlaceScore(SUMOVehicle &veh, MSStoppingPlace *place, const std::string &score)=0
store the stopping place score in the vehicle
virtual void resetStoppingPlaceScores(SUMOVehicle &veh)=0
forget all stopping place score for this vehicle
virtual void setNumberStoppingPlaceReroutes(SUMOVehicle &veh, int value)=0
update the number of reroutes for the vehicle
virtual bool validComponentValues(StoppingPlaceParamMap_t &stoppingPlaceValues)
Whether the stopping place should be discarded due to its results from the component evaluation (allo...
virtual bool evaluateCustomComponents(SUMOVehicle &veh, double brakeGap, bool newDestination, MSStoppingPlace *alternative, double occupancy, double prob, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, StoppingPlaceParamMap_t &stoppingPlaceValues, ConstMSEdgeVector &newRoute, ConstMSEdgeVector &stoppingPlaceApproach, StoppingPlaceParamMap_t &maxValues, StoppingPlaceParamMap_t &addInput)
Compute some custom target function components.
std::pair< MSStoppingPlace *, bool > StoppingPlaceVisible
virtual double getLastStepStoppingPlaceOccupancy(MSStoppingPlace *stoppingPlace)=0
Return the number of occupied places of the StoppingPlace from the previous time step.
virtual bool evaluateDestination(SUMOVehicle &veh, double brakeGap, bool newDestination, MSStoppingPlace *alternative, double occupancy, double prob, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, StoppingPlaceMap_t &stoppingPlaces, std::map< MSStoppingPlace *, ConstMSEdgeVector > &newRoutes, std::map< MSStoppingPlace *, ConstMSEdgeVector > &stoppingPlaceApproaches, StoppingPlaceParamMap_t &maxValues, StoppingPlaceParamMap_t &addInput, const int insertStopIndex=0, const bool keepCurrentStop=true)
compute the target function for a single alternative
MSStoppingPlaceRerouter()=delete
Constructor.
const SUMOVTypeParameter & getParameter() const
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
bool hasParameter(const std::string &key) const
Returns whether the parameter is set.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
static const RGBColor DEFAULT_COLOR
The default color (for vehicle types and vehicles)
Definition RGBColor.h:202
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
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
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 int getRNGIndex() const =0
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
virtual SumoRNG * getRNG() const =0
Returns the associated RNG for this object.
virtual const MSEdge * getEdge() const =0
Returns the edge the object is currently at.
virtual double getPositionOnLane() const =0
Get the object's position along the lane.
Representation of a vehicle.
Definition SUMOVehicle.h:62
virtual const std::list< MSStop > & getStops() const =0
virtual double getArrivalPos() const =0
Returns this vehicle's desired arrivalPos for its current route (may change on reroute)
virtual double getBrakeGap(bool delayed=false) const =0
get distance for coming to a stop (used for rerouting checks)
virtual std::vector< std::pair< int, double > > getStopIndices() const =0
return list of route indices and stop positions for the remaining stops
virtual const ConstMSEdgeVector::const_iterator & getCurrentRouteEdge() const =0
Returns an iterator pointing to the current edge in this vehicles route.
virtual const MSRoute & getRoute() const =0
Returns the current route.
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter