Line data Source code
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 : /****************************************************************************/
14 : /// @file MSLCM_LC2013.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Friedemann Wesner
18 : /// @author Sascha Krieg
19 : /// @author Michael Behrisch
20 : /// @author Laura Bieker
21 : /// @author Leonhard Luecken
22 : /// @date Fri, 08.10.2013
23 : ///
24 : // A lane change model developed by J. Erdmann
25 : // based on the model of D. Krajzewicz developed between 2004 and 2011 (MSLCM_DK2004)
26 : /****************************************************************************/
27 : #include <config.h>
28 :
29 : #include <iostream>
30 : #include <utils/xml/SUMOSAXAttributes.h>
31 : #include <utils/common/RandHelper.h>
32 : #include <utils/common/StringUtils.h>
33 : #include <microsim/transportables/MSPModel.h>
34 : #include <microsim/transportables/MSTransportableControl.h>
35 : #include <microsim/MSEdge.h>
36 : #include <microsim/MSLane.h>
37 : #include <microsim/MSLink.h>
38 : #include <microsim/MSDriverState.h>
39 : #include <microsim/MSNet.h>
40 : #include <microsim/MSStop.h>
41 : #include "MSLCHelper.h"
42 : #include "MSLCM_LC2013.h"
43 :
44 :
45 : // ===========================================================================
46 : // variable definitions
47 : // ===========================================================================
48 : #define LOOK_FORWARD 10.
49 :
50 : #define JAM_FACTOR 1.
51 :
52 : #define LCA_RIGHT_IMPATIENCE -1.
53 : #define CUT_IN_LEFT_SPEED_THRESHOLD 27.
54 :
55 : #define LOOK_AHEAD_MIN_SPEED 0.0
56 : #define LOOK_AHEAD_SPEED_MEMORY 0.9
57 :
58 : #define HELP_DECEL_FACTOR 1.0
59 :
60 : #define HELP_OVERTAKE (10.0 / 3.6)
61 : #define MIN_FALLBEHIND (7.0 / 3.6)
62 :
63 : #define RELGAIN_NORMALIZATION_MIN_SPEED 10.0
64 : #define URGENCY 2.0
65 : #define OPPOSITE_URGENCY 5.0
66 :
67 : #define KEEP_RIGHT_TIME 5.0 // the number of seconds after which a vehicle should move to the right lane
68 :
69 : #define KEEP_RIGHT_HEADWAY 2.0
70 : #define MAX_ONRAMP_LENGTH 200.
71 : #define TURN_LANE_DIST 200.0 // the distance at which a lane leading elsewhere is considered to be a turn-lane that must be avoided
72 :
73 : #define LC_RESOLUTION_SPEED_LAT 0.5 // the lateral speed (in m/s) for a standing vehicle which was unable to finish a continuous LC in time (in case mySpeedLatStanding==0), see #3771
74 :
75 : #define REACT_TO_STOPPED_DISTANCE 100
76 : #define BLOCKER_IS_BLOCKED_TIME_THRESHOLD 5 // the time after which a blocking neighbor is treated similar to a stopped vehicle
77 :
78 : #define HYST_PRECISION 10000000
79 :
80 : // ===========================================================================
81 : // debug defines
82 : // ===========================================================================
83 : //#define DEBUG_CONSTRUCTOR
84 : //#define DEBUG_PATCH_SPEED
85 : //#define DEBUG_INFORMED
86 : //#define DEBUG_INFORMER
87 : //#define DEBUG_WANTS_CHANGE
88 : //#define DEBUG_SLOW_DOWN
89 : //#define DEBUG_COOPERATE
90 : //#define DEBUG_SAVE_BLOCKER_LENGTH
91 :
92 : //#define DEBUG_COND (myVehicle.getID() == "ego")
93 : #define DEBUG_COND (myVehicle.isSelected())
94 : //#define DEBUG_COND (true)
95 :
96 : // ===========================================================================
97 : // member method definitions
98 : // ===========================================================================
99 3693551 : MSLCM_LC2013::MSLCM_LC2013(MSVehicle& v) :
100 : MSAbstractLaneChangeModel(v, LaneChangeModel::LC2013),
101 3693551 : mySpeedGainProbabilityLeft(0),
102 3693551 : mySpeedGainProbabilityRight(0),
103 3693551 : myKeepRightProbability(0),
104 3693551 : myLeadingBlockerLength(0),
105 3693551 : myLeftSpace(0),
106 3693551 : myLookAheadSpeed(LOOK_AHEAD_MIN_SPEED),
107 3693551 : myDontBrake(false),
108 3693551 : myStrategicParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_STRATEGIC_PARAM, 1)),
109 3693551 : myCooperativeParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_COOPERATIVE_PARAM, 1)),
110 3693551 : mySpeedGainParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAIN_PARAM, 1)),
111 3693551 : myKeepRightParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_KEEPRIGHT_PARAM, 1)),
112 3693551 : myOppositeParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_OPPOSITE_PARAM, 1)),
113 3693551 : myLookaheadLeft(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_LOOKAHEADLEFT, 2.0)),
114 3693551 : mySpeedGainRight(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAINRIGHT, 0.1)),
115 3693551 : mySpeedGainLookahead(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD, 0)),
116 3693551 : mySpeedGainRemainTime(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAIN_REMAIN_TIME, 20)),
117 3693551 : mySpeedGainUrgency(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAIN_URGENCY, 50)),
118 3693551 : myRoundaboutBonus(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_COOPERATIVE_ROUNDABOUT, myCooperativeParam)),
119 3693551 : myCooperativeSpeed(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_COOPERATIVE_SPEED, myCooperativeParam)),
120 3693551 : myKeepRightAcceptanceTime(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_KEEPRIGHT_ACCEPTANCE_TIME, -1)),
121 3693551 : myOvertakeDeltaSpeedFactor(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_OVERTAKE_DELTASPEED_FACTOR, 0)),
122 7387102 : myExperimentalParam1(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_EXPERIMENTAL1, 0)) {
123 3693551 : initDerivedParameters();
124 : #ifdef DEBUG_CONSTRUCTOR
125 : if (DEBUG_COND) {
126 : std::cout << SIMTIME
127 : << " create lcModel veh=" << myVehicle.getID()
128 : << " lcStrategic=" << myStrategicParam
129 : << " lcCooperative=" << myCooperativeParam
130 : << " lcSpeedGain=" << mySpeedGainParam
131 : << " lcKeepRight=" << myKeepRightParam
132 : << "\n";
133 : }
134 : #endif
135 3693551 : }
136 :
137 7386964 : MSLCM_LC2013::~MSLCM_LC2013() {
138 3693482 : changed();
139 7386964 : }
140 :
141 :
142 : void
143 3702653 : MSLCM_LC2013::initDerivedParameters() {
144 3702653 : if (mySpeedGainParam <= 0) {
145 7096 : myChangeProbThresholdRight = std::numeric_limits<long long int>::max();
146 7096 : myChangeProbThresholdLeft = std::numeric_limits<long long int>::max();
147 : } else {
148 3695557 : myChangeProbThresholdRight = (long long int)((0.2 / mySpeedGainRight) / mySpeedGainParam * HYST_PRECISION);
149 3695557 : myChangeProbThresholdLeft = (long long int)(0.2 / mySpeedGainParam * HYST_PRECISION);
150 : }
151 3702653 : }
152 :
153 :
154 : bool
155 8795 : MSLCM_LC2013::debugVehicle() const {
156 8795 : return DEBUG_COND;
157 : }
158 :
159 :
160 : int
161 241465841 : MSLCM_LC2013::wantsChange(
162 : int laneOffset,
163 : MSAbstractLaneChangeModel::MSLCMessager& msgPass,
164 : int blocked,
165 : const std::pair<MSVehicle*, double>& leader,
166 : const std::pair<MSVehicle*, double>& follower,
167 : const std::pair<MSVehicle*, double>& neighLead,
168 : const std::pair<MSVehicle*, double>& neighFollow,
169 : const MSLane& neighLane,
170 : const std::vector<MSVehicle::LaneQ>& preb,
171 : MSVehicle** lastBlocked,
172 : MSVehicle** firstBlocked) {
173 :
174 : #ifdef DEBUG_WANTS_CHANGE
175 : if (DEBUG_COND) {
176 : std::cout << "\nWANTS_CHANGE\n" << SIMTIME
177 : << std::setprecision(gPrecision)
178 : << " veh=" << myVehicle.getID()
179 : << " lane=" << myVehicle.getLane()->getID()
180 : << " pos=" << myVehicle.getPositionOnLane()
181 : << " posLat=" << myVehicle.getLateralPositionOnLane()
182 : << " speed=" << myVehicle.getSpeed()
183 : << " considerChangeTo=" << (laneOffset == -1 ? "right" : "left")
184 : << "\n";
185 : }
186 : #endif
187 :
188 241465841 : const int result = _wantsChange(laneOffset, msgPass, blocked, leader, follower, neighLead, neighFollow, neighLane, preb, *lastBlocked, *firstBlocked);
189 :
190 : #ifdef DEBUG_WANTS_CHANGE
191 : if (DEBUG_COND) {
192 : std::cout << SIMTIME << " veh=" << myVehicle.getID() << " result=" << toString((LaneChangeAction)result) << " blocked=" << toString((LaneChangeAction)blocked) << "\n\n\n";
193 : }
194 : #endif
195 :
196 241465841 : return result;
197 : }
198 :
199 :
200 : double
201 549404401 : MSLCM_LC2013::patchSpeed(const double min, const double wanted, const double max, const MSCFModel& cfModel) {
202 :
203 : #ifdef DEBUG_PATCH_SPEED
204 : if (DEBUG_COND) {
205 : std::cout << "\nPATCH_SPEED\n"
206 : << SIMTIME
207 : << " veh=" << myVehicle.getID()
208 : << " lane=" << myVehicle.getLane()->getID()
209 : << " pos=" << myVehicle.getPositionOnLane()
210 : << " v=" << myVehicle.getSpeed()
211 : << " min=" << min
212 : << " wanted=" << wanted
213 : << " max=" << max
214 : << "\n";
215 : }
216 : #endif
217 :
218 : // negative min speed may be passed when using ballistic updated
219 549404401 : const double newSpeed = _patchSpeed(MAX2(min, 0.0), wanted, max, cfModel);
220 :
221 : #ifdef DEBUG_PATCH_SPEED
222 : if (DEBUG_COND) {
223 : const std::string patched = (wanted != newSpeed ? " patched=" + toString(newSpeed) : "");
224 : std::cout << patched
225 : << "\n";
226 : }
227 : #endif
228 :
229 549404401 : return newSpeed;
230 : }
231 :
232 :
233 : double
234 549404401 : MSLCM_LC2013::_patchSpeed(double min, const double wanted, double max, const MSCFModel& cfModel) {
235 549404401 : int state = myOwnState;
236 : #ifdef DEBUG_PATCH_SPEED
237 : if (DEBUG_COND) {
238 : std::cout
239 : << "\n" << SIMTIME << std::setprecision(gPrecision)
240 : << " patchSpeed state=" << toString((LaneChangeAction)state) << " myLCAccelerationAdvices=" << toString(myLCAccelerationAdvices)
241 : << "\n speed=" << myVehicle.getSpeed() << " min=" << min << " wanted=" << wanted
242 : << "\n myLeadingBlockerLength=" << myLeadingBlockerLength
243 : << "\n";
244 : }
245 : #endif
246 :
247 : // letting vehicles merge in at the end of the lane in case of counter-lane change, step#2
248 : double nVSafe = wanted;
249 : bool gotOne = false;
250 : // if we want to change and have a blocking leader and there is enough room for him in front of us
251 549404401 : if (myLeadingBlockerLength != 0) {
252 552836 : double space = myLeftSpace - myLeadingBlockerLength - POSITION_EPS;
253 : #ifdef DEBUG_PATCH_SPEED
254 : if (DEBUG_COND) {
255 : std::cout << SIMTIME << " veh=" << myVehicle.getID() << " myLeftSpace=" << myLeftSpace << " myLeadingBlockerLength=" << myLeadingBlockerLength << " space=" << space << "\n";
256 : }
257 : #endif
258 552836 : if (space > 0 && (myVehicle.getLane()->isNormal() || myVehicle.getCurrentEdge()->isRoundabout())) {
259 : // compute speed for decelerating towards a place which allows the blocking leader to merge in in front
260 424023 : const double vMinEmergency = myVehicle.getCarFollowModel().minNextSpeedEmergency(myVehicle.getSpeed(), &myVehicle);
261 424023 : double safe = cfModel.stopSpeed(&myVehicle, myVehicle.getSpeed(), space, MSCFModel::CalcReason::LANE_CHANGE);
262 : max = MIN2(max, MAX2(safe, vMinEmergency));
263 : // if we are approaching this place
264 424023 : if (safe < wanted) {
265 : // return this speed as the speed to use
266 45157 : if (safe < min) {
267 4715 : if (safe >= vMinEmergency) {
268 : // permit harder braking if needed and helpful
269 : min = MAX2(vMinEmergency, safe);
270 : }
271 : }
272 : #ifdef DEBUG_PATCH_SPEED
273 : if (DEBUG_COND) {
274 : std::cout << SIMTIME << " veh=" << myVehicle.getID() << " slowing down for leading blocker, safe=" << safe << (safe + NUMERICAL_EPS < min ? " (not enough)" : "") << "\n";
275 : }
276 : #endif
277 : nVSafe = MAX2(min, safe);
278 : gotOne = true;
279 : }
280 : }
281 : }
282 :
283 549404401 : const double coopWeight = MAX2(0.0, MIN2(1.0, myCooperativeSpeed));
284 572664475 : for (auto i : myLCAccelerationAdvices) {
285 : double a = i.first;
286 23260074 : double v = myVehicle.getSpeed() + ACCEL2SPEED(a);
287 :
288 23260074 : if (v >= min && v <= max && (MSGlobals::gSemiImplicitEulerUpdate
289 : // ballistic update: (negative speeds may appear, e.g. min<0, v<0), BUT:
290 : // XXX: LaneChanging returns -1 to indicate no restrictions, which leads to probs here (Leo), refs. #2577
291 : // As a quick fix, we just dismiss cases where v=-1
292 : // VERY rarely (whenever a requested help-acceleration is really indicated by v=-1)
293 : // this can lead to failing lane-change attempts, though)
294 256083 : || v != -1)) {
295 5577952 : if (i.second) {
296 : // own advice, no scaling needed
297 : nVSafe = MIN2(v, nVSafe);
298 : } else {
299 2261482 : nVSafe = MIN2(v * coopWeight + (1 - coopWeight) * wanted, nVSafe);
300 : }
301 : gotOne = true;
302 : #ifdef DEBUG_PATCH_SPEED
303 : if (DEBUG_COND) {
304 : std::cout << SIMTIME << " veh=" << myVehicle.getID() << " got nVSafe=" << nVSafe << " isOwn: " << i.second << " rawV=" << v << "\n";
305 : }
306 : #endif
307 : } else {
308 : if (v < min) {
309 : #ifdef DEBUG_PATCH_SPEED
310 : if (DEBUG_COND) {
311 : std::cout << SIMTIME << " veh=" << myVehicle.getID() << " ignoring low nVSafe=" << v << " min=" << min << "\n";
312 : }
313 : #endif
314 : } else {
315 : #ifdef DEBUG_PATCH_SPEED
316 : if (DEBUG_COND) {
317 : std::cout << SIMTIME << " veh=" << myVehicle.getID() << " ignoring high nVSafe=" << v << " max=" << max << "\n";
318 : }
319 : #endif
320 : }
321 : }
322 : }
323 : // myDontBrake is used in counter-lane-change situations with relief connection
324 549404401 : if (gotOne && !myDontBrake) {
325 : #ifdef DEBUG_PATCH_SPEED
326 : if (DEBUG_COND) {
327 : std::cout << SIMTIME << " veh=" << myVehicle.getID() << " got vSafe\n";
328 : }
329 : #endif
330 : return nVSafe;
331 : }
332 :
333 : // check whether the vehicle is blocked
334 544669399 : if ((state & LCA_WANTS_LANECHANGE) != 0 && (state & LCA_BLOCKED) != 0) {
335 13359543 : if ((state & LCA_STRATEGIC) != 0) {
336 : // necessary decelerations are controlled via vSafe. If there are
337 : // none it means we should speed up
338 : #ifdef DEBUG_PATCH_SPEED
339 : if (DEBUG_COND) {
340 : std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_WANTS_LANECHANGE (strat, no vSafe)\n";
341 : }
342 : #endif
343 2908296 : return (max + wanted) / 2.0;
344 10451247 : } else if ((state & LCA_COOPERATIVE) != 0) {
345 : // only minor adjustments in speed should be done
346 754086 : if ((state & LCA_BLOCKED_BY_LEADER) != 0) {
347 : #ifdef DEBUG_PATCH_SPEED
348 : if (DEBUG_COND) {
349 : std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_LEADER (coop)\n";
350 : }
351 : #endif
352 612866 : if (wanted >= 0.) {
353 612866 : return (MAX2(0., min) + wanted) / 2.0;
354 : } else {
355 : return wanted;
356 : }
357 : }
358 141220 : if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
359 : #ifdef DEBUG_PATCH_SPEED
360 : if (DEBUG_COND) {
361 : std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_FOLLOWER (coop)\n";
362 : }
363 : #endif
364 141220 : return (max + wanted) / 2.0;
365 : }
366 : //} else { // VARIANT_16
367 : // // only accelerations should be performed
368 : // if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
369 : // if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_FOLLOWER\n";
370 : // return (max + wanted) / 2.0;
371 : // }
372 : }
373 : }
374 :
375 : /*
376 : // decelerate if being a blocking follower
377 : // (and does not have to change lanes)
378 : if ((state & LCA_AMBLOCKINGFOLLOWER) != 0) {
379 : if (fabs(max - myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle)) < 0.001 && min == 0) { // !!! was standing
380 : if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER (standing)\n";
381 : return 0;
382 : }
383 : if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER\n";
384 :
385 : //return min; // VARIANT_3 (brakeStrong)
386 : return (min + wanted) / 2.0;
387 : }
388 : if ((state & LCA_AMBACKBLOCKER) != 0) {
389 : if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
390 : if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBACKBLOCKER (standing)\n";
391 : //return min; VARIANT_9 (backBlockVSafe)
392 : return nVSafe;
393 : }
394 : }
395 : if ((state & LCA_AMBACKBLOCKER_STANDING) != 0) {
396 : if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBACKBLOCKER_STANDING\n";
397 : //return min;
398 : return nVSafe;
399 : }
400 : */
401 :
402 : // accelerate if being a blocking leader or blocking follower not able to brake
403 : // (and does not have to change lanes)
404 541007017 : if ((state & LCA_AMBLOCKINGLEADER) != 0 && myCooperativeSpeed >= 0) {
405 : #ifdef DEBUG_PATCH_SPEED
406 : if (DEBUG_COND) {
407 : std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGLEADER\n";
408 : }
409 : #endif
410 1543154 : return (max + wanted) / 2.0;
411 : }
412 :
413 : if ((state & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
414 : #ifdef DEBUG_PATCH_SPEED
415 : if (DEBUG_COND) {
416 : std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER_DONTBRAKE\n";
417 : }
418 : #endif
419 : /*
420 : // VARIANT_4 (dontbrake)
421 : if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
422 : return wanted;
423 : }
424 : return (min + wanted) / 2.0;
425 : */
426 : }
427 539463863 : if (!myVehicle.getLane()->getEdge().hasLaneChanger()) {
428 : // remove chaning information if on a road with a single lane
429 302370223 : changed();
430 : }
431 : return wanted;
432 : }
433 :
434 :
435 : void*
436 4620227 : MSLCM_LC2013::inform(void* info, MSVehicle* sender) {
437 : UNUSED_PARAMETER(sender);
438 : Info* pinfo = (Info*)info;
439 : assert(pinfo->first >= 0 || !MSGlobals::gSemiImplicitEulerUpdate);
440 4620227 : addLCSpeedAdvice(pinfo->first, false);
441 4620227 : myOwnState |= pinfo->second;
442 : #ifdef DEBUG_INFORMED
443 : if (DEBUG_COND) {
444 : std::cout << SIMTIME
445 : << " veh=" << myVehicle.getID()
446 : << " informedBy=" << sender->getID()
447 : << " info=" << pinfo->second
448 : << " vSafe=" << pinfo->first
449 : << "\n";
450 : }
451 : #endif
452 4620227 : delete pinfo;
453 4620227 : return (void*) true;
454 : }
455 :
456 : double
457 4584398 : MSLCM_LC2013::overtakeDistance(const MSVehicle* follower, const MSVehicle* leader, const double gap, double followerSpeed, double leaderSpeed) {
458 4584398 : followerSpeed = followerSpeed == INVALID_SPEED ? follower->getSpeed() : followerSpeed;
459 4584398 : leaderSpeed = leaderSpeed == INVALID_SPEED ? leader->getSpeed() : leaderSpeed;
460 : double overtakeDist = (gap // drive to back of leader
461 4584398 : + leader->getVehicleType().getLengthWithGap() // drive to front of leader
462 4584398 : + follower->getVehicleType().getLength() // follower back reaches leader front
463 4584398 : + leader->getCarFollowModel().getSecureGap( // save gap to leader
464 4584398 : leader, follower, leaderSpeed, followerSpeed, follower->getCarFollowModel().getMaxDecel()));
465 4584398 : return MAX2(overtakeDist, 0.);
466 : }
467 :
468 :
469 : double
470 4732871 : MSLCM_LC2013::informLeader(MSAbstractLaneChangeModel::MSLCMessager& msgPass,
471 : int blocked,
472 : int dir,
473 : const std::pair<MSVehicle*, double>& neighLead,
474 : double remainingSeconds) {
475 4732871 : double plannedSpeed = myVehicle.getSpeed();
476 4732871 : if (!isOpposite()) {
477 4637737 : plannedSpeed = MIN2(plannedSpeed,
478 4637737 : myVehicle.getCarFollowModel().stopSpeed(&myVehicle, myVehicle.getSpeed(), myLeftSpace - myLeadingBlockerLength));
479 : }
480 5526241 : for (auto i : myLCAccelerationAdvices) {
481 : const double a = i.first;
482 793370 : if (a >= -myVehicle.getCarFollowModel().getMaxDecel()) {
483 793350 : plannedSpeed = MIN2(plannedSpeed, myVehicle.getSpeed() + ACCEL2SPEED(a));
484 : }
485 : }
486 : #ifdef DEBUG_INFORMER
487 : if (DEBUG_COND) {
488 : std::cout << "\nINFORM_LEADER"
489 : << "\nspeed=" << myVehicle.getSpeed() << " planned=" << plannedSpeed << "\n";
490 : }
491 : #endif
492 :
493 4732871 : const MSVehicle* const nv = neighLead.first;
494 4732871 : if (nv == nullptr) {
495 : // not overtaking
496 : return plannedSpeed;
497 : }
498 4501313 : const double neighNextSpeed = nv->getSpeed() - ACCEL2SPEED(MAX2(1.0, -nv->getAcceleration()));
499 : double neighNextGap;
500 4501313 : if (MSGlobals::gSemiImplicitEulerUpdate) {
501 4269554 : neighNextGap = neighLead.second + SPEED2DIST(neighNextSpeed - plannedSpeed);
502 : } else {
503 231759 : neighNextGap = neighLead.second + SPEED2DIST((nv->getSpeed() + neighNextSpeed) / 2) - SPEED2DIST((myVehicle.getSpeed() + plannedSpeed) / 2);
504 : }
505 4501313 : if ((blocked & LCA_BLOCKED_BY_LEADER) != 0) {
506 3622128 : if (MSLCHelper::divergentRoute(myVehicle, *nv)) {
507 : //std::cout << SIMTIME << " ego=" << myVehicle.getID() << " ignoresDivergentBlockingLeader=" << nv->getID() << "\n";
508 : return plannedSpeed;
509 : }
510 : #ifdef DEBUG_INFORMER
511 : if (DEBUG_COND) {
512 : std::cout << " blocked by leader nv=" << nv->getID() << " nvSpeed=" << nv->getSpeed() << " needGap="
513 : << myVehicle.getCarFollowModel().getSecureGap(&myVehicle, nv, myVehicle.getSpeed(), nv->getSpeed(), nv->getCarFollowModel().getMaxDecel()) << "\n";
514 : }
515 : #endif
516 : // decide whether we want to overtake the leader or follow it
517 : double overtakeTime;
518 3618124 : const double overtakeDist = overtakeDistance(&myVehicle, nv, neighLead.second);
519 3618124 : const double dv = plannedSpeed - nv->getSpeed();
520 :
521 3618124 : if (dv > myOvertakeDeltaSpeedFactor * myVehicle.getLane()->getSpeedLimit()) {
522 1537536 : overtakeTime = overtakeDist / dv;
523 : } else if (nv->getWaitingSeconds() > BLOCKER_IS_BLOCKED_TIME_THRESHOLD
524 1181222 : && !isOpposite()
525 3235575 : && (myVehicle.getVehicleType().getLengthWithGap() + nv->getVehicleType().getLengthWithGap()) <= myLeftSpace) {
526 : // -> set overtakeTime to indicate possibility of overtaking (only if there is enough space)
527 1026270 : overtakeTime = remainingSeconds - 1;
528 : } else {
529 : // -> set overtakeTime to something indicating impossibility of overtaking
530 1054318 : overtakeTime = remainingSeconds + 1;
531 : }
532 :
533 : #ifdef DEBUG_INFORMER
534 : if (DEBUG_COND) {
535 : std::cout << SIMTIME << " informLeader() of " << myVehicle.getID()
536 : << "\nnv = " << nv->getID()
537 : << "\nplannedSpeed = " << plannedSpeed
538 : << "\nleaderSpeed = " << nv->getSpeed()
539 : << "\nmyLeftSpace = " << myLeftSpace
540 : << "\nremainingSeconds = " << remainingSeconds
541 : << "\novertakeDist = " << overtakeDist
542 : << "\novertakeTime = " << overtakeTime
543 : << std::endl;
544 : }
545 : #endif
546 :
547 3618124 : if ((dv < myOvertakeDeltaSpeedFactor * myVehicle.getLane()->getSpeedLimit()
548 : // overtaking on the right on an uncongested highway is forbidden (noOvertakeLCLeft)
549 2732006 : || (dir == LCA_MLEFT && avoidOvertakeRight(neighLead.first))
550 : // not enough space to overtake?
551 5306957 : || (MSGlobals::gSemiImplicitEulerUpdate && myLeftSpace - myLeadingBlockerLength - myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed()) < overtakeDist)
552 : // using brakeGap() without headway seems adequate in a situation where the obstacle (the lane end) is not moving [XXX implemented in branch ticket860, can be used in general if desired, refs. #2575] (Leo).
553 2565874 : || (!MSGlobals::gSemiImplicitEulerUpdate && myLeftSpace - myLeadingBlockerLength - myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed(), getCarFollowModel().getMaxDecel(), 0.) < overtakeDist)
554 : // not enough time to overtake? (skipped for a stopped leader [currently only for ballistic update XXX: check if appropriate for euler, too, refs. #2575] to ensure that it can be overtaken if only enough space is exists) (Leo)
555 2548776 : || (remainingSeconds < overtakeTime && (MSGlobals::gSemiImplicitEulerUpdate || !nv->isStopped())))
556 : // opposite driving and must overtake
557 4345739 : && (!neighLead.first->isStopped() || (isOpposite() && neighLead.second >= 0))) {
558 : // cannot overtake
559 1611024 : msgPass.informNeighLeader(new Info(std::numeric_limits<double>::max(), dir | LCA_AMBLOCKINGLEADER), &myVehicle);
560 : // slow down smoothly to follow leader
561 : // account for minor decelerations by the leader (dawdling)
562 4833072 : double targetSpeed = MAX3(myVehicle.getCarFollowModel().minNextSpeed(myVehicle.getSpeed(), &myVehicle),
563 1611024 : getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighNextGap, neighNextSpeed, nv->getCarFollowModel().getMaxDecel()),
564 : // avoid changing on intersection
565 1631899 : (myVehicle.getLane()->isNormal() || myVehicle.getCurrentEdge()->isRoundabout()) ? 0 : ACCEL2SPEED(myVehicle.getCarFollowModel().getMaxAccel()));
566 1611024 : if (targetSpeed < myVehicle.getSpeed()) {
567 : // slow down smoothly to follow leader
568 531900 : const double decel = remainingSeconds == 0. ? myVehicle.getCarFollowModel().getMaxDecel() :
569 531900 : MIN2(myVehicle.getCarFollowModel().getMaxDecel(),
570 531900 : MAX2(MIN_FALLBEHIND, (myVehicle.getSpeed() - targetSpeed) / remainingSeconds));
571 531900 : const double nextSpeed = MIN2(plannedSpeed, MAX2(0.0, myVehicle.getSpeed() - ACCEL2SPEED(decel)));
572 : #ifdef DEBUG_INFORMER
573 : if (DEBUG_COND) {
574 : std::cout << SIMTIME
575 : << " cannot overtake leader nv=" << nv->getID()
576 : << " dv=" << dv
577 : << " myLookAheadSpeed=" << myLookAheadSpeed
578 : << " myLeftSpace=" << myLeftSpace
579 : << " overtakeDist=" << overtakeDist
580 : << " overtakeTime=" << overtakeTime
581 : << " remainingSeconds=" << remainingSeconds
582 : << " currentGap=" << neighLead.second
583 : << " brakeGap=" << myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed(), getCarFollowModel().getMaxDecel(), 0.)
584 : << " neighNextSpeed=" << neighNextSpeed
585 : << " neighNextGap=" << neighNextGap
586 : << " targetSpeed=" << targetSpeed
587 : << " nextSpeed=" << nextSpeed
588 : << "\n";
589 : }
590 : #endif
591 531900 : addLCSpeedAdvice(nextSpeed);
592 531900 : return nextSpeed;
593 : } else {
594 : // leader is fast enough anyway
595 : #ifdef DEBUG_INFORMER
596 : if (DEBUG_COND) {
597 : std::cout << SIMTIME
598 : << " cannot overtake fast leader nv=" << nv->getID()
599 : << " dv=" << dv
600 : << " myLookAheadSpeed=" << myLookAheadSpeed
601 : << " myLeftSpace=" << myLeftSpace
602 : << " overtakeDist=" << overtakeDist
603 : << " myLeadingBlockerLength=" << myLeadingBlockerLength
604 : << " overtakeTime=" << overtakeTime
605 : << " remainingSeconds=" << remainingSeconds
606 : << " currentGap=" << neighLead.second
607 : << " neighNextSpeed=" << neighNextSpeed
608 : << " neighNextGap=" << neighNextGap
609 : << " targetSpeed=" << targetSpeed
610 : << "\n";
611 : }
612 : #endif
613 1079124 : addLCSpeedAdvice(targetSpeed);
614 1079124 : return plannedSpeed;
615 : }
616 : } else {
617 : // overtaking, leader should not accelerate
618 : #ifdef DEBUG_INFORMER
619 : if (DEBUG_COND) {
620 : std::cout << SIMTIME
621 : << " wants to overtake leader nv=" << nv->getID()
622 : << " dv=" << dv
623 : << " overtakeDist=" << overtakeDist
624 : << " remainingSeconds=" << remainingSeconds
625 : << " overtakeTime=" << overtakeTime
626 : << " currentGap=" << neighLead.second
627 : << " secureGap=" << nv->getCarFollowModel().getSecureGap(nv, &myVehicle, nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel())
628 : << "\n";
629 : }
630 : #endif
631 : // no need to pass a message if the neighbor is waiting/stuck anyway (but sending it would risk deadlock)
632 2007100 : if (nv->getWaitingSeconds() <= BLOCKER_IS_BLOCKED_TIME_THRESHOLD) {
633 870751 : msgPass.informNeighLeader(new Info(nv->getSpeed(), dir | LCA_AMBLOCKINGLEADER), &myVehicle);
634 : }
635 2007100 : return -1; // XXX: using -1 is ambiguous for the ballistic update! Currently this is being catched in patchSpeed() (Leo), consider returning INVALID_SPEED, refs. #2577
636 : }
637 : } else { // (remainUnblocked)
638 : // we are not blocked now. make sure we stay far enough from the leader
639 1758370 : const double targetSpeed = MAX2(
640 879185 : myVehicle.getCarFollowModel().minNextSpeed(myVehicle.getSpeed(), &myVehicle),
641 879185 : getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighNextGap, neighNextSpeed, nv->getCarFollowModel().getMaxDecel()));
642 879185 : addLCSpeedAdvice(targetSpeed);
643 : #ifdef DEBUG_INFORMER
644 : if (DEBUG_COND) {
645 : std::cout << " not blocked by leader nv=" << nv->getID()
646 : << " nvSpeed=" << nv->getSpeed()
647 : << " gap=" << neighLead.second
648 : << " neighNextSpeed=" << neighNextSpeed
649 : << " neighNextGap=" << neighNextGap
650 : << " needGap=" << myVehicle.getCarFollowModel().getSecureGap(&myVehicle, nv, myVehicle.getSpeed(), nv->getSpeed(), nv->getCarFollowModel().getMaxDecel())
651 : << " targetSpeed=" << targetSpeed
652 : << "\n";
653 : }
654 : #endif
655 : return MIN2(targetSpeed, plannedSpeed);
656 : }
657 : }
658 :
659 : void
660 2721681 : MSLCM_LC2013::informFollower(MSAbstractLaneChangeModel::MSLCMessager& msgPass,
661 : int blocked,
662 : int dir,
663 : const std::pair<MSVehicle*, double>& neighFollow,
664 : double remainingSeconds,
665 : double plannedSpeed) {
666 :
667 2721681 : MSVehicle* nv = neighFollow.first;
668 2721681 : const double plannedAccel = SPEED2ACCEL(MAX2(MIN2(getCarFollowModel().getMaxAccel(), plannedSpeed - myVehicle.getSpeed()), -getCarFollowModel().getMaxDecel()));
669 :
670 : #ifdef DEBUG_INFORMER
671 : if (DEBUG_COND) {
672 : std::cout << "\nINFORM_FOLLOWER"
673 : << "\nspeed=" << myVehicle.getSpeed() << " planned=" << plannedSpeed << "\n";
674 : }
675 : #endif
676 :
677 : // decide whether we will request help to cut in before the follower or allow to be overtaken
678 : // first check whether the neighbor is even willing to help
679 2721681 : if (nv != nullptr && (nv->getLaneChangeModel().getCooperativeHelpTime() < 0 || myVehicle.getWaitingSeconds() < nv->getLaneChangeModel().getCooperativeHelpTime())) {
680 : // ego vehicle has not been waiting long enough to be eligible for unconditional help
681 2367416 : if (nv->getLaneChangeModel().getCooperativeHelpThreshold() >= 0 && (nv->getSpeed() - plannedSpeed) > nv->getLaneChangeModel().getCooperativeHelpThreshold()) {
682 : // neighhbor not willing to help because ego is much slower
683 : #ifdef DEBUG_INFORMER
684 : if (DEBUG_COND) {
685 : std::cout << "\n nv=" << nv->getID() << " not willing to help because ego is much slower\n";
686 : }
687 : #endif
688 : return;
689 : }
690 2354698 : const double nvLaneMax = nv->getLane()->getVehicleMaxSpeed(nv);
691 2354698 : if (nv->isSelected()) {
692 0 : std::cout << SIMTIME << " ego=" << myVehicle.getID() << " rel=" << nv->getSpeed() / nvLaneMax << " min=" << nv->getLaneChangeModel().getCooperativeMinSpeed() << "\n";
693 : }
694 2354698 : if (nv->getSpeed() / nvLaneMax < nv->getLaneChangeModel().getCooperativeMinSpeed()) {
695 : // neighbor not willing to help because it is already to slow and does not want to disturb the flow
696 : #ifdef DEBUG_INFORMER
697 : if (DEBUG_COND) {
698 : std::cout << "\n nv=" << nv->getID() << " not willing to help because it is already too slow\n";
699 : }
700 : #endif
701 : return;
702 : }
703 : }
704 :
705 2706442 : if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0 && nv != nullptr) {
706 1564652 : if (MSLCHelper::divergentRoute(myVehicle, *nv)) {
707 : //std::cout << SIMTIME << " ego=" << myVehicle.getID() << " ignoresDivergentBlockingFollower=" << nv->getID() << "\n";
708 : return;
709 : }
710 : #ifdef DEBUG_INFORMER
711 : if (DEBUG_COND) {
712 : std::cout << " blocked by follower nv=" << nv->getID() << " nvSpeed=" << nv->getSpeed() << " needGap="
713 : << nv->getCarFollowModel().getSecureGap(nv, &myVehicle, nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel()) << " planned=" << plannedSpeed << "\n";
714 : }
715 : #endif
716 : // are we fast enough to cut in without any help?
717 1564558 : if (MAX2(plannedSpeed, 0.) - nv->getSpeed() >= HELP_OVERTAKE) {
718 89857 : const double neededGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, nv->getSpeed(), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
719 89857 : if ((neededGap - neighFollow.second) / remainingSeconds < (MAX2(plannedSpeed, 0.) - nv->getSpeed())) {
720 : #ifdef DEBUG_INFORMER
721 : if (DEBUG_COND) {
722 : std::cout << " wants to cut in before nv=" << nv->getID() << " without any help." << "\nneededGap = " << neededGap << "\n";
723 : }
724 : #endif
725 : // follower might even accelerate but not to much
726 : // XXX: I don't understand this. The needed gap was determined for nv->getSpeed(), not for (plannedSpeed - HELP_OVERTAKE)?! (Leo), refs. #2578
727 78162 : msgPass.informNeighFollower(new Info(MAX2(plannedSpeed, 0.) - HELP_OVERTAKE, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
728 78162 : return;
729 : }
730 : }
731 :
732 : // PARAMETERS
733 : // assume other vehicle will assume the equivalent of 1 second of
734 : // maximum deceleration to help us (will probably be spread over
735 : // multiple seconds)
736 : // -----------
737 : const double helpDecel = nv->getCarFollowModel().getMaxDecel() * HELP_DECEL_FACTOR;
738 :
739 : // follower's new speed in next step
740 : double neighNewSpeed;
741 : // follower's new speed after 1s.
742 : double neighNewSpeed1s;
743 : // velocity difference, gap after follower-deceleration
744 : double dv, decelGap;
745 :
746 1486396 : if (MSGlobals::gSemiImplicitEulerUpdate) {
747 : // euler
748 1351942 : neighNewSpeed = MAX2(0., nv->getSpeed() - ACCEL2SPEED(helpDecel));
749 1351942 : neighNewSpeed1s = MAX2(0., nv->getSpeed() - helpDecel); // TODO: consider introduction of a configurable anticipationTime here (see far below in the !blocked part). Refs. #2578
750 : // change in the gap between ego and blocker over 1 second (not STEP!)
751 : // XXX: though here it is calculated as if it were one step!? (Leo) Refs. #2578
752 1351942 : dv = plannedSpeed - neighNewSpeed1s; // XXX: what is this quantity (if TS!=1)?
753 : // new gap between follower and self in case the follower does brake for 1s
754 : // XXX: if the step-length is not 1s., this is not the gap after 1s. deceleration!
755 : // And this formula overestimates the real gap. Isn't that problematic? (Leo)
756 : // Below, it seems that decelGap > secureGap is taken to indicate the possibility
757 : // to cut in within the next time-step. However, this is not the case, if TS<1s.,
758 : // since decelGap is (not exactly, though!) the gap after 1s. Refs. #2578
759 1351942 : decelGap = neighFollow.second + dv;
760 : } else {
761 : // ballistic
762 : // negative newSpeed-extrapolation possible, if stop lies within the next time-step
763 : // XXX: this code should work for the euler case as well, since gapExtrapolation() takes
764 : // care of this, but for TS!=1 we will have different behavior (see previous remark) Refs. #2578
765 134454 : neighNewSpeed = nv->getSpeed() - ACCEL2SPEED(helpDecel);
766 134454 : neighNewSpeed1s = nv->getSpeed() - helpDecel;
767 :
768 134454 : dv = myVehicle.getSpeed() - nv->getSpeed(); // current velocity difference
769 268908 : decelGap = getCarFollowModel().gapExtrapolation(1., neighFollow.second, myVehicle.getSpeed(),
770 134454 : nv->getSpeed(), plannedAccel, -helpDecel, myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
771 : }
772 :
773 1486396 : const double secureGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, MAX2(neighNewSpeed1s, 0.),
774 1486396 : MAX2(plannedSpeed, 0.), myVehicle.getCarFollowModel().getMaxDecel());
775 :
776 1486396 : const double onRampThreshold = myVehicle.getLane()->getSpeedLimit() * 0.8 * myExperimentalParam1 * (1 - myVehicle.getImpatience());
777 :
778 : #ifdef DEBUG_INFORMER
779 : if (DEBUG_COND) {
780 : std::cout << SIMTIME
781 : << " speed=" << myVehicle.getSpeed()
782 : << " plannedSpeed=" << plannedSpeed
783 : << " threshold=" << onRampThreshold
784 : << " neighNewSpeed=" << neighNewSpeed
785 : << " neighNewSpeed1s=" << neighNewSpeed1s
786 : << " dv=" << dv
787 : << " gap=" << neighFollow.second
788 : << " decelGap=" << decelGap
789 : << " secureGap=" << secureGap
790 : << "\n";
791 : }
792 : #endif
793 : // prevent vehicles on an on ramp stopping the main flow
794 : if (dir == LCA_MLEFT
795 619491 : && myVehicle.getLane()->isAccelLane()
796 1553199 : && neighNewSpeed1s < onRampThreshold) {
797 : return;
798 : }
799 :
800 1467380 : if (decelGap > 0 && decelGap >= secureGap) {
801 : // XXX: This does not assure that the leader can cut in in the next step if TS < 1 (see above)
802 : // this seems to be supposed in the following (euler code)...?! (Leo) Refs. #2578
803 :
804 : // if the blocking follower brakes it could help
805 : // how hard does it actually need to be?
806 : // to be safe in the next step the following equation has to hold for the follower's vsafe:
807 : // vsafe <= followSpeed(gap=currentGap - SPEED2DIST(vsafe), ...)
808 : double vsafe, vsafe1;
809 :
810 99164 : if (MSGlobals::gSemiImplicitEulerUpdate) {
811 : // euler
812 : // we compute an upper bound on vsafe by doing the computation twice
813 89167 : vsafe1 = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed(
814 89167 : nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed), plannedSpeed, getCarFollowModel().getMaxDecel()));
815 89167 : vsafe = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed(
816 89167 : nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed - vsafe1), plannedSpeed, getCarFollowModel().getMaxDecel()));
817 : //assert(vsafe <= vsafe1); assertion does not hold for models with randomness in followSpeed (W99)
818 : } else {
819 : // ballistic
820 :
821 : // XXX: This block should actually do as well for euler update (TODO: test!), refs #2575
822 : // we compute an upper bound on vsafe
823 : // next step's gap without help deceleration (nv's speed assumed constant)
824 9997 : double nextGap = getCarFollowModel().gapExtrapolation(TS,
825 9997 : neighFollow.second, myVehicle.getSpeed(),
826 9997 : nv->getSpeed(), plannedAccel, 0,
827 9997 : myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
828 : #ifdef DEBUG_INFORMER
829 : if (DEBUG_COND) {
830 : std::cout << "nextGap=" << nextGap << " (without help decel) \n";
831 : }
832 : #endif
833 :
834 : // NOTE: the second argument of MIN2() can get larger than nv->getSpeed()
835 19994 : vsafe1 = MIN2(nv->getSpeed(), MAX2(neighNewSpeed,
836 9997 : nv->getCarFollowModel().followSpeed(nv,
837 9997 : nv->getSpeed(), nextGap,
838 : MAX2(0., plannedSpeed),
839 : getCarFollowModel().getMaxDecel())));
840 :
841 :
842 : // next step's gap with possibly less than maximal help deceleration (in case vsafe1 > neighNewSpeed)
843 9997 : double decel2 = SPEED2ACCEL(nv->getSpeed() - vsafe1);
844 9997 : nextGap = getCarFollowModel().gapExtrapolation(TS,
845 9997 : neighFollow.second, myVehicle.getSpeed(),
846 9997 : nv->getSpeed(), plannedAccel, -decel2,
847 9997 : myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
848 :
849 : // vsafe = MAX(neighNewSpeed, safe speed assuming next_gap)
850 : // Thus, the gap resulting from vsafe is larger or equal to next_gap
851 : // in contrast to the euler case, where nv's follow speed doesn't depend on the actual speed,
852 : // we need to assure, that nv doesn't accelerate
853 19994 : vsafe = MIN2(nv->getSpeed(), MAX2(neighNewSpeed,
854 9997 : nv->getCarFollowModel().followSpeed(nv,
855 9997 : nv->getSpeed(), nextGap,
856 : MAX2(0., plannedSpeed),
857 : getCarFollowModel().getMaxDecel())));
858 :
859 : assert(vsafe >= vsafe1 - NUMERICAL_EPS);
860 :
861 : #ifdef DEBUG_INFORMER
862 : if (DEBUG_COND) {
863 : std::cout << "nextGap=" << nextGap
864 : << " (with vsafe1 and help decel) \nvsafe1=" << vsafe1
865 : << " vsafe=" << vsafe
866 : << "\n";
867 : }
868 : #endif
869 :
870 : // For subsecond simulation, this might not lead to secure gaps for a long time,
871 : // we seek to establish a secure gap as soon as possible
872 9997 : double nextSecureGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, vsafe, plannedSpeed, getCarFollowModel().getMaxDecel());
873 :
874 9997 : if (nextGap < nextSecureGap) {
875 : // establish a secureGap as soon as possible
876 : vsafe = neighNewSpeed;
877 : }
878 :
879 : #ifdef DEBUG_INFORMER
880 : if (DEBUG_COND) {
881 : std::cout << "nextGap=" << nextGap
882 : << " minNextSecureGap=" << nextSecureGap
883 : << " vsafe=" << vsafe << "\n";
884 : }
885 : #endif
886 :
887 : }
888 99164 : msgPass.informNeighFollower(
889 99164 : new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
890 :
891 : #ifdef DEBUG_INFORMER
892 : if (DEBUG_COND) {
893 : std::cout << " wants to cut in before nv=" << nv->getID()
894 : << " vsafe1=" << vsafe1 << " vsafe=" << vsafe
895 : << " newSecGap="
896 : << nv->getCarFollowModel().getSecureGap(nv, &myVehicle, vsafe,
897 : plannedSpeed,
898 : myVehicle.getCarFollowModel().getMaxDecel())
899 : << "\n";
900 : }
901 : #endif
902 1368216 : } else if ((MSGlobals::gSemiImplicitEulerUpdate && dv > 0 && dv * remainingSeconds > (secureGap - decelGap + POSITION_EPS))
903 1289252 : || (!MSGlobals::gSemiImplicitEulerUpdate && dv > 0 && dv * (remainingSeconds - 1) > secureGap - decelGap + POSITION_EPS)
904 : ) {
905 :
906 : // XXX: Alternative formulation (encapsulating differences of euler and ballistic) TODO: test, refs. #2575
907 : // double eventualGap = getCarFollowModel().gapExtrapolation(remainingSeconds - 1., decelGap, plannedSpeed, neighNewSpeed1s);
908 : // } else if (eventualGap > secureGap + POSITION_EPS) {
909 :
910 :
911 : // NOTE: This case corresponds to the situation, where some time is left to perform the lc
912 : // For the ballistic case this is interpreted as follows:
913 : // If the follower breaks with helpDecel for one second, this vehicle maintains the plannedSpeed,
914 : // and both continue with their speeds for remainingSeconds seconds the gap will suffice for a laneChange
915 : // For the euler case we had the following comment:
916 : // 'decelerating once is sufficient to open up a large enough gap in time', but:
917 : // XXX: 1) Decelerating *once* does not necessarily lead to the gap decelGap! (if TS<1s.) (Leo)
918 : // 2) Probably, the if() for euler should test for dv * (remainingSeconds-1) > ..., too ?!, refs. #2578
919 81898 : msgPass.informNeighFollower(new Info(neighNewSpeed, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
920 : #ifdef DEBUG_INFORMER
921 : if (DEBUG_COND) {
922 : std::cout << " wants to cut in before nv=" << nv->getID() << " (eventually)\n";
923 : }
924 : #endif
925 1286318 : } else if (dir == LCA_MRIGHT && nv->getLaneChangeModel().avoidOvertakeRight(&myVehicle)) {
926 : // XXX: check if this requires a special treatment for the ballistic update, refs. #2575
927 : const double vhelp = MAX2(neighNewSpeed, HELP_OVERTAKE);
928 1304 : msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
929 : #ifdef DEBUG_INFORMER
930 : if (DEBUG_COND) {
931 : std::cout << " wants to cut in before nv=" << nv->getID() << " (nv cannot overtake right)\n";
932 : }
933 : #endif
934 : } else {
935 1285014 : double vhelp = MAX2(nv->getSpeed(), myVehicle.getSpeed() + HELP_OVERTAKE);
936 : //if (dir == LCA_MRIGHT && myVehicle.getWaitingSeconds() > LCA_RIGHT_IMPATIENCE &&
937 : // nv->getSpeed() > myVehicle.getSpeed()) {
938 1285014 : if (nv->getSpeed() > myVehicle.getSpeed() &&
939 324820 : ((dir == LCA_MRIGHT && myVehicle.getWaitingSeconds() > LCA_RIGHT_IMPATIENCE) // NOTE: it might be considered to use myVehicle.getAccumulatedWaitingSeconds() > LCA_RIGHT_IMPATIENCE instead (Leo). Refs. #2578
940 240269 : || (dir == LCA_MLEFT && plannedSpeed > CUT_IN_LEFT_SPEED_THRESHOLD) // VARIANT_22 (slowDownLeft)
941 : // XXX this is a hack to determine whether the vehicles is on an on-ramp. This information should be retrieved from the network itself
942 240240 : || (dir == LCA_MLEFT && myVehicle.getLane()->getLength() > MAX_ONRAMP_LENGTH)
943 : )) {
944 : // let the follower slow down to increase the likelihood that later vehicles will be slow enough to help
945 : // follower should still be fast enough to open a gap
946 : // XXX: The probability for that success would be larger if the slow down of the appropriate following vehicle
947 : // would take place without the immediate follower slowing down. We might consider to model reactions of
948 : // vehicles that are not immediate followers. (Leo) -> see ticket #2532
949 377743 : vhelp = MAX2(neighNewSpeed, myVehicle.getSpeed() + HELP_OVERTAKE);
950 : #ifdef DEBUG_INFORMER
951 : if (DEBUG_COND) {
952 : // NOTE: the condition labeled "VARIANT_22" seems to imply that this could as well concern the *left* follower?! (Leo)
953 : // Further, vhelp might be larger than nv->getSpeed(), so the request issued below is not to slow down!? (see below) Refs. #2578
954 : std::cout << " wants right follower to slow down a bit\n";
955 : }
956 : #endif
957 377743 : if (MSGlobals::gSemiImplicitEulerUpdate) {
958 : // euler
959 324780 : if ((nv->getSpeed() - myVehicle.getSpeed()) / helpDecel < remainingSeconds) {
960 :
961 : #ifdef DEBUG_INFORMER
962 : if (DEBUG_COND) {
963 : // NOTE: the condition labeled "VARIANT_22" seems to imply that this could as well concern the *left* follower?! Refs. #2578
964 : std::cout << " wants to cut in before right follower nv=" << nv->getID() << " (eventually)\n";
965 : }
966 : #endif
967 : // XXX: I don't understand. This vhelp might be larger than nv->getSpeed() but the above condition seems to rely
968 : // on the reasoning that if nv breaks with helpDecel for remaining Seconds, nv will be so slow, that this
969 : // vehicle will be able to cut in. But nv might have overtaken this vehicle already (or am I missing sth?). (Leo)
970 : // Ad: To my impression, the intention behind allowing larger speeds for the blocking follower is to prevent a
971 : // situation, where an overlapping follower keeps blocking the ego vehicle. Refs. #2578
972 309477 : msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
973 309477 : return;
974 : }
975 : } else {
976 :
977 : // ballistic (this block is a bit different to the logic in the euler part, but in general suited to work on euler as well.. must be tested <- TODO, refs. #2575)
978 : // estimate gap after remainingSeconds.
979 : // Assumptions:
980 : // (A1) leader continues with currentSpeed. (XXX: That might be wrong: Think of accelerating on an on-ramp or of a congested region ahead!)
981 : // (A2) follower breaks with helpDecel.
982 52963 : const double gapAfterRemainingSecs = getCarFollowModel().gapExtrapolation(
983 52963 : remainingSeconds, neighFollow.second, myVehicle.getSpeed(), nv->getSpeed(), 0, -helpDecel, myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
984 52963 : const double secureGapAfterRemainingSecs = nv->getCarFollowModel().getSecureGap(nv, &myVehicle,
985 52963 : MAX2(nv->getSpeed() - remainingSeconds * helpDecel, 0.), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel());
986 52963 : if (gapAfterRemainingSecs >= secureGapAfterRemainingSecs) { // XXX: here it would be wise to check whether there is enough space for eventual braking if the maneuver doesn't succeed
987 : #ifdef DEBUG_INFORMER
988 : if (DEBUG_COND) {
989 : std::cout << " wants to cut in before follower nv=" << nv->getID() << " (eventually)\n";
990 : }
991 : #endif
992 : // NOTE: ballistic uses neighNewSpeed instead of vhelp, see my note above. (Leo)
993 : // TODO: recheck if this might cause suboptimal behaviour in some LC-situations. Refs. #2578
994 9263 : msgPass.informNeighFollower(new Info(neighNewSpeed, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
995 9263 : return;
996 : }
997 : }
998 :
999 :
1000 : }
1001 :
1002 : #ifdef DEBUG_INFORMER
1003 : if (DEBUG_COND) {
1004 : std::cout << SIMTIME
1005 : << " veh=" << myVehicle.getID()
1006 : << " informs follower " << nv->getID()
1007 : << " vhelp=" << vhelp
1008 : << "\n";
1009 : }
1010 : #endif
1011 :
1012 966274 : msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
1013 : // This follower is supposed to overtake us. Slow down smoothly to allow this.
1014 966274 : const double overtakeDist = overtakeDistance(nv, &myVehicle, neighFollow.second, vhelp, plannedSpeed);
1015 : // speed difference to create a sufficiently large gap
1016 966274 : const double needDV = overtakeDist / remainingSeconds;
1017 : // make sure the deceleration is not to strong (XXX: should be assured in finalizeSpeed -> TODO: remove the MAX2 if agreed) -> prob with possibly non-existing maximal deceleration for som CF Models(?) Refs. #2578
1018 1074790 : addLCSpeedAdvice(MAX2(vhelp - needDV, myVehicle.getSpeed() - ACCEL2SPEED(myVehicle.getCarFollowModel().getMaxDecel())));
1019 :
1020 : #ifdef DEBUG_INFORMER
1021 : if (DEBUG_COND) {
1022 : std::cout << SIMTIME
1023 : << " veh=" << myVehicle.getID()
1024 : << " wants to be overtaken by=" << nv->getID()
1025 : << " overtakeDist=" << overtakeDist
1026 : << " vneigh=" << nv->getSpeed()
1027 : << " vhelp=" << vhelp
1028 : << " needDV=" << needDV
1029 : << " vsafe=" << myLCAccelerationAdvices.back().first
1030 : << "\n";
1031 : }
1032 : #endif
1033 : }
1034 1141790 : } else if (neighFollow.first != nullptr && (blocked & LCA_BLOCKED_BY_LEADER)) {
1035 : // we are not blocked by the follower now, make sure it remains that way
1036 590440 : const double vsafe = MSLCHelper::getSpeedPreservingSecureGap(myVehicle, *neighFollow.first, neighFollow.second, plannedSpeed);
1037 590440 : msgPass.informNeighFollower(new Info(vsafe, dir), &myVehicle);
1038 :
1039 : #ifdef DEBUG_INFORMER
1040 : if (DEBUG_COND) {
1041 : std::cout << " wants to cut in before non-blocking follower nv=" << nv->getID() << "\n";
1042 : }
1043 : #endif
1044 : }
1045 : }
1046 :
1047 :
1048 : void
1049 546569898 : MSLCM_LC2013::prepareStep() {
1050 546569898 : MSAbstractLaneChangeModel::prepareStep();
1051 : // keep information about strategic change direction
1052 546569898 : if (!isChangingLanes()) {
1053 546026885 : myOwnState = (myOwnState & LCA_STRATEGIC) ? (myOwnState & LCA_WANTS_LANECHANGE) : 0;
1054 : }
1055 546569898 : myLeadingBlockerLength = 0;
1056 546569898 : myLeftSpace = 0;
1057 : myLCAccelerationAdvices.clear();
1058 546569898 : myDontBrake = false;
1059 : // truncate to work around numerical instability between different builds
1060 546569898 : if (mySigma > 0 && !isChangingLanes()) {
1061 : // disturb lateral position directly
1062 1154 : const double maxDist = SPEED2DIST(myVehicle.getVehicleType().getMaxSpeedLat());
1063 1154 : const double oldPosLat = myVehicle.getLateralPositionOnLane();
1064 1154 : const double overlap = myVehicle.getLateralOverlap();
1065 : double scaledDelta;
1066 1154 : if (overlap > 0) {
1067 : // return to within lane boundary
1068 : scaledDelta = MIN2(overlap, maxDist);
1069 23 : if (myVehicle.getLateralPositionOnLane() > 0) {
1070 7 : scaledDelta *= -1;
1071 : }
1072 : } else {
1073 : // random drift
1074 1131 : double deltaPosLat = OUProcess::step(oldPosLat,
1075 1131 : myVehicle.getActionStepLengthSecs(),
1076 1131 : MAX2(NUMERICAL_EPS, (1 - mySigma) * 100), mySigma) - oldPosLat;
1077 1131 : deltaPosLat = MAX2(MIN2(deltaPosLat, maxDist), -maxDist);
1078 1131 : scaledDelta = deltaPosLat * myVehicle.getSpeed() / myVehicle.getLane()->getSpeedLimit();
1079 : }
1080 1154 : myVehicle.setLateralPositionOnLane(oldPosLat + scaledDelta);
1081 1154 : setSpeedLat(DIST2SPEED(scaledDelta));
1082 : } else {
1083 546568744 : resetSpeedLat();
1084 : }
1085 546569898 : }
1086 :
1087 :
1088 : void
1089 306812201 : MSLCM_LC2013::changed() {
1090 306812201 : myOwnState = 0;
1091 306812201 : mySpeedGainProbabilityLeft = 0;
1092 306812201 : mySpeedGainProbabilityRight = 0;
1093 306812201 : myKeepRightProbability = 0;
1094 306812201 : if (myVehicle.getBestLaneOffset() == 0) {
1095 : // if we are not yet on our best lane there might still be unseen blockers
1096 : // (during patchSpeed)
1097 306685688 : myLeadingBlockerLength = 0;
1098 306685688 : myLeftSpace = 0;
1099 : }
1100 306812201 : myLookAheadSpeed = LOOK_AHEAD_MIN_SPEED;
1101 : myLCAccelerationAdvices.clear();
1102 306812201 : myDontBrake = false;
1103 306812201 : myLeadingBlockerLength = 0;
1104 306812201 : }
1105 :
1106 :
1107 : void
1108 8235 : MSLCM_LC2013::resetState() {
1109 8235 : myOwnState = 0;
1110 8235 : mySpeedGainProbabilityLeft = 0;
1111 8235 : mySpeedGainProbabilityRight = 0;
1112 8235 : myKeepRightProbability = 0;
1113 8235 : myLeadingBlockerLength = 0;
1114 8235 : myLeftSpace = 0;
1115 8235 : myLookAheadSpeed = LOOK_AHEAD_MIN_SPEED;
1116 : myLCAccelerationAdvices.clear();
1117 8235 : myDontBrake = false;
1118 8235 : }
1119 :
1120 :
1121 : int
1122 241465841 : MSLCM_LC2013::_wantsChange(
1123 : int laneOffset,
1124 : MSAbstractLaneChangeModel::MSLCMessager& msgPass,
1125 : int blocked,
1126 : const std::pair<MSVehicle*, double>& leader,
1127 : const std::pair<MSVehicle*, double>& follower,
1128 : const std::pair<MSVehicle*, double>& neighLead,
1129 : const std::pair<MSVehicle*, double>& neighFollow,
1130 : const MSLane& neighLane,
1131 : const std::vector<MSVehicle::LaneQ>& preb,
1132 : MSVehicle* lastBlocked,
1133 : MSVehicle* firstBlocked) {
1134 : assert(laneOffset == 1 || laneOffset == -1);
1135 241465841 : const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
1136 : // compute bestLaneOffset
1137 : MSVehicle::LaneQ curr, neigh, best;
1138 : int bestLaneOffset = 0;
1139 : // What do these "dists" mean? Please comment. (Leo) Ad: I now think the following:
1140 : // currentDist is the distance that the vehicle can go on its route without having to
1141 : // change lanes from the current lane. neighDist as currentDist for the considered target lane (i.e., neigh)
1142 : // If this is true I suggest to put this into the docu of wantsChange()
1143 : double currentDist = 0;
1144 : double neighDist = 0;
1145 : int currIdx = 0;
1146 241465841 : const bool checkOpposite = &neighLane.getEdge() != &myVehicle.getLane()->getEdge();
1147 241465841 : const MSLane* prebLane = myVehicle.getLane();
1148 241465841 : if (prebLane->getEdge().isInternal()) {
1149 : // internal edges are not kept inside the bestLanes structure
1150 1200174 : if (isOpposite()) {
1151 567 : prebLane = prebLane->getNormalPredecessorLane();
1152 : } else {
1153 1199607 : prebLane = prebLane->getLinkCont()[0]->getLane();
1154 : }
1155 : }
1156 : // special case: vehicle considers changing to the opposite direction edge
1157 : const int prebOffset = laneOffset;
1158 422645920 : for (int p = 0; p < (int) preb.size(); ++p) {
1159 : //if (DEBUG_COND) {
1160 : // std::cout << " p=" << p << " prebLane=" << prebLane->getID() << " preb.p=" << preb[p].lane->getID() << "\n";
1161 : //}
1162 422645920 : if (preb[p].lane == prebLane && p + laneOffset >= 0) {
1163 : assert(p + prebOffset < (int)preb.size());
1164 : curr = preb[p];
1165 241465841 : neigh = preb[p + prebOffset];
1166 241465841 : currentDist = curr.length;
1167 241465841 : neighDist = neigh.length;
1168 241465841 : bestLaneOffset = curr.bestLaneOffset;
1169 241465841 : if (bestLaneOffset == 0 && preb[p + prebOffset].bestLaneOffset == 0 && !checkOpposite) {
1170 : #ifdef DEBUG_WANTS_CHANGE
1171 : if (DEBUG_COND) {
1172 : std::cout << STEPS2TIME(currentTime)
1173 : << " veh=" << myVehicle.getID()
1174 : << " bestLaneOffsetOld=" << bestLaneOffset
1175 : << " bestLaneOffsetNew=" << laneOffset
1176 : << "\n";
1177 : }
1178 : #endif
1179 : bestLaneOffset = prebOffset;
1180 : }
1181 241465841 : best = preb[p + bestLaneOffset];
1182 : currIdx = p;
1183 : break;
1184 : }
1185 : }
1186 : assert(curr.lane != nullptr);
1187 : assert(neigh.lane != nullptr);
1188 : assert(best.lane != nullptr);
1189 : // direction specific constants
1190 241465841 : const bool right = (laneOffset == -1);
1191 241465841 : const double posOnLane = getForwardPos();
1192 : double driveToNextStop = -std::numeric_limits<double>::max();
1193 241465841 : if (myVehicle.nextStopDist() < std::numeric_limits<double>::max()
1194 241465841 : && &myVehicle.getNextStop().lane->getEdge() == &myVehicle.getLane()->getEdge()) {
1195 : // vehicle can always drive up to stop distance
1196 : // @note this information is dynamic and thus not available in updateBestLanes()
1197 : // @note: nextStopDist was compute before the vehicle moved
1198 1763313 : driveToNextStop = myVehicle.nextStopDist();
1199 1763313 : const double stopPos = posOnLane + myVehicle.nextStopDist() - myVehicle.getLastStepDist();
1200 : #ifdef DEBUG_WANTS_CHANGE
1201 : if (DEBUG_COND) {
1202 : std::cout << SIMTIME << std::setprecision(gPrecision) << " veh=" << myVehicle.getID()
1203 : << " stopDist=" << myVehicle.nextStopDist()
1204 : << " lastDist=" << myVehicle.getLastStepDist()
1205 : << " stopPos=" << stopPos
1206 : << " currentDist=" << currentDist
1207 : << " neighDist=" << neighDist
1208 : << "\n";
1209 : }
1210 : #endif
1211 : currentDist = MAX2(currentDist, stopPos);
1212 : neighDist = MAX2(neighDist, stopPos);
1213 : }
1214 241465841 : const int lca = (right ? LCA_RIGHT : LCA_LEFT);
1215 : const int myLca = (right ? LCA_MRIGHT : LCA_MLEFT);
1216 : const int lcaCounter = (right ? LCA_LEFT : LCA_RIGHT);
1217 241465841 : bool changeToBest = (right && bestLaneOffset < 0) || (!right && bestLaneOffset > 0);
1218 : // keep information about being a leader/follower
1219 241465841 : int ret = (myOwnState & 0xffff0000);
1220 : int req = 0; // the request to change or stay
1221 :
1222 241465841 : ret = slowDownForBlocked(lastBlocked, ret);
1223 241465841 : if (lastBlocked != firstBlocked) {
1224 7732419 : ret = slowDownForBlocked(firstBlocked, ret);
1225 : }
1226 :
1227 : #ifdef DEBUG_WANTS_CHANGE
1228 : if (DEBUG_COND) {
1229 : std::cout << SIMTIME
1230 : << " veh=" << myVehicle.getID()
1231 : << " _wantsChange state=" << myOwnState
1232 : << " myLCAccelerationAdvices=" << toString(myLCAccelerationAdvices)
1233 : << " firstBlocked=" << Named::getIDSecure(firstBlocked)
1234 : << " lastBlocked=" << Named::getIDSecure(lastBlocked)
1235 : << " leader=" << Named::getIDSecure(leader.first)
1236 : << " leaderGap=" << leader.second
1237 : << " follower=" << Named::getIDSecure(follower.first)
1238 : << " followerGap=" << follower.second
1239 : << " neighLead=" << Named::getIDSecure(neighLead.first)
1240 : << " neighLeadGap=" << neighLead.second
1241 : << " neighFollow=" << Named::getIDSecure(neighFollow.first)
1242 : << " neighFollowGap=" << neighFollow.second
1243 : << "\n";
1244 : }
1245 : #endif
1246 :
1247 : // we try to estimate the distance which is necessary to get on a lane
1248 : // we have to get on in order to keep our route
1249 : // we assume we need something that depends on our velocity
1250 : // and compare this with the free space on our wished lane
1251 : //
1252 : // if the free space is somehow(<-?) less than the space we need, we should
1253 : // definitely try to get to the desired lane
1254 : //
1255 : // this rule forces our vehicle to change the lane if a lane changing is necessary soon
1256 :
1257 :
1258 : // we do not want the lookahead distance to change all the time so we let it decay slowly
1259 : // (in contrast, growth is applied instantaneously)
1260 241465841 : if (myVehicle.getSpeed() > myLookAheadSpeed) {
1261 41046376 : myLookAheadSpeed = myVehicle.getSpeed();
1262 : } else {
1263 : // memory decay factor for this action step
1264 200419465 : const double memoryFactor = 1. - (1. - LOOK_AHEAD_SPEED_MEMORY) * myVehicle.getActionStepLengthSecs();
1265 : assert(memoryFactor > 0.);
1266 200419465 : myLookAheadSpeed = MAX2(LOOK_AHEAD_MIN_SPEED,
1267 200419465 : (memoryFactor * myLookAheadSpeed + (1 - memoryFactor) * myVehicle.getSpeed()));
1268 : }
1269 241465841 : double laDist = myLookAheadSpeed * LOOK_FORWARD * myStrategicParam * (right ? 1 : myLookaheadLeft);
1270 241465841 : laDist += myVehicle.getVehicleType().getLengthWithGap() * 2.;
1271 241465841 : const bool hasStoppedLeader = leader.first != 0 && leader.first->isStopped() && leader.second < (currentDist - posOnLane);
1272 241465841 : const bool hasBidiLeader = myVehicle.getLane()->getBidiLane() != nullptr && MSLCHelper::isBidiLeader(leader.first, curr.bestContinuations);
1273 241465841 : const bool hasBidiNeighLeader = neighLane.getBidiLane() != nullptr && MSLCHelper::isBidiLeader(neighLead.first, neigh.bestContinuations);
1274 :
1275 241465841 : if (bestLaneOffset == 0 && hasBidiLeader) {
1276 : // getting out of the way is enough to clear the blockage
1277 : laDist = 0;
1278 241464754 : } else if (bestLaneOffset == 0 && hasStoppedLeader) {
1279 : // react to a stopped leader on the current lane
1280 : // The value of laDist is doubled below for the check whether the lc-maneuver can be taken out
1281 : // on the remaining distance (because the vehicle has to change back and forth). Therefore multiply with 0.5.
1282 79320 : laDist = 0.5 * (myVehicle.getVehicleType().getLengthWithGap()
1283 79320 : + leader.first->getVehicleType().getLengthWithGap()
1284 79320 : + leader.second);
1285 241385434 : } else if (bestLaneOffset == laneOffset && neighLead.first != 0 && (neighLead.first->isStopped() || hasBidiNeighLeader) && neighLead.second < (currentDist - posOnLane)) {
1286 : // react to a stopped leader on the target lane (if it is the bestLane)
1287 285056 : if (isOpposite()) {
1288 : // always allow changing back
1289 51398 : laDist = (myVehicle.getVehicleType().getLengthWithGap()
1290 51398 : + neighLead.first->getVehicleType().getLengthWithGap()
1291 51398 : + neighLead.second);
1292 233658 : } else if (!hasStoppedLeader &&
1293 214095 : ((neighLead.second + myVehicle.getVehicleType().getLengthWithGap() + neighLead.first->getVehicleType().getLengthWithGap()) < (currentDist - posOnLane)
1294 6306 : || hasBidiNeighLeader)) {
1295 : // do not change to the target lane until passing the stopped vehicle
1296 : // (unless the vehicle blocks our intended stopping position, then we have to wait anyway)
1297 : changeToBest = false;
1298 : }
1299 : }
1300 241465841 : if (myStrategicParam < 0) {
1301 : laDist = -1e3; // never perform strategic change
1302 : }
1303 :
1304 : // free space that is available for changing
1305 : //const double neighSpeed = (neighLead.first != 0 ? neighLead.first->getSpeed() :
1306 : // neighFollow.first != 0 ? neighFollow.first->getSpeed() :
1307 : // best.lane->getSpeedLimit());
1308 : // @note: while this lets vehicles change earlier into the correct direction
1309 : // it also makes the vehicles more "selfish" and prevents changes which are necessary to help others
1310 :
1311 :
1312 :
1313 : // Next we assign to roundabout edges a larger distance than to normal edges
1314 : // in order to decrease sense of lc urgency and induce higher usage of inner roundabout lanes.
1315 241465841 : const double roundaboutBonus = MSLCHelper::getRoundaboutDistBonus(myVehicle, myRoundaboutBonus, curr, neigh, best);
1316 241465841 : currentDist += roundaboutBonus;
1317 241465841 : neighDist += roundaboutBonus;
1318 :
1319 241465841 : const double usableDist = MAX2(currentDist - posOnLane - best.occupation * JAM_FACTOR, driveToNextStop);
1320 : //- (best.lane->getVehicleNumber() * neighSpeed)); // VARIANT 9 jfSpeed
1321 241465841 : const double maxJam = MAX2(preb[currIdx + prebOffset].occupation, preb[currIdx].occupation);
1322 241465841 : const double vMax = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
1323 241465841 : const double neighVMax = neighLane.getVehicleMaxSpeed(&myVehicle);
1324 : // upper bound which will be restricted successively
1325 241465841 : double thisLaneVSafe = vMax;
1326 241465841 : const bool checkOverTakeRight = avoidOvertakeRight(neighLead.first, true);
1327 :
1328 241465841 : double neighLeftPlace = MAX2(0.0, neighDist - posOnLane - maxJam);
1329 241465841 : if (neighLead.first != 0 && neighLead.first->isStopped()) {
1330 242891 : neighLeftPlace = MIN2(neighLeftPlace, neighLead.second);
1331 : }
1332 :
1333 : #ifdef DEBUG_WANTS_CHANGE
1334 : if (DEBUG_COND) {
1335 : std::cout << STEPS2TIME(currentTime)
1336 : << " veh=" << myVehicle.getID()
1337 : << " laSpeed=" << myLookAheadSpeed
1338 : << " laDist=" << laDist
1339 : << " currentDist=" << currentDist
1340 : << " usableDist=" << usableDist
1341 : << " bestLaneOffset=" << bestLaneOffset
1342 : << " best.occupation=" << best.occupation
1343 : << " best.length=" << best.length
1344 : << "\n roundaboutBonus=" << roundaboutBonus
1345 : << " maxJam=" << maxJam
1346 : << " neighDist=" << neighDist
1347 : << " neighLeftPlace=" << neighLeftPlace
1348 : << (hasBidiLeader ? " bidiLeader" : "")
1349 : << (hasBidiNeighLeader ? " bidiNeighLeader" : "")
1350 : << "\n";
1351 : }
1352 : #endif
1353 :
1354 : bool changeLeftToAvoidOvertakeRight = false;
1355 195203240 : if (changeToBest && bestLaneOffset == curr.bestLaneOffset
1356 252721390 : && currentDistDisallows(usableDist, bestLaneOffset, laDist)) {
1357 : /// @brief we urgently need to change lanes to follow our route
1358 4675186 : ret = ret | lca | LCA_STRATEGIC | LCA_URGENT;
1359 : } else {
1360 : // VARIANT_20 (noOvertakeRight)
1361 236790655 : if (neighLead.first != 0 && checkOverTakeRight && !right) {
1362 : // check for slower leader on the left. we should not overtake but
1363 : // rather move left ourselves (unless congested)
1364 : const MSVehicle* nv = neighLead.first;
1365 12016604 : double deltaV = 0.;
1366 12016604 : double vSafe = 0.;
1367 12016604 : if (canOvertakeRight(nv, neighLead.second, vMax - neighLane.getVehicleMaxSpeed(nv), HELP_OVERTAKE, vSafe, deltaV)) {
1368 2316949 : if (mySpeedGainProbabilityLeft < myChangeProbThresholdLeft) {
1369 2476789 : vSafe = MAX2(vSafe, nv->getSpeed());
1370 : }
1371 2316949 : thisLaneVSafe = MIN2(thisLaneVSafe, vSafe);
1372 2316949 : addLCSpeedAdvice(vSafe);
1373 : // only generate impulse for overtaking left shortly before braking would be necessary
1374 2316949 : const double deltaGapFuture = deltaV * 8;
1375 2316949 : const double vSafeFuture = getCarFollowModel().followSpeed(
1376 2316949 : &myVehicle, myVehicle.getSpeed(), neighLead.second - deltaGapFuture, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel());
1377 2316949 : if (vSafeFuture < vSafe) {
1378 1900314 : const double relativeGain = deltaV / MAX2(vMax,
1379 1900314 : RELGAIN_NORMALIZATION_MIN_SPEED);
1380 1900314 : mySpeedGainProbabilityLeft += (long long int)(myVehicle.getActionStepLengthSecs() * relativeGain * HYST_PRECISION);
1381 : changeLeftToAvoidOvertakeRight = true;
1382 : }
1383 : #ifdef DEBUG_WANTS_CHANGE
1384 : if (DEBUG_COND) {
1385 : std::cout << STEPS2TIME(currentTime)
1386 : << " avoid overtaking on the right nv=" << nv->getID()
1387 : << " deltaV=" << deltaV
1388 : << " nvSpeed=" << nv->getSpeed()
1389 : << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1390 : << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1391 : << " planned acceleration =" << myLCAccelerationAdvices.back().first
1392 : << "\n";
1393 : }
1394 : #endif
1395 : }
1396 : }
1397 236790655 : const bool currFreeUntilNeighEnd = leader.first == nullptr || neighDist - posOnLane <= leader.second;
1398 457700433 : const double overtakeDist = (leader.first == 0 || hasBidiLeader ? -1 :
1399 220909778 : leader.second + myVehicle.getVehicleType().getLength() + leader.first->getVehicleType().getLengthWithGap());
1400 237029401 : const double overtakeDist2 = (neighLead.first == 0 || !neighLead.first->isStopped() ? -1 :
1401 238746 : neighLead.second + myVehicle.getVehicleType().getLength() + neighLead.first->getVehicleType().getLengthWithGap());
1402 220914372 : if (leader.first != 0 && (leader.first->isStopped() || hasBidiLeader) && leader.second < REACT_TO_STOPPED_DISTANCE
1403 : // current destination leaves enough space to overtake the leader
1404 121684 : && MIN2(neighDist, currentDist) - posOnLane > overtakeDist
1405 : // maybe do not overtake on the right at high speed
1406 78434 : && (!checkOverTakeRight || !right)
1407 76744 : && myStrategicParam >= 0
1408 236866811 : && (neighLead.first == 0 || !neighLead.first->isStopped()
1409 : // neighboring stopped vehicle leaves enough space to overtake leader
1410 21438 : || neighLead.second > overtakeDist
1411 : // if we cannot pass neighLead before reaching leader we must find another free lane
1412 18600 : || (overtakeDist2 > leader.second && hasFreeLane(laneOffset, neighLead)))) {
1413 : // avoid becoming stuck behind a stopped leader
1414 58060 : currentDist = myVehicle.getPositionOnLane() + leader.second;
1415 : #ifdef DEBUG_WANTS_CHANGE
1416 : if (DEBUG_COND) {
1417 : std::cout << " veh=" << myVehicle.getID() << " overtake stopped leader=" << leader.first->getID()
1418 : << " overtakeDist=" << overtakeDist
1419 : << " overtakeDist2=" << overtakeDist
1420 : << " hasFreeLane=" << hasFreeLane(laneOffset, neighLead)
1421 : << " remaining=" << MIN2(neighDist, currentDist) - posOnLane
1422 : << "\n";
1423 : }
1424 : #endif
1425 58060 : ret = ret | lca | LCA_STRATEGIC | LCA_URGENT;
1426 236732595 : } else if (!changeToBest && currentDistDisallows(neighLeftPlace, abs(bestLaneOffset) + 2, laDist) && !hasBidiLeader) {
1427 : // the opposite lane-changing direction should be done than the one examined herein
1428 : // we'll check whether we assume we could change anyhow and get back in time...
1429 : //
1430 : // this rule prevents the vehicle from moving in opposite direction of the best lane
1431 : // unless the way till the end where the vehicle has to be on the best lane
1432 : // is long enough
1433 : #ifdef DEBUG_WANTS_CHANGE
1434 : if (DEBUG_COND) {
1435 : std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (1) neighLeftPlace=" << neighLeftPlace << "\n";
1436 : }
1437 : #endif
1438 41727963 : ret = ret | LCA_STAY | LCA_STRATEGIC;
1439 195004632 : } else if (bestLaneOffset == 0 && (neighLeftPlace * 2. < laDist)) {
1440 : // the current lane is the best and a lane-changing would cause a situation
1441 : // of which we assume we will not be able to return to the lane we have to be on.
1442 : // this rule prevents the vehicle from leaving the current, best lane when it is
1443 : // close to this lane's end
1444 : #ifdef DEBUG_WANTS_CHANGE
1445 : if (DEBUG_COND) {
1446 : std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (2) neighLeftPlace=" << neighLeftPlace << "\n";
1447 : }
1448 : #endif
1449 0 : ret = ret | LCA_STAY | LCA_STRATEGIC;
1450 : } else if (bestLaneOffset == 0
1451 4059509 : && (leader.first == 0 || !leader.first->isStopped())
1452 4050054 : && !hasBidiLeader
1453 4050051 : && neigh.bestContinuations.back()->getLinkCont().size() != 0
1454 2393927 : && roundaboutBonus == 0
1455 907759 : && !checkOpposite
1456 803214 : && ((myStrategicParam >= 0 && neighDist < TURN_LANE_DIST)
1457 : // lane changing cannot possibly help
1458 753346 : || (myStrategicParam < 0 && currFreeUntilNeighEnd))
1459 : ) {
1460 : // VARIANT_21 (stayOnBest)
1461 : // we do not want to leave the best lane for a lane which leads elsewhere
1462 : // unless our leader is stopped or we are approaching a roundabout
1463 : #ifdef DEBUG_WANTS_CHANGE
1464 : if (DEBUG_COND) {
1465 : std::cout << " veh=" << myVehicle.getID() << " does not want to leave the bestLane (neighDist=" << neighDist << ")\n";
1466 : }
1467 : #endif
1468 49951 : ret = ret | LCA_STAY | LCA_STRATEGIC;
1469 : }
1470 : }
1471 : // check for overriding TraCI requests
1472 : #ifdef DEBUG_WANTS_CHANGE
1473 : if (DEBUG_COND) {
1474 : std::cout << STEPS2TIME(currentTime) << " veh=" << myVehicle.getID() << " ret=" << toString((LaneChangeAction)ret);
1475 : }
1476 : #endif
1477 : // store state before canceling
1478 241465841 : getCanceledState(laneOffset) |= ret | blocked;
1479 241465841 : ret = myVehicle.influenceChangeDecision(ret);
1480 241465841 : if ((ret & lcaCounter) != 0) {
1481 : // we are not interested in traci requests for the opposite direction here
1482 27 : ret &= ~(LCA_TRACI | lcaCounter | LCA_URGENT);
1483 : }
1484 : #ifdef DEBUG_WANTS_CHANGE
1485 : if (DEBUG_COND) {
1486 : std::cout << " retAfterInfluence=" << toString((LaneChangeAction)ret) << "\n";
1487 : }
1488 : #endif
1489 :
1490 241465841 : if ((ret & LCA_STAY) != 0) {
1491 : // remove TraCI flags because it should not be included in "state-without-traci"
1492 41856479 : ret = getCanceledState(laneOffset);
1493 41856479 : return ret;
1494 : }
1495 199609362 : if ((ret & LCA_URGENT) != 0) {
1496 : // prepare urgent lane change maneuver
1497 : // save the left space
1498 4732962 : myLeftSpace = currentDist - posOnLane;
1499 4732962 : if (changeToBest && abs(bestLaneOffset) > 1 && myVehicle.getNumRemainingEdges() > 1) {
1500 : // there might be a vehicle which needs to counter-lane-change one lane further and we cannot see it yet
1501 748656 : myLeadingBlockerLength = MAX2(getExtraReservation(bestLaneOffset, neighDist - currentDist), myLeadingBlockerLength);
1502 : #ifdef DEBUG_SAVE_BLOCKER_LENGTH
1503 : if (DEBUG_COND) {
1504 : std::cout << " reserving space for unseen blockers myLeadingBlockerLength=" << myLeadingBlockerLength << "\n";
1505 : }
1506 : #endif
1507 : }
1508 :
1509 : // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1
1510 : // if there is a leader and he wants to change to the opposite direction
1511 4732962 : const bool canContinue = curr.bestContinuations.size() > 1;
1512 4732962 : bool canReserve = MSLCHelper::updateBlockerLength(myVehicle, neighLead.first, lcaCounter, myLeftSpace - POSITION_EPS, canContinue, myLeadingBlockerLength);
1513 4732962 : if (firstBlocked != neighLead.first) {
1514 4472950 : canReserve &= MSLCHelper::updateBlockerLength(myVehicle, firstBlocked, lcaCounter, myLeftSpace - POSITION_EPS, canContinue, myLeadingBlockerLength);
1515 : }
1516 : #ifdef DEBUG_SAVE_BLOCKER_LENGTH
1517 : if (DEBUG_COND) {
1518 : std::cout << SIMTIME << " canReserve=" << canReserve << " canContinue=" << canContinue << "\n";
1519 : }
1520 : #endif
1521 4732962 : if (!canReserve && !isOpposite()) {
1522 : // we have a low-priority relief connection
1523 : // std::cout << SIMTIME << " veh=" << myVehicle.getID() << " cannotReserve for blockers\n";
1524 12361 : myDontBrake = canContinue;
1525 : }
1526 :
1527 4732962 : const int remainingLanes = MAX2(1, abs(bestLaneOffset));
1528 4732962 : const double urgency = isOpposite() ? OPPOSITE_URGENCY : URGENCY;
1529 4732962 : const double remainingSeconds = ((ret & LCA_TRACI) == 0 ?
1530 : //MAX2(STEPS2TIME(TS), (myLeftSpace-myLeadingBlockerLength) / MAX2(myLookAheadSpeed, NUMERICAL_EPS) / remainingLanes / urgency) :
1531 4972625 : MAX2(STEPS2TIME(TS), myLeftSpace / MAX2(myLookAheadSpeed, NUMERICAL_EPS) / remainingLanes / urgency) :
1532 180 : myVehicle.getInfluencer().changeRequestRemainingSeconds(currentTime));
1533 4732962 : if (!hasBidiNeighLeader) {
1534 4732871 : const double plannedSpeed = informLeader(msgPass, blocked, myLca, neighLead, remainingSeconds);
1535 : // NOTE: for the ballistic update case negative speeds may indicate a stop request,
1536 : // while informLeader returns -1 in that case. Refs. #2577
1537 4732871 : if (plannedSpeed >= 0 || (!MSGlobals::gSemiImplicitEulerUpdate && plannedSpeed != -1)) {
1538 : // maybe we need to deal with a blocking follower
1539 2725740 : const bool hasBidiNeighFollower = neighLane.getBidiLane() != nullptr && MSLCHelper::isBidiFollower(&myVehicle, neighFollow.first);
1540 : if (!hasBidiNeighFollower) {
1541 2721681 : informFollower(msgPass, blocked, myLca, neighFollow, remainingSeconds, plannedSpeed);
1542 : }
1543 : }
1544 : #ifdef DEBUG_WANTS_CHANGE
1545 : if (DEBUG_COND) {
1546 : std::cout << STEPS2TIME(currentTime)
1547 : << " veh=" << myVehicle.getID()
1548 : << " myLeftSpace=" << myLeftSpace
1549 : << " remainingSeconds=" << remainingSeconds
1550 : << " plannedSpeed=" << plannedSpeed
1551 : << "\n";
1552 : }
1553 : #endif
1554 : } else {
1555 : #ifdef DEBUG_WANTS_CHANGE
1556 : if (DEBUG_COND) {
1557 : std::cout << STEPS2TIME(currentTime)
1558 : << " veh=" << myVehicle.getID()
1559 : << " myLeftSpace=" << myLeftSpace
1560 : << " remainingSeconds=" << remainingSeconds
1561 : << " hasBidiNeighLeader\n";
1562 : }
1563 : #endif
1564 : }
1565 :
1566 :
1567 : // remove TraCI flags because it should not be included in "state-without-traci"
1568 4732962 : ret = getCanceledState(laneOffset);
1569 4732962 : return ret;
1570 : }
1571 :
1572 : // we wish to anticipate future speeds. This is difficult when the leading
1573 : // vehicles are still accelerating so we resort to comparing speeds for the near future (1s) in this case
1574 182966946 : const bool acceleratingLeader = (neighLead.first != 0 && neighLead.first->getAcceleration() > 0)
1575 285029593 : || (leader.first != 0 && leader.first->getAcceleration() > 0);
1576 194876400 : double neighLaneVSafe = MIN2(neighVMax, anticipateFollowSpeed(neighLead, neighDist, neighVMax, acceleratingLeader));
1577 194876400 : thisLaneVSafe = MIN2(thisLaneVSafe, anticipateFollowSpeed(leader, currentDist, vMax, acceleratingLeader));
1578 : //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " thisLaneVSafe=" << thisLaneVSafe << " neighLaneVSafe=" << neighLaneVSafe << "\n";
1579 :
1580 :
1581 : // a high inconvenience prevents cooperative changes and the following things are inconvenient:
1582 : // - a desire to change in the opposite direction for speedGain
1583 : // - low anticipated speed on the neighboring lane
1584 : // - high occupancy on the neighboring lane while in a roundabout
1585 :
1586 : double inconvenience = laneOffset < 0
1587 194876400 : ? (double)mySpeedGainProbabilityLeft / (double)myChangeProbThresholdRight
1588 100801482 : : (double)mySpeedGainProbabilityRight / (double)myChangeProbThresholdLeft;
1589 :
1590 251017334 : const double relSpeedDiff = thisLaneVSafe == 0 ? 0 : (thisLaneVSafe - neighLaneVSafe) / MAX2(thisLaneVSafe, neighLaneVSafe);
1591 : inconvenience = MAX2(relSpeedDiff, inconvenience);
1592 : inconvenience = MIN2(1.0, inconvenience);
1593 :
1594 194876400 : const bool speedGainInconvenient = inconvenience > myCooperativeParam;
1595 194876400 : const bool neighOccupancyInconvenient = neigh.lane->getBruttoOccupancy() > curr.lane->getBruttoOccupancy();
1596 : #ifdef DEBUG_WANTS_CHANGE
1597 : if (DEBUG_COND) {
1598 : std::cout << STEPS2TIME(currentTime)
1599 : << " veh=" << myVehicle.getID()
1600 : << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1601 : << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1602 : << " neighSpeedFactor=" << (thisLaneVSafe / neighLaneVSafe - 1)
1603 : << " inconvenience=" << inconvenience
1604 : << " speedInconv=" << speedGainInconvenient
1605 : << " occInconv=" << neighOccupancyInconvenient
1606 : << "\n";
1607 : }
1608 : #endif
1609 :
1610 : // VARIANT_15
1611 194876400 : if (roundaboutBonus > 0) {
1612 :
1613 : #ifdef DEBUG_WANTS_CHANGE
1614 : if (DEBUG_COND) {
1615 : std::cout << STEPS2TIME(currentTime)
1616 : << " veh=" << myVehicle.getID()
1617 : << " roundaboutBonus=" << roundaboutBonus
1618 : << " myLeftSpace=" << myLeftSpace
1619 : << "\n";
1620 : }
1621 : #endif
1622 : // try to use the inner lanes of a roundabout to increase throughput
1623 : // unless we are approaching the exit
1624 4672503 : if (lca == LCA_LEFT) {
1625 : // if inconvenience is not too high, request collaborative change (currently only for ballistic update)
1626 : // TODO: test this for euler update! Refs. #2575
1627 809034 : if (MSGlobals::gSemiImplicitEulerUpdate || !neighOccupancyInconvenient) {
1628 : // if(MSGlobals::gSemiImplicitEulerUpdate || !speedGainInconvenient){
1629 809034 : req = ret | lca | LCA_COOPERATIVE;
1630 : }
1631 : } else {
1632 : // if inconvenience is not too high, request collaborative change (currently only for ballistic update)
1633 3863469 : if (MSGlobals::gSemiImplicitEulerUpdate || neighOccupancyInconvenient) {
1634 : // if(MSGlobals::gSemiImplicitEulerUpdate || speedGainInconvenient){
1635 3863469 : req = ret | LCA_STAY | LCA_COOPERATIVE;
1636 : }
1637 : }
1638 4672503 : if (!cancelRequest(req, laneOffset)) {
1639 4672503 : return ret | req;
1640 : }
1641 : }
1642 :
1643 : // let's also regard the case where the vehicle is driving on a highway...
1644 : // in this case, we do not want to get to the dead-end of an on-ramp
1645 190203897 : if (right) {
1646 90211449 : if (bestLaneOffset == 0 && myVehicle.getLane()->getSpeedLimit() > 80. / 3.6 && myLookAheadSpeed > SUMO_const_haltingSpeed) {
1647 : #ifdef DEBUG_WANTS_CHANGE
1648 : if (DEBUG_COND) {
1649 : std::cout << " veh=" << myVehicle.getID() << " does not want to get stranded on the on-ramp of a highway\n";
1650 : }
1651 : #endif
1652 87738 : req = ret | LCA_STAY | LCA_STRATEGIC;
1653 87738 : if (!cancelRequest(req, laneOffset)) {
1654 : return ret | req;
1655 : }
1656 : }
1657 : }
1658 : // --------
1659 :
1660 : // -------- make place on current lane if blocking follower
1661 : //if (amBlockingFollowerPlusNB()) {
1662 : // std::cout << myVehicle.getID() << ", " << currentDistAllows(neighDist, bestLaneOffset, laDist)
1663 : // << " neighDist=" << neighDist
1664 : // << " currentDist=" << currentDist
1665 : // << "\n";
1666 : //}
1667 :
1668 : if (amBlockingFollowerPlusNB()
1669 149600 : && (!speedGainInconvenient)
1670 149087 : && ((myOwnState & myLca) != 0) // VARIANT_6 : counterNoHelp
1671 190163352 : && (changeToBest || currentDistAllows(neighDist, abs(bestLaneOffset) + 1, laDist))) {
1672 :
1673 : // VARIANT_2 (nbWhenChangingToHelp)
1674 : #ifdef DEBUG_COOPERATE
1675 : if (DEBUG_COND) {
1676 : std::cout << STEPS2TIME(currentTime)
1677 : << " veh=" << myVehicle.getID()
1678 : << " wantsChangeToHelp=" << (right ? "right" : "left")
1679 : << " state=" << myOwnState
1680 : << (((myOwnState & myLca) == 0) ? " (counter)" : "")
1681 : << "\n";
1682 : }
1683 : #endif
1684 47173 : req = ret | lca | LCA_COOPERATIVE | LCA_URGENT ;//| LCA_CHANGE_TO_HELP;
1685 47173 : if (!cancelRequest(req, laneOffset)) {
1686 47167 : if ((blocked & LCA_BLOCKED_BY_LEFT_FOLLOWER) && !right && mySpeedGainProbabilityLeft > (long long int)(mySpeedGainUrgency * HYST_PRECISION)) {
1687 287 : MSVehicle* nv = neighFollow.first;
1688 287 : const bool hasBidiNeighFollower = neighLane.getBidiLane() != nullptr && MSLCHelper::isBidiFollower(&myVehicle, nv);
1689 287 : if (nv != nullptr && !hasBidiNeighFollower) {
1690 287 : const double helpSpeed = MAX2(nv->getCarFollowModel().minNextSpeed(nv->getSpeed(), nv), myVehicle.getSpeed() - 1);
1691 287 : msgPass.informNeighFollower(new Info(helpSpeed, myLca | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
1692 : }
1693 : }
1694 47167 : return ret | req;
1695 : }
1696 : }
1697 :
1698 : // --------
1699 :
1700 :
1701 : //// -------- security checks for krauss
1702 : //// (vsafe fails when gap<0)
1703 : //if ((blocked & LCA_BLOCKED) != 0) {
1704 : // return ret;
1705 : //}
1706 : //// --------
1707 :
1708 : // -------- higher speed
1709 : //if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { //!!!
1710 : // return ret;
1711 : //}
1712 :
1713 190069012 : if (neighLane.getEdge().getPersons().size() > 0) {
1714 : // react to pedestrians
1715 52178 : adaptSpeedToPedestrians(myVehicle.getLane(), thisLaneVSafe);
1716 52178 : adaptSpeedToPedestrians(&neighLane, neighLaneVSafe);
1717 : }
1718 :
1719 190069012 : const double relativeGain = (neighLaneVSafe - thisLaneVSafe) / MAX2(neighLaneVSafe,
1720 190069012 : RELGAIN_NORMALIZATION_MIN_SPEED);
1721 :
1722 : #ifdef DEBUG_WANTS_CHANGE
1723 : if (DEBUG_COND) {
1724 : std::cout << STEPS2TIME(currentTime)
1725 : << " veh=" << myVehicle.getID()
1726 : << " currentDist=" << currentDist
1727 : << " neighDist=" << neighDist
1728 : << " thisVSafe=" << thisLaneVSafe
1729 : << " neighVSafe=" << neighLaneVSafe
1730 : << " relGain=" << toString(relativeGain, 8)
1731 : << "\n";
1732 : }
1733 : #endif
1734 :
1735 190069012 : if (right) {
1736 : // ONLY FOR CHANGING TO THE RIGHT
1737 90119616 : if (thisLaneVSafe - 5 / 3.6 > neighLaneVSafe) {
1738 : // ok, the current lane is faster than the right one...
1739 60768009 : mySpeedGainProbabilityRight = (long long int)((double)mySpeedGainProbabilityRight * pow(0.5, myVehicle.getActionStepLengthSecs()));
1740 : //myKeepRightProbability /= 2.0;
1741 : } else {
1742 : // ok, the current lane is not (much) faster than the right one
1743 29351607 : mySpeedGainProbabilityRight += (long long int)(myVehicle.getActionStepLengthSecs() * relativeGain * HYST_PRECISION);
1744 :
1745 : // honor the obligation to keep right (Rechtsfahrgebot)
1746 29351607 : const double roadSpeedFactor = vMax / myVehicle.getLane()->getSpeedLimit(); // differse from speedFactor if vMax < speedLimit
1747 : double acceptanceTime;
1748 29351607 : if (myKeepRightAcceptanceTime == -1) {
1749 : // legacy behavior: scale acceptance time with current speed and
1750 : // use old hard-coded constant
1751 58700606 : acceptanceTime = 7 * roadSpeedFactor * MAX2(1.0, myVehicle.getSpeed());
1752 : } else {
1753 1304 : acceptanceTime = myKeepRightAcceptanceTime * roadSpeedFactor;
1754 1511 : if (follower.first != nullptr && follower.second < 2 * follower.first->getCarFollowModel().brakeGap(follower.first->getSpeed())) {
1755 : // reduce acceptanceTime if the follower vehicle is faster or wants to drive faster
1756 207 : if (follower.first->getSpeed() >= myVehicle.getSpeed()) {
1757 380 : acceptanceTime *= MAX2(1.0, myVehicle.getSpeed()) / MAX2(1.0, follower.first->getSpeed());
1758 190 : const double fRSF = follower.first->getLane()->getVehicleMaxSpeed(follower.first) / follower.first->getLane()->getSpeedLimit();
1759 190 : if (fRSF > roadSpeedFactor) {
1760 120 : acceptanceTime /= fRSF;
1761 : }
1762 : }
1763 : }
1764 : }
1765 29351607 : double fullSpeedGap = MAX2(0., neighDist - myVehicle.getCarFollowModel().brakeGap(vMax));
1766 29351607 : double fullSpeedDrivingSeconds = MIN2(acceptanceTime, fullSpeedGap / vMax);
1767 29351607 : if (neighLead.first != 0 && neighLead.first->getSpeed() < vMax) {
1768 23139771 : fullSpeedGap = MAX2(0., MIN2(fullSpeedGap,
1769 23139771 : neighLead.second - myVehicle.getCarFollowModel().getSecureGap(&myVehicle, neighLead.first,
1770 23139771 : vMax, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())));
1771 23139771 : fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - neighLead.first->getSpeed()));
1772 : }
1773 : // stay on the current lane if we cannot overtake a slow leader on the right
1774 4630334 : if (checkOverTakeRight && leader.first != 0
1775 33458415 : && leader.first->getLane()->getVehicleMaxSpeed(leader.first) < vMax) {
1776 1297010 : fullSpeedGap = MIN2(fullSpeedGap, leader.second);
1777 1297010 : fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - leader.first->getSpeed()));
1778 : }
1779 :
1780 29351607 : const double deltaProb = (myChangeProbThresholdRight == std::numeric_limits<long long int>::max()) ? 0 :
1781 29338705 : ((double)myChangeProbThresholdRight * (fullSpeedDrivingSeconds / acceptanceTime) / KEEP_RIGHT_TIME);
1782 29351607 : myKeepRightProbability -= (long long int)(myVehicle.getActionStepLengthSecs() * deltaProb);
1783 :
1784 : //std::cout << STEPS2TIME(currentTime)
1785 : // << " veh=" << myVehicle.getID()
1786 : // << " acceptanceTime=" << acceptanceTime
1787 : // << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1788 : // << " dProb=" << deltaProb
1789 : // << " myKeepRightProbability=" << myKeepRightProbability
1790 : // << "\n";
1791 :
1792 : #ifdef DEBUG_WANTS_CHANGE
1793 : if (DEBUG_COND) {
1794 : std::cout << STEPS2TIME(currentTime)
1795 : << " veh=" << myVehicle.getID()
1796 : << " vMax=" << vMax
1797 : << " neighDist=" << neighDist
1798 : << " brakeGap=" << myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed())
1799 : << " leaderSpeed=" << (neighLead.first == 0 ? -1 : neighLead.first->getSpeed())
1800 : << " secGap=" << (neighLead.first == 0 ? -1 : myVehicle.getCarFollowModel().getSecureGap(&myVehicle, neighLead.first,
1801 : myVehicle.getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()))
1802 : << " acceptanceTime=" << acceptanceTime
1803 : << " fullSpeedGap=" << fullSpeedGap
1804 : << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1805 : << " dProb=" << deltaProb / HYST_PRECISION
1806 : << " myKeepRightProbability=" << myKeepRightProbability / HYST_PRECISION
1807 : << "\n";
1808 : }
1809 : #endif
1810 29351607 : if ((long long int)((double)myKeepRightProbability * myKeepRightParam) < -myChangeProbThresholdRight) {
1811 3141080 : req = ret | lca | LCA_KEEPRIGHT;
1812 3141080 : if (!cancelRequest(req, laneOffset)) {
1813 3140680 : return ret | req;
1814 : }
1815 : }
1816 : }
1817 :
1818 : #ifdef DEBUG_WANTS_CHANGE
1819 : if (DEBUG_COND) {
1820 : std::cout << STEPS2TIME(currentTime)
1821 : << " veh=" << myVehicle.getID()
1822 : << " speed=" << myVehicle.getSpeed()
1823 : << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1824 : << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1825 : << " thisLaneVSafe=" << thisLaneVSafe
1826 : << " neighLaneVSafe=" << neighLaneVSafe
1827 : << " relativeGain=" << relativeGain
1828 : << " blocked=" << blocked
1829 : << "\n";
1830 : }
1831 : #endif
1832 :
1833 86978936 : if (mySpeedGainProbabilityRight > myChangeProbThresholdRight
1834 87490207 : && neighDist / MAX2(.1, myVehicle.getSpeed()) > mySpeedGainRemainTime) { //./MAX2( .1, myVehicle.getSpeed())) { // -.1
1835 490673 : req = ret | lca | LCA_SPEEDGAIN;
1836 490673 : if (mySpeedGainProbabilityRight > (long long int)(mySpeedGainUrgency * HYST_PRECISION)) {
1837 237 : req |= LCA_URGENT;
1838 : }
1839 490673 : if (!cancelRequest(req, laneOffset)) {
1840 490673 : return ret | req;
1841 : }
1842 : }
1843 : } else {
1844 : // ONLY FOR CHANGING TO THE LEFT
1845 99949396 : if (thisLaneVSafe > neighLaneVSafe) {
1846 : // this lane is better
1847 59872085 : mySpeedGainProbabilityLeft = (long long int)((double)mySpeedGainProbabilityLeft * pow(0.5, myVehicle.getActionStepLengthSecs()));
1848 40077311 : } else if (thisLaneVSafe == neighLaneVSafe) {
1849 20120300 : mySpeedGainProbabilityLeft = (long long int)((double)mySpeedGainProbabilityLeft * pow(0.8, myVehicle.getActionStepLengthSecs()));
1850 : } else {
1851 19957011 : mySpeedGainProbabilityLeft += (long long int)(myVehicle.getActionStepLengthSecs() * relativeGain * HYST_PRECISION);
1852 : }
1853 : // VARIANT_19 (stayRight)
1854 : //if (neighFollow.first != 0) {
1855 : // MSVehicle* nv = neighFollow.first;
1856 : // const double secGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel());
1857 : // if (neighFollow.second < secGap * KEEP_RIGHT_HEADWAY) {
1858 : // // do not change left if it would inconvenience faster followers
1859 : // return ret | LCA_STAY | LCA_SPEEDGAIN;
1860 : // }
1861 : //}
1862 :
1863 : #ifdef DEBUG_WANTS_CHANGE
1864 : if (DEBUG_COND) {
1865 : std::cout << STEPS2TIME(currentTime)
1866 : << " veh=" << myVehicle.getID()
1867 : << " speed=" << myVehicle.getSpeed()
1868 : << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1869 : << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1870 : << " thisLaneVSafe=" << thisLaneVSafe
1871 : << " neighLaneVSafe=" << neighLaneVSafe
1872 : << " relativeGain=" << relativeGain
1873 : << " blocked=" << blocked
1874 : << "\n";
1875 : }
1876 : #endif
1877 :
1878 99949396 : if (mySpeedGainProbabilityLeft > myChangeProbThresholdLeft
1879 9944385 : && (relativeGain > NUMERICAL_EPS || changeLeftToAvoidOvertakeRight)
1880 115055180 : && neighDist / MAX2(.1, myVehicle.getSpeed()) > mySpeedGainRemainTime) { // .1
1881 7248355 : req = ret | lca | LCA_SPEEDGAIN;
1882 7248355 : if (mySpeedGainProbabilityLeft > (long long int)(mySpeedGainUrgency * HYST_PRECISION)) {
1883 2284 : req |= LCA_URGENT;
1884 : }
1885 7248355 : if (!cancelRequest(req, laneOffset)) {
1886 7248239 : if ((req & LCA_URGENT) && (blocked & LCA_BLOCKED_BY_LEFT_FOLLOWER)) {
1887 2183 : MSVehicle* nv = neighFollow.first;
1888 2183 : const bool hasBidiNeighFollower = neighLane.getBidiLane() != nullptr && MSLCHelper::isBidiFollower(&myVehicle, nv);
1889 2183 : if (nv != nullptr && !hasBidiNeighFollower) {
1890 2183 : const double helpSpeed = MAX2(nv->getCarFollowModel().minNextSpeed(nv->getSpeed(), nv), myVehicle.getSpeed() - 1);
1891 2183 : msgPass.informNeighFollower(new Info(helpSpeed, myLca | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
1892 : }
1893 : }
1894 7248239 : return ret | req;
1895 : }
1896 : }
1897 : }
1898 : // --------
1899 179189420 : if (changeToBest && bestLaneOffset == curr.bestLaneOffset
1900 2641519 : && myStrategicParam >= 0
1901 2634827 : && relativeGain >= 0
1902 922656 : && (right ? mySpeedGainProbabilityRight : mySpeedGainProbabilityLeft) > 0) {
1903 : // change towards the correct lane, speedwise it does not hurt
1904 136056 : req = ret | lca | LCA_STRATEGIC;
1905 136056 : if (!cancelRequest(req, laneOffset)) {
1906 136056 : return ret | req;
1907 : }
1908 : }
1909 : #ifdef DEBUG_WANTS_CHANGE
1910 : if (DEBUG_COND) {
1911 : std::cout << STEPS2TIME(currentTime)
1912 : << " veh=" << myVehicle.getID()
1913 : << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1914 : << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1915 : << " myKeepRightProbability=" << myKeepRightProbability / HYST_PRECISION
1916 : << " thisLaneVSafe=" << thisLaneVSafe
1917 : << " neighLaneVSafe=" << neighLaneVSafe
1918 : << "\n";
1919 : }
1920 : #endif
1921 :
1922 : return ret;
1923 : }
1924 :
1925 :
1926 : double
1927 389752800 : MSLCM_LC2013::anticipateFollowSpeed(const std::pair<MSVehicle*, double>& leaderDist, double dist, double vMax, bool acceleratingLeader) {
1928 389752800 : const MSVehicle* leader = leaderDist.first;
1929 389752800 : const double gap = leaderDist.second;
1930 : double futureSpeed;
1931 389752800 : if (acceleratingLeader) {
1932 : // XXX see #6562
1933 270847604 : const double maxSpeed1s = (myVehicle.getSpeed() + myVehicle.getCarFollowModel().getMaxAccel()
1934 270847604 : - ACCEL2SPEED(myVehicle.getCarFollowModel().getMaxAccel()));
1935 270847604 : if (leader == nullptr) {
1936 4991882 : if (hasBlueLight()) {
1937 : // can continue from any lane if necessary
1938 : futureSpeed = vMax;
1939 : } else {
1940 4991840 : futureSpeed = getCarFollowModel().followSpeed(&myVehicle, maxSpeed1s, dist, 0, 0);
1941 : }
1942 : } else {
1943 265855722 : futureSpeed = getCarFollowModel().followSpeed(&myVehicle, maxSpeed1s, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1944 : }
1945 : } else {
1946 : // onInsertion = true because the vehicle has already moved
1947 118905196 : if (leader == nullptr) {
1948 17265745 : if (hasBlueLight()) {
1949 : // can continue from any lane if necessary
1950 : futureSpeed = vMax;
1951 : } else {
1952 17264170 : futureSpeed = getCarFollowModel().maximumSafeStopSpeed(dist, getCarFollowModel().getMaxDecel(), myVehicle.getSpeed(), true);
1953 : }
1954 : } else {
1955 101639451 : futureSpeed = getCarFollowModel().maximumSafeFollowSpeed(gap, myVehicle.getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), true);
1956 : }
1957 : }
1958 : futureSpeed = MIN2(vMax, futureSpeed);
1959 389752800 : if (leader != nullptr && gap > 0 && mySpeedGainLookahead > 0) {
1960 1004 : const double futureLeaderSpeed = acceleratingLeader ? leader->getLane()->getVehicleMaxSpeed(leader) : leader->getSpeed();
1961 1004 : const double deltaV = vMax - futureLeaderSpeed;
1962 1004 : if (deltaV > 0 && gap > 0) {
1963 986 : const double secGap = getCarFollowModel().getSecureGap(&myVehicle, leader, futureSpeed, leader->getSpeed(), getCarFollowModel().getMaxDecel());
1964 986 : const double fullSpeedGap = gap - secGap;
1965 986 : if (fullSpeedGap / deltaV < mySpeedGainLookahead) {
1966 : // anticipate future braking by computing the average
1967 : // speed over the next few seconds
1968 : const double gapClosingTime = MAX2(0.0, fullSpeedGap / deltaV);
1969 190 : const double foreCastTime = mySpeedGainLookahead * 2;
1970 : //if (DEBUG_COND) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " leader=" << leader->getID() << " gap=" << gap << " deltaV=" << deltaV << " futureSpeed=" << futureSpeed << " futureLeaderSpeed=" << futureLeaderSpeed;
1971 190 : futureSpeed = MIN2(futureSpeed, (gapClosingTime * futureSpeed + (foreCastTime - gapClosingTime) * futureLeaderSpeed) / foreCastTime);
1972 : //if (DEBUG_COND) std::cout << " newFutureSpeed=" << futureSpeed << "\n";
1973 : }
1974 : }
1975 : }
1976 389752800 : return futureSpeed;
1977 : }
1978 :
1979 :
1980 : int
1981 249198260 : MSLCM_LC2013::slowDownForBlocked(MSVehicle* blocked, int state) {
1982 : // if this vehicle is blocking someone in front, we maybe decelerate to let him in
1983 249198260 : if (blocked != nullptr) {
1984 18750785 : double gap = blocked->getPositionOnLane() - blocked->getVehicleType().getLength() - myVehicle.getPositionOnLane() - myVehicle.getVehicleType().getMinGap();
1985 : #ifdef DEBUG_SLOW_DOWN
1986 : if (DEBUG_COND) {
1987 : std::cout << SIMTIME
1988 : << " veh=" << myVehicle.getID()
1989 : << " blocked=" << Named::getIDSecure(blocked)
1990 : << " gap=" << gap
1991 : << "\n";
1992 : }
1993 : #endif
1994 18750785 : if (gap > POSITION_EPS) {
1995 : //const bool blockedWantsUrgentRight = (((*blocked)->getLaneChangeModel().getOwnState() & LCA_RIGHT != 0)
1996 : // && ((*blocked)->getLaneChangeModel().getOwnState() & LCA_URGENT != 0));
1997 :
1998 14948291 : if (myVehicle.getSpeed() < myVehicle.getCarFollowModel().getMaxDecel()
1999 : //|| blockedWantsUrgentRight // VARIANT_10 (helpblockedRight)
2000 : ) {
2001 13177249 : if (blocked->getSpeed() < SUMO_const_haltingSpeed) {
2002 7415241 : state |= LCA_AMBACKBLOCKER_STANDING;
2003 : } else {
2004 5762008 : state |= LCA_AMBACKBLOCKER;
2005 : }
2006 26354498 : addLCSpeedAdvice(getCarFollowModel().followSpeed(
2007 13177249 : &myVehicle, myVehicle.getSpeed(),
2008 13177249 : gap - POSITION_EPS, blocked->getSpeed(),
2009 : blocked->getCarFollowModel().getMaxDecel()), false);
2010 :
2011 : //(*blocked) = 0; // VARIANT_14 (furtherBlock)
2012 : #ifdef DEBUG_SLOW_DOWN
2013 : if (DEBUG_COND) {
2014 : std::cout << SIMTIME
2015 : << " veh=" << myVehicle.getID()
2016 : << " slowing down for"
2017 : << " blocked=" << Named::getIDSecure(blocked)
2018 : << " helpSpeed=" << myLCAccelerationAdvices.back().first
2019 : << "\n";
2020 : }
2021 : #endif
2022 : } /*else if ((*blocked)->getWaitingSeconds() > 30 && gap > myVehicle.getBrakeGap()) {
2023 : // experimental else-branch...
2024 :
2025 : state |= LCA_AMBACKBLOCKER;
2026 : addLCSpeedAdvice(getCarFollowModel().followSpeed(
2027 : &myVehicle, myVehicle.getSpeed(),
2028 : (gap - POSITION_EPS), (*blocked)->getSpeed(),
2029 : (*blocked)->getCarFollowModel().getMaxDecel()));
2030 : } */
2031 : }
2032 : }
2033 249198260 : return state;
2034 : }
2035 :
2036 :
2037 : void
2038 104356 : MSLCM_LC2013::adaptSpeedToPedestrians(const MSLane* lane, double& v) {
2039 104356 : if (lane->hasPedestrians()) {
2040 : #ifdef DEBUG_WANTS_CHANGE
2041 : if (DEBUG_COND) {
2042 : std::cout << SIMTIME << " adapt to pedestrians on lane=" << lane->getID() << "\n";
2043 : }
2044 : #endif
2045 20717 : PersonDist leader = lane->nextBlocking(myVehicle.getPositionOnLane(),
2046 20717 : myVehicle.getRightSideOnLane(), myVehicle.getRightSideOnLane() + myVehicle.getVehicleType().getWidth(),
2047 20717 : ceil(myVehicle.getSpeed() / myVehicle.getCarFollowModel().getMaxDecel()));
2048 20717 : if (leader.first != 0) {
2049 7685 : const double stopSpeed = myVehicle.getCarFollowModel().stopSpeed(&myVehicle, myVehicle.getSpeed(), leader.second - myVehicle.getVehicleType().getMinGap());
2050 12606 : v = MIN2(v, stopSpeed);
2051 : #ifdef DEBUG_WANTS_CHANGE
2052 : if (DEBUG_COND) {
2053 : std::cout << SIMTIME << " pedLeader=" << leader.first->getID() << " dist=" << leader.second << " v=" << v << "\n";
2054 : }
2055 : #endif
2056 : }
2057 : }
2058 104356 : }
2059 :
2060 :
2061 : double
2062 619931 : MSLCM_LC2013::computeSpeedLat(double latDist, double& maneuverDist, bool urgent) const {
2063 619931 : double result = MSAbstractLaneChangeModel::computeSpeedLat(latDist, maneuverDist, urgent);
2064 : #ifdef DEBUG_WANTS_CHANGE
2065 : if (DEBUG_COND) {
2066 : std::cout << SIMTIME << " veh=" << myVehicle.getID() << " myLeftSpace=" << myLeftSpace << " latDist=" << latDist << " maneuverDist=" << maneuverDist << " result=" << result << "\n";
2067 : }
2068 : #endif
2069 619931 : if (myLeftSpace > POSITION_EPS || !urgent) {
2070 505105 : double speedBound = myMaxSpeedLatStanding + myMaxSpeedLatFactor * myVehicle.getSpeed();
2071 505105 : if (isChangingLanes()) {
2072 : speedBound = MAX2(LC_RESOLUTION_SPEED_LAT, speedBound);
2073 : }
2074 505105 : result = MAX2(-speedBound, MIN2(speedBound, result));
2075 : }
2076 619931 : return result;
2077 : }
2078 :
2079 :
2080 : double
2081 503154553 : MSLCM_LC2013::getSafetyFactor() const {
2082 503154553 : return 1 / myAssertive;
2083 : }
2084 :
2085 : double
2086 8464299 : MSLCM_LC2013::getOppositeSafetyFactor() const {
2087 8464299 : return myOppositeParam <= 0 ? std::numeric_limits<double>::max() : 1 / myOppositeParam;
2088 : }
2089 :
2090 : bool
2091 142949 : MSLCM_LC2013::saveBlockerLength(double length, double foeLeftSpace) {
2092 142949 : const bool canReserve = MSLCHelper::canSaveBlockerLength(myVehicle, length, myLeftSpace);
2093 142949 : if (!isOpposite() && (canReserve || myLeftSpace > foeLeftSpace)) {
2094 130508 : myLeadingBlockerLength = MAX2(length, myLeadingBlockerLength);
2095 : #ifdef DEBUG_SAVE_BLOCKER_LENGTH
2096 : if (DEBUG_COND) {
2097 : std::cout << SIMTIME << " saveBlockerLength veh=" << myVehicle.getID() << " canReserve=" << canReserve << " myLeftSpace=" << myLeftSpace << " foeLeftSpace=" << foeLeftSpace << "\n";
2098 : }
2099 : #endif
2100 130508 : if (myLeftSpace == 0 && foeLeftSpace < 0) {
2101 : // called from opposite overtaking, myLeftSpace must be initialized
2102 127741 : myLeftSpace = myVehicle.getBestLanes()[myVehicle.getLane()->getIndex()].length - myVehicle.getPositionOnLane();
2103 : }
2104 130508 : return true;
2105 : } else {
2106 : return false;
2107 : }
2108 : }
2109 :
2110 :
2111 : bool
2112 25483 : MSLCM_LC2013::hasFreeLane(int laneOffset, const std::pair<MSVehicle*, double>& neighLeadStopped) const {
2113 25483 : if (neighLeadStopped.first == nullptr) {
2114 : return true;
2115 : }
2116 25483 : int dir = (laneOffset > 0 ? 1 : -1);
2117 25483 : const MSLane* neigh = myVehicle.getLane()->getParallelLane(laneOffset);
2118 25483 : if (dir > 0 && !neigh->allowsChangingLeft(myVehicle.getVClass())) {
2119 : return false;
2120 25483 : } else if (dir < 0 && !neigh->allowsChangingRight(myVehicle.getVClass())) {
2121 : return false;
2122 : }
2123 25483 : int nextOffset = laneOffset + dir;
2124 25483 : const MSLane* next = myVehicle.getLane()->getParallelLane(nextOffset);
2125 25483 : if (next == nullptr || !next->allowsVehicleClass(myVehicle.getVClass())) {
2126 17972 : return false;
2127 : }
2128 7511 : const double overtakeDist = neighLeadStopped.second + neighLeadStopped.first->getVehicleType().getLengthWithGap() + myVehicle.getLength() + POSITION_EPS;
2129 7511 : std::pair<MSVehicle* const, double> nextLead = next->getLeader(&myVehicle, myVehicle.getPositionOnLane(), myVehicle.getBestLanesContinuation(next), overtakeDist);
2130 8015 : return nextLead.first == nullptr || nextLead.second >= overtakeDist || hasFreeLane(nextOffset, nextLead);
2131 : }
2132 :
2133 :
2134 : std::string
2135 150 : MSLCM_LC2013::getParameter(const std::string& key) const {
2136 150 : if (key == toString(SUMO_ATTR_LCA_STRATEGIC_PARAM)) {
2137 36 : return toString(myStrategicParam);
2138 114 : } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_PARAM)) {
2139 36 : return toString(myCooperativeParam);
2140 78 : } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_PARAM)) {
2141 36 : return toString(mySpeedGainParam);
2142 42 : } else if (key == toString(SUMO_ATTR_LCA_KEEPRIGHT_PARAM)) {
2143 0 : return toString(myKeepRightParam);
2144 42 : } else if (key == toString(SUMO_ATTR_LCA_OPPOSITE_PARAM)) {
2145 0 : return toString(myOppositeParam);
2146 42 : } else if (key == toString(SUMO_ATTR_LCA_LOOKAHEADLEFT)) {
2147 0 : return toString(myLookaheadLeft);
2148 42 : } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAINRIGHT)) {
2149 0 : return toString(mySpeedGainRight);
2150 42 : } else if (key == toString(SUMO_ATTR_LCA_ASSERTIVE)) {
2151 0 : return toString(myAssertive);
2152 42 : } else if (key == toString(SUMO_ATTR_LCA_OVERTAKE_RIGHT)) {
2153 0 : return toString(myOvertakeRightParam);
2154 42 : } else if (key == toString(SUMO_ATTR_LCA_SIGMA)) {
2155 0 : return toString(mySigma);
2156 42 : } else if (key == toString(SUMO_ATTR_LCA_KEEPRIGHT_ACCEPTANCE_TIME)) {
2157 0 : return toString(myKeepRightAcceptanceTime);
2158 42 : } else if (key == toString(SUMO_ATTR_LCA_OVERTAKE_DELTASPEED_FACTOR)) {
2159 0 : return toString(myOvertakeDeltaSpeedFactor);
2160 42 : } else if (key == toString(SUMO_ATTR_LCA_STRATEGIC_LOOKAHEAD)) {
2161 0 : return toString(myStrategicLookahead);
2162 42 : } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD)) {
2163 0 : return toString(mySpeedGainLookahead);
2164 42 : } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_REMAIN_TIME)) {
2165 0 : return toString(mySpeedGainRemainTime);
2166 42 : } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_ROUNDABOUT)) {
2167 0 : return toString(myRoundaboutBonus);
2168 42 : } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_SPEED)) {
2169 0 : return toString(myCooperativeSpeed);
2170 42 : } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING)) {
2171 0 : return toString(myMaxSpeedLatStanding);
2172 42 : } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR)) {
2173 0 : return toString(myMaxSpeedLatFactor);
2174 42 : } else if (key == toString(SUMO_ATTR_LCA_MAXDISTLATSTANDING)) {
2175 0 : return toString(myMaxDistLatStanding);
2176 : // access to internal state for debugging in sumo-gui (not documented since it may change at any time)
2177 42 : } else if (key == "speedGainProbabilityRight") {
2178 0 : return toString(mySpeedGainProbabilityRight / HYST_PRECISION);
2179 42 : } else if (key == "speedGainProbabilityLeft") {
2180 0 : return toString(mySpeedGainProbabilityLeft / HYST_PRECISION);
2181 42 : } else if (key == "keepRightProbability") {
2182 0 : return toString(-myKeepRightProbability / HYST_PRECISION);
2183 42 : } else if (key == "lookAheadSpeed") {
2184 0 : return toString(myLookAheadSpeed);
2185 : // motivation relative to threshold
2186 42 : } else if (key == "speedGainRP") {
2187 0 : return toString(mySpeedGainProbabilityRight / myChangeProbThresholdRight);
2188 42 : } else if (key == "speedGainLP") {
2189 0 : return toString(mySpeedGainProbabilityLeft / myChangeProbThresholdLeft);
2190 42 : } else if (key == "keepRightP") {
2191 0 : return toString((double)myKeepRightProbability * myKeepRightParam / -(double)myChangeProbThresholdRight);
2192 : }
2193 168 : throw InvalidArgument("Parameter '" + key + "' is not supported for laneChangeModel of type '" + toString(myModel) + "'");
2194 : }
2195 :
2196 :
2197 : void
2198 12052 : MSLCM_LC2013::setParameter(const std::string& key, const std::string& value) {
2199 : double doubleValue;
2200 : try {
2201 12052 : doubleValue = StringUtils::toDouble(value);
2202 0 : } catch (NumberFormatException&) {
2203 0 : throw InvalidArgument("Setting parameter '" + key + "' requires a number for laneChangeModel of type '" + toString(myModel) + "'");
2204 0 : }
2205 12052 : if (key == toString(SUMO_ATTR_LCA_STRATEGIC_PARAM)) {
2206 3174 : myStrategicParam = doubleValue;
2207 8878 : } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_PARAM)) {
2208 36 : myCooperativeParam = doubleValue;
2209 8842 : } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_PARAM)) {
2210 0 : mySpeedGainParam = doubleValue;
2211 8842 : } else if (key == toString(SUMO_ATTR_LCA_KEEPRIGHT_PARAM)) {
2212 0 : myKeepRightParam = doubleValue;
2213 8842 : } else if (key == toString(SUMO_ATTR_LCA_OPPOSITE_PARAM)) {
2214 0 : myOppositeParam = doubleValue;
2215 8842 : } else if (key == toString(SUMO_ATTR_LCA_LOOKAHEADLEFT)) {
2216 0 : myLookaheadLeft = doubleValue;
2217 8842 : } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAINRIGHT)) {
2218 0 : mySpeedGainRight = doubleValue;
2219 8842 : } else if (key == toString(SUMO_ATTR_LCA_ASSERTIVE)) {
2220 0 : myAssertive = doubleValue;
2221 8842 : } else if (key == toString(SUMO_ATTR_LCA_OVERTAKE_RIGHT)) {
2222 0 : myOvertakeRightParam = doubleValue;
2223 8842 : } else if (key == toString(SUMO_ATTR_LCA_SIGMA)) {
2224 0 : mySigma = doubleValue;
2225 8842 : } else if (key == toString(SUMO_ATTR_LCA_KEEPRIGHT_ACCEPTANCE_TIME)) {
2226 0 : myKeepRightAcceptanceTime = doubleValue;
2227 8842 : } else if (key == toString(SUMO_ATTR_LCA_OVERTAKE_DELTASPEED_FACTOR)) {
2228 0 : myOvertakeDeltaSpeedFactor = doubleValue;
2229 8842 : } else if (key == toString(SUMO_ATTR_LCA_STRATEGIC_LOOKAHEAD)) {
2230 0 : myStrategicLookahead = doubleValue;
2231 8842 : } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD)) {
2232 2946 : mySpeedGainLookahead = doubleValue;
2233 5896 : } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_REMAIN_TIME)) {
2234 2946 : mySpeedGainRemainTime = doubleValue;
2235 2950 : } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_ROUNDABOUT)) {
2236 0 : myRoundaboutBonus = doubleValue;
2237 2950 : } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_SPEED)) {
2238 0 : myCooperativeSpeed = doubleValue;
2239 2950 : } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING)) {
2240 0 : myMaxSpeedLatStanding = doubleValue;
2241 2950 : } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR)) {
2242 0 : myMaxSpeedLatFactor = doubleValue;
2243 2950 : } else if (key == toString(SUMO_ATTR_LCA_MAXDISTLATSTANDING)) {
2244 0 : myMaxDistLatStanding = doubleValue;
2245 : // access to internal state
2246 2950 : } else if (key == "speedGainProbabilityRight") {
2247 0 : mySpeedGainProbabilityRight = (long long int)(doubleValue * HYST_PRECISION);
2248 2950 : } else if (key == "speedGainProbabilityLeft") {
2249 0 : mySpeedGainProbabilityLeft = (long long int)(doubleValue * HYST_PRECISION);
2250 2950 : } else if (key == "keepRightProbability") {
2251 0 : myKeepRightProbability = (long long int)(-doubleValue * HYST_PRECISION);
2252 2950 : } else if (key == "lookAheadSpeed") {
2253 0 : myLookAheadSpeed = doubleValue;
2254 : } else {
2255 11800 : throw InvalidArgument("Setting parameter '" + key + "' is not supported for laneChangeModel of type '" + toString(myModel) + "'");
2256 : }
2257 9102 : initDerivedParameters();
2258 9102 : }
2259 :
2260 :
2261 : void
2262 2560 : MSLCM_LC2013::saveState(OutputDevice& out) const {
2263 2560 : MSAbstractLaneChangeModel::saveState(out);
2264 : std::vector<long long int> lcState;
2265 2560 : lcState.push_back(mySpeedGainProbabilityLeft);
2266 2560 : lcState.push_back(mySpeedGainProbabilityRight);
2267 2560 : lcState.push_back(myKeepRightProbability);
2268 2560 : lcState.push_back((long long int)(myLookAheadSpeed * HYST_PRECISION));
2269 2560 : lcState.push_back(myDontBrake);
2270 2560 : out.writeAttr(SUMO_ATTR_LCSTATE2, lcState);
2271 2560 : }
2272 :
2273 :
2274 : void
2275 3462 : MSLCM_LC2013::loadState(const SUMOSAXAttributes& attrs) {
2276 3462 : MSAbstractLaneChangeModel::loadState(attrs);
2277 3462 : if (attrs.hasAttribute(SUMO_ATTR_LCSTATE2)) {
2278 3462 : std::istringstream bis(attrs.getString(SUMO_ATTR_LCSTATE2));
2279 3462 : bis >> mySpeedGainProbabilityLeft;
2280 3462 : bis >> mySpeedGainProbabilityRight;
2281 3462 : bis >> myKeepRightProbability;
2282 : long long laSpeed;
2283 : bis >> laSpeed;
2284 3462 : myLookAheadSpeed = (double)laSpeed / HYST_PRECISION;
2285 3462 : bis >> myDontBrake;
2286 3462 : }
2287 3462 : }
2288 :
2289 :
2290 :
2291 : /****************************************************************************/
|