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