LCOV - code coverage report
Current view: top level - src/microsim/lcmodels - MSAbstractLaneChangeModel.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 95.0 % 522 496
Test Date: 2024-12-21 15:45:41 Functions: 93.3 % 60 56

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    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        43246 : MSAbstractLaneChangeModel::initGlobalOptions(const OptionsCont& oc) {
      73        43246 :     myAllowOvertakingRight = oc.getBool("lanechange.overtake-right");
      74        43246 :     myLCOutput = oc.isSet("lanechange-output");
      75        43246 :     myLCStartedOutput = oc.getBool("lanechange-output.started");
      76        43246 :     myLCEndedOutput = oc.getBool("lanechange-output.ended");
      77        43246 :     myLCXYOutput = oc.getBool("lanechange-output.xy");
      78        43246 : }
      79              : 
      80              : 
      81              : MSAbstractLaneChangeModel*
      82      4396363 : MSAbstractLaneChangeModel::build(LaneChangeModel lcm, MSVehicle& v) {
      83      4396363 :     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      4396341 :     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      4394469 :         case LaneChangeModel::DEFAULT:
      96      4394469 :             if (MSGlobals::gLateralResolution <= 0) {
      97      3613826 :                 return new MSLCM_LC2013(v);
      98              :             } else {
      99       780643 :                 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      4396341 : MSAbstractLaneChangeModel::MSAbstractLaneChangeModel(MSVehicle& v, const LaneChangeModel model) :
     108      4396341 :     myVehicle(v),
     109      4396341 :     myOwnState(0),
     110      4396341 :     myPreviousState(0),
     111      4396341 :     myPreviousState2(0),
     112      4396341 :     myCanceledStateRight(LCA_NONE),
     113      4396341 :     myCanceledStateCenter(LCA_NONE),
     114      4396341 :     myCanceledStateLeft(LCA_NONE),
     115      4396341 :     mySpeedLat(0),
     116      4396341 :     myAccelerationLat(0),
     117      4396341 :     myAngleOffset(0),
     118      4396341 :     myPreviousAngleOffset(0),
     119      4396341 :     myCommittedSpeed(0),
     120      4396341 :     myLaneChangeCompletion(1.0),
     121      4396341 :     myLaneChangeDirection(0),
     122      4396341 :     myAlreadyChanged(false),
     123      4396341 :     myShadowLane(nullptr),
     124      4396341 :     myTargetLane(nullptr),
     125      4396341 :     myModel(model),
     126      4396341 :     myLastLateralGapLeft(0.),
     127      4396341 :     myLastLateralGapRight(0.),
     128      4396341 :     myLastLeaderGap(0.),
     129      4396341 :     myLastFollowerGap(0.),
     130      4396341 :     myLastLeaderSecureGap(0.),
     131      4396341 :     myLastFollowerSecureGap(0.),
     132      4396341 :     myLastOrigLeaderGap(0.),
     133      4396341 :     myLastOrigLeaderSecureGap(0.),
     134      4396341 :     myLastLeaderSpeed(0),
     135      4396341 :     myLastFollowerSpeed(0),
     136      4396341 :     myLastOrigLeaderSpeed(0),
     137      4396341 :     myDontResetLCGaps(false),
     138      4396341 :     myStrategicLookahead(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_STRATEGIC_LOOKAHEAD, UNDEFINED_LOOKAHEAD)),
     139      4396341 :     myMaxSpeedLatStanding(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING, v.getVehicleType().getMaxSpeedLat())),
     140      4396341 :     myMaxSpeedLatFactor(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR, 1)),
     141      8792682 :     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      4396341 :                          (v.getVClass() & (SVC_BICYCLE | SVC_MOTORCYCLE | SVC_MOPED)) != 0 ? std::numeric_limits<double>::max() : 1.6)),
     144      4396341 :     mySigma(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SIGMA, 0.0)),
     145      4396341 :     myOvertakeRightParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_OVERTAKE_RIGHT, 0)),
     146      4396341 :     myHaveBlueLight(v.getDevice(typeid(MSDevice_Bluelight)) != nullptr), // see MSVehicle::initDevices
     147      4396341 :     myLastLaneChangeOffset(0),
     148      4396341 :     myAmOpposite(false),
     149      4396341 :     myManeuverDist(0.),
     150      8792682 :     myPreviousManeuverDist(0.) {
     151              :     saveLCState(-1, LCA_UNKNOWN, LCA_UNKNOWN);
     152              :     saveLCState(0, LCA_UNKNOWN, LCA_UNKNOWN);
     153              :     saveLCState(1, LCA_UNKNOWN, LCA_UNKNOWN);
     154      4396341 : }
     155              : 
     156              : 
     157      4396265 : MSAbstractLaneChangeModel::~MSAbstractLaneChangeModel() {
     158      4396265 : }
     159              : 
     160              : void
     161    244590099 : MSAbstractLaneChangeModel::setOwnState(const int state) {
     162    244590099 :     myPreviousState2 = myPreviousState;
     163    244590099 :     myOwnState = state;
     164    244590099 :     myPreviousState = state; // myOwnState is modified in prepareStep so we make a backup
     165    244590099 : }
     166              : 
     167              : void
     168            0 : MSAbstractLaneChangeModel::updateSafeLatDist(const double travelledLatDist) {
     169              :     UNUSED_PARAMETER(travelledLatDist);
     170            0 : }
     171              : 
     172              : 
     173              : void
     174     74339604 : MSAbstractLaneChangeModel::setManeuverDist(const double dist) {
     175              : #ifdef DEBUG_MANEUVER
     176              :     if (DEBUG_COND) {
     177              :         std::cout << SIMTIME
     178              :                   << " veh=" << myVehicle.getID()
     179              :                   << " setManeuverDist() old=" << myManeuverDist << " new=" << dist
     180              :                   << std::endl;
     181              :     }
     182              : #endif
     183     74339604 :     myManeuverDist = fabs(dist) < NUMERICAL_EPS ? 0. : dist;
     184              :     // store value which may be modified by the model during the next step
     185     74339604 :     myPreviousManeuverDist = myManeuverDist;
     186     74339604 : }
     187              : 
     188              : 
     189              : double
     190    685470418 : MSAbstractLaneChangeModel::getManeuverDist() const {
     191    685470418 :     return myManeuverDist;
     192              : }
     193              : 
     194              : double
     195     13240514 : MSAbstractLaneChangeModel::getPreviousManeuverDist() const {
     196     13240514 :     return myPreviousManeuverDist;
     197              : }
     198              : 
     199              : void
     200     31662010 : MSAbstractLaneChangeModel::saveNeighbors(const int dir, const MSLeaderDistanceInfo& followers, const MSLeaderDistanceInfo& leaders) {
     201     31662010 :     if (dir == -1) {
     202     14297822 :         myLeftFollowers = std::make_shared<MSLeaderDistanceInfo>(followers);
     203     14297822 :         myLeftLeaders = std::make_shared<MSLeaderDistanceInfo>(leaders);
     204     17364188 :     } else if (dir == 1) {
     205     17364188 :         myRightFollowers = std::make_shared<MSLeaderDistanceInfo>(followers);
     206     17364188 :         myRightLeaders = std::make_shared<MSLeaderDistanceInfo>(leaders);
     207              :     } else {
     208              :         // dir \in {-1,1} !
     209              :         assert(false);
     210              :     }
     211     31662010 : }
     212              : 
     213              : 
     214              : void
     215    191115031 : MSAbstractLaneChangeModel::saveNeighbors(const int dir, const std::pair<MSVehicle* const, double>& follower, const std::pair<MSVehicle* const, double>& leader) {
     216    191115031 :     if (dir == -1) {
     217     90967473 :         myLeftFollowers = std::make_shared<MSLeaderDistanceInfo>(follower, myVehicle.getLane()->getWidth());
     218    181934946 :         myLeftLeaders = std::make_shared<MSLeaderDistanceInfo>(leader, myVehicle.getLane()->getWidth());
     219    100147558 :     } else if (dir == 1) {
     220    100147558 :         myRightFollowers = std::make_shared<MSLeaderDistanceInfo>(follower, myVehicle.getLane()->getWidth());
     221    200295116 :         myRightLeaders = std::make_shared<MSLeaderDistanceInfo>(leader, myVehicle.getLane()->getWidth());
     222              :     } else {
     223              :         // dir \in {-1,1} !
     224              :         assert(false);
     225              :     }
     226    191115031 : }
     227              : 
     228              : 
     229              : void
     230    311863861 : MSAbstractLaneChangeModel::clearNeighbors() {
     231              :     myLeftFollowers = nullptr;
     232              :     myLeftLeaders = nullptr;
     233              :     myRightFollowers = nullptr;
     234              :     myRightLeaders = nullptr;
     235    311863861 : }
     236              : 
     237              : 
     238              : const std::shared_ptr<MSLeaderDistanceInfo>
     239            0 : MSAbstractLaneChangeModel::getFollowers(const int dir) {
     240            0 :     if (dir == -1) {
     241              :         return myLeftFollowers;
     242            0 :     } else if (dir == 1) {
     243              :         return myRightFollowers;
     244              :     } else {
     245              :         // dir \in {-1,1} !
     246              :         assert(false);
     247              :     }
     248              :     return nullptr;
     249              : }
     250              : 
     251              : const std::shared_ptr<MSLeaderDistanceInfo>
     252            0 : MSAbstractLaneChangeModel::getLeaders(const int dir) {
     253            0 :     if (dir == -1) {
     254              :         return myLeftLeaders;
     255            0 :     } else if (dir == 1) {
     256              :         return myRightLeaders;
     257              :     } else {
     258              :         // dir \in {-1,1} !
     259              :         assert(false);
     260              :     }
     261              :     return nullptr;
     262              : }
     263              : 
     264              : 
     265              : bool
     266          109 : MSAbstractLaneChangeModel::congested(const MSVehicle* const neighLeader) {
     267          109 :     if (neighLeader == nullptr) {
     268              :         return false;
     269              :     }
     270              :     // Congested situation are relevant only on highways (maxSpeed > 70km/h)
     271              :     // and congested on German Highways means that the vehicles have speeds
     272              :     // below 60km/h. Overtaking on the right is allowed then.
     273            0 :     if ((myVehicle.getLane()->getSpeedLimit() <= 70.0 / 3.6) || (neighLeader->getLane()->getSpeedLimit() <= 70.0 / 3.6)) {
     274              : 
     275            0 :         return false;
     276              :     }
     277            0 :     if (myVehicle.congested() && neighLeader->congested()) {
     278              :         return true;
     279              :     }
     280              :     return false;
     281              : }
     282              : 
     283              : 
     284              : bool
     285    237389380 : MSAbstractLaneChangeModel::avoidOvertakeRight() const {
     286    237389380 :     return (!myAllowOvertakingRight
     287    237383929 :             && !myVehicle.congested()
     288     35368591 :             && myVehicle.getVehicleType().getVehicleClass() != SVC_EMERGENCY
     289    272755930 :             && (myOvertakeRightParam == 0 || myOvertakeRightParam < RandHelper::rand(myVehicle.getRNG())));
     290              : }
     291              : 
     292              : bool
     293          109 : MSAbstractLaneChangeModel::predInteraction(const std::pair<MSVehicle*, double>& leader) {
     294          109 :     if (leader.first == 0) {
     295              :         return false;
     296              :     }
     297              :     // let's check it on highways only
     298            0 :     if (leader.first->getSpeed() < (80.0 / 3.6)) {
     299              :         return false;
     300              :     }
     301            0 :     return leader.second < getCarFollowModel().interactionGap(&myVehicle, leader.first->getSpeed());
     302              : }
     303              : 
     304              : 
     305              : bool
     306      1024661 : MSAbstractLaneChangeModel::startLaneChangeManeuver(MSLane* source, MSLane* target, int direction) {
     307      1024661 :     if (MSGlobals::gLaneChangeDuration > DELTA_T) {
     308        36365 :         myLaneChangeCompletion = 0;
     309        36365 :         myLaneChangeDirection = direction;
     310        36365 :         setManeuverDist((target->getWidth() + source->getWidth()) * 0.5 * direction);
     311        36365 :         myVehicle.switchOffSignal(MSVehicle::VEH_SIGNAL_BLINKER_RIGHT | MSVehicle::VEH_SIGNAL_BLINKER_LEFT);
     312        36365 :         myVehicle.switchOnSignal(((direction == 1) != MSGlobals::gLefthand) ? MSVehicle::VEH_SIGNAL_BLINKER_LEFT : MSVehicle::VEH_SIGNAL_BLINKER_RIGHT);
     313        36365 :         if (myLCOutput) {
     314          650 :             memorizeGapsAtLCInit();
     315              :         }
     316        36365 :         return true;
     317              :     } else {
     318       988296 :         primaryLaneChanged(source, target, direction);
     319       988296 :         return false;
     320              :     }
     321              : }
     322              : 
     323              : void
     324          650 : MSAbstractLaneChangeModel::memorizeGapsAtLCInit() {
     325          650 :     myDontResetLCGaps = true;
     326          650 : }
     327              : 
     328              : void
     329          649 : MSAbstractLaneChangeModel::clearGapsAtLCInit() {
     330          649 :     myDontResetLCGaps = false;
     331          649 : }
     332              : 
     333              : void
     334      1024445 : MSAbstractLaneChangeModel::primaryLaneChanged(MSLane* source, MSLane* target, int direction) {
     335      1024445 :     initLastLaneChangeOffset(direction);
     336      1024445 :     myVehicle.leaveLane(MSMoveReminder::NOTIFICATION_LANE_CHANGE, target);
     337      1024445 :     source->leftByLaneChange(&myVehicle);
     338      2048890 :     laneChangeOutput("change", source, target, direction); // record position on the source edge in case of opposite change
     339      1024445 :     if (&source->getEdge() != &target->getEdge()) {
     340        42605 :         changedToOpposite();
     341              : #ifdef DEBUG_OPPOSITE
     342              :         if (debugVehicle()) {
     343              :             std::cout << SIMTIME << " veh=" << myVehicle.getID() << " primaryLaneChanged source=" << source->getID() << " target=" << target->getID() << " nowOpposite=" << myAmOpposite << "\n";
     344              :         }
     345              : #endif
     346        42605 :         myVehicle.setTentativeLaneAndPosition(target, source->getOppositePos(myVehicle.getPositionOnLane()), -myVehicle.getLateralPositionOnLane());
     347        42605 :         target->forceVehicleInsertion(&myVehicle, myVehicle.getPositionOnLane(), MSMoveReminder::NOTIFICATION_LANE_CHANGE, myVehicle.getLateralPositionOnLane());
     348       981840 :     } else if (myAmOpposite) {
     349              : #ifdef DEBUG_OPPOSITE
     350              :         if (debugVehicle()) {
     351              :             std::cout << SIMTIME << " veh=" << myVehicle.getID() << " primaryLaneChanged source=" << source->getID() << " target=" << target->getID() << " stayOpposite\n";
     352              :         }
     353              : #endif
     354          230 :         myAlreadyChanged = true;
     355          230 :         myVehicle.setTentativeLaneAndPosition(target, myVehicle.getPositionOnLane(), myVehicle.getLateralPositionOnLane());
     356          230 :         if (!MSGlobals::gSublane) {
     357              :             // in the continous case, the vehicle is added to the target lane via MSLaneChanger::continueChange / registerHop
     358              :             // in the sublane case, the vehicle is added to the target lane via MSLaneChangerSublane::checkChangeOppositeSublane / MSLane::myTmpVehicles
     359           80 :             target->forceVehicleInsertion(&myVehicle, myVehicle.getPositionOnLane(), MSMoveReminder::NOTIFICATION_LANE_CHANGE, myVehicle.getLateralPositionOnLane());
     360              :         }
     361              :     } else {
     362       981610 :         myVehicle.enterLaneAtLaneChange(target);
     363       981610 :         target->enteredByLaneChange(&myVehicle);
     364              :     }
     365              :     // Assure that the drive items are up to date (even if the following step is no actionstep for the vehicle).
     366              :     // This is necessary because the lane advance uses the target lane from the corresponding drive item.
     367      1024445 :     myVehicle.updateDriveItems();
     368      1024445 :     changed();
     369      1024445 : }
     370              : 
     371              : void
     372      1024729 : MSAbstractLaneChangeModel::laneChangeOutput(const std::string& tag, MSLane* source, MSLane* target, int direction, double maneuverDist) {
     373      1024729 :     if (myLCOutput) {
     374        14841 :         OutputDevice& of = OutputDevice::getDeviceByOption("lanechange-output");
     375        14841 :         of.openTag(tag);
     376        14841 :         of.writeAttr(SUMO_ATTR_ID, myVehicle.getID());
     377        14841 :         of.writeAttr(SUMO_ATTR_TYPE, myVehicle.getVehicleType().getID());
     378        29682 :         of.writeAttr(SUMO_ATTR_TIME, time2string(MSNet::getInstance()->getCurrentTimeStep()));
     379              :         of.writeAttr(SUMO_ATTR_FROM, source->getID());
     380              :         of.writeAttr(SUMO_ATTR_TO, target->getID());
     381              :         of.writeAttr(SUMO_ATTR_DIR, direction);
     382        14841 :         of.writeAttr(SUMO_ATTR_SPEED, myVehicle.getSpeed());
     383        14841 :         of.writeAttr(SUMO_ATTR_POSITION, myVehicle.getPositionOnLane());
     384        59364 :         of.writeAttr("reason", toString((LaneChangeAction)(myOwnState & ~(
     385              :                                             LCA_RIGHT | LCA_LEFT
     386              :                                             | LCA_AMBLOCKINGLEADER | LCA_AMBLOCKINGFOLLOWER
     387              :                                             | LCA_MRIGHT | LCA_MLEFT
     388        29682 :                                             | LCA_AMBACKBLOCKER | LCA_AMBACKBLOCKER_STANDING))) + myVehicle.getParameter().getParameter("lcReason"));
     389        29682 :         of.writeAttr("leaderGap", myLastLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderGap));
     390        29682 :         of.writeAttr("leaderSecureGap", myLastLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderSecureGap));
     391        29682 :         of.writeAttr("leaderSpeed", myLastLeaderSpeed == NO_NEIGHBOR ? "None" : toString(myLastLeaderSpeed));
     392        29682 :         of.writeAttr("followerGap", myLastFollowerGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerGap));
     393        29682 :         of.writeAttr("followerSecureGap", myLastFollowerSecureGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerSecureGap));
     394        29682 :         of.writeAttr("followerSpeed", myLastFollowerSpeed == NO_NEIGHBOR ? "None" : toString(myLastFollowerSpeed));
     395        29682 :         of.writeAttr("origLeaderGap", myLastOrigLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderGap));
     396        29682 :         of.writeAttr("origLeaderSecureGap", myLastOrigLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderSecureGap));
     397        29682 :         of.writeAttr("origLeaderSpeed", myLastOrigLeaderSpeed == NO_NEIGHBOR ? "None" : toString(myLastOrigLeaderSpeed));
     398        14841 :         if (MSGlobals::gLateralResolution > 0) {
     399         6537 :             const double latGap = direction < 0 ? myLastLateralGapRight : myLastLateralGapLeft;
     400        13074 :             of.writeAttr("latGap", latGap == NO_NEIGHBOR ? "None" : toString(latGap));
     401         6537 :             if (maneuverDist != 0) {
     402          408 :                 of.writeAttr("maneuverDistance", toString(maneuverDist));
     403              :             }
     404              :         }
     405        14841 :         if (myLCXYOutput) {
     406           62 :             of.writeAttr(SUMO_ATTR_X, myVehicle.getPosition().x());
     407          124 :             of.writeAttr(SUMO_ATTR_Y, myVehicle.getPosition().y());
     408              :         }
     409        14841 :         of.closeTag();
     410        14841 :         if (MSGlobals::gLaneChangeDuration > DELTA_T) {
     411          649 :             clearGapsAtLCInit();
     412              :         }
     413              :     }
     414      1024729 : }
     415              : 
     416              : 
     417              : double
     418       612662 : MSAbstractLaneChangeModel::computeSpeedLat(double /*latDist*/, double& maneuverDist, bool /*urgent*/) const {
     419       612662 :     if (myVehicle.getVehicleType().wasSet(VTYPEPARS_MAXSPEED_LAT_SET)) {
     420          686 :         int stepsToChange = (int)ceil(fabs(maneuverDist) / SPEED2DIST(myVehicle.getVehicleType().getMaxSpeedLat()));
     421          686 :         return DIST2SPEED(maneuverDist / stepsToChange);
     422              :     } else {
     423       611976 :         return maneuverDist / STEPS2TIME(MSGlobals::gLaneChangeDuration);
     424              :     }
     425              : }
     426              : 
     427              : 
     428              : double
     429        93302 : MSAbstractLaneChangeModel::getAssumedDecelForLaneChangeDuration() const {
     430        93302 :     return MAX2(LC_ASSUMED_DECEL, -myVehicle.getAcceleration());
     431              : }
     432              : 
     433              : void
     434     77376607 : MSAbstractLaneChangeModel::setSpeedLat(double speedLat) {
     435     77376607 :     myAccelerationLat = SPEED2ACCEL(speedLat - mySpeedLat);
     436     77376607 :     mySpeedLat = speedLat;
     437     77376607 : }
     438              : 
     439              : 
     440              : void
     441    546169510 : MSAbstractLaneChangeModel::resetSpeedLat() {
     442    546169510 :     if (MSGlobals::gLaneChangeDuration > 0 && !isChangingLanes()) {
     443      2396313 :         setSpeedLat(0);
     444              :     }
     445    546169510 : }
     446              : 
     447              : 
     448              : bool
     449       565862 : MSAbstractLaneChangeModel::updateCompletion() {
     450              :     const bool pastBefore = pastMidpoint();
     451              :     // maneuverDist is not updated in the context of continuous lane changing but represents the full LC distance
     452       565862 :     double maneuverDist = getManeuverDist();
     453       565862 :     setSpeedLat(computeSpeedLat(0, maneuverDist, (myOwnState & LCA_URGENT) != 0));
     454       565862 :     myLaneChangeCompletion += (SPEED2DIST(mySpeedLat) / myManeuverDist);
     455       565862 :     return !pastBefore && pastMidpoint();
     456              : }
     457              : 
     458              : 
     459              : void
     460        55567 : MSAbstractLaneChangeModel::endLaneChangeManeuver(const MSMoveReminder::Notification reason) {
     461              :     UNUSED_PARAMETER(reason);
     462        55567 :     myLaneChangeCompletion = 1;
     463        55567 :     cleanupShadowLane();
     464        55567 :     cleanupTargetLane();
     465              :     myNoPartiallyOccupatedByShadow.clear();
     466        55567 :     myVehicle.switchOffSignal(MSVehicle::VEH_SIGNAL_BLINKER_RIGHT | MSVehicle::VEH_SIGNAL_BLINKER_LEFT);
     467        55567 :     myVehicle.fixPosition();
     468        55567 :     if (myAmOpposite && reason != MSMoveReminder::NOTIFICATION_LANE_CHANGE) {
     469          148 :         if (reason == MSMoveReminder::NOTIFICATION_PARKING && myVehicle.getNextStop().isOpposite) {
     470              :             // opposite driving continues after parking
     471              :         } else {
     472              :             // aborted maneuver
     473              : #ifdef DEBUG_OPPOSITE
     474              :             if (debugVehicle()) {
     475              :                 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " aborted maneuver (no longer opposite)\n";
     476              :             }
     477              : #endif
     478          123 :             changedToOpposite();
     479              :         }
     480              :     }
     481        55567 : }
     482              : 
     483              : 
     484              : MSLane*
     485     15696989 : MSAbstractLaneChangeModel::getShadowLane(const MSLane* lane, double posLat) const {
     486     15696989 :     if (std::find(myNoPartiallyOccupatedByShadow.begin(), myNoPartiallyOccupatedByShadow.end(), lane) == myNoPartiallyOccupatedByShadow.end()) {
     487              :         // initialize shadow lane
     488     15696989 :         const double overlap = myVehicle.getLateralOverlap(posLat, lane);
     489              : #ifdef DEBUG_SHADOWLANE
     490              :         if (debugVehicle()) {
     491              :             std::cout << SIMTIME << " veh=" << myVehicle.getID() << " posLat=" << posLat << " overlap=" << overlap << "\n";
     492              :         }
     493              : #endif
     494     15696989 :         if (myAmOpposite) {
     495              :             // return the neigh-lane in forward direction
     496       542218 :             return lane->getParallelLane(1);
     497     15154771 :         } else if (overlap > NUMERICAL_EPS) {
     498      8651764 :             const int shadowDirection = posLat < 0 ? -1 : 1;
     499      8651764 :             return lane->getParallelLane(shadowDirection);
     500      6503007 :         } else if (isChangingLanes() && myLaneChangeCompletion < 0.5) {
     501              :             // "reserve" target lane even when there is no overlap yet
     502       247961 :             return lane->getParallelLane(myLaneChangeDirection);
     503              :         } else {
     504              :             return nullptr;
     505              :         }
     506              :     } else {
     507              :         return nullptr;
     508              :     }
     509              : }
     510              : 
     511              : 
     512              : MSLane*
     513     15564975 : MSAbstractLaneChangeModel::getShadowLane(const MSLane* lane) const {
     514     15564975 :     return getShadowLane(lane, myVehicle.getLateralPositionOnLane());
     515              : }
     516              : 
     517              : 
     518              : void
     519      4452416 : MSAbstractLaneChangeModel::cleanupShadowLane() {
     520      4452416 :     if (myShadowLane != nullptr) {
     521        16297 :         if (debugVehicle()) {
     522            0 :             std::cout << SIMTIME << " cleanupShadowLane\n";
     523              :         }
     524        16297 :         myShadowLane->resetPartialOccupation(&myVehicle);
     525        16297 :         myShadowLane = nullptr;
     526              :     }
     527      4452822 :     for (std::vector<MSLane*>::const_iterator it = myShadowFurtherLanes.begin(); it != myShadowFurtherLanes.end(); ++it) {
     528          406 :         if (debugVehicle()) {
     529            0 :             std::cout << SIMTIME << " cleanupShadowLane2\n";
     530              :         }
     531          406 :         (*it)->resetPartialOccupation(&myVehicle);
     532              :     }
     533              :     myShadowFurtherLanes.clear();
     534              :     myNoPartiallyOccupatedByShadow.clear();
     535      4452416 : }
     536              : 
     537              : void
     538      4452416 : MSAbstractLaneChangeModel::cleanupTargetLane() {
     539      4452416 :     if (myTargetLane != nullptr) {
     540          642 :         if (debugVehicle()) {
     541            0 :             std::cout << SIMTIME << " cleanupTargetLane\n";
     542              :         }
     543          642 :         myTargetLane->resetManeuverReservation(&myVehicle);
     544          642 :         myTargetLane = nullptr;
     545              :     }
     546      4452418 :     for (std::vector<MSLane*>::const_iterator it = myFurtherTargetLanes.begin(); it != myFurtherTargetLanes.end(); ++it) {
     547            2 :         if (debugVehicle()) {
     548            0 :             std::cout << SIMTIME << " cleanupTargetLane\n";
     549              :         }
     550            2 :         if (*it != nullptr) {
     551            2 :             (*it)->resetManeuverReservation(&myVehicle);
     552              :         }
     553              :     }
     554              :     myFurtherTargetLanes.clear();
     555              : //    myNoPartiallyOccupatedByShadow.clear();
     556      4452416 : }
     557              : 
     558              : 
     559              : bool
     560     26022107 : MSAbstractLaneChangeModel::cancelRequest(int state, int laneOffset) {
     561              :     // store request before canceling
     562     26022107 :     getCanceledState(laneOffset) |= state;
     563     26022107 :     int ret = myVehicle.influenceChangeDecision(state);
     564     26022107 :     return ret != state;
     565              : }
     566              : 
     567              : double
     568     17854926 : MSAbstractLaneChangeModel::getMaxSpeedLat2() const {
     569     17854926 :     return MAX2(myVehicle.getVehicleType().getMaxSpeedLat(), myMaxSpeedLatStanding);
     570              : }
     571              : 
     572              : void
     573      1024445 : MSAbstractLaneChangeModel::initLastLaneChangeOffset(int dir) {
     574      1024445 :     if (dir > 0) {
     575       558579 :         myLastLaneChangeOffset = 1;
     576       465866 :     } else if (dir < 0) {
     577       465866 :         myLastLaneChangeOffset = -1;
     578              :     }
     579      1024445 : }
     580              : 
     581              : void
     582      5573740 : MSAbstractLaneChangeModel::updateShadowLane() {
     583      5573740 :     if (!MSGlobals::gSublane) {
     584              :         // assume each vehicle drives at the center of its lane and act as if it fits
     585       498502 :         return;
     586              :     }
     587      5075238 :     if (myShadowLane != nullptr) {
     588              : #ifdef DEBUG_SHADOWLANE
     589              :         if (debugVehicle()) {
     590              :             std::cout << SIMTIME << " updateShadowLane()\n";
     591              :         }
     592              : #endif
     593      1785169 :         myShadowLane->resetPartialOccupation(&myVehicle);
     594              :     }
     595      5075238 :     myShadowLane = getShadowLane(myVehicle.getLane());
     596              :     std::vector<MSLane*> passed;
     597      5075238 :     if (myShadowLane != nullptr) {
     598      1801466 :         myShadowLane->setPartialOccupation(&myVehicle);
     599      1801466 :         const std::vector<MSLane*>& further = myVehicle.getFurtherLanes();
     600      1801466 :         if (myAmOpposite) {
     601              :             assert(further.size() == 0);
     602              :         } else {
     603              :             const std::vector<double>& furtherPosLat = myVehicle.getFurtherLanesPosLat();
     604              :             assert(further.size() == furtherPosLat.size());
     605      1582869 :             passed.push_back(myShadowLane);
     606      1714883 :             for (int i = 0; i < (int)further.size(); ++i) {
     607       132014 :                 MSLane* shadowFurther = getShadowLane(further[i], furtherPosLat[i]);
     608              : #ifdef DEBUG_SHADOWLANE
     609              :                 if (debugVehicle()) {
     610              :                     std::cout << SIMTIME << "   further=" << further[i]->getID() << " (posLat=" << furtherPosLat[i] << ") shadowFurther=" << Named::getIDSecure(shadowFurther) << "\n";
     611              :                 }
     612              : #endif
     613       132014 :                 if (shadowFurther != nullptr && shadowFurther->getLinkTo(passed.back()) != nullptr) {
     614        55684 :                     passed.push_back(shadowFurther);
     615              :                 }
     616              :             }
     617              :             std::reverse(passed.begin(), passed.end());
     618              :         }
     619              :     } else {
     620      3273772 :         if (isChangingLanes() && myVehicle.getLateralOverlap() > NUMERICAL_EPS) {
     621            4 :             WRITE_WARNING("Vehicle '" + myVehicle.getID() + "' could not finish continuous lane change (lane disappeared) time=" +
     622              :                           time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
     623            1 :             endLaneChangeManeuver();
     624              :         }
     625              :     }
     626              : #ifdef DEBUG_SHADOWLANE
     627              :     if (debugVehicle()) {
     628              :         std::cout << SIMTIME << " updateShadowLane() veh=" << myVehicle.getID()
     629              :                   << " newShadowLane=" << Named::getIDSecure(myShadowLane)
     630              :                   << "\n   before:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << " further=" << toString(myVehicle.getFurtherLanes()) << " passed=" << toString(passed);
     631              :         std::cout << std::endl;
     632              :     }
     633              : #endif
     634      5075238 :     myVehicle.updateFurtherLanes(myShadowFurtherLanes, myShadowFurtherLanesPosLat, passed);
     635              : #ifdef DEBUG_SHADOWLANE
     636              :     if (debugVehicle()) std::cout
     637              :                 << "\n   after:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << "\n";
     638              : #endif
     639      5075238 : }
     640              : 
     641              : 
     642              : int
     643      9334168 : MSAbstractLaneChangeModel::getShadowDirection() const {
     644      9334168 :     if (isChangingLanes()) {
     645       634981 :         if (pastMidpoint()) {
     646       206144 :             return -myLaneChangeDirection;
     647              :         } else {
     648       428837 :             return myLaneChangeDirection;
     649              :         }
     650      8699187 :     } else if (myShadowLane == nullptr) {
     651              :         return 0;
     652      8699187 :     } else if (myAmOpposite) {
     653              :         // return neigh-lane in forward direction
     654              :         return 1;
     655      8176179 :     } else if (&myShadowLane->getEdge() == &myVehicle.getLane()->getEdge()) {
     656      8074089 :         return myShadowLane->getIndex() - myVehicle.getLane()->getIndex();
     657              :     } else {
     658              :         // overlap with opposite direction lane
     659              :         return 1;
     660              :     }
     661              : }
     662              : 
     663              : 
     664              : MSLane*
     665     78892831 : MSAbstractLaneChangeModel::updateTargetLane() {
     666              : #ifdef DEBUG_TARGET_LANE
     667              :     MSLane* oldTarget = myTargetLane;
     668              :     std::vector<MSLane*> oldFurtherTargets = myFurtherTargetLanes;
     669              :     if (debugVehicle()) {
     670              :         std::cout << SIMTIME << " veh '" << myVehicle.getID() << "' (lane=" << myVehicle.getLane()->getID() << ") updateTargetLane()"
     671              :                   << "\n   oldTarget: " << (oldTarget == nullptr ? "NULL" : oldTarget->getID())
     672              :                   << " oldFurtherTargets: " << toString(oldFurtherTargets);
     673              :     }
     674              : #endif
     675     78892831 :     if (myTargetLane != nullptr) {
     676       199409 :         myTargetLane->resetManeuverReservation(&myVehicle);
     677              :     }
     678              :     // Clear old further target lanes
     679     78903264 :     for (MSLane* oldTargetLane : myFurtherTargetLanes) {
     680        10433 :         if (oldTargetLane != nullptr) {
     681         8559 :             oldTargetLane->resetManeuverReservation(&myVehicle);
     682              :         }
     683              :     }
     684              :     myFurtherTargetLanes.clear();
     685              : 
     686              :     // Get new target lanes and issue a maneuver reservation.
     687              :     int targetDir;
     688     78892831 :     myTargetLane = determineTargetLane(targetDir);
     689     78892831 :     if (myTargetLane != nullptr) {
     690       200051 :         myTargetLane->setManeuverReservation(&myVehicle);
     691              :         // further targets are just the target lanes corresponding to the vehicle's further lanes
     692              :         // @note In a neglectable amount of situations we might add a reservation for a shadow further lane.
     693       210486 :         for (MSLane* furtherLane : myVehicle.getFurtherLanes()) {
     694        10435 :             MSLane* furtherTargetLane = furtherLane->getParallelLane(targetDir);
     695        10435 :             myFurtherTargetLanes.push_back(furtherTargetLane);
     696        10435 :             if (furtherTargetLane != nullptr) {
     697         8561 :                 furtherTargetLane->setManeuverReservation(&myVehicle);
     698              :             }
     699              :         }
     700              :     }
     701              : #ifdef DEBUG_TARGET_LANE
     702              :     if (debugVehicle()) {
     703              :         std::cout << "\n   newTarget (maneuverDist=" << myManeuverDist << " offset=" << targetDir << "): " << (myTargetLane == nullptr ? "NULL" : myTargetLane->getID())
     704              :                   << " newFurtherTargets: " << toString(myFurtherTargetLanes)
     705              :                   << std::endl;
     706              :     }
     707              : #endif
     708     78892831 :     return myTargetLane;
     709              : }
     710              : 
     711              : 
     712              : MSLane*
     713     78892831 : MSAbstractLaneChangeModel::determineTargetLane(int& targetDir) const {
     714     78892831 :     targetDir = 0;
     715     78892831 :     if (myManeuverDist == 0) {
     716              :         return nullptr;
     717              :     }
     718              :     // Current lateral boundaries of the vehicle
     719      2255269 :     const double vehRight = myVehicle.getLateralPositionOnLane() - 0.5 * myVehicle.getWidth();
     720      2255269 :     const double vehLeft = myVehicle.getLateralPositionOnLane() + 0.5 * myVehicle.getWidth();
     721      2255269 :     const double halfLaneWidth = 0.5 * myVehicle.getLane()->getWidth();
     722              : 
     723      2255269 :     if (vehRight + myManeuverDist < -halfLaneWidth) {
     724              :         // Vehicle intends to traverse the right lane boundary
     725       301461 :         targetDir = -1;
     726      1953808 :     } else if (vehLeft + myManeuverDist > halfLaneWidth) {
     727              :         // Vehicle intends to traverse the left lane boundary
     728       469080 :         targetDir = 1;
     729              :     }
     730      2255269 :     if (targetDir == 0) {
     731              :         // Presently, no maneuvering into another lane is begun.
     732              :         return nullptr;
     733              :     }
     734       770541 :     MSLane* target = myVehicle.getLane()->getParallelLane(targetDir);
     735       770541 :     if (target == nullptr || target == myShadowLane) {
     736              :         return nullptr;
     737              :     } else {
     738              :         return target;
     739              :     }
     740              : }
     741              : 
     742              : 
     743              : 
     744              : double
     745    630134063 : MSAbstractLaneChangeModel::calcAngleOffset() {
     746              :     double result = 0.;
     747    630134063 :     if (!(fabs(mySpeedLat) < NUMERICAL_EPS && fabs(myPreviousAngleOffset * 180 / M_PI) < NUMERICAL_EPS)) {
     748     18102250 :         if (myVehicle.getLength() < sqrt(SPEED2DIST(mySpeedLat) * SPEED2DIST(mySpeedLat) + SPEED2DIST(myVehicle.getSpeed()) * SPEED2DIST(myVehicle.getSpeed()))) {
     749      5383158 :             result = atan2(mySpeedLat, myVehicle.getSpeed());
     750              :         } else {
     751     12719092 :             result = myPreviousAngleOffset + asin((sin(M_PI / 2 - myPreviousAngleOffset) * (SPEED2DIST(mySpeedLat) - tan(myPreviousAngleOffset) * SPEED2DIST(myVehicle.getSpeed()))) / myVehicle.getLength());
     752              :         }
     753              :     }
     754              : 
     755    630134063 :     myAngleOffset = result;
     756    630134063 :     return result;
     757              : }
     758              : 
     759              : 
     760              : double
     761        94024 : MSAbstractLaneChangeModel::estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel, bool urgent) const {
     762              : 
     763        94024 :     const SUMOVTypeParameter::SubParams& lcParams = myVehicle.getVehicleType().getParameter().getLCParams();
     764       140814 :     if (lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING) == lcParams.end() && lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR) == lcParams.end()) {
     765        46790 :         if (!myVehicle.getVehicleType().wasSet(VTYPEPARS_MAXSPEED_LAT_SET)) {
     766              :             // no dependency of lateral speed on longitudinal speed. (Only called prior to LC initialization to determine whether it could be completed)
     767        46764 :             return STEPS2TIME(MSGlobals::gLaneChangeDuration);
     768              :         } else {
     769           26 :             return remainingManeuverDist / myVehicle.getVehicleType().getMaxSpeedLat();
     770              :         }
     771              :     }
     772              : 
     773        47234 :     if (remainingManeuverDist == 0) {
     774              :         return 0;
     775              :     }
     776              : 
     777              :     // Check argument assumptions
     778              :     assert(speed >= 0);
     779              :     assert(remainingManeuverDist >= 0);
     780              :     assert(decel > 0);
     781              :     assert(myVehicle.getVehicleType().getMaxSpeedLat() > 0);
     782              :     assert(myMaxSpeedLatStanding <= myVehicle.getVehicleType().getMaxSpeedLat());
     783              :     assert(myMaxSpeedLatStanding >= 0);
     784              : 
     785              :     // for brevity
     786              :     const double v0 = speed;
     787              :     const double D = remainingManeuverDist;
     788              :     const double b = decel;
     789        47234 :     const double wmin = myMaxSpeedLatStanding;
     790        47234 :     const double f = myMaxSpeedLatFactor;
     791        47234 :     const double wmax = myVehicle.getVehicleType().getMaxSpeedLat();
     792              : 
     793              :     /* Here's the approach for the calculation of the required time for the LC:
     794              :      * To obtain the maximal LC-duration, for v(t) we assume that v(t)=max(0, v0-b*t),
     795              :      * Where v(t)=0 <=> t >= ts:=v0/b
     796              :      * For the lateral speed w(t) this gives:
     797              :      * w(t) = min(wmax, wmin + f*v(t))
     798              :      * The lateral distance covered until t is
     799              :      * d(t) = int_0^t w(s) ds
     800              :      * We distinguish three possibilities for the solution d(T)=D, where T is the time of the LC completion.
     801              :      * 1) w(T) = wmax, i.e. v(T)>(wmax-wmin)/f
     802              :      * 2) wmin < w(T) < wmax, i.e. (wmax-wmin)/f > v(T) > 0
     803              :      * 3) w(T) = wmin, i.e., v(T)=0
     804              :      */
     805        47234 :     const double vm = (wmax - wmin) / f;
     806              :     double distSoFar = 0.;
     807              :     double timeSoFar = 0.;
     808              :     double v = v0;
     809        47234 :     if (v > vm) {
     810         1065 :         const double wmaxTime = (v0 - vm) / b;
     811         1065 :         const double d1 = wmax * wmaxTime;
     812         1065 :         if (d1 >= D) {
     813          422 :             return D / wmax;
     814              :         } else {
     815          643 :             distSoFar += d1;
     816          643 :             timeSoFar += wmaxTime;
     817              :             v = vm;
     818              :         }
     819              :     }
     820        46812 :     if (v > 0) {
     821              :         /* Here, w(t1+t) = wmin + f*v(t1+t) = wmin + f*(v - b*t)
     822              :          * Thus, the additional lateral distance covered after time t is:
     823              :          * d2 = (wmin + f*v)*t - 0.5*f*b*t^2
     824              :          * and the additional lateral distance covered until v=0 at t=v/b is:
     825              :          * d2 = (wmin + 0.5*f*v)*t
     826              :          */
     827         4605 :         const double t = v / b; // stop time
     828         4605 :         const double d2 = (wmin + 0.5 * f * v) * t; // lateral distance covered until stop
     829              :         assert(d2 > 0);
     830         4605 :         if (distSoFar + d2 >= D) {
     831              :             // LC is completed during this phase
     832           12 :             const double x = 0.5 * f * b;
     833           12 :             const double y = wmin + f * v;
     834              :             /* Solve D - distSoFar = y*t - x*t^2.
     835              :              * 0 = x*t^2 - y*t/x + (D - distSoFar)/x
     836              :              */
     837           12 :             const double p = 0.5 * y / x;
     838           12 :             const double q = (D - distSoFar) / x;
     839              :             assert(p * p - q > 0);
     840           12 :             const double t2 = p + sqrt(p * p - q);
     841           12 :             return timeSoFar + t2;
     842              :         } else {
     843              :             distSoFar += d2;
     844         4593 :             timeSoFar += t;
     845              :             //v = 0;
     846              :         }
     847              :     }
     848              :     // If we didn't return yet this means the LC was not completed until the vehicle stops (if braking with rate b)
     849        46800 :     if (wmin == 0) {
     850              :         // LC won't be completed if vehicle stands
     851        46800 :         double maneuverDist = remainingManeuverDist;
     852        46800 :         const double vModel = computeSpeedLat(maneuverDist, maneuverDist, urgent);
     853        46800 :         double result = D / vModel;
     854              :         // make sure that the vehicle isn't braking to a stop during the manuever
     855        46800 :         if (vModel > SUMO_const_haltingSpeed && (vModel + myVehicle.getAcceleration() * result) > SUMO_const_haltingSpeed) {
     856              :             // unless the model tells us something different
     857              :             return result;
     858              :         } else {
     859        46075 :             return -1;
     860              :         }
     861              :     } else {
     862              :         // complete LC with lateral speed wmin
     863            0 :         return timeSoFar + (D - distSoFar) / wmin;
     864              :     }
     865              : }
     866              : 
     867              : SUMOTime
     868        46405 : MSAbstractLaneChangeModel::remainingTime() const {
     869              :     assert(isChangingLanes()); // Only to be called during ongoing lane change
     870        46405 :     const SUMOVTypeParameter::SubParams& lcParams = myVehicle.getVehicleType().getParameter().getLCParams();
     871        92449 :     if (lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING) == lcParams.end() && lcParams.find(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR) == lcParams.end()) {
     872        46044 :         if (myVehicle.getVehicleType().wasSet(VTYPEPARS_MAXSPEED_LAT_SET)) {
     873            0 :             return TIME2STEPS((1. - myLaneChangeCompletion) * myManeuverDist / myVehicle.getVehicleType().getMaxSpeedLat());
     874              :         } else {
     875        46044 :             return (SUMOTime)((1. - myLaneChangeCompletion) * (double)MSGlobals::gLaneChangeDuration);
     876              :         }
     877              :     }
     878              :     // Using maxSpeedLat(Factor/Standing)
     879          361 :     const bool urgent = (myOwnState & LCA_URGENT) != 0;
     880          406 :     return TIME2STEPS(estimateLCDuration(myVehicle.getSpeed(),
     881              :                                          fabs(myManeuverDist * (1 - myLaneChangeCompletion)),
     882              :                                          myVehicle.getCarFollowModel().getMaxDecel(), urgent));
     883              : }
     884              : 
     885              : 
     886              : void
     887      2343976 : MSAbstractLaneChangeModel::setShadowApproachingInformation(MSLink* link) const {
     888              :     //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " set shadow approaching=" << link->getViaLaneOrLane()->getID() << "\n";
     889      2343976 :     myApproachedByShadow.push_back(link);
     890      2343976 : }
     891              : 
     892              : void
     893    558436228 : MSAbstractLaneChangeModel::removeShadowApproachingInformation() const {
     894    560780204 :     for (std::vector<MSLink*>::iterator it = myApproachedByShadow.begin(); it != myApproachedByShadow.end(); ++it) {
     895              :         //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " remove shadow approaching=" << (*it)->getViaLaneOrLane()->getID() << "\n";
     896      2343976 :         (*it)->removeApproaching(&myVehicle);
     897              :     }
     898              :     myApproachedByShadow.clear();
     899    558436228 : }
     900              : 
     901              : 
     902              : 
     903              : void
     904     41784662 : MSAbstractLaneChangeModel::checkTraCICommands() {
     905     41784662 :     int newstate = myVehicle.influenceChangeDecision(myOwnState);
     906     41784662 :     int oldstate = myVehicle.getLaneChangeModel().getOwnState();
     907     41784662 :     if (myOwnState != newstate) {
     908           20 :         if (MSGlobals::gLateralResolution > 0.) {
     909              :             // Calculate and set the lateral maneuver distance corresponding to the change request
     910              :             // to induce a corresponding sublane change.
     911           15 :             const int dir = (newstate & LCA_RIGHT) != 0 ? -1 : ((newstate & LCA_LEFT) != 0 ? 1 : 0);
     912              :             // minimum distance to move the vehicle fully onto the lane at offset dir
     913           15 :             const double latLaneDist = myVehicle.lateralDistanceToLane(dir);
     914           15 :             if ((newstate & LCA_TRACI) != 0) {
     915           15 :                 if ((newstate & LCA_STAY) != 0) {
     916            0 :                     setManeuverDist(0.);
     917           15 :                 } else if (((newstate & LCA_RIGHT) != 0 && dir < 0)
     918           10 :                            || ((newstate & LCA_LEFT) != 0 && dir > 0)) {
     919            5 :                     setManeuverDist(latLaneDist);
     920              :                 }
     921              :             }
     922           15 :             if (myVehicle.hasInfluencer()) {
     923              :                 // lane change requests override sublane change requests
     924           15 :                 myVehicle.getInfluencer().resetLatDist();
     925              :             }
     926              : 
     927              :         }
     928           20 :         setOwnState(newstate);
     929              :     } else {
     930              :         // Check for sublane change requests
     931     41784642 :         if (myVehicle.hasInfluencer() && myVehicle.getInfluencer().getLatDist() != 0) {
     932          380 :             const double maneuverDist = myVehicle.getInfluencer().getLatDist();
     933          380 :             myVehicle.getLaneChangeModel().setManeuverDist(maneuverDist);
     934          380 :             myVehicle.getInfluencer().resetLatDist();
     935          380 :             newstate |= LCA_TRACI;
     936          380 :             if (myOwnState != newstate) {
     937            5 :                 setOwnState(newstate);
     938              :             }
     939          380 :             if (gDebugFlag2) {
     940            0 :                 std::cout << "     traci influenced maneuverDist=" << maneuverDist << "\n";
     941              :             }
     942              :         }
     943              :     }
     944     41784662 :     if (gDebugFlag2) {
     945            0 :         std::cout << SIMTIME << " veh=" << myVehicle.getID() << " stateAfterTraCI=" << toString((LaneChangeAction)newstate) << " original=" << toString((LaneChangeAction)oldstate) << "\n";
     946              :     }
     947     41784662 : }
     948              : 
     949              : void
     950        42757 : MSAbstractLaneChangeModel::changedToOpposite() {
     951        42757 :     myAmOpposite = !myAmOpposite;
     952        42757 :     myAlreadyChanged = true;
     953        42757 : }
     954              : 
     955              : void
     956       667689 : MSAbstractLaneChangeModel::setFollowerGaps(CLeaderDist follower, double secGap)  {
     957       667689 :     if (follower.first != 0) {
     958       384925 :         myLastFollowerGap = follower.second + follower.first->getVehicleType().getMinGap();
     959       384925 :         myLastFollowerSecureGap = secGap;
     960       384925 :         myLastFollowerSpeed = follower.first->getSpeed();
     961              :     }
     962       667689 : }
     963              : 
     964              : void
     965       667689 : MSAbstractLaneChangeModel::setLeaderGaps(CLeaderDist leader, double secGap) {
     966       667689 :     if (leader.first != 0) {
     967       476549 :         myLastLeaderGap = leader.second + myVehicle.getVehicleType().getMinGap();
     968       476549 :         myLastLeaderSecureGap = secGap;
     969       476549 :         myLastLeaderSpeed = leader.first->getSpeed();
     970              :     }
     971       667689 : }
     972              : 
     973              : void
     974       667689 : MSAbstractLaneChangeModel::setOrigLeaderGaps(CLeaderDist leader, double secGap) {
     975       667689 :     if (leader.first != 0) {
     976       395359 :         myLastOrigLeaderGap = leader.second + myVehicle.getVehicleType().getMinGap();
     977       395359 :         myLastOrigLeaderSecureGap = secGap;
     978       395359 :         myLastOrigLeaderSpeed = leader.first->getSpeed();
     979              :     }
     980       667689 : }
     981              : 
     982              : void
     983    548517976 : MSAbstractLaneChangeModel::prepareStep() {
     984    548517976 :     getCanceledState(-1) = LCA_NONE;
     985    548517976 :     getCanceledState(0) = LCA_NONE;
     986    548517976 :     getCanceledState(1) = LCA_NONE;
     987              :     saveLCState(-1, LCA_UNKNOWN, LCA_UNKNOWN);
     988              :     saveLCState(0, LCA_UNKNOWN, LCA_UNKNOWN);
     989              :     saveLCState(1, LCA_UNKNOWN, LCA_UNKNOWN);
     990    548517976 :     myLastLateralGapRight = NO_NEIGHBOR;
     991    548517976 :     myLastLateralGapLeft = NO_NEIGHBOR;
     992    548517976 :     if (!myDontResetLCGaps) {
     993    548513115 :         myLastLeaderGap = NO_NEIGHBOR;
     994    548513115 :         myLastLeaderSecureGap = NO_NEIGHBOR;
     995    548513115 :         myLastFollowerGap = NO_NEIGHBOR;
     996    548513115 :         myLastFollowerSecureGap = NO_NEIGHBOR;
     997    548513115 :         myLastOrigLeaderGap = NO_NEIGHBOR;
     998    548513115 :         myLastOrigLeaderSecureGap = NO_NEIGHBOR;
     999    548513115 :         myLastLeaderSpeed = NO_NEIGHBOR;
    1000    548513115 :         myLastFollowerSpeed = NO_NEIGHBOR;
    1001    548513115 :         myLastOrigLeaderSpeed = NO_NEIGHBOR;
    1002              :     }
    1003    548517976 :     myCommittedSpeed = 0;
    1004    548517976 : }
    1005              : 
    1006              : void
    1007         6537 : MSAbstractLaneChangeModel::setFollowerGaps(const MSLeaderDistanceInfo& vehicles) {
    1008              :     int rightmost;
    1009              :     int leftmost;
    1010         6537 :     vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
    1011        27220 :     for (int i = rightmost; i <= leftmost; ++i) {
    1012        20683 :         CLeaderDist vehDist = vehicles[i];
    1013        20683 :         if (vehDist.first != 0) {
    1014        12731 :             const MSVehicle* leader = &myVehicle;
    1015              :             const MSVehicle* follower = vehDist.first;
    1016        12731 :             const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
    1017        12731 :             if (netGap < myLastFollowerGap && netGap >= 0) {
    1018         5465 :                 myLastFollowerGap = netGap;
    1019         5465 :                 myLastFollowerSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
    1020         5465 :                 myLastFollowerSpeed = follower->getSpeed();
    1021              :             }
    1022              :         }
    1023              :     }
    1024         6537 : }
    1025              : 
    1026              : void
    1027         6537 : MSAbstractLaneChangeModel::setLeaderGaps(const MSLeaderDistanceInfo& vehicles) {
    1028              :     int rightmost;
    1029              :     int leftmost;
    1030         6537 :     vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
    1031        27220 :     for (int i = rightmost; i <= leftmost; ++i) {
    1032        20683 :         CLeaderDist vehDist = vehicles[i];
    1033        20683 :         if (vehDist.first != 0) {
    1034              :             const MSVehicle* leader = vehDist.first;
    1035        15512 :             const MSVehicle* follower = &myVehicle;
    1036        15512 :             const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
    1037        15512 :             if (netGap < myLastLeaderGap && netGap >= 0) {
    1038         5884 :                 myLastLeaderGap = netGap;
    1039         5884 :                 myLastLeaderSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
    1040         5884 :                 myLastLeaderSpeed = leader->getSpeed();
    1041              :             }
    1042              :         }
    1043              :     }
    1044         6537 : }
    1045              : 
    1046              : void
    1047         6537 : MSAbstractLaneChangeModel::setOrigLeaderGaps(const MSLeaderDistanceInfo& vehicles) {
    1048              :     int rightmost;
    1049              :     int leftmost;
    1050         6537 :     vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
    1051        27115 :     for (int i = rightmost; i <= leftmost; ++i) {
    1052        20578 :         CLeaderDist vehDist = vehicles[i];
    1053        20578 :         if (vehDist.first != 0) {
    1054              :             const MSVehicle* leader = vehDist.first;
    1055         8880 :             const MSVehicle* follower = &myVehicle;
    1056         8880 :             const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
    1057         8880 :             if (netGap < myLastOrigLeaderGap && netGap >= 0) {
    1058         3481 :                 myLastOrigLeaderGap = netGap;
    1059         3481 :                 myLastOrigLeaderSecureGap = follower->getCarFollowModel().getSecureGap(follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
    1060         3481 :                 myLastOrigLeaderSpeed = leader->getSpeed();
    1061              :             }
    1062              :         }
    1063              :     }
    1064         6537 : }
    1065              : 
    1066              : 
    1067              : bool
    1068     23075101 : MSAbstractLaneChangeModel::isStrategicBlocked() const {
    1069     23075101 :     const int stateRight = mySavedStateRight.second;
    1070     23075101 :     if (
    1071              :         (stateRight & LCA_STRATEGIC) != 0
    1072              :         && (stateRight & LCA_RIGHT) != 0
    1073       937412 :         && (stateRight & LCA_BLOCKED) != 0) {
    1074              :         return true;
    1075              :     }
    1076     22499443 :     const int stateLeft = mySavedStateLeft.second;
    1077     22499443 :     if (
    1078              :         (stateLeft & LCA_STRATEGIC) != 0
    1079              :         && (stateLeft & LCA_LEFT) != 0
    1080        73219 :         && (stateLeft & LCA_BLOCKED) != 0) {
    1081        15627 :         return true;
    1082              :     }
    1083              :     return false;
    1084              : }
    1085              : 
    1086              : double
    1087    224015495 : MSAbstractLaneChangeModel::getForwardPos() const {
    1088    224015495 :     return myAmOpposite ? myVehicle.getLane()->getLength() - myVehicle.getPositionOnLane() : myVehicle.getPositionOnLane();
    1089              : }
    1090              : 
    1091              : 
    1092              : int
    1093         1426 : MSAbstractLaneChangeModel::getNormalizedLaneIndex() {
    1094         1426 :     const int i = myVehicle.getLane()->getIndex();
    1095         1426 :     if (myAmOpposite) {
    1096          790 :         return myVehicle.getLane()->getParallelOpposite()->getEdge().getNumLanes() + myVehicle.getLane()->getEdge().getNumLanes() - 1 - i;
    1097              :     } else {
    1098              :         return i;
    1099              :     }
    1100              : }
    1101              : 
    1102              : void
    1103     41466362 : MSAbstractLaneChangeModel::addLCSpeedAdvice(const double vSafe, bool ownAdvice) {
    1104     41466362 :     const double accel = SPEED2ACCEL(vSafe - myVehicle.getSpeed());
    1105     41466362 :     myLCAccelerationAdvices.push_back({accel, ownAdvice});
    1106     41466362 : }
    1107              : 
    1108              : 
    1109              : void
    1110         2181 : MSAbstractLaneChangeModel::saveState(OutputDevice& out) const {
    1111              :     std::vector<std::string> lcState;
    1112         2181 :     if (MSGlobals::gLaneChangeDuration > 0) {
    1113            1 :         lcState.push_back(toString(mySpeedLat));
    1114            1 :         lcState.push_back(toString(myLaneChangeCompletion));
    1115            2 :         lcState.push_back(toString(myLaneChangeDirection));
    1116              :     }
    1117         2181 :     if (lcState.size() > 0) {
    1118              :         out.writeAttr(SUMO_ATTR_LCSTATE, lcState);
    1119              :     }
    1120         2181 : }
    1121              : 
    1122              : void
    1123         3871 : MSAbstractLaneChangeModel::loadState(const SUMOSAXAttributes& attrs) {
    1124         3871 :     if (attrs.hasAttribute(SUMO_ATTR_LCSTATE)) {
    1125            1 :         std::istringstream bis(attrs.getString(SUMO_ATTR_LCSTATE));
    1126            1 :         bis >> mySpeedLat;
    1127            1 :         bis >> myLaneChangeCompletion;
    1128            1 :         bis >> myLaneChangeDirection;
    1129            1 :     }
    1130         3871 : }
        

Generated by: LCOV version 2.0-1