LCOV - code coverage report
Current view: top level - src/microsim/lcmodels - MSAbstractLaneChangeModel.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 95.2 % 546 520
Test Date: 2025-12-06 15:35:27 Functions: 93.5 % 62 58

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

Generated by: LCOV version 2.0-1