LCOV - code coverage report
Current view: top level - src/microsim/lcmodels - MSAbstractLaneChangeModel.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 94.6 % 573 542
Test Date: 2026-08-23 15:49:09 Functions: 93.7 % 63 59

            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    MSAbstractLaneChangeModel.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Friedemann Wesner
      17              : /// @author  Sascha Krieg
      18              : /// @author  Michael Behrisch
      19              : /// @author  Jakob Erdmann
      20              : /// @author  Leonhard Luecken
      21              : /// @date    Fri, 29.04.2005
      22              : ///
      23              : // Interface for lane-change models
      24              : /****************************************************************************/
      25              : 
      26              : // ===========================================================================
      27              : // DEBUG
      28              : // ===========================================================================
      29              : //#define DEBUG_TARGET_LANE
      30              : //#define DEBUG_SHADOWLANE
      31              : //#define DEBUG_OPPOSITE
      32              : //#define DEBUG_MANEUVER
      33              : #define DEBUG_COND (myVehicle.isSelected())
      34              : 
      35              : #include <config.h>
      36              : 
      37              : #include <utils/options/OptionsCont.h>
      38              : #include <utils/xml/SUMOSAXAttributes.h>
      39              : #include <utils/geom/GeomHelper.h>
      40              : #include <microsim/MSNet.h>
      41              : #include <microsim/MSEdge.h>
      42              : #include <microsim/MSLane.h>
      43              : #include <microsim/MSLink.h>
      44              : #include <microsim/MSStop.h>
      45              : #include <microsim/MSStoppingPlace.h>
      46              : #include <microsim/MSDriverState.h>
      47              : #include <microsim/MSGlobals.h>
      48              : #include <microsim/devices/MSDevice_Bluelight.h>
      49              : #include "MSLCM_DK2008.h"
      50              : #include "MSLCM_LC2013.h"
      51              : #include "MSLCM_LC2013_CC.h"
      52              : #include "MSLCM_SL2015.h"
      53              : #include "MSAbstractLaneChangeModel.h"
      54              : 
      55              : /* -------------------------------------------------------------------------
      56              :  * static members
      57              :  * ----------------------------------------------------------------------- */
      58              : bool MSAbstractLaneChangeModel::myAllowOvertakingRight(false);
      59              : bool MSAbstractLaneChangeModel::myLCOutput(false);
      60              : bool MSAbstractLaneChangeModel::myLCStartedOutput(false);
      61              : bool MSAbstractLaneChangeModel::myLCEndedOutput(false);
      62              : bool MSAbstractLaneChangeModel::myLCXYOutput(false);
      63              : const double MSAbstractLaneChangeModel::NO_NEIGHBOR(std::numeric_limits<double>::max());
      64              : const double MSAbstractLaneChangeModel::UNDEFINED_LOOKAHEAD(-1);
      65              : 
      66              : #define LC_ASSUMED_DECEL 1.0 // the minimal constant deceleration assumed to estimate the duration of a continuous lane-change at its initiation.
      67              : 
      68              : /* -------------------------------------------------------------------------
      69              :  * MSAbstractLaneChangeModel-methods
      70              :  * ----------------------------------------------------------------------- */
      71              : 
      72              : void
      73        42871 : MSAbstractLaneChangeModel::initGlobalOptions(const OptionsCont& oc) {
      74        42871 :     myAllowOvertakingRight = oc.getBool("lanechange.overtake-right");
      75        42871 :     myLCOutput = oc.isSet("lanechange-output");
      76        42871 :     myLCStartedOutput = oc.getBool("lanechange-output.started");
      77        42871 :     myLCEndedOutput = oc.getBool("lanechange-output.ended");
      78        42871 :     myLCXYOutput = oc.getBool("lanechange-output.xy");
      79        42871 : }
      80              : 
      81              : 
      82              : MSAbstractLaneChangeModel*
      83      4534071 : MSAbstractLaneChangeModel::build(LaneChangeModel lcm, MSVehicle& v) {
      84      4534071 :     if (MSGlobals::gLateralResolution > 0 && lcm != LaneChangeModel::SL2015 && lcm != LaneChangeModel::DEFAULT) {
      85           44 :         throw ProcessError(TLF("Lane change model '%' is not compatible with sublane simulation", toString(lcm)));
      86              :     }
      87      4534049 :     switch (lcm) {
      88            8 :         case LaneChangeModel::DK2008:
      89            8 :             return new MSLCM_DK2008(v);
      90         1290 :         case LaneChangeModel::LC2013:
      91         1290 :             return new MSLCM_LC2013(v);
      92            0 :         case LaneChangeModel::LC2013_CC:
      93            0 :             return new MSLCM_LC2013_CC(v);
      94          574 :         case LaneChangeModel::SL2015:
      95          574 :             return new MSLCM_SL2015(v);
      96      4532177 :         case LaneChangeModel::DEFAULT:
      97      4532177 :             if (MSGlobals::gLateralResolution <= 0) {
      98      3692261 :                 return new MSLCM_LC2013(v);
      99              :             } else {
     100       839916 :                 return new MSLCM_SL2015(v);
     101              :             }
     102            0 :         default:
     103            0 :             throw ProcessError(TLF("Lane change model '%' not implemented", toString(lcm)));
     104              :     }
     105              : }
     106              : 
     107              : 
     108      4534049 : MSAbstractLaneChangeModel::MSAbstractLaneChangeModel(MSVehicle& v, const LaneChangeModel model) :
     109      4534049 :     myVehicle(v),
     110      4534049 :     myOwnState(0),
     111      4534049 :     myPreviousState(0),
     112      4534049 :     myPreviousState2(0),
     113      4534049 :     myCanceledStateRight(LCA_NONE),
     114      4534049 :     myCanceledStateCenter(LCA_NONE),
     115      4534049 :     myCanceledStateLeft(LCA_NONE),
     116      4534049 :     mySpeedLat(0),
     117      4534049 :     myAccelerationLat(0),
     118      4534049 :     myAngleOffset(0),
     119      4534049 :     myPreviousAngleOffset(0),
     120      4534049 :     myCommittedSpeed(0),
     121      4534049 :     myLaneChangeCompletion(1.0),
     122      4534049 :     myLaneChangeDirection(0),
     123      4534049 :     myAlreadyChanged(false),
     124      4534049 :     myShadowLane(nullptr),
     125      4534049 :     myTargetLane(nullptr),
     126      4534049 :     myModel(model),
     127      4534049 :     myLastLateralGapLeft(0.),
     128      4534049 :     myLastLateralGapRight(0.),
     129      4534049 :     myLastLeaderGap(0.),
     130      4534049 :     myLastFollowerGap(0.),
     131      4534049 :     myLastLeaderSecureGap(0.),
     132      4534049 :     myLastFollowerSecureGap(0.),
     133      4534049 :     myLastOrigLeaderGap(0.),
     134      4534049 :     myLastOrigLeaderSecureGap(0.),
     135      4534049 :     myLastLeaderSpeed(0),
     136      4534049 :     myLastFollowerSpeed(0),
     137      4534049 :     myLastOrigLeaderSpeed(0),
     138      4534049 :     myDontResetLCGaps(false),
     139      4534049 :     myStrategicLookahead(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_STRATEGIC_LOOKAHEAD, UNDEFINED_LOOKAHEAD)),
     140      4534049 :     myMaxSpeedLatStanding(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING, v.getVehicleType().getMaxSpeedLat())),
     141      4534049 :     myMaxSpeedLatFactor(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR, 1)),
     142      9068098 :     myMaxDistLatStanding(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXDISTLATSTANDING,
     143              :                          // prevent lateral sliding for cars but permit for two-wheelers due to better maneuverability
     144      4534049 :                          (v.getVClass() & (SVC_BICYCLE | SVC_MOTORCYCLE | SVC_MOPED)) != 0 ? std::numeric_limits<double>::max() : 1.6)),
     145      4534049 :     mySigma(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SIGMA, 0.0)),
     146      4534049 :     myOvertakeRightParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_OVERTAKE_RIGHT, 0)),
     147      4534049 :     myAssertive(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_ASSERTIVE, 1)),
     148      4534049 :     myCooperativeHelpTime(TIME2STEPS(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_COOPERATIVE_HELPTIME, 60))),
     149      4534049 :     myCooperativeHelpThreshold(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_COOPERATIVE_HELPTHRESHOLD, -1)),
     150      4534049 :     myCooperativeMinSpeed(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_COOPERATIVE_MINSPEED, 0)),
     151      4534049 :     myHaveBlueLight(v.getDevice(typeid(MSDevice_Bluelight)) != nullptr), // see MSVehicle::initDevices
     152      4534049 :     myLastLaneChangeOffset(0),
     153      4534049 :     myAmOpposite(false),
     154      4534049 :     myManeuverDist(0.),
     155      9068098 :     myPreviousManeuverDist(0.) {
     156              :     saveLCState(-1, LCA_UNKNOWN, LCA_UNKNOWN);
     157              :     saveLCState(0, LCA_UNKNOWN, LCA_UNKNOWN);
     158              :     saveLCState(1, LCA_UNKNOWN, LCA_UNKNOWN);
     159      4534049 : }
     160              : 
     161              : 
     162      4533972 : MSAbstractLaneChangeModel::~MSAbstractLaneChangeModel() {
     163      4533972 : }
     164              : 
     165              : void
     166    294608580 : MSAbstractLaneChangeModel::setOwnState(const int state) {
     167    294608580 :     myPreviousState2 = myPreviousState;
     168    294608580 :     myOwnState = state;
     169    294608580 :     myPreviousState = state; // myOwnState is modified in prepareStep so we make a backup
     170    294608580 : }
     171              : 
     172              : void
     173            0 : MSAbstractLaneChangeModel::updateSafeLatDist(const double travelledLatDist) {
     174              :     UNUSED_PARAMETER(travelledLatDist);
     175            0 : }
     176              : 
     177              : 
     178              : void
     179     83411816 : MSAbstractLaneChangeModel::setManeuverDist(const double dist) {
     180              : #ifdef DEBUG_MANEUVER
     181              :     if (DEBUG_COND) {
     182              :         std::cout << SIMTIME
     183              :                   << " veh=" << myVehicle.getID()
     184              :                   << " setManeuverDist() old=" << myManeuverDist << " new=" << dist
     185              :                   << std::endl;
     186              :     }
     187              : #endif
     188     83411816 :     myManeuverDist = fabs(dist) < NUMERICAL_EPS ? 0. : dist;
     189              :     // store value which may be modified by the model during the next step
     190     83411816 :     myPreviousManeuverDist = myManeuverDist;
     191     83411816 : }
     192              : 
     193              : 
     194              : double
     195    698229414 : MSAbstractLaneChangeModel::getManeuverDist() const {
     196    698229414 :     return myManeuverDist;
     197              : }
     198              : 
     199              : double
     200     14378916 : MSAbstractLaneChangeModel::getPreviousManeuverDist() const {
     201     14378916 :     return myPreviousManeuverDist;
     202              : }
     203              : 
     204              : void
     205     36266425 : MSAbstractLaneChangeModel::saveNeighbors(const int dir, const MSLeaderDistanceInfo& followers, const MSLeaderDistanceInfo& leaders) {
     206     36266425 :     if (dir == -1) {
     207     16759178 :         myLeftFollowers = std::make_shared<MSLeaderDistanceInfo>(followers);
     208     16759178 :         myLeftLeaders = std::make_shared<MSLeaderDistanceInfo>(leaders);
     209     19507247 :     } else if (dir == 1) {
     210     19507247 :         myRightFollowers = std::make_shared<MSLeaderDistanceInfo>(followers);
     211     19507247 :         myRightLeaders = std::make_shared<MSLeaderDistanceInfo>(leaders);
     212              :     } else {
     213              :         // dir \in {-1,1} !
     214              :         assert(false);
     215              :     }
     216     36266425 : }
     217              : 
     218              : 
     219              : void
     220    241469267 : MSAbstractLaneChangeModel::saveNeighbors(const int dir, const std::pair<MSVehicle* const, double>& follower, const std::pair<MSVehicle* const, double>& leader) {
     221    241469267 :     if (dir == -1) {
     222    115728424 :         myLeftFollowers = std::make_shared<MSLeaderDistanceInfo>(follower, myVehicle.getLane()->getWidth());
     223    231456848 :         myLeftLeaders = std::make_shared<MSLeaderDistanceInfo>(leader, myVehicle.getLane()->getWidth());
     224    125740843 :     } else if (dir == 1) {
     225    125740843 :         myRightFollowers = std::make_shared<MSLeaderDistanceInfo>(follower, myVehicle.getLane()->getWidth());
     226    251481686 :         myRightLeaders = std::make_shared<MSLeaderDistanceInfo>(leader, myVehicle.getLane()->getWidth());
     227              :     } else {
     228              :         // dir \in {-1,1} !
     229              :         assert(false);
     230              :     }
     231    241469267 : }
     232              : 
     233              : 
     234              : void
     235    369838341 : MSAbstractLaneChangeModel::clearNeighbors() {
     236              :     myLeftFollowers = nullptr;
     237              :     myLeftLeaders = nullptr;
     238              :     myRightFollowers = nullptr;
     239              :     myRightLeaders = nullptr;
     240    369838341 : }
     241              : 
     242              : 
     243              : const std::shared_ptr<MSLeaderDistanceInfo>
     244            0 : MSAbstractLaneChangeModel::getFollowers(const int dir) {
     245            0 :     if (dir == -1) {
     246              :         return myLeftFollowers;
     247            0 :     } else if (dir == 1) {
     248              :         return myRightFollowers;
     249              :     } else {
     250              :         // dir \in {-1,1} !
     251              :         assert(false);
     252              :     }
     253              :     return nullptr;
     254              : }
     255              : 
     256              : const std::shared_ptr<MSLeaderDistanceInfo>
     257            0 : MSAbstractLaneChangeModel::getLeaders(const int dir) {
     258            0 :     if (dir == -1) {
     259              :         return myLeftLeaders;
     260            0 :     } else if (dir == 1) {
     261              :         return myRightLeaders;
     262              :     } else {
     263              :         // dir \in {-1,1} !
     264              :         assert(false);
     265              :     }
     266              :     return nullptr;
     267              : }
     268              : 
     269              : 
     270              : bool
     271          109 : MSAbstractLaneChangeModel::congested(const MSVehicle* const neighLeader) {
     272          109 :     if (neighLeader == nullptr) {
     273              :         return false;
     274              :     }
     275              :     // Congested situation are relevant only on highways (maxSpeed > 70km/h)
     276              :     // and congested on German Highways means that the vehicles have speeds
     277              :     // below 60km/h. Overtaking on the right is allowed then.
     278            0 :     if ((myVehicle.getLane()->getSpeedLimit() <= 70.0 / 3.6) || (neighLeader->getLane()->getSpeedLimit() <= 70.0 / 3.6)) {
     279              : 
     280            0 :         return false;
     281              :     }
     282            0 :     if (myVehicle.congested() && neighLeader->congested()) {
     283              :         return true;
     284              :     }
     285              :     return false;
     286              : }
     287              : 
     288              : 
     289              : bool
     290    297768046 : MSAbstractLaneChangeModel::avoidOvertakeRight(const MSVehicle* const neighLeader, const bool allowProb) const {
     291    297768046 :     return (!myAllowOvertakingRight  // the highway case
     292    297762595 :             && !myVehicle.congested()
     293     39273171 :             && myVehicle.getVehicleType().getVehicleClass() != SVC_EMERGENCY
     294    595530641 :             && (!allowProb || myOvertakeRightParam == 0 || myOvertakeRightParam < RandHelper::rand(myVehicle.getRNG()))) ||
     295    185308313 :            (neighLeader != nullptr && neighLeader->isStopped()  // the bus stop case
     296       341960 :             && neighLeader->getStops().front().busstop != nullptr
     297    297799457 :             && !StringUtils::toBool(neighLeader->getStops().front().busstop->getParameter("allowOvertakeRight", "true")));
     298              : }
     299              : 
     300              : bool
     301          109 : MSAbstractLaneChangeModel::predInteraction(const std::pair<MSVehicle*, double>& leader) {
     302          109 :     if (leader.first == 0) {
     303              :         return false;
     304              :     }
     305              :     // let's check it on highways only
     306            0 :     if (leader.first->getSpeed() < (80.0 / 3.6)) {
     307              :         return false;
     308              :     }
     309            0 :     return leader.second < getCarFollowModel().interactionGap(&myVehicle, leader.first->getSpeed());
     310              : }
     311              : 
     312              : 
     313              : bool
     314      1138391 : MSAbstractLaneChangeModel::startLaneChangeManeuver(MSLane* source, MSLane* target, int direction) {
     315      1138391 :     if (MSGlobals::gLaneChangeDuration > DELTA_T) {
     316        43070 :         myLaneChangeCompletion = 0;
     317        43070 :         myLaneChangeDirection = direction;
     318        43070 :         setManeuverDist((target->getWidth() + source->getWidth()) * 0.5 * direction);
     319        43070 :         myVehicle.switchOffSignal(MSVehicle::VEH_SIGNAL_BLINKER_RIGHT | MSVehicle::VEH_SIGNAL_BLINKER_LEFT);
     320        43070 :         myVehicle.switchOnSignal(((direction == 1) != MSGlobals::gLefthand) ? MSVehicle::VEH_SIGNAL_BLINKER_LEFT : MSVehicle::VEH_SIGNAL_BLINKER_RIGHT);
     321        43070 :         if (myLCOutput) {
     322          830 :             memorizeGapsAtLCInit();
     323              :         }
     324        43070 :         return true;
     325              :     } else {
     326      1095321 :         primaryLaneChanged(source, target, direction);
     327      1095321 :         return false;
     328              :     }
     329              : }
     330              : 
     331              : void
     332          830 : MSAbstractLaneChangeModel::memorizeGapsAtLCInit() {
     333          830 :     myDontResetLCGaps = true;
     334          830 : }
     335              : 
     336              : void
     337          829 : MSAbstractLaneChangeModel::clearGapsAtLCInit() {
     338          829 :     myDontResetLCGaps = false;
     339          829 : }
     340              : 
     341              : void
     342      1138103 : MSAbstractLaneChangeModel::primaryLaneChanged(MSLane* source, MSLane* target, int direction) {
     343      1138103 :     initLastLaneChangeOffset(direction);
     344      1138103 :     myVehicle.leaveLane(MSMoveReminder::NOTIFICATION_LANE_CHANGE, target);
     345      1138103 :     source->leftByLaneChange(&myVehicle);
     346      2276206 :     laneChangeOutput("change", source, target, direction); // record position on the source edge in case of opposite change
     347      1138103 :     if (&source->getEdge() != &target->getEdge()) {
     348        44219 :         changedToOpposite();
     349              : #ifdef DEBUG_OPPOSITE
     350              :         if (debugVehicle()) {
     351              :             std::cout << SIMTIME << " veh=" << myVehicle.getID() << " primaryLaneChanged source=" << source->getID() << " target=" << target->getID() << " nowOpposite=" << myAmOpposite << "\n";
     352              :         }
     353              : #endif
     354        44219 :         myVehicle.setTentativeLaneAndPosition(target, source->getOppositePos(myVehicle.getPositionOnLane()), -myVehicle.getLateralPositionOnLane());
     355        44219 :         target->forceVehicleInsertion(&myVehicle, myVehicle.getPositionOnLane(), MSMoveReminder::NOTIFICATION_LANE_CHANGE, myVehicle.getLateralPositionOnLane());
     356      1093884 :     } else if (myAmOpposite) {
     357              : #ifdef DEBUG_OPPOSITE
     358              :         if (debugVehicle()) {
     359              :             std::cout << SIMTIME << " veh=" << myVehicle.getID() << " primaryLaneChanged source=" << source->getID() << " target=" << target->getID() << " stayOpposite\n";
     360              :         }
     361              : #endif
     362          230 :         myAlreadyChanged = true;
     363          230 :         myVehicle.setTentativeLaneAndPosition(target, myVehicle.getPositionOnLane(), myVehicle.getLateralPositionOnLane());
     364          230 :         if (!MSGlobals::gSublane) {
     365              :             // in the continous case, the vehicle is added to the target lane via MSLaneChanger::continueChange / registerHop
     366              :             // in the sublane case, the vehicle is added to the target lane via MSLaneChangerSublane::checkChangeOppositeSublane / MSLane::myTmpVehicles
     367           80 :             target->forceVehicleInsertion(&myVehicle, myVehicle.getPositionOnLane(), MSMoveReminder::NOTIFICATION_LANE_CHANGE, myVehicle.getLateralPositionOnLane());
     368              :         }
     369              :     } else {
     370      1093654 :         myVehicle.enterLaneAtLaneChange(target);
     371      1093654 :         target->enteredByLaneChange(&myVehicle);
     372              :     }
     373              :     // Assure that the drive items are up to date (even if the following step is no actionstep for the vehicle).
     374              :     // This is necessary because the lane advance uses the target lane from the corresponding drive item.
     375      1138103 :     myVehicle.updateDriveItems();
     376      1138103 :     changed();
     377      1138103 : }
     378              : 
     379              : void
     380      1138365 : MSAbstractLaneChangeModel::laneChangeOutput(const std::string& tag, MSLane* source, MSLane* target, int direction, double maneuverDist) {
     381      1138365 :     if (myLCOutput) {
     382        17137 :         OutputDevice& of = OutputDevice::getDeviceByOption("lanechange-output");
     383        17137 :         of.openTag(tag);
     384        17137 :         of.writeAttr(SUMO_ATTR_ID, myVehicle.getID());
     385        17137 :         of.writeAttr(SUMO_ATTR_TYPE, myVehicle.getVehicleType().getID());
     386        17137 :         of.writeAttr(SUMO_ATTR_TIME, time2string(MSNet::getInstance()->getCurrentTimeStep()));
     387        17137 :         of.writeAttr(SUMO_ATTR_FROM, source->getID());
     388        17137 :         of.writeAttr(SUMO_ATTR_TO, target->getID());
     389        17137 :         of.writeAttr(SUMO_ATTR_DIR, direction);
     390        17137 :         of.writeAttr(SUMO_ATTR_SPEED, myVehicle.getSpeed());
     391        17137 :         of.writeAttr(SUMO_ATTR_POSITION, myVehicle.getPositionOnLane());
     392        51411 :         of.writeAttr("reason", toString((LaneChangeAction)(myOwnState & ~(
     393              :                                             LCA_RIGHT | LCA_LEFT
     394              :                                             | LCA_AMBLOCKINGLEADER | LCA_AMBLOCKINGFOLLOWER
     395              :                                             | LCA_MRIGHT | LCA_MLEFT
     396        34274 :                                             | LCA_AMBACKBLOCKER | LCA_AMBACKBLOCKER_STANDING))) + myVehicle.getParameter().getParameter("lcReason"));
     397        17137 :         of.writeAttr("leaderGap", myLastLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderGap), myLastLeaderGap == NO_NEIGHBOR);
     398        17137 :         of.writeAttr("leaderSecureGap", myLastLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderSecureGap), myLastLeaderSecureGap == NO_NEIGHBOR);
     399        17137 :         of.writeAttr("leaderSpeed", myLastLeaderSpeed == NO_NEIGHBOR ? "None" : toString(myLastLeaderSpeed), myLastLeaderSpeed == NO_NEIGHBOR);
     400        17137 :         of.writeAttr("followerGap", myLastFollowerGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerGap), myLastFollowerGap == NO_NEIGHBOR);
     401        17137 :         of.writeAttr("followerSecureGap", myLastFollowerSecureGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerSecureGap), myLastFollowerSecureGap == NO_NEIGHBOR);
     402        17137 :         of.writeAttr("followerSpeed", myLastFollowerSpeed == NO_NEIGHBOR ? "None" : toString(myLastFollowerSpeed), myLastFollowerSpeed == NO_NEIGHBOR);
     403        17137 :         of.writeAttr("origLeaderGap", myLastOrigLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderGap), myLastOrigLeaderGap == NO_NEIGHBOR);
     404        17137 :         of.writeAttr("origLeaderSecureGap", myLastOrigLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderSecureGap), myLastOrigLeaderSecureGap == NO_NEIGHBOR);
     405        17137 :         of.writeAttr("origLeaderSpeed", myLastOrigLeaderSpeed == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderSpeed), myLastOrigLeaderSpeed == NO_NEIGHBOR);
     406        17137 :         if (MSGlobals::gLateralResolution > 0) {
     407         7869 :             const double latGap = direction < 0 ? myLastLateralGapRight : myLastLateralGapLeft;
     408         7869 :             of.writeAttr("latGap", latGap == NO_NEIGHBOR ? "None" : toString(latGap), latGap == NO_NEIGHBOR);
     409         7869 :             if (maneuverDist != 0) {
     410          372 :                 of.writeAttr("maneuverDistance", toString(maneuverDist));
     411              :             }
     412              :         }
     413        17137 :         if (myLCXYOutput) {
     414           62 :             of.writeAttr(SUMO_ATTR_X, myVehicle.getPosition().x());
     415           62 :             of.writeAttr(SUMO_ATTR_Y, myVehicle.getPosition().y());
     416              :         }
     417        17137 :         of.closeTag();
     418        17137 :         if (MSGlobals::gLaneChangeDuration > DELTA_T) {
     419          829 :             clearGapsAtLCInit();
     420              :         }
     421              :     }
     422      1138365 : }
     423              : 
     424              : 
     425              : double
     426       619955 : MSAbstractLaneChangeModel::computeSpeedLat(double /*latDist*/, double& maneuverDist, bool /*urgent*/) const {
     427       619955 :     if (myVehicle.getVehicleType().wasSet(VTYPEPARS_MAXSPEED_LAT_SET)) {
     428          686 :         int stepsToChange = (int)ceil(fabs(maneuverDist) / SPEED2DIST(myVehicle.getVehicleType().getMaxSpeedLat()));
     429          686 :         return DIST2SPEED(maneuverDist / stepsToChange);
     430              :     } else {
     431       619269 :         return maneuverDist / STEPS2TIME(MSGlobals::gLaneChangeDuration);
     432              :     }
     433              : }
     434              : 
     435              : 
     436              : double
     437        80833 : MSAbstractLaneChangeModel::getAssumedDecelForLaneChangeDuration() const {
     438        80833 :     return MAX2(LC_ASSUMED_DECEL, -myVehicle.getAcceleration());
     439              : }
     440              : 
     441              : void
     442     86633435 : MSAbstractLaneChangeModel::setSpeedLat(double speedLat) {
     443     86633435 :     myAccelerationLat = SPEED2ACCEL(speedLat - mySpeedLat);
     444     86633435 :     mySpeedLat = speedLat;
     445     86633435 : }
     446              : 
     447              : 
     448              : void
     449    618109649 : MSAbstractLaneChangeModel::resetSpeedLat() {
     450    618109649 :     if (MSGlobals::gLaneChangeDuration > 0 && !isChangingLanes()) {
     451      2562943 :         setSpeedLat(0);
     452              :     }
     453    618109649 : }
     454              : 
     455              : 
     456              : bool
     457       593482 : MSAbstractLaneChangeModel::updateCompletion() {
     458              :     const bool pastBefore = pastMidpoint();
     459              :     // maneuverDist is not updated in the context of continuous lane changing but represents the full LC distance
     460       593482 :     double maneuverDist = getManeuverDist();
     461       593482 :     setSpeedLat(computeSpeedLat(0, maneuverDist, (myOwnState & LCA_URGENT) != 0));
     462       593482 :     myLaneChangeCompletion += (SPEED2DIST(mySpeedLat) / myManeuverDist);
     463       593482 :     return !pastBefore && pastMidpoint();
     464              : }
     465              : 
     466              : 
     467              : void
     468        71298 : MSAbstractLaneChangeModel::endLaneChangeManeuver(const MSMoveReminder::Notification reason) {
     469              :     UNUSED_PARAMETER(reason);
     470        71298 :     myLaneChangeCompletion = 1;
     471        71298 :     cleanupShadowLane();
     472        71298 :     cleanupTargetLane();
     473              :     myNoPartiallyOccupatedByShadow.clear();
     474        71298 :     myVehicle.switchOffSignal(MSVehicle::VEH_SIGNAL_BLINKER_RIGHT | MSVehicle::VEH_SIGNAL_BLINKER_LEFT);
     475        71298 :     myVehicle.fixPosition();
     476        71298 :     if (myAmOpposite && reason != MSMoveReminder::NOTIFICATION_LANE_CHANGE) {
     477          133 :         if (reason == MSMoveReminder::NOTIFICATION_PARKING && myVehicle.getNextStop().isOpposite) {
     478              :             // opposite driving continues after parking
     479              :         } else {
     480              :             // aborted maneuver
     481              : #ifdef DEBUG_OPPOSITE
     482              :             if (debugVehicle()) {
     483              :                 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " aborted maneuver (no longer opposite)\n";
     484              :             }
     485              : #endif
     486          108 :             changedToOpposite();
     487              :         }
     488              :     }
     489        71298 : }
     490              : 
     491              : 
     492              : MSLane*
     493     18546810 : MSAbstractLaneChangeModel::getShadowLane(const MSLane* lane, double posLat) const {
     494     18546810 :     if (std::find(myNoPartiallyOccupatedByShadow.begin(), myNoPartiallyOccupatedByShadow.end(), lane) == myNoPartiallyOccupatedByShadow.end()) {
     495              :         // initialize shadow lane
     496     18546726 :         const double overlap = myVehicle.getLateralOverlap(posLat, lane);
     497              : #ifdef DEBUG_SHADOWLANE
     498              :         if (debugVehicle()) {
     499              :             std::cout << SIMTIME << " veh=" << myVehicle.getID() << " posLat=" << posLat << " overlap=" << overlap << "\n";
     500              :         }
     501              : #endif
     502     18546726 :         if (myAmOpposite) {
     503              :             // return the neigh-lane in forward direction
     504       540223 :             return lane->getParallelLane(1);
     505     18006503 :         } else if (overlap > NUMERICAL_EPS) {
     506     10564561 :             const int shadowDirection = posLat < 0 ? -1 : 1;
     507     10564561 :             return lane->getParallelLane(shadowDirection);
     508      7441942 :         } else if (isChangingLanes() && myLaneChangeCompletion < 0.5) {
     509              :             // "reserve" target lane even when there is no overlap yet
     510       254337 :             return lane->getParallelLane(myLaneChangeDirection);
     511              :         } else {
     512              :             return nullptr;
     513              :         }
     514              :     } else {
     515              :         return nullptr;
     516              :     }
     517              : }
     518              : 
     519              : 
     520              : MSLane*
     521     18407712 : MSAbstractLaneChangeModel::getShadowLane(const MSLane* lane) const {
     522     18407712 :     return getShadowLane(lane, myVehicle.getLateralPositionOnLane());
     523              : }
     524              : 
     525              : 
     526              : void
     527      4605832 : MSAbstractLaneChangeModel::cleanupShadowLane() {
     528      4605832 :     if (myShadowLane != nullptr) {
     529        22436 :         if (debugVehicle()) {
     530            0 :             std::cout << SIMTIME << " cleanupShadowLane\n";
     531              :         }
     532        22436 :         myShadowLane->resetPartialOccupation(&myVehicle);
     533        22436 :         myShadowLane = nullptr;
     534              :     }
     535      4606898 :     for (MSLane* further : myShadowFurtherLanes) {
     536         1066 :         if (debugVehicle()) {
     537            0 :             std::cout << SIMTIME << " cleanupShadowLane2\n";
     538              :         }
     539         1066 :         further->resetPartialOccupation(&myVehicle);
     540         1066 :         if (further->getBidiLane() != nullptr) {
     541           30 :             further->getBidiLane()->resetPartialOccupation(&myVehicle);
     542              :         }
     543              :     }
     544              :     myShadowFurtherLanes.clear();
     545              :     myNoPartiallyOccupatedByShadow.clear();
     546      4605832 : }
     547              : 
     548              : void
     549      4605832 : MSAbstractLaneChangeModel::cleanupTargetLane() {
     550      4605832 :     if (myTargetLane != nullptr) {
     551          617 :         if (debugVehicle()) {
     552            0 :             std::cout << SIMTIME << " cleanupTargetLane\n";
     553              :         }
     554          617 :         myTargetLane->resetManeuverReservation(&myVehicle);
     555          617 :         myTargetLane = nullptr;
     556              :     }
     557      4605841 :     for (std::vector<MSLane*>::const_iterator it = myFurtherTargetLanes.begin(); it != myFurtherTargetLanes.end(); ++it) {
     558            9 :         if (debugVehicle()) {
     559            0 :             std::cout << SIMTIME << " cleanupTargetLane\n";
     560              :         }
     561            9 :         if (*it != nullptr) {
     562            9 :             (*it)->resetManeuverReservation(&myVehicle);
     563              :         }
     564              :     }
     565              :     myFurtherTargetLanes.clear();
     566              : //    myNoPartiallyOccupatedByShadow.clear();
     567      4605832 : }
     568              : 
     569              : 
     570              : bool
     571     28925061 : MSAbstractLaneChangeModel::cancelRequest(int state, int laneOffset) {
     572              :     // store request before canceling
     573     28925061 :     getCanceledState(laneOffset) |= state;
     574     28925061 :     int ret = myVehicle.influenceChangeDecision(state);
     575     28925061 :     return ret != state;
     576              : }
     577              : 
     578              : double
     579     19940387 : MSAbstractLaneChangeModel::getMaxSpeedLat2() const {
     580     19940387 :     return MAX2(myVehicle.getVehicleType().getMaxSpeedLat(), myMaxSpeedLatStanding);
     581              : }
     582              : 
     583              : void
     584      1138103 : MSAbstractLaneChangeModel::initLastLaneChangeOffset(int dir) {
     585      1138103 :     if (dir > 0) {
     586       626355 :         myLastLaneChangeOffset = 1;
     587       511748 :     } else if (dir < 0) {
     588       511748 :         myLastLaneChangeOffset = -1;
     589              :     }
     590      1138103 : }
     591              : 
     592              : void
     593      6152236 : MSAbstractLaneChangeModel::updateShadowLane() {
     594      6152236 :     if (!MSGlobals::gSublane) {
     595              :         // assume each vehicle drives at the center of its lane and act as if it fits
     596       640253 :         return;
     597              :     }
     598      5511983 :     if (myShadowLane != nullptr) {
     599              : #ifdef DEBUG_SHADOWLANE
     600              :         if (debugVehicle()) {
     601              :             std::cout << SIMTIME << " updateShadowLane()\n";
     602              :         }
     603              : #endif
     604      1910993 :         myShadowLane->resetPartialOccupation(&myVehicle);
     605              :     }
     606      5511983 :     myShadowLane = getShadowLane(myVehicle.getLane());
     607              :     std::vector<MSLane*> passed;
     608      5511983 :     if (myShadowLane != nullptr) {
     609      1933429 :         myShadowLane->setPartialOccupation(&myVehicle);
     610      1933429 :         const std::vector<MSLane*>& further = myVehicle.getFurtherLanes();
     611      1933429 :         if (myAmOpposite) {
     612              :             assert(further.size() == 0);
     613              :         } else {
     614              :             const std::vector<double>& furtherPosLat = myVehicle.getFurtherLanesPosLat();
     615              :             assert(further.size() == furtherPosLat.size());
     616      1715742 :             passed.push_back(myShadowLane);
     617      1854840 :             for (int i = 0; i < (int)further.size(); ++i) {
     618       139098 :                 MSLane* shadowFurther = getShadowLane(further[i], furtherPosLat[i]);
     619              : #ifdef DEBUG_SHADOWLANE
     620              :                 if (debugVehicle()) {
     621              :                     std::cout << SIMTIME << "   further=" << further[i]->getID() << " (posLat=" << furtherPosLat[i] << ") shadowFurther=" << Named::getIDSecure(shadowFurther) << "\n";
     622              :                 }
     623              : #endif
     624       139098 :                 if (shadowFurther != nullptr && shadowFurther->getLinkTo(passed.back()) != nullptr) {
     625        61099 :                     passed.push_back(shadowFurther);
     626              :                 }
     627              :             }
     628              :             std::reverse(passed.begin(), passed.end());
     629              :         }
     630              :     } else {
     631      3578554 :         if (isChangingLanes() && myVehicle.getLateralOverlap() > NUMERICAL_EPS) {
     632            4 :             WRITE_WARNING("Vehicle '" + myVehicle.getID() + "' could not finish continuous lane change (lane disappeared) time=" +
     633              :                           time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
     634            1 :             endLaneChangeManeuver();
     635              :         }
     636              :     }
     637              : #ifdef DEBUG_SHADOWLANE
     638              :     if (debugVehicle()) {
     639              :         std::cout << SIMTIME << " updateShadowLane() veh=" << myVehicle.getID()
     640              :                   << " newShadowLane=" << Named::getIDSecure(myShadowLane)
     641              :                   << "\n   before:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << " further=" << toString(myVehicle.getFurtherLanes()) << " passed=" << toString(passed);
     642              :         std::cout << std::endl;
     643              :     }
     644              : #endif
     645      5511983 :     myVehicle.updateFurtherLanes(myShadowFurtherLanes, myShadowFurtherLanesPosLat, passed);
     646              : #ifdef DEBUG_SHADOWLANE
     647              :     if (debugVehicle()) std::cout
     648              :                 << "\n   after:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << "\n";
     649              : #endif
     650      5511983 : }
     651              : 
     652              : 
     653              : int
     654      9921593 : MSAbstractLaneChangeModel::getShadowDirection() const {
     655      9921593 :     if (isChangingLanes()) {
     656       694051 :         if (pastMidpoint()) {
     657       253489 :             return -myLaneChangeDirection;
     658              :         } else {
     659       440562 :             return myLaneChangeDirection;
     660              :         }
     661      9227542 :     } else if (myShadowLane == nullptr) {
     662              :         return 0;
     663      9227542 :     } else if (myAmOpposite) {
     664              :         // return neigh-lane in forward direction
     665              :         return 1;
     666      8720041 :     } else if (&myShadowLane->getEdge() == &myVehicle.getLane()->getEdge()) {
     667      8618286 :         return myShadowLane->getIndex() - myVehicle.getLane()->getIndex();
     668              :     } else {
     669              :         // overlap with opposite direction lane
     670              :         return 1;
     671              :     }
     672              : }
     673              : 
     674              : 
     675              : MSLane*
     676     88328060 : MSAbstractLaneChangeModel::updateTargetLane() {
     677              : #ifdef DEBUG_TARGET_LANE
     678              :     MSLane* oldTarget = myTargetLane;
     679              :     std::vector<MSLane*> oldFurtherTargets = myFurtherTargetLanes;
     680              :     if (debugVehicle()) {
     681              :         std::cout << SIMTIME << " veh '" << myVehicle.getID() << "' (lane=" << myVehicle.getLane()->getID() << ") updateTargetLane()"
     682              :                   << "\n   oldTarget: " << (oldTarget == nullptr ? "NULL" : oldTarget->getID())
     683              :                   << " oldFurtherTargets: " << toString(oldFurtherTargets);
     684              :     }
     685              : #endif
     686     88328060 :     if (myTargetLane != nullptr) {
     687       221364 :         myTargetLane->resetManeuverReservation(&myVehicle);
     688              :     }
     689              :     // Clear old further target lanes
     690     88341567 :     for (MSLane* oldTargetLane : myFurtherTargetLanes) {
     691        13507 :         if (oldTargetLane != nullptr) {
     692         8779 :             oldTargetLane->resetManeuverReservation(&myVehicle);
     693              :         }
     694              :     }
     695              :     myFurtherTargetLanes.clear();
     696              : 
     697              :     // Get new target lanes and issue a maneuver reservation.
     698              :     int targetDir;
     699     88328060 :     myTargetLane = determineTargetLane(targetDir);
     700     88328060 :     if (myTargetLane != nullptr) {
     701       221981 :         myTargetLane->setManeuverReservation(&myVehicle);
     702              :         // further targets are just the target lanes corresponding to the vehicle's further lanes
     703              :         // @note In a neglectable amount of situations we might add a reservation for a shadow further lane.
     704       235497 :         for (MSLane* furtherLane : myVehicle.getFurtherLanes()) {
     705        13516 :             MSLane* furtherTargetLane = furtherLane->getParallelLane(targetDir);
     706        13516 :             myFurtherTargetLanes.push_back(furtherTargetLane);
     707        13516 :             if (furtherTargetLane != nullptr) {
     708         8788 :                 furtherTargetLane->setManeuverReservation(&myVehicle);
     709              :             }
     710              :         }
     711              :     }
     712              : #ifdef DEBUG_TARGET_LANE
     713              :     if (debugVehicle()) {
     714              :         std::cout << "\n   newTarget (maneuverDist=" << myManeuverDist << " offset=" << targetDir << "): " << (myTargetLane == nullptr ? "NULL" : myTargetLane->getID())
     715              :                   << " newFurtherTargets: " << toString(myFurtherTargetLanes)
     716              :                   << std::endl;
     717              :     }
     718              : #endif
     719     88328060 :     return myTargetLane;
     720              : }
     721              : 
     722              : 
     723              : MSLane*
     724     88328060 : MSAbstractLaneChangeModel::determineTargetLane(int& targetDir) const {
     725     88328060 :     targetDir = 0;
     726     88328060 :     if (myManeuverDist == 0) {
     727              :         return nullptr;
     728              :     }
     729              :     // Current lateral boundaries of the vehicle
     730      2487543 :     const double vehRight = myVehicle.getLateralPositionOnLane() - 0.5 * myVehicle.getWidth();
     731      2487543 :     const double vehLeft = myVehicle.getLateralPositionOnLane() + 0.5 * myVehicle.getWidth();
     732      2487543 :     const double halfLaneWidth = 0.5 * myVehicle.getLane()->getWidth();
     733              : 
     734      2487543 :     if (vehRight + myManeuverDist < -halfLaneWidth) {
     735              :         // Vehicle intends to traverse the right lane boundary
     736       333661 :         targetDir = -1;
     737      2153882 :     } else if (vehLeft + myManeuverDist > halfLaneWidth) {
     738              :         // Vehicle intends to traverse the left lane boundary
     739       521030 :         targetDir = 1;
     740              :     }
     741      2487543 :     if (targetDir == 0) {
     742              :         // Presently, no maneuvering into another lane is begun.
     743              :         return nullptr;
     744              :     }
     745       854691 :     MSLane* target = myVehicle.getLane()->getParallelLane(targetDir);
     746       854691 :     if (target == nullptr || target == myShadowLane) {
     747              :         return nullptr;
     748              :     } else {
     749              :         return target;
     750              :     }
     751              : }
     752              : 
     753              : 
     754              : 
     755              : double
     756    712472594 : MSAbstractLaneChangeModel::calcAngleOffset() {
     757              :     double result = 0.;
     758    712472594 :     if (!(fabs(mySpeedLat) < NUMERICAL_EPS && fabs(myPreviousAngleOffset * 180 / M_PI) < NUMERICAL_EPS)) {
     759     20721389 :         if (myVehicle.getLength() < sqrt(SPEED2DIST(mySpeedLat) * SPEED2DIST(mySpeedLat) + SPEED2DIST(myVehicle.getSpeed()) * SPEED2DIST(myVehicle.getSpeed()))) {
     760      5727429 :             result = atan2(mySpeedLat, myVehicle.getSpeed());
     761              :         } else {
     762     14993960 :             result = myPreviousAngleOffset + asin((sin(M_PI / 2 - myPreviousAngleOffset) * (SPEED2DIST(mySpeedLat) - tan(myPreviousAngleOffset) * SPEED2DIST(myVehicle.getSpeed()))) / myVehicle.getLength());
     763              :         }
     764              :     }
     765              : 
     766    712472594 :     myAngleOffset = result;
     767    712472594 :     return result;
     768              : }
     769              : 
     770              : 
     771              : double
     772        81555 : MSAbstractLaneChangeModel::estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel, bool urgent) const {
     773              : 
     774        81555 :     const SUMOVTypeParameter::SubParams& lcParams = myVehicle.getVehicleType().getParameter().getLCParams();
     775       136206 :     if (lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING) == lcParams.end() && lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR) == lcParams.end()) {
     776        54651 :         if (!myVehicle.getVehicleType().wasSet(VTYPEPARS_MAXSPEED_LAT_SET)) {
     777              :             // no dependency of lateral speed on longitudinal speed. (Only called prior to LC initialization to determine whether it could be completed)
     778        54625 :             return STEPS2TIME(MSGlobals::gLaneChangeDuration);
     779              :         } else {
     780           26 :             return remainingManeuverDist / myVehicle.getVehicleType().getMaxSpeedLat();
     781              :         }
     782              :     }
     783              : 
     784        26904 :     if (remainingManeuverDist == 0) {
     785              :         return 0;
     786              :     }
     787              : 
     788              :     // Check argument assumptions
     789              :     assert(speed >= 0);
     790              :     assert(remainingManeuverDist >= 0);
     791              :     assert(decel > 0);
     792              :     assert(myVehicle.getVehicleType().getMaxSpeedLat() > 0);
     793              :     assert(myMaxSpeedLatStanding <= myVehicle.getVehicleType().getMaxSpeedLat());
     794              :     assert(myMaxSpeedLatStanding >= 0);
     795              : 
     796              :     // for brevity
     797              :     const double v0 = speed;
     798              :     const double D = remainingManeuverDist;
     799              :     const double b = decel;
     800        26904 :     const double wmin = myMaxSpeedLatStanding;
     801        26904 :     const double f = myMaxSpeedLatFactor;
     802        26904 :     const double wmax = myVehicle.getVehicleType().getMaxSpeedLat();
     803              : 
     804              :     /* Here's the approach for the calculation of the required time for the LC:
     805              :      * To obtain the maximal LC-duration, for v(t) we assume that v(t)=max(0, v0-b*t),
     806              :      * Where v(t)=0 <=> t >= ts:=v0/b
     807              :      * For the lateral speed w(t) this gives:
     808              :      * w(t) = min(wmax, wmin + f*v(t))
     809              :      * The lateral distance covered until t is
     810              :      * d(t) = int_0^t w(s) ds
     811              :      * We distinguish three possibilities for the solution d(T)=D, where T is the time of the LC completion.
     812              :      * 1) w(T) = wmax, i.e. v(T)>(wmax-wmin)/f
     813              :      * 2) wmin < w(T) < wmax, i.e. (wmax-wmin)/f > v(T) > 0
     814              :      * 3) w(T) = wmin, i.e., v(T)=0
     815              :      */
     816        26904 :     const double vm = (wmax - wmin) / f;
     817              :     double distSoFar = 0.;
     818              :     double timeSoFar = 0.;
     819              :     double v = v0;
     820        26904 :     if (v > vm) {
     821         1411 :         const double wmaxTime = (v0 - vm) / b;
     822         1411 :         const double d1 = wmax * wmaxTime;
     823         1411 :         if (d1 >= D) {
     824          420 :             return D / wmax;
     825              :         } else {
     826          991 :             distSoFar += d1;
     827          991 :             timeSoFar += wmaxTime;
     828              :             v = vm;
     829              :         }
     830              :     }
     831        26484 :     if (v > 0) {
     832              :         /* Here, w(t1+t) = wmin + f*v(t1+t) = wmin + f*(v - b*t)
     833              :          * Thus, the additional lateral distance covered after time t is:
     834              :          * d2 = (wmin + f*v)*t - 0.5*f*b*t^2
     835              :          * and the additional lateral distance covered until v=0 at t=v/b is:
     836              :          * d2 = (wmin + 0.5*f*v)*t
     837              :          */
     838         5655 :         const double t = v / b; // stop time
     839         5655 :         const double d2 = (wmin + 0.5 * f * v) * t; // lateral distance covered until stop
     840              :         assert(d2 > 0);
     841         5655 :         if (distSoFar + d2 >= D) {
     842              :             // LC is completed during this phase
     843           11 :             const double x = 0.5 * f * b;
     844           11 :             const double y = wmin + f * v;
     845              :             /* Solve D - distSoFar = y*t - x*t^2.
     846              :              * 0 = x*t^2 - y*t/x + (D - distSoFar)/x
     847              :              */
     848           11 :             const double p = 0.5 * y / x;
     849           11 :             const double q = (D - distSoFar) / x;
     850              :             assert(p * p - q > 0);
     851           11 :             const double t2 = p + sqrt(p * p - q);
     852           11 :             return timeSoFar + t2;
     853              :         } else {
     854              :             distSoFar += d2;
     855         5644 :             timeSoFar += t;
     856              :             //v = 0;
     857              :         }
     858              :     }
     859              :     // If we didn't return yet this means the LC was not completed until the vehicle stops (if braking with rate b)
     860        26473 :     if (wmin == 0) {
     861              :         // LC won't be completed if vehicle stands
     862        26473 :         double maneuverDist = remainingManeuverDist;
     863        26473 :         const double vModel = computeSpeedLat(maneuverDist, maneuverDist, urgent);
     864        26473 :         double result = D / vModel;
     865              :         // make sure that the vehicle isn't braking to a stop during the manuever
     866        26473 :         if (vModel > SUMO_const_haltingSpeed && (vModel + myVehicle.getAcceleration() * result) > SUMO_const_haltingSpeed) {
     867              :             // unless the model tells us something different
     868              :             return result;
     869              :         } else {
     870        25725 :             return -1;
     871              :         }
     872              :     } else {
     873              :         // complete LC with lateral speed wmin
     874            0 :         return timeSoFar + (D - distSoFar) / wmin;
     875              :     }
     876              : }
     877              : 
     878              : SUMOTime
     879        54636 : MSAbstractLaneChangeModel::remainingTime() const {
     880              :     assert(isChangingLanes()); // Only to be called during ongoing lane change
     881        54636 :     const SUMOVTypeParameter::SubParams& lcParams = myVehicle.getVehicleType().getParameter().getLCParams();
     882       108911 :     if (lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING) == lcParams.end() && lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR) == lcParams.end()) {
     883        54275 :         if (myVehicle.getVehicleType().wasSet(VTYPEPARS_MAXSPEED_LAT_SET)) {
     884            0 :             return TIME2STEPS((1. - myLaneChangeCompletion) * myManeuverDist / myVehicle.getVehicleType().getMaxSpeedLat());
     885              :         } else {
     886        54275 :             return (SUMOTime)((1. - myLaneChangeCompletion) * (double)MSGlobals::gLaneChangeDuration);
     887              :         }
     888              :     }
     889              :     // Using maxSpeedLat(Factor/Standing)
     890          361 :     const bool urgent = (myOwnState & LCA_URGENT) != 0;
     891          406 :     return TIME2STEPS(estimateLCDuration(myVehicle.getSpeed(),
     892              :                                          fabs(myManeuverDist * (1 - myLaneChangeCompletion)),
     893              :                                          myVehicle.getCarFollowModel().getMaxDecel(), urgent));
     894              : }
     895              : 
     896              : 
     897              : void
     898      2447757 : MSAbstractLaneChangeModel::setShadowApproachingInformation(MSLink* link) const {
     899              :     //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " set shadow approaching=" << link->getViaLaneOrLane()->getID() << "\n";
     900      2447757 :     myApproachedByShadow.push_back(link);
     901      2447757 : }
     902              : 
     903              : void
     904    645011233 : MSAbstractLaneChangeModel::removeShadowApproachingInformation() const {
     905    647458990 :     for (std::vector<MSLink*>::iterator it = myApproachedByShadow.begin(); it != myApproachedByShadow.end(); ++it) {
     906              :         //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " remove shadow approaching=" << (*it)->getViaLaneOrLane()->getID() << "\n";
     907      2447757 :         (*it)->removeApproaching(&myVehicle);
     908              :     }
     909              :     myApproachedByShadow.clear();
     910    645011233 : }
     911              : 
     912              : 
     913              : 
     914              : void
     915     41336561 : MSAbstractLaneChangeModel::checkTraCICommands() {
     916     41336561 :     int newstate = myVehicle.influenceChangeDecision(myOwnState);
     917     41336561 :     int oldstate = myVehicle.getLaneChangeModel().getOwnState();
     918     41336561 :     if (myOwnState != newstate) {
     919           16 :         if (MSGlobals::gLateralResolution > 0.) {
     920              :             // Calculate and set the lateral maneuver distance corresponding to the change request
     921              :             // to induce a corresponding sublane change.
     922           12 :             const int dir = (newstate & LCA_RIGHT) != 0 ? -1 : ((newstate & LCA_LEFT) != 0 ? 1 : 0);
     923              :             // minimum distance to move the vehicle fully onto the lane at offset dir
     924           12 :             const double latLaneDist = myVehicle.lateralDistanceToLane(dir);
     925           12 :             if ((newstate & LCA_TRACI) != 0) {
     926           12 :                 if ((newstate & LCA_STAY) != 0) {
     927            0 :                     setManeuverDist(0.);
     928           12 :                 } else if (((newstate & LCA_RIGHT) != 0 && dir < 0)
     929            8 :                            || ((newstate & LCA_LEFT) != 0 && dir > 0)) {
     930            4 :                     setManeuverDist(latLaneDist);
     931              :                 }
     932              :             }
     933           12 :             if (myVehicle.hasInfluencer()) {
     934              :                 // lane change requests override sublane change requests
     935           12 :                 myVehicle.getInfluencer().resetLatDist();
     936              :             }
     937              : 
     938              :         }
     939           16 :         setOwnState(newstate);
     940              :     } else {
     941              :         // Check for sublane change requests
     942     41336545 :         if (myVehicle.hasInfluencer() && myVehicle.getInfluencer().getLatDist() != 0) {
     943          304 :             const double maneuverDist = myVehicle.getInfluencer().getLatDist();
     944          304 :             myVehicle.getLaneChangeModel().setManeuverDist(maneuverDist);
     945          304 :             myVehicle.getInfluencer().resetLatDist();
     946          304 :             newstate |= LCA_TRACI;
     947          304 :             if (myOwnState != newstate) {
     948            4 :                 setOwnState(newstate);
     949              :             }
     950          304 :             if (gDebugFlag2) {
     951            0 :                 std::cout << "     traci influenced maneuverDist=" << maneuverDist << "\n";
     952              :             }
     953              :         }
     954              :     }
     955     41336561 :     if (gDebugFlag2) {
     956            0 :         std::cout << SIMTIME << " veh=" << myVehicle.getID() << " stateAfterTraCI=" << toString((LaneChangeAction)newstate) << " original=" << toString((LaneChangeAction)oldstate) << "\n";
     957              :     }
     958     41336561 : }
     959              : 
     960              : void
     961        44381 : MSAbstractLaneChangeModel::changedToOpposite() {
     962        44381 :     myAmOpposite = !myAmOpposite;
     963        44381 :     myAlreadyChanged = true;
     964        44381 : }
     965              : 
     966              : void
     967       748862 : MSAbstractLaneChangeModel::setFollowerGaps(CLeaderDist follower, double secGap)  {
     968       748862 :     if (follower.first != 0) {
     969       419656 :         myLastFollowerGap = follower.second + follower.first->getVehicleType().getMinGap();
     970       419656 :         myLastFollowerSecureGap = secGap;
     971       419656 :         myLastFollowerSpeed = follower.first->getSpeed();
     972              :     }
     973       748862 : }
     974              : 
     975              : void
     976       748862 : MSAbstractLaneChangeModel::setLeaderGaps(CLeaderDist leader, double secGap) {
     977       748862 :     if (leader.first != 0) {
     978       549162 :         myLastLeaderGap = leader.second + myVehicle.getVehicleType().getMinGap();
     979       549162 :         myLastLeaderSecureGap = secGap;
     980       549162 :         myLastLeaderSpeed = leader.first->getSpeed();
     981              :     }
     982       748862 : }
     983              : 
     984              : void
     985       748862 : MSAbstractLaneChangeModel::setOrigLeaderGaps(CLeaderDist leader, double secGap) {
     986       748862 :     if (leader.first != 0) {
     987       444477 :         myLastOrigLeaderGap = leader.second + myVehicle.getVehicleType().getMinGap();
     988       444477 :         myLastOrigLeaderSecureGap = secGap;
     989       444477 :         myLastOrigLeaderSpeed = leader.first->getSpeed();
     990              :     }
     991       748862 : }
     992              : 
     993              : void
     994    630100849 : MSAbstractLaneChangeModel::prepareStep() {
     995    630100849 :     getCanceledState(-1) = LCA_NONE;
     996    630100849 :     getCanceledState(0) = LCA_NONE;
     997    630100849 :     getCanceledState(1) = LCA_NONE;
     998              :     saveLCState(-1, LCA_UNKNOWN, LCA_UNKNOWN);
     999              :     saveLCState(0, LCA_UNKNOWN, LCA_UNKNOWN);
    1000              :     saveLCState(1, LCA_UNKNOWN, LCA_UNKNOWN);
    1001    630100849 :     myLastLateralGapRight = NO_NEIGHBOR;
    1002    630100849 :     myLastLateralGapLeft = NO_NEIGHBOR;
    1003    630100849 :     if (!myDontResetLCGaps) {
    1004    630095766 :         myLastLeaderGap = NO_NEIGHBOR;
    1005    630095766 :         myLastLeaderSecureGap = NO_NEIGHBOR;
    1006    630095766 :         myLastFollowerGap = NO_NEIGHBOR;
    1007    630095766 :         myLastFollowerSecureGap = NO_NEIGHBOR;
    1008    630095766 :         myLastOrigLeaderGap = NO_NEIGHBOR;
    1009    630095766 :         myLastOrigLeaderSecureGap = NO_NEIGHBOR;
    1010    630095766 :         myLastLeaderSpeed = NO_NEIGHBOR;
    1011    630095766 :         myLastFollowerSpeed = NO_NEIGHBOR;
    1012    630095766 :         myLastOrigLeaderSpeed = NO_NEIGHBOR;
    1013              :     }
    1014    630100849 :     myCommittedSpeed = 0;
    1015    630100849 : }
    1016              : 
    1017              : void
    1018         7869 : MSAbstractLaneChangeModel::setFollowerGaps(const MSLeaderDistanceInfo& vehicles) {
    1019              :     int rightmost;
    1020              :     int leftmost;
    1021         7869 :     vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
    1022        31844 :     for (int i = rightmost; i <= leftmost; ++i) {
    1023        23975 :         CLeaderDist vehDist = vehicles[i];
    1024        23975 :         if (vehDist.first != 0) {
    1025        15819 :             const MSVehicle* leader = &myVehicle;
    1026              :             const MSVehicle* follower = vehDist.first;
    1027        15819 :             const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
    1028        15819 :             if (netGap < myLastFollowerGap && netGap >= 0) {
    1029         6829 :                 myLastFollowerGap = netGap;
    1030         6829 :                 myLastFollowerSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
    1031         6829 :                 myLastFollowerSpeed = follower->getSpeed();
    1032              :             }
    1033              :         }
    1034              :     }
    1035         7869 : }
    1036              : 
    1037              : void
    1038         7869 : MSAbstractLaneChangeModel::setLeaderGaps(const MSLeaderDistanceInfo& vehicles) {
    1039              :     int rightmost;
    1040              :     int leftmost;
    1041         7869 :     vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
    1042        31844 :     for (int i = rightmost; i <= leftmost; ++i) {
    1043        23975 :         CLeaderDist vehDist = vehicles[i];
    1044        23975 :         if (vehDist.first != 0) {
    1045              :             const MSVehicle* leader = vehDist.first;
    1046        18691 :             const MSVehicle* follower = &myVehicle;
    1047        18691 :             const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
    1048        18691 :             if (netGap < myLastLeaderGap && netGap >= 0) {
    1049         7448 :                 myLastLeaderGap = netGap;
    1050         7448 :                 myLastLeaderSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
    1051         7448 :                 myLastLeaderSpeed = leader->getSpeed();
    1052              :             }
    1053              :         }
    1054              :     }
    1055         7869 : }
    1056              : 
    1057              : void
    1058         7869 : MSAbstractLaneChangeModel::setOrigLeaderGaps(const MSLeaderDistanceInfo& vehicles) {
    1059              :     int rightmost;
    1060              :     int leftmost;
    1061         7869 :     vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
    1062        31738 :     for (int i = rightmost; i <= leftmost; ++i) {
    1063        23869 :         CLeaderDist vehDist = vehicles[i];
    1064        23869 :         if (vehDist.first != 0) {
    1065              :             const MSVehicle* leader = vehDist.first;
    1066        12305 :             const MSVehicle* follower = &myVehicle;
    1067        12305 :             const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
    1068        12305 :             if (netGap < myLastOrigLeaderGap && netGap >= 0) {
    1069         4914 :                 myLastOrigLeaderGap = netGap;
    1070         4914 :                 myLastOrigLeaderSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
    1071         4914 :                 myLastOrigLeaderSpeed = leader->getSpeed();
    1072              :             }
    1073              :         }
    1074              :     }
    1075         7869 : }
    1076              : 
    1077              : 
    1078              : bool
    1079     27682076 : MSAbstractLaneChangeModel::isStrategicBlocked() const {
    1080     27682076 :     const int stateRight = mySavedStateRight.second;
    1081     27682076 :     if (
    1082              :         (stateRight & LCA_STRATEGIC) != 0
    1083              :         && (stateRight & LCA_RIGHT) != 0
    1084       860004 :         && (stateRight & LCA_BLOCKED) != 0) {
    1085              :         return true;
    1086              :     }
    1087     27113421 :     const int stateLeft = mySavedStateLeft.second;
    1088     27113421 :     if (
    1089              :         (stateLeft & LCA_STRATEGIC) != 0
    1090              :         && (stateLeft & LCA_LEFT) != 0
    1091       208246 :         && (stateLeft & LCA_BLOCKED) != 0) {
    1092       142467 :         return true;
    1093              :     }
    1094              :     return false;
    1095              : }
    1096              : 
    1097              : double
    1098    361969150 : MSAbstractLaneChangeModel::getForwardPos() const {
    1099    361969150 :     return myAmOpposite ? myVehicle.getLane()->getLength() - myVehicle.getPositionOnLane() : myVehicle.getPositionOnLane();
    1100              : }
    1101              : 
    1102              : 
    1103              : int
    1104         1425 : MSAbstractLaneChangeModel::getNormalizedLaneIndex() {
    1105         1425 :     const int i = myVehicle.getLane()->getIndex();
    1106         1425 :     if (myAmOpposite) {
    1107          789 :         return myVehicle.getLane()->getParallelOpposite()->getEdge().getNumLanes() + myVehicle.getLane()->getEdge().getNumLanes() - 1 - i;
    1108              :     } else {
    1109              :         return i;
    1110              :     }
    1111              : }
    1112              : 
    1113              : void
    1114     51441471 : MSAbstractLaneChangeModel::addLCSpeedAdvice(const double vSafe, bool ownAdvice) {
    1115     51441471 :     const double accel = SPEED2ACCEL(vSafe - myVehicle.getSpeed());
    1116     51441471 :     myLCAccelerationAdvices.push_back({accel, ownAdvice});
    1117     51441471 : }
    1118              : 
    1119              : 
    1120              : bool
    1121     14877871 : MSAbstractLaneChangeModel::canOvertakeRight(const MSVehicle* const nv, const double dist, const double maxSpeedDiff, const double helpOvertakeSpeed, double& vSafe, double& deltaV) const {
    1122     14877871 :     deltaV = MAX2(maxSpeedDiff, myVehicle.getSpeed() - nv->getSpeed());
    1123     14877871 :     if (deltaV > 0) {
    1124      2876878 :         const double vMaxDecel = getCarFollowModel().getSpeedAfterMaxDecel(myVehicle.getSpeed());
    1125      2876878 :         const double vSafeFollow = getCarFollowModel().followSpeed(
    1126      2876878 :                                         &myVehicle, myVehicle.getSpeed(), dist, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel());
    1127      2876878 :         const double vStayBehind = nv->getSpeed() - helpOvertakeSpeed;
    1128      2876878 :         if (vSafeFollow >= vMaxDecel) {
    1129      2577263 :             vSafe = vSafeFollow;
    1130              :         } else {
    1131       299615 :             vSafe = MAX2(vMaxDecel, vStayBehind);
    1132              :         }
    1133      2876878 :         return true;
    1134              :     }
    1135              :     return false;
    1136              : }
    1137              : 
    1138              : 
    1139              : void
    1140         2625 : MSAbstractLaneChangeModel::saveState(OutputDevice& out) const {
    1141              :     std::vector<double> lcState;
    1142         2625 :     lcState.push_back((double)myOwnState);
    1143         2625 :     for (const auto& item : myLCAccelerationAdvices) {
    1144            0 :         lcState.push_back(item.first);
    1145            0 :         lcState.push_back((double)item.second);
    1146              :     }
    1147         2625 :     out.writeAttr(SUMO_ATTR_LCSTATE_BASE, lcState);
    1148              : 
    1149         2625 :     if (MSGlobals::gLaneChangeDuration > 0) {
    1150            1 :         out.writeAttr(SUMO_ATTR_LCSTATE, std::vector<double> {mySpeedLat, myLaneChangeCompletion, (double)myLaneChangeDirection});
    1151              :     }
    1152         2625 : }
    1153              : 
    1154              : void
    1155         3483 : MSAbstractLaneChangeModel::loadState(const SUMOSAXAttributes& attrs) {
    1156         3483 :     if (attrs.hasAttribute(SUMO_ATTR_LCSTATE_BASE)) {
    1157         6966 :         std::istringstream bis(attrs.getString(SUMO_ATTR_LCSTATE_BASE));
    1158              :         double token;
    1159              :         bis >> token;
    1160         3483 :         myOwnState = (int)token; // double is suffciently precise
    1161              :         double prev = std::numeric_limits<double>::max();
    1162         6966 :         while (bis >> token) {
    1163            0 :             if (prev != std::numeric_limits<double>::max()) {
    1164            0 :                 myLCAccelerationAdvices.push_back(std::make_pair(prev, (bool)token));
    1165              :                 prev = std::numeric_limits<double>::max();
    1166              :             }
    1167            0 :             prev = token;
    1168              :         }
    1169         3483 :     }
    1170         3483 :     if (attrs.hasAttribute(SUMO_ATTR_LCSTATE)) {
    1171            1 :         std::istringstream bis(attrs.getString(SUMO_ATTR_LCSTATE));
    1172            1 :         bis >> mySpeedLat;
    1173            1 :         bis >> myLaneChangeCompletion;
    1174            1 :         bis >> myLaneChangeDirection;
    1175            1 :     }
    1176         3483 : }
    1177              : 
    1178              : 
    1179              : double
    1180      3929020 : MSAbstractLaneChangeModel::getExtraReservation(int bestLaneOffset, double neighExtraDist) const {
    1181      3929020 :     if (neighExtraDist > myVehicle.getVehicleType().getLengthWithGap()) {
    1182              :         return 0;
    1183              :     }
    1184      3928738 :     if (bestLaneOffset < -1) {
    1185              :         return 20;
    1186      3886642 :     } else if (bestLaneOffset > 1) {
    1187       405418 :         return 40;
    1188              :     }
    1189              :     return 0;
    1190              : }
    1191              : 
    1192              : 
    1193              : double
    1194    596399248 : MSAbstractLaneChangeModel::getCooperativeHelpSpeed(const MSLane* lane, double distToLaneEnd) const {
    1195    596399248 :     if (myCooperativeHelpTime >= 0) {
    1196    596399248 :         std::pair<double, SUMOTime> backAndWaiting = lane->getEdge().getLastBlocked(lane->getIndex());
    1197    596399248 :         if (backAndWaiting.second >= myCooperativeHelpTime) {
    1198      2257692 :             double gap = distToLaneEnd - lane->getLength() + backAndWaiting.first - myVehicle.getVehicleType().getMinGap() - NUMERICAL_EPS;
    1199      2257692 :             if (backAndWaiting.first < 0) {
    1200       392415 :                 if (myVehicle.getLane()->getToJunction() == lane->getFromJunction()) {
    1201       214567 :                     if (myVehicle.getLane()->isInternal()) {
    1202              :                         // already on the junction, potentially blocking lane change, do not stop
    1203              :                         gap = -1;
    1204              :                     } else {
    1205              :                         // stop before entering the junction
    1206       195790 :                         gap = myVehicle.getLane()->getLength() - myVehicle.getPositionOnLane();
    1207              :                     }
    1208              :                 }
    1209              :             }
    1210      2238915 :             if (gap > 0) {
    1211      1445703 :                 double stopSpeed = myVehicle.getCarFollowModel().stopSpeed(&myVehicle, myVehicle.getSpeed(), gap);
    1212              :                 //if (myVehicle.isSelected() && stopSpeed < myVehicle.getSpeed()) {
    1213              :                 //    std::cout << SIMTIME << " veh=" << myVehicle.getID() << " lane=" << lane->getID() << " dte=" << distToLaneEnd << " gap=" << gap << " backPos=" << backAndWaiting.first << " waiting=" << backAndWaiting.second << " helpTime=" << myCooperativeHelpTime << " stopSpeed=" << stopSpeed << " minNext=" << myVehicle.getCarFollowModel().minNextSpeed(myVehicle.getSpeed(), &myVehicle) << "\n";
    1214              :                 //}
    1215      1445703 :                 if (stopSpeed >= myVehicle.getCarFollowModel().minNextSpeed(myVehicle.getSpeed(), &myVehicle)) {
    1216              :                     // regular braking is helpful
    1217      1443490 :                     return stopSpeed;
    1218              :                 }
    1219              :             }
    1220              :         }
    1221              :     }
    1222              :     // do not restrict speed
    1223              :     return std::numeric_limits<double>::max();
    1224              : }
        

Generated by: LCOV version 2.0-1