Eclipse SUMO - Simulation of Urban MObility
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-2024 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
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>
27 #include <microsim/MSParkingArea.h>
29 #include <microsim/MSVehicleType.h>
32 
33 #define DEBUGCOND (veh.isSelected())
34 
35 
37 MSStoppingPlaceRerouter::MSStoppingPlaceRerouter(SumoXMLTag stoppingType, std::string paramPrefix, bool checkValidity, bool checkVisibility, StoppingPlaceParamMap_t addEvalParams, StoppingPlaceParamSwitchMap_t addInvertParams) :
38  myStoppingType(stoppingType), myParamPrefix(paramPrefix), myCheckValidity(checkValidity), myConsiderDestVisibility(checkVisibility) {
39  myEvalParams = { {"probability", 0.}, {"capacity", 0.}, {"timefrom", 0.}, {"timeto", 0.}, {"distancefrom", 0.}, {"distanceto", 1.}, {"absfreespace", 0.}, {"relfreespace", 0.}, };
40  myInvertParams = { {"probability", false}, { "capacity", true }, { "timefrom", false }, { "timeto", false }, { "distancefrom", false }, { "distanceto", false }, { "absfreespace", true }, { "relfreespace", true } };
41  for (auto param : addEvalParams) {
42  myEvalParams[param.first] = param.second;
43  myInvertParams[param.first] = (addInvertParams.count(param.first) > 0) ? addInvertParams[param.first] : false;
44  }
45  for (auto param : myEvalParams) {
46  myNormParams.insert({param.first, param.first != "probability"});
47  }
48 }
49 
51 MSStoppingPlaceRerouter::reroute(std::vector<StoppingPlaceVisible>& stoppingPlaceCandidates, const std::vector<double>& probs, SUMOVehicle& veh, bool& newDestination, ConstMSEdgeVector& newRoute, StoppingPlaceParamMap_t& scores, const MSEdgeVector& closedEdges) {
52  // Reroute destination from initial stopping place to an alternative stopping place
53  // if the following conditions are met:
54  // - next stop target is a stopping place of the right type
55  // - target is included in the current alternative set
56  // - target is visibly full
57  // Any stopping places that are visibly full at the current location are
58  // committed to the stopping place memory corresponding to their type
59 
60  MSStoppingPlace* nearStoppingPlace = nullptr;
61 
62  // get vehicle params
63  MSStoppingPlace* destStoppingPlace = nullptr;
64  bool destVisible = false;
66  destStoppingPlace = veh.getNextParkingArea();
67  if (destStoppingPlace == nullptr) {
68  // not driving towards the right type of stop
69  return nullptr;
70  }
71  destVisible = (&destStoppingPlace->getLane().getEdge() == veh.getEdge());
72  // if the vehicle is on the destination stop edge it is always visible
73  for (auto stoppingPlace : stoppingPlaceCandidates) {
74  if (stoppingPlace.first == destStoppingPlace && stoppingPlace.second) {
75  destVisible = true;
76  break;
77  }
78  }
79  }
80  const MSRoute& route = veh.getRoute();
81 
82  MSStoppingPlace* onTheWay = nullptr;
83  const int stopAnywhere = (int)getWeight(veh, "anywhere", -1);
84  // check whether we are ready to accept any free stopping place along the
85  // way to our destination
86  if (stopAnywhere < 0 || stopAnywhere > getNumberStoppingPlaceReroutes(veh)) {
87  if (!destVisible) {
88  // cannot determine destination occupancy, only register visibly full
89  for (const StoppingPlaceVisible& stoppingPlace : stoppingPlaceCandidates) {
90  if (stoppingPlace.second && getLastStepStoppingPlaceOccupancy(stoppingPlace.first) >= getStoppingPlaceCapacity(stoppingPlace.first)) {
91  rememberStoppingPlaceScore(veh, stoppingPlace.first, "occupied");
92  rememberBlockedStoppingPlace(veh, stoppingPlace.first, &stoppingPlace.first->getLane().getEdge() == veh.getEdge());
93  }
94  }
95 #ifdef DEBUG_STOPPINGPLACE
96  if (DEBUGCOND) {
97  //std::cout << SIMTIME << " << " veh=" << veh.getID()
98  // << " dest=" << ((destStoppingPlace == nullptr)? "null" : destStoppingPlace->getID()) << " stopAnywhere=" << stopAnywhere << "reroutes=" << getNumberStoppingPlaceReroutes(veh) << " stay on original route\n";
99  }
100 #endif
101  }
102  } else {
103  double bestDist = std::numeric_limits<double>::max();
104  const double brakeGap = veh.getBrakeGap(true);
105  for (StoppingPlaceVisible& item : stoppingPlaceCandidates) {
106  if (item.second) {
107  if (&item.first->getLane().getEdge() == veh.getEdge()
108  && getLastStepStoppingPlaceOccupancy(item.first) < getStoppingPlaceCapacity(item.first)) {
109  const double distToStart = item.first->getBeginLanePosition() - veh.getPositionOnLane();
110  const double distToEnd = item.first->getEndLanePosition() - veh.getPositionOnLane();
111  if (distToEnd > brakeGap) {
112  rememberStoppingPlaceScore(veh, item.first, "dist=" + toString(distToStart));
113  if (distToStart < bestDist) {
114  bestDist = distToStart;
115  onTheWay = item.first;
116  }
117  } else {
118  rememberStoppingPlaceScore(veh, item.first, "tooClose");
119  }
120  }
121  }
122  }
123 #ifdef DEBUG_STOPPINGPLACE
124  if (DEBUGCOND) {
125  std::cout << SIMTIME << " veh=" << veh.getID()
126  << " dest=" << ((destStoppingPlace == nullptr) ? "null" : destStoppingPlace->getID()) << " stopAnywhere=" << stopAnywhere << " reroutes=" << getNumberStoppingPlaceReroutes(veh) << " alongTheWay=" << Named::getIDSecure(onTheWay) << "\n";
127  }
128 #endif
129  }
130  if (myConsiderDestVisibility && !destVisible && onTheWay == nullptr) {
131  return nullptr;
132  }
133 
134  if (!myConsiderDestVisibility || getLastStepStoppingPlaceOccupancy(destStoppingPlace) >= getStoppingPlaceCapacity(destStoppingPlace) || onTheWay != nullptr) {
135  // if the current route ends at the stopping place, the new route will
136  // also end at the new stopping place
137  newDestination = (destStoppingPlace != nullptr && &destStoppingPlace->getLane().getEdge() == route.getLastEdge()
138  && veh.getArrivalPos() >= destStoppingPlace->getBeginLanePosition()
139  && veh.getArrivalPos() <= destStoppingPlace->getEndLanePosition()
140  && veh.getStops().size() == 1);
141 
142 #ifdef DEBUG_STOPPINGPLACE
143  if (DEBUGCOND) {
144  std::cout << SIMTIME << " veh=" << veh.getID()
145  << " newDest=" << newDestination
146  << " onTheWay=" << Named::getIDSecure(onTheWay)
147  << "\n";
148  }
149 #endif
150  std::map<MSStoppingPlace*, ConstMSEdgeVector> newRoutes;
151  std::map<MSStoppingPlace*, ConstMSEdgeVector> stopApproaches;
152  StoppingPlaceParamMap_t weights = collectWeights(veh); // add option to patch values for interdependent values
153  StoppingPlaceParamMap_t maxValues;
154  for (auto param : weights) {
155  maxValues[param.first] = 0.;
156  }
157 
158  // a map stores elegible stopping places
159  StoppingPlaceMap_t stoppingPlaces;
160  SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = getRouter(veh, closedEdges);
161  const double brakeGap = veh.getBrakeGap(true);
162 
163  if (onTheWay != nullptr) {
164  // compute new route
165  if (newDestination) {
166  newRoute.push_back(veh.getEdge());
167  } else {
168  bool valid = evaluateDestination(veh, brakeGap, newDestination, onTheWay, getLastStepStoppingPlaceOccupancy(onTheWay), 1, router, stoppingPlaces, newRoutes, stopApproaches, maxValues, scores);
169  if (!valid) {
170  WRITE_WARNINGF(TL("Stopping place '%' along the way cannot be used by vehicle '%' for unknown reason"), onTheWay->getID(), veh.getID());
171  return nullptr;
172  }
173  newRoute = newRoutes[onTheWay];
174  }
175  return onTheWay;
176  }
177  int numAlternatives = 0;
178  std::vector<std::tuple<SUMOTime, MSStoppingPlace*, int>> blockedTimes;
180 
181  if (destStoppingPlace != nullptr) {
182  rememberStoppingPlaceScore(veh, destStoppingPlace, "occupied");
183  rememberBlockedStoppingPlace(veh, destStoppingPlace, &destStoppingPlace->getLane().getEdge() == veh.getEdge());
184  }
185  const SUMOTime stoppingPlaceMemory = TIME2STEPS(getWeight(veh, "memory", 600));
186  const double stoppingPlaceFrustration = getWeight(veh, "frustration", 100);
187  const double stoppingPlaceKnowledge = getWeight(veh, "knowledge", 0);
188 
189  for (int i = 0; i < (int)stoppingPlaceCandidates.size(); ++i) {
190  // alternative occupancy is randomized (but never full) if invisible
191  // current destination must be visible at this point
192  if (!useStoppingPlace(stoppingPlaceCandidates[i].first)) {
193  continue;
194  }
195  const bool visible = stoppingPlaceCandidates[i].second || (stoppingPlaceCandidates[i].first == destStoppingPlace && destVisible);
196  double occupancy = getStoppingPlaceOccupancy(stoppingPlaceCandidates[i].first);
197  if (!visible && (stoppingPlaceKnowledge == 0 || stoppingPlaceKnowledge < RandHelper::rand(veh.getRNG()))) {
198  double capacity = getStoppingPlaceCapacity(stoppingPlaceCandidates[i].first);
199  const double minOccupancy = MIN2(capacity - NUMERICAL_EPS, (getNumberStoppingPlaceReroutes(veh) * capacity / stoppingPlaceFrustration));
200  occupancy = RandHelper::rand(minOccupancy, capacity);
201  // previously visited?
202  SUMOTime blockedTime = sawBlockedStoppingPlace(veh, stoppingPlaceCandidates[i].first, false);
203  if (blockedTime >= 0 && SIMSTEP - blockedTime < stoppingPlaceMemory) {
204  // assume it's still occupied
205  occupancy = capacity;
206  blockedTimes.push_back(std::make_tuple(blockedTime, stoppingPlaceCandidates[i].first, i));
207 #ifdef DEBUG_STOPPINGPLACE
208  if (DEBUGCOND) {
209  std::cout << " altStoppingPlace=" << stoppingPlaceCandidates[i].first->getID() << " was blocked at " << time2string(blockedTime) << "\n";
210  }
211 #endif
212  }
213  }
214  if (occupancy < getStoppingPlaceCapacity(stoppingPlaceCandidates[i].first)) {
215  if (evaluateDestination(veh, brakeGap, newDestination, stoppingPlaceCandidates[i].first, occupancy, probs[i], router, stoppingPlaces, newRoutes, stopApproaches, maxValues, scores)) {
216  numAlternatives++;
217  }
218  } else if (visible) {
219  // might only be visible now (i.e. because it's on the other
220  // side of the street), so we should remember this for later.
221  rememberStoppingPlaceScore(veh, stoppingPlaceCandidates[i].first, "occupied");
222  rememberBlockedStoppingPlace(veh, stoppingPlaceCandidates[i].first, &stoppingPlaceCandidates[i].first->getLane().getEdge() == veh.getEdge());
223  }
224  }
225 
226  if (numAlternatives == 0) {
227  // use parkingArea with lowest blockedTime
228  std::sort(blockedTimes.begin(), blockedTimes.end(),
229  [](std::tuple<SUMOTime, MSStoppingPlace*, int> const & t1, std::tuple<SUMOTime, MSStoppingPlace*, int> const & t2) {
230  if (std::get<0>(t1) < std::get<0>(t2)) {
231  return true;
232  }
233  if (std::get<0>(t1) == std::get<0>(t2)) {
234  if (std::get<1>(t1)->getID() < std::get<1>(t2)->getID()) {
235  return true;
236  }
237  if (std::get<1>(t1)->getID() == std::get<1>(t2)->getID()) {
238  return std::get<2>(t1) < std::get<2>(t2);
239  }
240  }
241  return false;
242  }
243  );
244  for (auto item : blockedTimes) {
245  MSStoppingPlace* sp = std::get<1>(item);
246  double prob = probs[std::get<2>(item)];
247  // all stopping places are occupied. We have no good basis for
248  // prefering one or the other based on estimated occupancy
249  double occupancy = RandHelper::rand(getStoppingPlaceCapacity(sp));
250  if (evaluateDestination(veh, brakeGap, newDestination, sp, occupancy, prob, router, stoppingPlaces, newRoutes, stopApproaches, maxValues, scores)) {
251 #ifdef DEBUG_STOPPINGPLACE
252  if (DEBUGCOND) {
253  std::cout << " altStoppingPlace=" << sp->getID() << " targeting occupied stopping place based on blockTime " << STEPS2TIME(std::get<0>(item)) << " among " << blockedTimes.size() << " alternatives\n";
254  }
255 #endif
256  numAlternatives = 1;
257  break;
258  }
259  //std::cout << " candidate=" << item.second->getID() << " observed=" << time2string(item.first) << "\n";
260  }
261  if (numAlternatives == 0) {
262  // take any random target but prefer one that hasn't been visited yet
263  std::vector<std::pair<SUMOTime, MSStoppingPlace*>> candidates;
264  for (const StoppingPlaceVisible& stoppingPlaceCandidate : stoppingPlaceCandidates) {
265  if (stoppingPlaceCandidate.first == destStoppingPlace) {
266  continue;
267  }
268  SUMOTime dummy = sawBlockedStoppingPlace(veh, stoppingPlaceCandidate.first, true);
269  if (dummy < 0) {
270  // randomize among the unvisited
271  dummy = -RandHelper::rand(1000000);
272  }
273  candidates.push_back(std::make_pair(dummy, stoppingPlaceCandidate.first));
274  }
275  std::sort(candidates.begin(), candidates.end(),
276  [](std::tuple<SUMOTime, MSStoppingPlace*> const & t1, std::tuple<SUMOTime, MSStoppingPlace*> const & t2) {
277  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());
278  }
279  );
280  for (auto item : candidates) {
281  if (evaluateDestination(veh, brakeGap, newDestination, item.second, 0, 1, router, stoppingPlaces, newRoutes, stopApproaches, maxValues, scores)) {
282 #ifdef DEBUG_STOPPINGPLACE
283  if (DEBUGCOND) {
284  std::cout << " altStoppingPlace=" << item.second->getID() << " targeting occupied stopping place (based on pure randomness) among " << candidates.size() << " alternatives\n";
285  }
286 #endif
287  numAlternatives = 1;
288  break;
289  }
290  }
291  }
292  }
293  getRouter(veh); // reset closed edges
294 
295 #ifdef DEBUG_STOPPINGPLACE
296  if (DEBUGCOND) {
297  std::cout << " maxValues=" << joinToString(maxValues, " ", ":") << "\n";
298  }
299 #endif
300 
301  // minimum cost to get the parking area
302  double minStoppingPlaceCost = 0.0;
303 
304  for (StoppingPlaceMap_t::iterator it = stoppingPlaces.begin(); it != stoppingPlaces.end(); ++it) {
305  // get the parking values
306  StoppingPlaceParamMap_t stoppingPlaceValues = it->second;
307 
308  if (weights["probability"] > 0. && maxValues["probability"] > 0.) {
309  // random search should not drive past a usable parking area
310  bool dominated = false;
311  double endPos = it->first->getEndLanePosition();
312  const ConstMSEdgeVector& to1 = stopApproaches[it->first];
313  assert(to1.size() > 0);
314  for (auto altSp : stoppingPlaces) {
315  if (altSp.first == it->first) {
316  continue;
317  }
318  const ConstMSEdgeVector& to2 = stopApproaches[altSp.first];
319  assert(to2.size() > 0);
320  if (to1.size() > to2.size()) {
321  if (std::equal(to2.begin(), to2.end(), to1.begin())) {
322  // other target lies on the route to the current candidate
323  dominated = true;
324  //std::cout << SIMTIME << " rrP veh=" << veh.getID() << " full=" << destParkArea->getID() << " cand=" << it->first->getID() << " onTheWay=" << altPa.first->getID() << "\n";
325  break;
326  }
327  } else if (to1 == to2 && endPos > altSp.first->getEndLanePosition()) {
328  // other target is on the same edge but ahead of the current candidate
329  dominated = true;
330  //std::cout << SIMTIME << " rrP veh=" << veh.getID() << " full=" << destParkArea->getID() << " cand=" << it->first->getID() << " sameEdge=" << altPa.first->getID() << "\n";
331  break;
332  }
333  }
334  double prob = 0;
335  if (!dominated) {
336  prob = RandHelper::rand(stoppingPlaceValues["probability"], veh.getRNG());
337  stoppingPlaceValues["probability"] = 1.0 - prob / maxValues["probability"];
338  } else {
339  // worst probability score
340  stoppingPlaceValues["probability"] = 1.0;
341  }
342  } else {
343  // value takes no effect due to weight=0
344  stoppingPlaceValues["probability"] = 0;
345  }
346 
347  // get the parking area cost
348  double stoppingPlaceCost = getTargetValue(stoppingPlaceValues, maxValues, weights, myNormParams, myInvertParams);
349  rememberStoppingPlaceScore(veh, it->first, toString(stoppingPlaceCost));
350 
351  // get the parking area with minimum cost
352  if (nearStoppingPlace == nullptr || stoppingPlaceCost < minStoppingPlaceCost) {
353  minStoppingPlaceCost = stoppingPlaceCost;
354  nearStoppingPlace = it->first;
355  newRoute = newRoutes[nearStoppingPlace];
356  }
357 #ifdef DEBUG_STOPPINGPLACE
358  if (DEBUGCOND) {
359  std::cout << " altStoppingPlace=" << it->first->getID() << " score=" << stoppingPlaceCost << " vals=" << joinToString(stoppingPlaceValues, " ", ":") << "\n";
360  }
361 #endif
362  }
363  // expose the scores of the best solution
364  if (nearStoppingPlace != nullptr) {
365  for (auto component : stoppingPlaces[nearStoppingPlace]) {
366  scores[component.first] = component.second;
367  }
368  }
370  } else {
371 #ifdef DEBUG_STOPPINGPLACE
372  if (DEBUGCOND) {
373  std::cout << SIMTIME << " veh=" << veh.getID() << " dest=" << destStoppingPlace->getID() << " sufficient space\n";
374  }
375 #endif
376  }
377 
378 #ifdef DEBUG_STOPPINGPLACE
379  if (DEBUGCOND) {
380  std::cout << " stoppingPlaceResult=" << Named::getIDSecure(nearStoppingPlace) << "\n";
381  }
382 #endif
383  return nearStoppingPlace;
384 }
385 
386 
387 bool
388 MSStoppingPlaceRerouter::evaluateDestination(SUMOVehicle& veh, double brakeGap, bool newDestination, MSStoppingPlace* alternative,
389  double occupancy, double prob, SUMOAbstractRouter<MSEdge, SUMOVehicle>& router, StoppingPlaceMap_t& stoppingPlaces,
390  std::map<MSStoppingPlace*, ConstMSEdgeVector>& newRoutes, std::map<MSStoppingPlace*, ConstMSEdgeVector>& stoppingPlaceApproaches,
391  StoppingPlaceParamMap_t& maxValues, StoppingPlaceParamMap_t& addInput) {
392 
393  // a map stores the stopping place values
394  StoppingPlaceParamMap_t stoppingPlaceValues;
395  const SUMOTime now = SIMSTEP;
396 
397  const MSRoute& route = veh.getRoute();
398  const RGBColor& c = route.getColor();
399  const MSEdge* stoppingPlaceEdge = &(alternative->getLane().getEdge());
400 
401  const bool includeInternalLengths = MSGlobals::gUsingInternalLanes && MSNet::getInstance()->hasInternalLinks();
402 
403  // Compute the route from the current edge to the stopping place edge
404  ConstMSEdgeVector edgesToStop;
405  const double targetPos = alternative->getLastFreePos(veh);
406  const MSEdge* rerouteOrigin = *veh.getRerouteOrigin();
407  router.compute(rerouteOrigin, veh.getPositionOnLane(), stoppingPlaceEdge, targetPos, &veh, now, edgesToStop, true);
408 
409  if (edgesToStop.size() > 0) {
410  // Compute the route from the stopping place edge to the end of the route
411  if (rerouteOrigin != veh.getEdge()) {
412  edgesToStop.insert(edgesToStop.begin(), veh.getEdge());
413  }
414  ConstMSEdgeVector edgesFromStop;
415  stoppingPlaceApproaches[alternative] = edgesToStop;
416 
417  const MSEdge* nextDestination = route.getLastEdge();
418  double nextPos = veh.getArrivalPos();
419  int nextDestinationIndex = route.size() - 1;
420  if (!newDestination) {
421  std::vector<std::pair<int, double> > stopIndices = veh.getStopIndices();
422  if (stopIndices.size() > 1) {
423  nextDestinationIndex = stopIndices[1].first;
424  nextDestination = route.getEdges()[nextDestinationIndex];
425  nextPos = stopIndices[1].second;
426 
427  }
428  router.compute(stoppingPlaceEdge, targetPos, nextDestination, nextPos, &veh, now, edgesFromStop, true);
429  }
430  if (edgesFromStop.size() > 0 || newDestination) {
431  stoppingPlaceValues["probability"] = prob;
432  if (stoppingPlaceValues["probability"] > maxValues["probability"]) {
433  maxValues["probability"] = stoppingPlaceValues["probability"];
434  }
435  stoppingPlaceValues["capacity"] = getStoppingPlaceCapacity(alternative);
436  stoppingPlaceValues["absfreespace"] = stoppingPlaceValues["capacity"] - occupancy;
437  // if capacity = 0 then absfreespace and relfreespace are also 0
438  stoppingPlaceValues["relfreespace"] = stoppingPlaceValues["absfreespace"] / MAX2(1.0, stoppingPlaceValues["capacity"]);
439  MSRoute routeToPark(route.getID() + "!to" + myParamPrefix + "#1", edgesToStop, false,
440  &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), route.getStops());
441 
442  // The distance from the current edge to the new parking area
443  double toPos = alternative->getBeginLanePosition();
444  if (&alternative->getLane().getEdge() == veh.getEdge()) {
445  toPos = MAX2(veh.getPositionOnLane(), toPos);
446  }
447  stoppingPlaceValues["distanceto"] = routeToPark.getDistanceBetween(veh.getPositionOnLane(), toPos,
448  routeToPark.begin(), routeToPark.end() - 1, includeInternalLengths);
449 
450  if (stoppingPlaceValues["distanceto"] == std::numeric_limits<double>::max()) {
451  WRITE_WARNINGF(TL("Invalid distance computation for vehicle '%' to stopping place '%' at time=%."),
452  veh.getID(), alternative->getID(), time2string(now));
453  }
454  const double endPos = getStoppingPlaceOccupancy(alternative) == getStoppingPlaceCapacity(alternative)
455  ? alternative->getLastFreePos(veh, veh.getPositionOnLane() + brakeGap)
456  : alternative->getEndLanePosition();
457  const double distToEnd = stoppingPlaceValues["distanceto"] - toPos + endPos;
458 
459  if (distToEnd < brakeGap) {
460  rememberStoppingPlaceScore(veh, alternative, "tooClose");
461  return false;
462  }
463 
464  // The time to reach the new stopping place
465  stoppingPlaceValues["timeto"] = router.recomputeCosts(edgesToStop, &veh, SIMSTEP) - ((alternative->getLane().getLength() - alternative->getEndLanePosition()) / alternative->getLane().getSpeedLimit());
466  ConstMSEdgeVector newEdges = edgesToStop;
467  if (newDestination) {
468  stoppingPlaceValues["distancefrom"] = 0;
469  stoppingPlaceValues["timefrom"] = 0;
470  } else {
471  MSRoute routeFromPark(route.getID() + "!from" + myParamPrefix + "#1", edgesFromStop, false,
472  &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), route.getStops());
473  // The distance from the new parking area to the end of the route
474  stoppingPlaceValues["distancefrom"] = routeFromPark.getDistanceBetween(alternative->getBeginLanePosition(), routeFromPark.getLastEdge()->getLength(),
475  routeFromPark.begin(), routeFromPark.end() - 1, includeInternalLengths);
476  if (stoppingPlaceValues["distancefrom"] == std::numeric_limits<double>::max()) {
477  WRITE_WARNINGF(TL("Invalid distance computation for vehicle '%' from stopping place '%' at time=%."),
478  veh.getID(), alternative->getID(), time2string(SIMSTEP));
479  }
480  // The time to reach this area
481  stoppingPlaceValues["timefrom"] = router.recomputeCosts(edgesFromStop, &veh, SIMSTEP) - (alternative->getEndLanePosition() / alternative->getLane().getSpeedLimit());
482  newEdges.insert(newEdges.end(), edgesFromStop.begin() + 1, edgesFromStop.end());
483  newEdges.insert(newEdges.end(), route.begin() + nextDestinationIndex + 1, route.end());
484  }
485 
486  // add some additional/custom target function components
487  if (!evaluateCustomComponents(veh, brakeGap, newDestination, alternative, occupancy, prob, router, stoppingPlaceValues, stoppingPlaceApproaches[alternative], newEdges, maxValues, addInput)) {
488  return false;
489  }
490  if (!myCheckValidity || validComponentValues(stoppingPlaceValues)) {
491  updateMaxValues(stoppingPlaceValues, maxValues);
492  stoppingPlaces[alternative] = stoppingPlaceValues;
493  newRoutes[alternative] = newEdges;
494  return true;
495  } else {
496  return false;
497  }
498  } else {
499  rememberStoppingPlaceScore(veh, alternative, "unreachable");
500  }
501  } else {
502  rememberStoppingPlaceScore(veh, alternative, "unreachable");
503  }
504  // unreachable
505  return false;
506 }
507 
508 
509 bool
510 MSStoppingPlaceRerouter::evaluateCustomComponents(SUMOVehicle& /*veh*/, double /*brakeGap*/, bool /*newDestination*/,
511  MSStoppingPlace* /*alternative*/, double /*occupancy*/, double /*prob*/, SUMOAbstractRouter<MSEdge, SUMOVehicle>& /*router*/,
512  StoppingPlaceParamMap_t& /*stoppingPlaceValues*/, ConstMSEdgeVector& /*newRoute*/, ConstMSEdgeVector& /*stoppingPlaceApproach*/,
513  StoppingPlaceParamMap_t& /*maxValues*/, StoppingPlaceParamMap_t& /*addInput*/) {
514  return true;
515 }
516 
517 
518 bool
520  return true;
521 }
522 
523 
524 bool
526  return true;
527 }
528 
529 
532  return MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), prohibited);
533 }
534 
535 
539  myEvalParams["distanceto"] = getWeight(veh, "distance.weight", myEvalParams["distanceto"]);
540  for (auto evalParam : myEvalParams) {
541  result[evalParam.first] = getWeight(veh, evalParam.first + ".weight", evalParam.second);
542  }
543  result["probability"] = getWeight(veh, "probability.weight", 0.);
544  return result;
545 }
546 
547 
548 double
549 MSStoppingPlaceRerouter::getWeight(SUMOVehicle& veh, const std::string param, const double defaultWeight, const bool warn) {
550  // get custom vehicle parameter
551  const std::string key = myParamPrefix + "." + param;
552  if (veh.getParameter().hasParameter(key)) {
553  try {
554  return StringUtils::toDouble(veh.getParameter().getParameter(key, "-1"));
555  } catch (...) {
556  WRITE_WARNINGF(TL("Invalid value '%' for vehicle parameter '%'"), veh.getParameter().getParameter(key, "-1"), key);
557  }
558  } else {
559  // get custom vType parameter
560  if (veh.getVehicleType().getParameter().hasParameter(key)) {
561  try {
563  } catch (...) {
564  WRITE_WARNINGF(TL("Invalid value '%' for vType parameter '%'"), veh.getVehicleType().getParameter().getParameter(key, "-1"), key);
565  }
566  }
567  }
568  if (warn) {
569  WRITE_MESSAGEF("Vehicle '%' does not supply vehicle parameter '%'. Using default of %\n", veh.getID(), key, toString(defaultWeight));
570  }
571  return defaultWeight;
572 }
573 
574 
575 void
577  for (auto it = maxValues.begin(); it != maxValues.end(); ++it) {
578  if (stoppingPlaceValues[it->first] > it->second) {
579  it->second = stoppingPlaceValues[it->first];
580  }
581  }
582 }
583 
584 
585 double
587  double cost = 0.;
588  for (StoppingPlaceParamMap_t::const_iterator sc = absValues.begin(); sc != absValues.end(); ++sc) {
589  double weight = weights.at(sc->first);
590  double val = sc->second;
591  if (norm.at(sc->first) && maxValues.at(sc->first) > 0.) {
592  val /= maxValues.at(sc->first);
593  }
594  cost += (invert.at(sc->first)) ? weight * (1. - val) : weight * val;
595  }
596  return cost;
597 }
598 
599 
600 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:74
std::vector< MSEdge * > MSEdgeVector
Definition: MSEdge.h:73
#define DEBUGCOND
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define WRITE_MESSAGEF(...)
Definition: MsgHandler.h:298
#define TL(string)
Definition: MsgHandler.h:315
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition: SUMOTime.cpp:69
#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
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_PARKING_AREA
A parking area.
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
double getLength() const
return the length of the edge
Definition: MSEdge.h:670
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:78
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition: MSLane.h:584
double getLength() const
Returns the lane's length.
Definition: MSLane.h:598
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:756
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:184
MSVehicleRouter & getRouterTT(const int rngIndex, const MSEdgeVector &prohibited=MSEdgeVector()) const
Definition: MSNet.cpp:1487
bool hasInternalLinks() const
return whether the network contains internal links
Definition: MSNet.h:780
int size() const
Returns the number of edges to pass.
Definition: MSRoute.cpp:85
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
const ConstMSEdgeVector & getEdges() const
Definition: MSRoute.h:124
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.
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
MSStoppingPlace * reroute(std::vector< StoppingPlaceVisible > &stoppingPlaceCandidates, const std::vector< double > &probs, SUMOVehicle &veh, bool &newDestination, ConstMSEdgeVector &newRoute, StoppingPlaceParamMap_t &scores, const MSEdgeVector &closedEdges={})
main method to trigger the rerouting to the "best" StoppingPlace according to the custom evaluation f...
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...
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
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)
compute the target function for a single alternative
StoppingPlaceParamMap_t myEvalParams
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.
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:199
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.cpp:94
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 int getRNGIndex() const =0
virtual SumoRNG * getRNG() const =0
Returns the associated RNG for this object.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
virtual const MSLane * getLane() const =0
Returns the lane the object is currently at.
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 ConstMSEdgeVector::const_iterator getRerouteOrigin() const =0
Returns the starting point for reroutes (usually the current edge)
virtual std::vector< std::pair< int, double > > getStopIndices() const =0
return list of route indices and stop positions for the remaining stops
virtual const MSRoute & getRoute() const =0
Returns the current route.
virtual MSParkingArea * getNextParkingArea()=0
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)
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter