Eclipse SUMO - Simulation of Urban MObility
MSLCHelper.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2013-2020 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 // Common functions for lane change models
19 /****************************************************************************/
20 
21 #include <microsim/MSEdge.h>
22 #include <microsim/MSVehicle.h>
24 #include "MSLCHelper.h"
25 
26 // ===========================================================================
27 // Debug flags
28 // ===========================================================================
29 //#define DEBUG_WANTS_CHANGE
30 
31 
32 // ===========================================================================
33 // member method definitions
34 // ===========================================================================
35 
36 double
38  double bonusParam,
39  const MSVehicle::LaneQ& curr,
40  const MSVehicle::LaneQ& neigh,
41  const MSVehicle::LaneQ& best) {
42  if (veh.getLaneChangeModel().isOpposite()) {
43  return 0;
44  }
45  const MSVehicle::LaneQ& inner = neigh.lane->getIndex() > curr.lane->getIndex() ? neigh : curr;
46 #ifdef DEBUG_WANTS_CHANGE
47  const bool debugVehicle = veh.getLaneChangeModel().debugVehicle();
48  if (debugVehicle) {
49  std::cout << SIMTIME << " veh=" << veh.getID() << " getRoundaboutDistBonus bonusParam=" << bonusParam
50  << " curr=" << curr.lane->getID()
51  << " neigh=" << neigh.lane->getID()
52  << " inner=" << inner.lane->getID()
53  << " best=" << best.lane->getID()
54  << "\n innerCont=" << toString(inner.bestContinuations)
55  << "\n bestCont=" << toString(best.bestContinuations)
56  << "\n";
57  }
58 #endif
59 
60  int roundaboutJunctionsAhead = 0;
61  bool enteredRoundabout = false;
62  double seen = -veh.getPositionOnLane();
63 
64  // first check using only normal lanes
65  for (int i = 0; i < (int)best.bestContinuations.size(); i++) {
66  const MSLane* lane = best.bestContinuations[i];
67  if (lane == nullptr) {
68  lane = veh.getLane();
69  }
70  if ((!enteredRoundabout || lane->getEdge().isRoundabout()) && i >= (int)inner.bestContinuations.size()) {
71  // no bonus if we cannot continue on the inner lane until leaving the roundabout
72 #ifdef DEBUG_WANTS_CHANGE
73  if (debugVehicle) {
74  std::cout << " noBonus: inner does not continue (lane=" << lane->getID() << ")\n";
75  }
76 #endif
77  return 0;
78  }
79  if (seen > 300) {
80  // avoid long look-ahead
81 #ifdef DEBUG_WANTS_CHANGE
82  if (debugVehicle) {
83  std::cout << " noBonus: seen=" << seen << " (lane=" << lane->getID() << ")\n";
84  }
85 #endif
86  return 0;
87  }
88  const MSJunction* junction = lane->getEdge().getToJunction();
89  if (lane->getEdge().isRoundabout()) {
90  enteredRoundabout = true;
91  if (junction->getIncoming().size() + junction->getOutgoing().size() > 2) {
92  roundaboutJunctionsAhead++;
93  }
94  } else if (enteredRoundabout) {
95  // only check the first roundabout
96  break;
97  }
98  seen += lane->getLength();
99  }
100  // no bonus if we want to take the next exit
101  if (roundaboutJunctionsAhead < 2) {
102  return 0;
103  }
104 
105  // compute bonus value based on jamming and exact distances (taking into
106  // account internal lanes)
107  double occupancyOuter = 0;
108  double occupancyInner = 0;
109  double distanceInRoundabout = 0;
110  MSLane* prevNormal = nullptr;
111  MSLane* prevInner = nullptr;
112  enteredRoundabout = false;
113  for (int i = 0; i < (int)best.bestContinuations.size(); i++) {
114  MSLane* lane = best.bestContinuations[i];
115  if (lane == nullptr) {
116  continue;
117  }
118  if (lane->getEdge().isRoundabout()) {
119  enteredRoundabout = true;
120  } else if (enteredRoundabout) {
121  // only check the first roundabout
122  break;
123  }
124  MSLane* via = nullptr;
125  if (prevNormal != nullptr) {
126  for (MSLink* link : prevNormal->getLinkCont()) {
127  if (link->getLane() == lane) {
128  via = link->getViaLane();
129  }
130  }
131  }
132  if (enteredRoundabout) {
133  distanceInRoundabout += lane->getLength();
134  if (via != nullptr) {
135  distanceInRoundabout += via->getLength();
136  }
137  }
138  // discount vehicles that are upstream from ego
139  const double upstreamDiscount = &lane->getEdge() == &veh.getLane()->getEdge()
140  ? (lane->getLength() - veh.getPositionOnLane()) / lane->getLength() : 1;
141  prevNormal = lane;
142  occupancyOuter += upstreamDiscount * lane->getBruttoVehLenSum();
143 #ifdef DEBUG_WANTS_CHANGE
144  if (debugVehicle) {
145  std::cout << " lane=" << lane->getID() << " occ=" << lane->getBruttoVehLenSum() << " discount=" << upstreamDiscount << " outer=" << occupancyOuter << "\n";
146  }
147 #endif
148  if (via != nullptr) {
149  occupancyOuter += via->getBruttoVehLenSum();
150 #ifdef DEBUG_WANTS_CHANGE
151  if (debugVehicle) {
152  std::cout << " via=" << via->getID() << " occ=" << via->getBruttoVehLenSum() << " outer=" << occupancyOuter << "\n";
153  }
154 #endif
155  }
156  if (i < (int)inner.bestContinuations.size()) {
157  MSLane* innerLane = inner.bestContinuations[i];
158  occupancyInner += upstreamDiscount * innerLane->getBruttoVehLenSum();
159 #ifdef DEBUG_WANTS_CHANGE
160  if (debugVehicle) {
161  std::cout << " inner=" << innerLane->getID() << " occ=" << innerLane->getBruttoVehLenSum() << " discount=" << upstreamDiscount << " inner=" << occupancyInner << "\n";
162  }
163 #endif
164  if (prevInner != nullptr) {
165  for (MSLink* link : prevInner->getLinkCont()) {
166  if (link->getLane() == innerLane && link->getViaLane() != nullptr) {
167  occupancyInner += link->getViaLane()->getBruttoVehLenSum();
168 #ifdef DEBUG_WANTS_CHANGE
169  if (debugVehicle) {
170  std::cout << " innerVia=" << link->getViaLane()->getID() << " occ=" << link->getViaLane()->getBruttoVehLenSum() << " inner=" << occupancyInner << "\n";
171  }
172 #endif
173  }
174  }
175  }
176  prevInner = innerLane;
177  }
178  }
179 
180 #ifdef DEBUG_WANTS_CHANGE
181  if (debugVehicle) {
182  std::cout << " distanceInRoundabout=" << distanceInRoundabout
183  << " roundaboutJunctionsAhead=" << roundaboutJunctionsAhead
184  << " occupancyInner=" << occupancyInner
185  << " occupancyOuter=" << occupancyOuter
186  << "\n";
187  }
188 #endif
189 
190  const double maxOccupancy = MAX2(occupancyInner, occupancyOuter);
191  if (maxOccupancy == 0) {
192  // no bonues if the roundabout is empty
193  return 0;
194  }
195  // give some bonus for using the inside lane at equal occupancy
196  const double bonus = roundaboutJunctionsAhead * 7.5;
197  const double relativeJam = (occupancyOuter - occupancyInner + bonus) / (maxOccupancy + bonus);
198  // no bonus if the inner lane or the left lane entering the roundabout is jammed
199  const double jamFactor = MAX2(0.0, relativeJam);
200  const double result = distanceInRoundabout * jamFactor * bonusParam * 9; // the 9 is abitrary and only there for backward compatibility
201 #ifdef DEBUG_WANTS_CHANGE
202  if (debugVehicle) {
203  std::cout << " relativeJam=" << relativeJam
204  << " jamFactor=" << jamFactor
205  << " distanceBonus=" << result
206  << "\n";
207  }
208 #endif
209  return result;
210 }
211 
212 
213 
214 /****************************************************************************/
#define SIMTIME
Definition: SUMOTime.h:60
T MAX2(T a, T b)
Definition: StdDefs.h:79
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:44
virtual bool debugVehicle() const
whether the current vehicles shall be debugged
bool isRoundabout() const
Definition: MSEdge.h:674
const MSJunction * getToJunction() const
Definition: MSEdge.h:392
The base class for an intersection.
Definition: MSJunction.h:58
const ConstMSEdgeVector & getIncoming() const
Definition: MSJunction.h:105
const ConstMSEdgeVector & getOutgoing() const
Definition: MSJunction.h:111
static double getRoundaboutDistBonus(const MSVehicle &veh, double bonusParam, const MSVehicle::LaneQ &curr, const MSVehicle::LaneQ &neigh, const MSVehicle::LaneQ &best)
Computes the artificial bonus distance for roundabout lanes this additional distance reduces the sens...
Definition: MSLCHelper.cpp:37
Representation of a lane in the micro simulation.
Definition: MSLane.h:82
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.h:640
double getBruttoVehLenSum() const
Returns the sum of lengths of vehicles, including their minGaps, which were on the lane during the la...
Definition: MSLane.h:1019
double getLength() const
Returns the lane's length.
Definition: MSLane.h:539
int getIndex() const
Returns the lane's index.
Definition: MSLane.h:562
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:673
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:4699
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition: MSVehicle.h:374
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:550
const std::string & getID() const
Returns the id.
Definition: Named.h:73
A structure representing the best lanes for continuing the current route starting at 'lane'.
Definition: MSVehicle.h:830
std::vector< MSLane * > bestContinuations
Definition: MSVehicle.h:850
MSLane * lane
The described lane.
Definition: MSVehicle.h:832