LCOV - code coverage report
Current view: top level - src/microsim/lcmodels - MSLCM_LC2013.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 93.1 % 715 666
Test Date: 2026-08-23 15:49:09 Functions: 100.0 % 28 28

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

Generated by: LCOV version 2.0-1