LCOV - code coverage report
Current view: top level - src/microsim/lcmodels - MSLCM_LC2013.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 615 661 93.0 %
Date: 2024-09-16 15:39:55 Functions: 26 26 100.0 %

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

Generated by: LCOV version 1.14