LCOV - code coverage report
Current view: top level - src/microsim - MSLane.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 97.5 % 1866 1819
Test Date: 2026-09-20 15:45:03 Functions: 96.8 % 154 149

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    MSLane.cpp
      15              : /// @author  Christian Roessel
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Daniel Krajzewicz
      18              : /// @author  Tino Morenz
      19              : /// @author  Axel Wegener
      20              : /// @author  Michael Behrisch
      21              : /// @author  Christoph Sommer
      22              : /// @author  Mario Krumnow
      23              : /// @author  Leonhard Luecken
      24              : /// @author  Mirko Barthauer
      25              : /// @date    Mon, 05 Mar 2001
      26              : ///
      27              : // Representation of a lane in the micro simulation
      28              : /****************************************************************************/
      29              : #include <config.h>
      30              : 
      31              : #include <cmath>
      32              : #include <bitset>
      33              : #include <iostream>
      34              : #include <cassert>
      35              : #include <functional>
      36              : #include <algorithm>
      37              : #include <iterator>
      38              : #include <exception>
      39              : #include <climits>
      40              : #include <set>
      41              : #include <utils/common/UtilExceptions.h>
      42              : #include <utils/common/StdDefs.h>
      43              : #include <utils/common/MsgHandler.h>
      44              : #include <utils/common/ToString.h>
      45              : #ifdef HAVE_FOX
      46              : #include <utils/common/ScopedLocker.h>
      47              : #endif
      48              : #include <utils/options/OptionsCont.h>
      49              : #include <utils/emissions/HelpersHarmonoise.h>
      50              : #include <utils/geom/GeomHelper.h>
      51              : #include <libsumo/TraCIConstants.h>
      52              : #include <microsim/transportables/MSPModel.h>
      53              : #include <microsim/transportables/MSTransportableControl.h>
      54              : #include <microsim/traffic_lights/MSRailSignal.h>
      55              : #include <microsim/traffic_lights/MSRailSignalControl.h>
      56              : #include <microsim/traffic_lights/MSDriveWay.h>
      57              : #include <microsim/lcmodels/MSAbstractLaneChangeModel.h>
      58              : #include <microsim/devices/MSDevice_Taxi.h>
      59              : #include <microsim/trigger/MSTriggeredRerouter.h>
      60              : #include <mesosim/MELoop.h>
      61              : #include "MSNet.h"
      62              : #include "MSVehicleType.h"
      63              : #include "MSEdge.h"
      64              : #include "MSEdgeControl.h"
      65              : #include "MSJunction.h"
      66              : #include "MSLogicJunction.h"
      67              : #include "MSLink.h"
      68              : #include "MSLane.h"
      69              : #include "MSVehicleTransfer.h"
      70              : #include "MSGlobals.h"
      71              : #include "MSVehicleControl.h"
      72              : #include "MSInsertionControl.h"
      73              : #include "MSVehicleControl.h"
      74              : #include "MSLeaderInfo.h"
      75              : #include "MSVehicle.h"
      76              : #include "MSStop.h"
      77              : 
      78              : //#define DEBUG_INSERTION
      79              : //#define DEBUG_PLAN_MOVE
      80              : //#define DEBUG_EXEC_MOVE
      81              : //#define DEBUG_CONTEXT
      82              : //#define DEBUG_PARTIALS
      83              : //#define DEBUG_MANEUVER_RESERVATIONS
      84              : //#define DEBUG_OPPOSITE
      85              : //#define DEBUG_VEHICLE_CONTAINER
      86              : //#define DEBUG_COLLISIONS
      87              : //#define DEBUG_JUNCTION_COLLISIONS
      88              : //#define DEBUG_PEDESTRIAN_COLLISIONS
      89              : //#define DEBUG_LANE_SORTER
      90              : //#define DEBUG_NO_CONNECTION
      91              : //#define DEBUG_SURROUNDING
      92              : //#define DEBUG_EXTRAPOLATE_DEPARTPOS
      93              : //#define DEBUG_ITERATOR
      94              : 
      95              : //#define DEBUG_COND (false)
      96              : //#define DEBUG_COND (true)
      97              : #define DEBUG_COND (isSelected())
      98              : #define DEBUG_COND2(obj) ((obj != nullptr && (obj)->isSelected()))
      99              : //#define DEBUG_COND (getID() == "ego")
     100              : //#define DEBUG_COND2(obj) ((obj != 0 && (obj)->getID() == "ego"))
     101              : //#define DEBUG_COND2(obj) (true)
     102              : 
     103              : 
     104              : // ===========================================================================
     105              : // static member definitions
     106              : // ===========================================================================
     107              : MSLane::DictType MSLane::myDict;
     108              : MSLane::CollisionAction MSLane::myCollisionAction(MSLane::COLLISION_ACTION_TELEPORT);
     109              : MSLane::CollisionAction MSLane::myIntermodalCollisionAction(MSLane::COLLISION_ACTION_WARN);
     110              : bool MSLane::myCheckJunctionCollisions(false);
     111              : double MSLane::myCheckJunctionCollisionMinGap(0);
     112              : SUMOTime MSLane::myCollisionStopTime(0);
     113              : SUMOTime MSLane::myIntermodalCollisionStopTime(0);
     114              : double MSLane::myCollisionMinGapFactor(1.0);
     115              : bool MSLane::myExtrapolateSubstepDepart(false);
     116              : std::vector<SumoRNG> MSLane::myRNGs;
     117              : DepartSpeedDefinition MSLane::myDefaultDepartSpeedDefinition(DepartSpeedDefinition::DEFAULT);
     118              : double MSLane::myDefaultDepartSpeed(0);
     119              : 
     120              : 
     121              : // ===========================================================================
     122              : // internal class method definitions
     123              : // ===========================================================================
     124              : void
     125    195872162 : MSLane::StoringVisitor::add(const MSLane* const l) const {
     126    195872162 :     switch (myDomain) {
     127       843440 :         case libsumo::CMD_GET_VEHICLE_VARIABLE: {
     128      1527138 :             for (const MSVehicle* veh : l->getVehiclesSecure()) {
     129       683698 :                 if (myShape.distance2D(veh->getPosition()) <= myRange) {
     130       339428 :                     myObjects.insert(veh);
     131              :                 }
     132              :             }
     133       843615 :             for (const MSBaseVehicle* veh : l->getParkingVehicles()) {
     134          175 :                 if (myShape.distance2D(veh->getPosition()) <= myRange) {
     135           36 :                     myObjects.insert(veh);
     136              :                 }
     137              :             }
     138       843440 :             l->releaseVehicles();
     139              :         }
     140       843440 :         break;
     141       834882 :         case libsumo::CMD_GET_PERSON_VARIABLE: {
     142       834882 :             l->getVehiclesSecure();
     143       834882 :             std::vector<MSTransportable*> persons = l->getEdge().getSortedPersons(MSNet::getInstance()->getCurrentTimeStep(), true);
     144       954089 :             for (auto p : persons) {
     145       119207 :                 if (myShape.distance2D(p->getPosition()) <= myRange) {
     146        62310 :                     myObjects.insert(p);
     147              :                 }
     148              :             }
     149       834882 :             l->releaseVehicles();
     150       834882 :         }
     151       834882 :         break;
     152    194128389 :         case libsumo::CMD_GET_EDGE_VARIABLE: {
     153    194128389 :             if (myShape.size() != 1 || l->getShape().distance2D(myShape[0]) <= myRange) {
     154    191889524 :                 myObjects.insert(&l->getEdge());
     155              :             }
     156              :         }
     157              :         break;
     158        65451 :         case libsumo::CMD_GET_LANE_VARIABLE: {
     159        65451 :             if (myShape.size() != 1 || l->getShape().distance2D(myShape[0]) <= myRange) {
     160        64563 :                 myObjects.insert(l);
     161              :             }
     162              :         }
     163              :         break;
     164              :         default:
     165              :             break;
     166              : 
     167              :     }
     168    195872162 : }
     169              : 
     170              : 
     171              : MSLane::AnyVehicleIterator&
     172  12595619111 : MSLane::AnyVehicleIterator::operator++() {
     173  12595619111 :     if (nextIsMyVehicles()) {
     174  12214969206 :         if (myI1 != myI1End) {
     175   8928667557 :             myI1 += myDirection;
     176   3286301649 :         } else if (myI3 != myI3End) {
     177   3286301649 :             myI3 += myDirection;
     178              :         }
     179              :         // else: already at end
     180              :     } else {
     181    380649905 :         myI2 += myDirection;
     182              :     }
     183              :     //if (DEBUG_COND2(myLane)) std::cout << SIMTIME << "          AnyVehicleIterator::operator++ lane=" << myLane->getID() << " myI1=" << myI1 << " myI2=" << myI2 << "\n";
     184  12595619111 :     return *this;
     185              : }
     186              : 
     187              : 
     188              : const MSVehicle*
     189  13327981439 : MSLane::AnyVehicleIterator::operator*() {
     190  13327981439 :     if (nextIsMyVehicles()) {
     191  12940253572 :         if (myI1 != myI1End) {
     192   9072514846 :             return myLane->myVehicles[myI1];
     193   3867738726 :         } else if (myI3 != myI3End) {
     194   3361003506 :             return myLane->myTmpVehicles[myI3];
     195              :         } else {
     196              :             assert(myI2 == myI2End);
     197              :             return nullptr;
     198              :         }
     199              :     } else {
     200    387727867 :         return myLane->myPartialVehicles[myI2];
     201              :     }
     202              : }
     203              : 
     204              : 
     205              : bool
     206  25923600550 : MSLane::AnyVehicleIterator::nextIsMyVehicles() const {
     207              : #ifdef DEBUG_ITERATOR
     208              :     if (DEBUG_COND2(myLane)) std::cout << SIMTIME << "          AnyVehicleIterator::nextIsMyVehicles lane=" << myLane->getID()
     209              :                                            << " myDownstream=" << myDownstream
     210              :                                            << " myI1=" << myI1
     211              :                                            << " myI1End=" << myI1End
     212              :                                            << " myI2=" << myI2
     213              :                                            << " myI2End=" << myI2End
     214              :                                            << " myI3=" << myI3
     215              :                                            << " myI3End=" << myI3End
     216              :                                            << "\n";
     217              : #endif
     218  25923600550 :     if (myI1 == myI1End && myI3 == myI3End) {
     219    760098603 :         if (myI2 != myI2End) {
     220              :             return false;
     221              :         } else {
     222    506735220 :             return true; // @note. must be caught
     223              :         }
     224              :     } else {
     225  25163501947 :         if (myI2 == myI2End) {
     226              :             return true;
     227              :         } else {
     228   7271546048 :             MSVehicle* cand = myI1 == myI1End ? myLane->myTmpVehicles[myI3] : myLane->myVehicles[myI1];
     229              : #ifdef DEBUG_ITERATOR
     230              :             if (DEBUG_COND2(myLane)) std::cout << "              "
     231              :                                                    << " veh1=" << cand->getID()
     232              :                                                    << " isTmp=" << (myI1 == myI1End)
     233              :                                                    << " veh2=" << myLane->myPartialVehicles[myI2]->getID()
     234              :                                                    << " pos1=" << cand->getPositionOnLane(myLane)
     235              :                                                    << " pos2=" << myLane->myPartialVehicles[myI2]->getPositionOnLane(myLane)
     236              :                                                    << "\n";
     237              : #endif
     238   7271546048 :             if (cand->getPositionOnLane() < myLane->myPartialVehicles[myI2]->getPositionOnLane(myLane)) {
     239   6803506249 :                 return myDownstream;
     240              :             } else {
     241    468039799 :                 return !myDownstream;
     242              :             }
     243              :         }
     244              :     }
     245              : }
     246              : 
     247              : 
     248              : // ===========================================================================
     249              : // member method definitions
     250              : // ===========================================================================
     251              : #ifdef _MSC_VER
     252              : #pragma warning(push)
     253              : #pragma warning(disable: 4355) // mask warning about "this" in initializers
     254              : #endif
     255      2157017 : MSLane::MSLane(const std::string& id, double maxSpeed, double friction, double length, MSEdge* const edge,
     256              :                int numericalID, const PositionVector& shape, double width,
     257              :                SVCPermissions permissions,
     258              :                SVCPermissions changeLeft, SVCPermissions changeRight,
     259              :                int index, bool isRampAccel,
     260              :                const std::string& type,
     261      2157017 :                const PositionVector& outlineShape) :
     262              :     Named(id),
     263      4314034 :     myNumericalID(numericalID), myShape(shape), myIndex(index),
     264      2157017 :     myVehicles(), myLength(length), myWidth(width),
     265      2157017 :     myEdge(edge), myMaxSpeed(maxSpeed),
     266      2157017 :     myFrictionCoefficient(friction),
     267      2157017 :     mySpeedModified(false),
     268      2157017 :     myPermissions(permissions),
     269      2157017 :     myChangeLeft(changeLeft),
     270      2157017 :     myChangeRight(changeRight),
     271      2157017 :     myOriginalPermissions(permissions),
     272      2157017 :     myLogicalPredecessorLane(nullptr),
     273      2157017 :     myCanonicalPredecessorLane(nullptr),
     274      2157017 :     myCanonicalSuccessorLane(nullptr),
     275      2157017 :     myBruttoVehicleLengthSum(0), myNettoVehicleLengthSum(0),
     276      2157017 :     myBruttoVehicleLengthSumToRemove(0), myNettoVehicleLengthSumToRemove(0),
     277      2157017 :     myRecalculateBruttoSum(false),
     278      2157017 :     myLeaderInfo(width, nullptr, 0.),
     279      2157017 :     myFollowerInfo(width, nullptr, 0.),
     280      2157017 :     myLeaderInfoTime(SUMOTime_MIN),
     281      2157017 :     myFollowerInfoTime(SUMOTime_MIN),
     282      2157017 :     myLengthGeometryFactor(MAX2(POSITION_EPS, myShape.length()) / myLength), // factor should not be 0
     283      2157017 :     myIsRampAccel(isRampAccel),
     284      2157017 :     myLaneType(type),
     285      2157017 :     myRightSideOnEdge(0), // initialized in MSEdge::initialize
     286      2157017 :     myRightmostSublane(0),
     287      2157017 :     myNeedsCollisionCheck(false),
     288      2157017 :     myOpposite(nullptr),
     289      2157017 :     myBidiLane(nullptr),
     290              : #ifdef HAVE_FOX
     291              :     mySimulationTask(*this, 0),
     292              : #endif
     293      4314034 :     myStopWatch(3) {
     294              :     // initialized in MSEdge::initialize
     295      2157017 :     initRestrictions();// may be reloaded again from initialized in MSEdge::closeBuilding
     296              :     assert(myRNGs.size() > 0);
     297      2157017 :     myRNGIndex = numericalID % myRNGs.size();
     298      2157017 :     if (outlineShape.size() > 0) {
     299        23936 :         myOutlineShape = new PositionVector(outlineShape);
     300              :     }
     301      2157017 : }
     302              : #ifdef _MSC_VER
     303              : #pragma warning(pop)
     304              : #endif
     305              : 
     306              : 
     307      5967956 : MSLane::~MSLane() {
     308      5078749 :     for (MSLink* const l : myLinks) {
     309      2940243 :         delete l;
     310              :     }
     311      2138506 :     delete myOutlineShape;
     312     12383474 : }
     313              : 
     314              : 
     315              : void
     316      2159681 : MSLane::initRestrictions() {
     317              :     // simplify unit testing without MSNet instance
     318      2159681 :     myRestrictions = MSGlobals::gUnitTests ? nullptr : MSNet::getInstance()->getRestrictions(myEdge->getEdgeType());
     319      2159681 : }
     320              : 
     321              : 
     322              : void
     323      2153984 : MSLane::checkBufferType() {
     324      2153984 :     if (MSGlobals::gNumSimThreads <= 1) {
     325              :         myVehBuffer.unsetCondition();
     326              : //    } else {
     327              : // this is an idea for better memory locality, lanes with nearby numerical ids get the same rng and thus the same thread
     328              : // first tests show no visible effect though
     329              : //        myRNGIndex = myNumericalID * myRNGs.size() / dictSize();
     330              :     }
     331      2153984 : }
     332              : 
     333              : 
     334              : void
     335      2967056 : MSLane::addLink(MSLink* link) {
     336      2967056 :     myLinks.push_back(link);
     337      2967056 : }
     338              : 
     339              : 
     340              : void
     341         8964 : MSLane::setOpposite(MSLane* oppositeLane) {
     342         8964 :     myOpposite = oppositeLane;
     343         8964 :     if (myOpposite != nullptr && getLength() > myOpposite->getLength()) {
     344           15 :         WRITE_WARNINGF(TL("Unequal lengths of neigh lane '%' and lane '%' (% != %)."), getID(), myOpposite->getID(), getLength(), myOpposite->getLength());
     345              :     }
     346         8964 : }
     347              : 
     348              : void
     349        33060 : MSLane::setBidiLane(MSLane* bidiLane) {
     350        33060 :     myBidiLane = bidiLane;
     351        33060 :     if (myBidiLane != nullptr && getLength() > myBidiLane->getLength()) {
     352           66 :         if (isNormal() || MSGlobals::gUsingInternalLanes) {
     353          198 :             WRITE_WARNINGF(TL("Unequal lengths of bidi lane '%' and lane '%' (% != %)."), getID(), myBidiLane->getID(), getLength(), myBidiLane->getLength());
     354              :         }
     355              :     }
     356        33060 : }
     357              : 
     358              : 
     359              : 
     360              : // ------ interaction with MSMoveReminder ------
     361              : void
     362      2612766 : MSLane::addMoveReminder(MSMoveReminder* rem, bool addToVehicles) {
     363      2612766 :     myMoveReminders.push_back(rem);
     364      2612766 :     if (addToVehicles) {
     365      2619900 :         for (MSVehicle* const veh : myVehicles) {
     366        15980 :             veh->addReminder(rem);
     367              :         }
     368              :     }
     369              :     // XXX: Here, the partial occupators are ignored!? Refs. #3255
     370      2612766 : }
     371              : 
     372              : 
     373              : void
     374            0 : MSLane::removeMoveReminder(MSMoveReminder* rem) {
     375            0 :     auto it = std::find(myMoveReminders.begin(), myMoveReminders.end(), rem);
     376            0 :     if (it != myMoveReminders.end()) {
     377            0 :         myMoveReminders.erase(it);
     378            0 :         for (MSVehicle* const veh : myVehicles) {
     379            0 :             veh->removeReminder(rem);
     380              :         }
     381              :     }
     382            0 : }
     383              : 
     384              : 
     385              : double
     386     18090263 : MSLane::setPartialOccupation(MSVehicle* v) {
     387              :     // multithreading: there are concurrent writes to myNeedsCollisionCheck but all of them should set it to true
     388     18090263 :     myNeedsCollisionCheck = true; // always check
     389              : #ifdef DEBUG_PARTIALS
     390              :     if (DEBUG_COND2(v)) {
     391              :         std::cout << SIMTIME << " setPartialOccupation. lane=" << getID() << " veh=" << v->getID() << "\n";
     392              :     }
     393              : #endif
     394              :     // XXX update occupancy here?
     395              : #ifdef HAVE_FOX
     396     18090263 :     ScopedLocker<> lock(myPartialOccupatorMutex, MSGlobals::gNumSimThreads > 1);
     397              : #endif
     398              :     //assert(std::find(myPartialVehicles.begin(), myPartialVehicles.end(), v) == myPartialVehicles.end());
     399     18090263 :     myPartialVehicles.push_back(v);
     400     20670394 :     return myLength;
     401              : }
     402              : 
     403              : 
     404              : void
     405     18090313 : MSLane::resetPartialOccupation(MSVehicle* v) {
     406              : #ifdef HAVE_FOX
     407     18090313 :     ScopedLocker<> lock(myPartialOccupatorMutex, MSGlobals::gNumSimThreads > 1);
     408              : #endif
     409              : #ifdef DEBUG_PARTIALS
     410              :     if (DEBUG_COND2(v)) {
     411              :         std::cout << SIMTIME << " resetPartialOccupation. lane=" << getID() << " veh=" << v->getID() << "\n";
     412              :     }
     413              : #endif
     414     19297683 :     for (VehCont::iterator i = myPartialVehicles.begin(); i != myPartialVehicles.end(); ++i) {
     415     19297621 :         if (v == *i) {
     416     18090251 :             myPartialVehicles.erase(i);
     417              :             // XXX update occupancy here?
     418              :             //std::cout << "    removed from myPartialVehicles\n";
     419              :             return;
     420              :         }
     421              :     }
     422              :     // bluelight eqipped vehicle can teleport onto the intersection without using a connection
     423              :     assert(false || MSGlobals::gClearState || v->getLaneChangeModel().hasBlueLight());
     424              : }
     425              : 
     426              : 
     427              : void
     428       229016 : MSLane::setManeuverReservation(MSVehicle* v) {
     429              : #ifdef DEBUG_MANEUVER_RESERVATIONS
     430              :     if (DEBUG_COND2(v)) {
     431              :         std::cout << SIMTIME << " setManeuverReservation. lane=" << getID() << " veh=" << v->getID() << "\n";
     432              :     }
     433              : #endif
     434       229016 :     myManeuverReservations.push_back(v);
     435       229016 : }
     436              : 
     437              : 
     438              : void
     439       229016 : MSLane::resetManeuverReservation(MSVehicle* v) {
     440              : #ifdef DEBUG_MANEUVER_RESERVATIONS
     441              :     if (DEBUG_COND2(v)) {
     442              :         std::cout << SIMTIME << " resetManeuverReservation(): lane=" << getID() << " veh=" << v->getID() << "\n";
     443              :     }
     444              : #endif
     445       278661 :     for (VehCont::iterator i = myManeuverReservations.begin(); i != myManeuverReservations.end(); ++i) {
     446       278661 :         if (v == *i) {
     447       229016 :             myManeuverReservations.erase(i);
     448              :             return;
     449              :         }
     450              :     }
     451              :     assert(false);
     452              : }
     453              : 
     454              : 
     455              : // ------ Vehicle emission ------
     456              : void
     457      3569988 : MSLane::incorporateVehicle(MSVehicle* veh, double pos, double speed, double posLat, const MSLane::VehCont::iterator& at, MSMoveReminder::Notification notification) {
     458      3569988 :     myNeedsCollisionCheck = true;
     459              :     assert(pos <= myLength || notification == MSMoveReminder::NOTIFICATION_LOAD_STATE);
     460              :     bool wasInactive = myVehicles.size() == 0;
     461      3569988 :     veh->enterLaneAtInsertion(this, pos, speed, posLat, notification);
     462      3569988 :     if (at == myVehicles.end()) {
     463              :         // vehicle will be the first on the lane
     464       677352 :         myVehicles.push_back(veh);
     465              :     } else {
     466      2892636 :         myVehicles.insert(at, veh);
     467              :     }
     468      3569988 :     myBruttoVehicleLengthSum += veh->getVehicleType().getLengthWithGap();
     469      3569988 :     myNettoVehicleLengthSum += veh->getVehicleType().getLength();
     470      3569988 :     myEdge->markDelayed();
     471      3569988 :     if (wasInactive) {
     472       659693 :         MSNet::getInstance()->getEdgeControl().gotActive(this);
     473              :     }
     474      3569988 :     if (getBidiLane() != nullptr && (!isRailway(veh->getVClass()) || (getPermissions() & ~SVC_RAIL_CLASSES) != 0)) {
     475              :         // railways don't need to "see" each other when moving in opposite directions on the same track (efficiency)
     476         1467 :         getBidiLane()->setPartialOccupation(veh);
     477              :     }
     478      3569988 : }
     479              : 
     480              : 
     481              : bool
     482       761446 : MSLane::lastInsertion(MSVehicle& veh, double mspeed, double posLat, bool patchSpeed) {
     483       761446 :     double pos = getLength() - POSITION_EPS;
     484       761446 :     MSVehicle* leader = getLastAnyVehicle();
     485              :     // back position of leader relative to this lane
     486              :     double leaderBack;
     487       761446 :     if (leader == nullptr) {
     488              :         /// look for a leaders on consecutive lanes
     489         3864 :         veh.setTentativeLaneAndPosition(this, pos, posLat);
     490         3864 :         veh.updateBestLanes(false, this);
     491         3864 :         std::pair<MSVehicle* const, double> leaderInfo = getLeader(&veh, pos, veh.getBestLanesContinuation(), veh.getCarFollowModel().brakeGap(mspeed));
     492         3864 :         leader = leaderInfo.first;
     493         3864 :         leaderBack = pos + leaderInfo.second + veh.getVehicleType().getMinGap();
     494              :     } else {
     495       757582 :         leaderBack = leader->getBackPositionOnLane(this);
     496              :         //std::cout << " leaderPos=" << leader->getPositionOnLane(this) << " leaderBack=" << leader->getBackPositionOnLane(this) << " leaderLane=" << leader->getLane()->getID() << "\n";
     497              :     }
     498         3864 :     if (leader == nullptr) {
     499              :         // insert at the end of this lane
     500         2652 :         return isInsertionSuccess(&veh, mspeed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED);
     501              :     } else {
     502              :         // try to insert behind the leader
     503       758794 :         const double frontGapNeeded = veh.getCarFollowModel().getSecureGap(&veh, leader, mspeed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap() + POSITION_EPS;
     504       758794 :         if (leaderBack >= frontGapNeeded) {
     505       427095 :             pos = MIN2(pos, leaderBack - frontGapNeeded);
     506       427095 :             bool result = isInsertionSuccess(&veh, mspeed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED);
     507              :             //if (!result) std::cout << " insertLast failed for " << veh.getID() << " pos=" << pos << " leaderBack=" << leaderBack << " frontGapNeeded=" << frontGapNeeded << "\n";
     508       427095 :             return result;
     509              :         }
     510              :         //std::cout << " insertLast failed for " << veh.getID() << " pos=" << pos << " leaderBack=" << leaderBack << " frontGapNeeded=" << frontGapNeeded << "\n";
     511              :     }
     512              :     return false;
     513              : }
     514              : 
     515              : 
     516              : bool
     517       585049 : MSLane::freeInsertion(MSVehicle& veh, double mspeed, double posLat,
     518              :                       MSMoveReminder::Notification notification) {
     519              :     // try to insert teleporting vehicles fully on this lane
     520       585049 :     double maxPos = myLength;
     521       585049 :     if (veh.hasStops() && veh.getNextStop().edge == veh.getCurrentRouteEdge()) {
     522         7173 :         maxPos = MAX2(0.0, veh.getNextStop().getEndPos(veh));
     523              :     }
     524       585049 :     const double minPos = (notification == MSMoveReminder::NOTIFICATION_TELEPORT ?
     525       288231 :                            MIN2(maxPos, veh.getVehicleType().getLength()) : 0);
     526       585049 :     veh.setTentativeLaneAndPosition(this, minPos, 0);
     527       585049 :     if (myVehicles.size() == 0) {
     528              :         // ensure sufficient gap to followers on predecessor lanes
     529        12711 :         const double backOffset = minPos - veh.getVehicleType().getLength();
     530        12711 :         const double missingRearGap = getMissingRearGap(&veh, backOffset, mspeed);
     531        12711 :         if (missingRearGap > 0) {
     532          986 :             if (minPos + missingRearGap <= maxPos) {
     533              :                 // @note. The rear gap is tailored to mspeed. If it changes due
     534              :                 // to a leader vehicle (on subsequent lanes) insertion will
     535              :                 // still fail. Under the right combination of acceleration and
     536              :                 // deceleration values there might be another insertion
     537              :                 // positions that would be successful be we do not look for it.
     538              :                 //std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " unclear @(340)\n";
     539          571 :                 return isInsertionSuccess(&veh, mspeed, minPos + missingRearGap, posLat, true, notification);
     540              :             }
     541              :             return false;
     542              :         } else {
     543        11725 :             return isInsertionSuccess(&veh, mspeed, minPos, posLat, true, notification);
     544              :         }
     545              : 
     546              :     } else {
     547              :         // check whether the vehicle can be put behind the last one if there is such
     548       572338 :         const MSVehicle* const leader = myVehicles.back(); // @todo reproduction of bogus old behavior. see #1961
     549       572338 :         const double leaderPos = leader->getBackPositionOnLane(this);
     550       572338 :         const double speed = leader->getSpeed();
     551       572338 :         const double frontGapNeeded = veh.getCarFollowModel().getSecureGap(&veh, leader, speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap();
     552       572338 :         if (leaderPos >= frontGapNeeded) {
     553       558643 :             const double tspeed = MIN2(veh.getCarFollowModel().insertionFollowSpeed(&veh, mspeed, frontGapNeeded, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), leader), mspeed);
     554              :             // check whether we can insert our vehicle behind the last vehicle on the lane
     555       558643 :             if (isInsertionSuccess(&veh, tspeed, minPos, posLat, true, notification)) {
     556              :                 //std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " pos=" << minPos<< " speed=" << speed  << " tspeed=" << tspeed << " frontGapNeeded=" << frontGapNeeded << " lead=" << leader->getID() << " lPos=" << leaderPos << "\n   vehsOnLane=" << toString(myVehicles) << " @(358)\n";
     557              :                 return true;
     558              :             }
     559              :         }
     560              :     }
     561              :     // go through the lane, look for free positions (starting after the last vehicle)
     562              :     MSLane::VehCont::iterator predIt = myVehicles.begin();
     563     12716585 :     while (predIt != myVehicles.end()) {
     564              :         // get leader (may be zero) and follower
     565              :         // @todo compute secure position in regard to sublane-model
     566     12276316 :         const MSVehicle* leader = predIt != myVehicles.end() - 1 ? *(predIt + 1) : nullptr;
     567     12276316 :         if (leader == nullptr && myPartialVehicles.size() > 0) {
     568        75363 :             leader = myPartialVehicles.front();
     569              :         }
     570     12276316 :         const MSVehicle* follower = *predIt;
     571              : 
     572              :         // patch speed if allowed
     573              :         double speed = mspeed;
     574     12276316 :         if (leader != nullptr) {
     575     11908245 :             speed = MIN2(leader->getSpeed(), mspeed);
     576              :         }
     577              : 
     578              :         // compute the space needed to not collide with leader
     579              :         double frontMax = maxPos;
     580              :         if (leader != nullptr) {
     581     11908245 :             double leaderRearPos = leader->getBackPositionOnLane(this);
     582     11908245 :             double frontGapNeeded = veh.getCarFollowModel().getSecureGap(&veh, leader, speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap();
     583     11908245 :             frontMax = MIN2(maxPos, leaderRearPos - frontGapNeeded);
     584              :         }
     585              :         // compute the space needed to not let the follower collide
     586     12276316 :         const double followPos = follower->getPositionOnLane() + follower->getVehicleType().getMinGap();
     587     12276316 :         const double backGapNeeded = follower->getCarFollowModel().getSecureGap(follower, &veh, follower->getSpeed(), veh.getSpeed(), veh.getCarFollowModel().getMaxDecel());
     588     12276316 :         const double backMin = followPos + backGapNeeded + veh.getVehicleType().getLength();
     589              : 
     590              :         // check whether there is enough room (given some extra space for rounding errors)
     591     12276316 :         if (frontMax > minPos && backMin + POSITION_EPS < frontMax) {
     592              :             // try to insert vehicle (should be always ok)
     593        21594 :             if (isInsertionSuccess(&veh, speed, backMin + POSITION_EPS, posLat, true, notification)) {
     594              :                 //std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " @(393)\n";
     595              :                 return true;
     596              :             }
     597              :         }
     598              :         ++predIt;
     599              :     }
     600              :     // first check at lane's begin
     601              :     //std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " fail final\n";
     602              :     return false;
     603              : }
     604              : 
     605              : 
     606              : double
     607     13557544 : MSLane::getDepartSpeed(const MSVehicle& veh, bool& patchSpeed) {
     608              :     double speed = 0;
     609     13557544 :     const SUMOVehicleParameter& pars = veh.getParameter();
     610     13557544 :     DepartSpeedDefinition dsd = pars.departSpeedProcedure;
     611     13557544 :     if (dsd == DepartSpeedDefinition::DEFAULT) {
     612      7103086 :         dsd = myDefaultDepartSpeedDefinition;
     613      7103086 :         if (dsd == DepartSpeedDefinition::GIVEN) {
     614      3904037 :             speed = myDefaultDepartSpeed;
     615              :         }
     616      6454458 :     } else if (dsd == DepartSpeedDefinition::GIVEN) {
     617      1376569 :         speed = pars.departSpeed;;
     618              :     }
     619     13557544 :     switch (dsd) {
     620      5280606 :         case DepartSpeedDefinition::GIVEN:
     621      5280606 :             patchSpeed = false;
     622      5280606 :             break;
     623        51959 :         case DepartSpeedDefinition::RANDOM:
     624       103918 :             speed = roundDecimal(RandHelper::rand(getVehicleMaxSpeed(&veh)), gPrecisionRandom);
     625        51959 :             patchSpeed = true;
     626        51959 :             break;
     627      2909560 :         case DepartSpeedDefinition::MAX:
     628      2909560 :             speed = getVehicleMaxSpeed(&veh);
     629      2909560 :             patchSpeed = true;
     630      2909560 :             break;
     631       374765 :         case DepartSpeedDefinition::DESIRED:
     632       374765 :             speed = getVehicleMaxSpeed(&veh);
     633       374765 :             patchSpeed = false;
     634       374765 :             break;
     635       137503 :         case DepartSpeedDefinition::LIMIT:
     636       137503 :             speed = getVehicleMaxSpeed(&veh) / veh.getChosenSpeedFactor();
     637       137503 :             patchSpeed = false;
     638       137503 :             break;
     639         8177 :         case DepartSpeedDefinition::LAST: {
     640         8177 :             MSVehicle* last = getLastAnyVehicle();
     641         8177 :             speed = getVehicleMaxSpeed(&veh);
     642         8177 :             if (last != nullptr) {
     643         7845 :                 speed = MIN2(speed, last->getSpeed());
     644         7845 :                 patchSpeed = false;
     645              :             }
     646              :             break;
     647              :         }
     648      4794974 :         case DepartSpeedDefinition::AVG: {
     649      4794974 :             speed = MIN2(getVehicleMaxSpeed(&veh), getMeanSpeed());
     650      4794974 :             if (getLastAnyVehicle() != nullptr) {
     651      4496255 :                 patchSpeed = false;
     652              :             }
     653              :             break;
     654              :         }
     655            0 :         case DepartSpeedDefinition::DEFAULT:
     656              :         default:
     657              :             // speed = 0 was set before
     658            0 :             patchSpeed = false; // @todo check
     659            0 :             break;
     660              :     }
     661     13557544 :     return speed;
     662              : }
     663              : 
     664              : 
     665              : double
     666     14042270 : MSLane::getDepartPosLat(const MSVehicle& veh) {
     667     14042270 :     const SUMOVehicleParameter& pars = veh.getParameter();
     668     14042270 :     switch (pars.departPosLatProcedure) {
     669       107661 :         case DepartPosLatDefinition::GIVEN:
     670       107661 :             return pars.departPosLat;
     671              :         case DepartPosLatDefinition::RIGHT:
     672        36054 :             return -getWidth() * 0.5 + veh.getVehicleType().getWidth() * 0.5;
     673              :         case DepartPosLatDefinition::LEFT:
     674        35843 :             return getWidth() * 0.5 - veh.getVehicleType().getWidth() * 0.5;
     675              :         case DepartPosLatDefinition::RANDOM: {
     676       233274 :             const double raw = RandHelper::rand(getWidth() - veh.getVehicleType().getWidth()) - getWidth() * 0.5 + veh.getVehicleType().getWidth() * 0.5;
     677       233274 :             return roundDecimal(raw, gPrecisionRandom);
     678              :         }
     679              :         case DepartPosLatDefinition::CENTER:
     680              :         case DepartPosLatDefinition::DEFAULT:
     681              :         // @note:
     682              :         // case DepartPosLatDefinition::FREE
     683              :         // case DepartPosLatDefinition::RANDOM_FREE
     684              :         // are not handled here because they involve multiple insertion attempts
     685              :         default:
     686              :             return 0;
     687              :     }
     688              : }
     689              : 
     690              : 
     691              : bool
     692     13557483 : MSLane::insertVehicle(MSVehicle& veh) {
     693              :     double pos = 0;
     694     13557483 :     bool patchSpeed = true; // whether the speed shall be adapted to infrastructure/traffic in front
     695     13557483 :     const SUMOVehicleParameter& pars = veh.getParameter();
     696     13557483 :     double speed = getDepartSpeed(veh, patchSpeed);
     697     13557483 :     double posLat = getDepartPosLat(veh);
     698              : 
     699              :     // determine the position
     700     13557483 :     switch (pars.departPosProcedure) {
     701       977137 :         case DepartPosDefinition::GIVEN:
     702       977137 :             pos = pars.departPos;
     703       977137 :             if (pos < 0.) {
     704       147272 :                 pos += myLength;
     705              :             }
     706              :             break;
     707       239194 :         case DepartPosDefinition::RANDOM:
     708       239194 :             pos = roundDecimal(RandHelper::rand(getLength()), gPrecisionRandom);
     709              :             break;
     710              :         case DepartPosDefinition::RANDOM_FREE: {
     711       532296 :             for (int i = 0; i < 10; i++) {
     712              :                 // we will try some random positions ...
     713              :                 pos = RandHelper::rand(getLength());
     714       484787 :                 posLat = getDepartPosLat(veh); // could be random as well
     715       484787 :                 if (isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED)) {
     716         2151 :                     MSNet::getInstance()->getInsertionControl().retractDescheduleDeparture(&veh);
     717         2151 :                     return true;
     718              :                 }
     719              :             }
     720              :             // ... and if that doesn't work, we put the vehicle to the free position
     721        47509 :             bool success = freeInsertion(veh, speed, posLat);
     722        47509 :             if (success) {
     723        12922 :                 MSNet::getInstance()->getInsertionControl().retractDescheduleDeparture(&veh);
     724              :             }
     725              :             return success;
     726              :         }
     727       249309 :         case DepartPosDefinition::FREE:
     728       249309 :             return freeInsertion(veh, speed, posLat);
     729       761446 :         case DepartPosDefinition::LAST:
     730       761446 :             return lastInsertion(veh, speed, posLat, patchSpeed);
     731         3842 :         case DepartPosDefinition::STOP:
     732         3842 :             if (veh.hasStops() && veh.getNextStop().edge == veh.getCurrentRouteEdge()) {
     733              :                 // getLastFreePos of stopping place could return negative position to avoid blocking the stop
     734         3836 :                 pos = MAX2(0.0, veh.getNextStop().getEndPos(veh));
     735              :                 break;
     736              :             }
     737              :             FALLTHROUGH;
     738              :         case DepartPosDefinition::BASE:
     739              :         case DepartPosDefinition::DEFAULT:
     740              :         case DepartPosDefinition::SPLIT_FRONT:
     741              :         default:
     742     11276901 :             if (pars.departProcedure == DepartDefinition::SPLIT) {
     743              :                 pos = getLength();
     744              :                 // find the vehicle from which we are splitting off (should only be a single lane to check)
     745              :                 AnyVehicleIterator end = anyVehiclesEnd();
     746            3 :                 for (AnyVehicleIterator it = anyVehiclesBegin(); it != end; ++it) {
     747           24 :                     const MSVehicle* cand = *it;
     748           24 :                     if (cand->isStopped() && cand->getNextStopParameter()->split == veh.getID()) {
     749           21 :                         if (pars.departPosProcedure == DepartPosDefinition::SPLIT_FRONT) {
     750            3 :                             pos = cand->getPositionOnLane() + cand->getVehicleType().getMinGap() + veh.getLength();
     751              :                         } else {
     752           18 :                             pos = cand->getBackPositionOnLane() - veh.getVehicleType().getMinGap();
     753              :                         }
     754              :                         break;
     755              :                     }
     756              :                 }
     757              :             } else {
     758     11276880 :                 pos = veh.basePos(myEdge);
     759              :             }
     760              :             break;
     761              :     }
     762              :     // determine the lateral position for special cases
     763     12497068 :     if (MSGlobals::gLateralResolution > 0) {
     764      1544326 :         switch (pars.departPosLatProcedure) {
     765              :             case DepartPosLatDefinition::RANDOM_FREE: {
     766            0 :                 for (int i = 0; i < 10; i++) {
     767              :                     // we will try some random positions ...
     768            0 :                     posLat = RandHelper::rand(getWidth()) - getWidth() * 0.5;
     769            0 :                     if (isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED)) {
     770              :                         return true;
     771              :                     }
     772              :                 }
     773              :                 FALLTHROUGH;
     774              :             }
     775              :             // no break! continue with DepartPosLatDefinition::FREE
     776              :             case DepartPosLatDefinition::FREE: {
     777              :                 // systematically test all positions until a free lateral position is found
     778         5778 :                 double posLatMin = -getWidth() * 0.5 + veh.getVehicleType().getWidth() * 0.5;
     779         5778 :                 double posLatMax = getWidth() * 0.5 - veh.getVehicleType().getWidth() * 0.5;
     780        18771 :                 for (posLat = posLatMin; posLat < posLatMax; posLat += MSGlobals::gLateralResolution) {
     781        16943 :                     if (isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED)) {
     782              :                         return true;
     783              :                     }
     784              :                 }
     785              :                 return false;
     786              :             }
     787              :             default:
     788              :                 break;
     789              :         }
     790              :     }
     791              :     // try to insert
     792     12491290 :     const bool success = isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED);
     793              : #ifdef DEBUG_EXTRAPOLATE_DEPARTPOS
     794              :     if (DEBUG_COND2(&veh)) {
     795              :         std::cout << SIMTIME << " veh=" << veh.getID() << " success=" << success << " extrapolate=" << myExtrapolateSubstepDepart << " delay=" << veh.getDepartDelay() << " speed=" << speed << "\n";
     796              :     }
     797              : #endif
     798     12491289 :     if (success && myExtrapolateSubstepDepart && veh.getDepartDelay() > 0) {
     799       228054 :         SUMOTime relevantDelay = MIN2(DELTA_T, veh.getDepartDelay());
     800              :         // try to compensate sub-step depart delay by moving the vehicle forward
     801       228054 :         speed = veh.getSpeed(); // may have been adapted in isInsertionSuccess
     802       228054 :         double dist = speed * STEPS2TIME(relevantDelay);
     803       228054 :         std::pair<MSVehicle* const, double> leaderInfo = getLeader(&veh, pos, veh.getBestLanesContinuation());
     804       228054 :         if (leaderInfo.first != nullptr) {
     805              :             MSVehicle* leader = leaderInfo.first;
     806       227804 :             const double frontGapNeeded = veh.getCarFollowModel().getSecureGap(&veh, leader, speed, leader->getSpeed(),
     807              :                                           leader->getCarFollowModel().getMaxDecel());
     808       227804 :             dist = MIN2(dist, leaderInfo.second - frontGapNeeded);
     809              :         }
     810       228054 :         if (dist > 0) {
     811       222464 :             veh.executeFractionalMove(dist);
     812              :         }
     813              :     }
     814              :     return success;
     815              : }
     816              : 
     817              : 
     818              : bool
     819      7745081 : MSLane::checkFailure(const MSVehicle* aVehicle, double& speed, double& dist, const double nspeed, const bool patchSpeed, const std::string errorMsg, InsertionCheck check) const {
     820      7745081 :     if (nspeed < speed) {
     821      3329192 :         if (patchSpeed) {
     822       691430 :             speed = MIN2(nspeed, speed);
     823       691430 :             dist = aVehicle->getCarFollowModel().brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
     824      2637762 :         } else if (speed > 0) {
     825      2637762 :             if ((aVehicle->getInsertionChecks() & (int)check) == 0) {
     826              :                 return false;
     827              :             }
     828      2637718 :             if (MSGlobals::gEmergencyInsert) {
     829              :                 // Check whether vehicle can stop at the given distance when applying emergency braking
     830           47 :                 double emergencyBrakeGap = 0.5 * speed * speed / aVehicle->getCarFollowModel().getEmergencyDecel();
     831           47 :                 if (emergencyBrakeGap <= dist) {
     832              :                     // Vehicle may stop in time with emergency deceleration
     833              :                     // still, emit a warning
     834          141 :                     WRITE_WARNINGF(TL("Vehicle '%' is inserted in an emergency situation, time=%."), aVehicle->getID(), time2string(SIMSTEP));
     835           47 :                     return false;
     836              :                 }
     837              :             }
     838              : 
     839      2637671 :             if (errorMsg != "") {
     840          156 :                 WRITE_ERRORF(TL("Vehicle '%' will not be able to depart on lane '%' with speed % (%), time=%."),
     841              :                              aVehicle->getID(), getID(), speed, errorMsg, time2string(SIMSTEP));
     842           39 :                 MSNet::getInstance()->getInsertionControl().descheduleDeparture(aVehicle);
     843              :             }
     844      2637671 :             return true;
     845              :         }
     846              :     }
     847              :     return false;
     848              : }
     849              : 
     850              : 
     851              : bool
     852     14097331 : MSLane::isInsertionSuccess(MSVehicle* aVehicle,
     853              :                            double speed, double pos, double posLat, bool patchSpeed,
     854              :                            MSMoveReminder::Notification notification) {
     855     14097331 :     int insertionChecks = aVehicle->getInsertionChecks();
     856     14097331 :     if (pos < 0 || pos > myLength) {
     857              :         // we may not start there
     858        11082 :         WRITE_WARNINGF(TL("Invalid departPos % given for vehicle '%', time=%. Inserting at lane end instead."),
     859              :                        pos, aVehicle->getID(), time2string(SIMSTEP));
     860         3694 :         pos = myLength;
     861              :     }
     862              : 
     863              : #ifdef DEBUG_INSERTION
     864              :     if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
     865              :         std::cout << "\nIS_INSERTION_SUCCESS\n"
     866              :                   << SIMTIME  << " lane=" << getID()
     867              :                   << " veh '" << aVehicle->getID()
     868              :                   << " bestLanes=" << toString(aVehicle->getBestLanesContinuation(this))
     869              :                   << " pos=" << pos
     870              :                   << " speed=" << speed
     871              :                   << " patchSpeed=" << patchSpeed
     872              :                   << "'\n";
     873              :     }
     874              : #endif
     875              : 
     876     14097331 :     aVehicle->setTentativeLaneAndPosition(this, pos, posLat);
     877     14097331 :     aVehicle->updateBestLanes(false, this);
     878              :     const MSCFModel& cfModel = aVehicle->getCarFollowModel();
     879     14097331 :     const std::vector<MSLane*>& bestLaneConts = aVehicle->getBestLanesContinuation(this);
     880              :     std::vector<MSLane*>::const_iterator ri = bestLaneConts.begin();
     881     14097331 :     double seen = getLength() - pos; // == distance from insertion position until the end of the currentLane
     882     14097331 :     double dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
     883     14097331 :     const bool isRail = aVehicle->isRail();
     884     14097331 :     if (isRail && insertionChecks != (int)InsertionCheck::NONE
     885        65067 :             && aVehicle->getParameter().departProcedure != DepartDefinition::SPLIT
     886        65043 :             && MSRailSignalControl::isSignalized(aVehicle->getVClass())
     887     14158867 :             && isRailwayOrShared(myPermissions)) {
     888        61405 :         const MSDriveWay* dw = MSDriveWay::getDepartureDriveway(aVehicle);
     889              :         MSEdgeVector occupied;
     890              : #ifdef DEBUG_INSERTION
     891              :         gDebugFlag4 = DEBUG_COND2(aVehicle) || DEBUG_COND;
     892              : #endif
     893        61405 :         if (dw->foeDriveWayOccupied(false, aVehicle, occupied)) {
     894        52617 :             setParameter("insertionBlocked:" + aVehicle->getID(), dw->getID());
     895              : #ifdef DEBUG_INSERTION
     896              :             if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
     897              :                 std::cout << "   foe of driveway " + dw->getID() + " has occupied edges " + toString(occupied) << "\n";
     898              :             }
     899              :             gDebugFlag4 = false;
     900              : #endif
     901              :             return false;
     902              :         }
     903              : #ifdef DEBUG_INSERTION
     904              :         gDebugFlag4 = false;
     905              : #endif
     906        61405 :     }
     907     14044714 :     if (getBidiLane() != nullptr && isRail) {
     908              :         // do not insert if the bidirectional edge is occupied
     909         1460 :         if (getBidiLane()->getVehicleNumberWithPartials() > 0 && (insertionChecks & (int)InsertionCheck::BIDI) != 0) {
     910              : #ifdef DEBUG_INSERTION
     911              :             if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
     912              :                 std::cout << "   bidi-lane occupied\n";
     913              :             }
     914              : #endif
     915              :             return false;
     916              :         }
     917              :         // do not insert the back of the train would be put onto an occupied bidi-lane
     918         1454 :         double backLength = aVehicle->getLength() - pos;
     919         1454 :         if (backLength > 0 && (insertionChecks & (int)InsertionCheck::BIDI) != 0) {
     920          236 :             MSLane* pred = getLogicalPredecessorLane();
     921          236 :             MSLane* bidi = pred == nullptr ? nullptr : pred->getBidiLane();
     922          382 :             while (backLength > 0 && bidi != nullptr) {
     923          194 :                 if (bidi->getVehicleNumberWithPartials() > 0) {
     924              : #ifdef DEBUG_INSERTION
     925              :                     if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
     926              :                         std::cout << "   bidi-lane furtherLanes occupied\n";
     927              :                     }
     928              : #endif
     929              :                     return false;
     930              :                 }
     931          146 :                 backLength -= bidi->getLength();
     932          146 :                 pred = pred->getLogicalPredecessorLane();
     933          146 :                 bidi = pred == nullptr ? nullptr : pred->getBidiLane();
     934              :             }
     935              :         }
     936              :     }
     937              :     MSLink* firstRailSignal = nullptr;
     938              :     double firstRailSignalDist = -1;
     939              :     // whether speed may be patched for unavoidable reasons (stops, speedLimits, ...)
     940     14044660 :     const bool patchSpeedSpecial = patchSpeed || aVehicle->getParameter().departSpeedProcedure != DepartSpeedDefinition::GIVEN;
     941              : 
     942              :     // before looping through the continuation lanes, check if a stop is scheduled on this lane
     943              :     // (the code is duplicated in the loop)
     944     14044660 :     if (aVehicle->hasStops()) {
     945       445647 :         const MSStop& nextStop = aVehicle->getNextStop();
     946       445647 :         if (nextStop.lane == this) {
     947       110601 :             std::stringstream msg;
     948              :             double distToStop, safeSpeed;
     949       110601 :             if (nextStop.pars.speed > 0) {
     950         1630 :                 msg << "scheduled waypoint on lane '" << myID << "' too close";
     951         1630 :                 distToStop = MAX2(0.0, nextStop.pars.startPos - pos);
     952         1630 :                 safeSpeed = cfModel.freeSpeed(aVehicle, speed, distToStop, nextStop.pars.speed, true, MSCFModel::CalcReason::FUTURE);
     953              :             } else {
     954       108971 :                 msg << "scheduled stop on lane '" << myID << "' too close";
     955       108971 :                 distToStop = nextStop.pars.endPos - pos;
     956       108971 :                 safeSpeed = cfModel.stopSpeed(aVehicle, speed, distToStop, MSCFModel::CalcReason::FUTURE);
     957              :             }
     958       331786 :             if (checkFailure(aVehicle, speed, dist, MAX2(0.0, safeSpeed), patchSpeedSpecial, msg.str(), InsertionCheck::STOP)) {
     959              :                 // we may not drive with the given velocity - we cannot stop at the stop
     960              :                 return false;
     961              :             }
     962       110601 :         }
     963              :     }
     964              :     // check leader vehicle first because it could have influenced the departSpeed (for departSpeed=avg)
     965              :     // get the pointer to the vehicle next in front of the given position
     966     14044652 :     const MSLeaderInfo leaders = getLastVehicleInformation(aVehicle, 0, pos);
     967              :     //if (aVehicle->getID() == "disabled") std::cout << " leaders=" << leaders.toString() << "\n";
     968     14044652 :     const double nspeed = safeInsertionSpeed(aVehicle, -pos, leaders, speed);
     969     21196152 :     if (nspeed == INVALID_SPEED || checkFailure(aVehicle, speed, dist, nspeed, patchSpeed, "", InsertionCheck::LEADER_GAP)) {
     970              :         // we may not drive with the given velocity - we crash into the leader
     971              : #ifdef DEBUG_INSERTION
     972              :         if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
     973              :             std::cout << SIMTIME << " isInsertionSuccess lane=" << getID()
     974              :                       << " veh=" << aVehicle->getID()
     975              :                       << " pos=" << pos
     976              :                       << " posLat=" << posLat
     977              :                       << " patchSpeed=" << patchSpeed
     978              :                       << " speed=" << speed
     979              :                       << " nspeed=" << nspeed
     980              :                       << " leaders=" << leaders.toString()
     981              :                       << " failed (@700)!\n";
     982              :         }
     983              : #endif
     984              :         return false;
     985              :     }
     986              : #ifdef DEBUG_INSERTION
     987              :     if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
     988              :         std::cout << SIMTIME << " speed = " << speed << " nspeed = " << nspeed << " leaders=" << leaders.toString() << "\n";
     989              :     }
     990              : #endif
     991              : 
     992      4564821 :     const MSRoute& r = aVehicle->getRoute();
     993      4564821 :     MSRouteIterator ce = r.begin();
     994              :     int nRouteSuccs = 1;
     995              :     MSLane* currentLane = this;
     996              :     MSLane* nextLane = this;
     997      6068709 :     SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / MAX2(speed, SUMO_const_haltingSpeed));
     998      4974629 :     while ((seen < dist || (isRail && firstRailSignal == nullptr)) && ri != bestLaneConts.end()) {
     999              :         // get the next link used...
    1000       514447 :         std::vector<MSLink*>::const_iterator link = succLinkSec(*aVehicle, nRouteSuccs, *currentLane, bestLaneConts);
    1001              :         // get the next used lane (including internal)
    1002       514447 :         if (currentLane->isLinkEnd(link)) {
    1003        13578 :             if (&currentLane->getEdge() == r.getLastEdge()) {
    1004              :                 // reached the end of the route
    1005        11019 :                 if (aVehicle->getParameter().arrivalSpeedProcedure == ArrivalSpeedDefinition::GIVEN) {
    1006           98 :                     const double remaining = seen + aVehicle->getArrivalPos() - currentLane->getLength();
    1007           98 :                     const double fspeed = cfModel.freeSpeed(aVehicle, speed, remaining, aVehicle->getParameter().arrivalSpeed, true, MSCFModel::CalcReason::FUTURE);
    1008          196 :                     if (checkFailure(aVehicle, speed, dist, fspeed,
    1009              :                                      patchSpeedSpecial, "arrival speed too low", InsertionCheck::ARRIVAL_SPEED)) {
    1010              :                         // we may not drive with the given velocity - we cannot match the specified arrival speed
    1011              :                         return false;
    1012              :                     }
    1013              :                 }
    1014        11019 :                 if (mayContinue(aVehicle) && hasUnsafeLink()) {
    1015              :                     // since the route is likely to continue we must be prepared for braking
    1016         1543 :                     if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, seen),
    1017         3086 :                                 patchSpeedSpecial, "junction '" + currentLane->getEdge().getToJunction()->getID() + "' too close", InsertionCheck::JUNCTION)) {
    1018              :                         // we may not drive with the given velocity - we cannot stop at the junction
    1019              :                         return false;
    1020              :                     }
    1021              :                 }
    1022              :             } else {
    1023              :                 // lane does not continue
    1024         2559 :                 if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, seen),
    1025         5118 :                                  patchSpeedSpecial, "junction '" + currentLane->getEdge().getToJunction()->getID() + "' too close", InsertionCheck::JUNCTION)) {
    1026              :                     // we may not drive with the given velocity - we cannot stop at the junction
    1027              :                     return false;
    1028              :                 }
    1029              :             }
    1030              :             break;
    1031              :         }
    1032       500869 :         if (isRail && firstRailSignal == nullptr) {
    1033              :             std::string constraintInfo;
    1034              :             bool isInsertionOrder;
    1035        18114 :             if (MSRailSignal::hasInsertionConstraint(*link, aVehicle, constraintInfo, isInsertionOrder)) {
    1036         6216 :                 setParameter((isInsertionOrder ? "insertionOrder" : "insertionConstraint:")
    1037         9261 :                              + aVehicle->getID(), constraintInfo);
    1038              : #ifdef DEBUG_INSERTION
    1039              :                 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
    1040              :                     std::cout << " insertion constraint at link " << (*link)->getDescription() << " not cleared \n";
    1041              :                 }
    1042              : #endif
    1043              :                 return false;
    1044              :             }
    1045              :         }
    1046              : 
    1047              :         // might also by a regular traffic_light instead of a rail_signal
    1048       497761 :         if (firstRailSignal == nullptr && (*link)->getTLLogic() != nullptr) {
    1049              :             firstRailSignal = *link;
    1050              :             firstRailSignalDist = seen;
    1051              :         }
    1052       497761 :         nextLane = (*link)->getViaLaneOrLane();
    1053       497761 :         if (!(*link)->opened(arrivalTime, speed, speed, aVehicle->getVehicleType().getLength(), aVehicle->getImpatience(),
    1054              :                              cfModel.getMaxDecel(), 0, posLat, nullptr, false, aVehicle)
    1055       472205 :                 || (*link)->railSignalWasPassed()
    1056       472202 :                 || !(*link)->havePriority()
    1057       946989 :                 || (*link)->getState() == LINKSTATE_ZIPPER) {
    1058              :             // have to stop at junction
    1059        50983 :             std::string errorMsg = "";
    1060        50983 :             const LinkState state = (*link)->getState();
    1061        50983 :             if (state == LINKSTATE_MINOR
    1062        50983 :                     || state == LINKSTATE_EQUAL
    1063              :                     || state == LINKSTATE_STOP
    1064              :                     || state == LINKSTATE_ALLWAY_STOP) {
    1065              :                 // no sense in trying later
    1066              :                 errorMsg = "unpriorised junction too close";
    1067        27280 :             } else if ((*link)->getTLLogic() != nullptr && !(*link)->getTLLogic()->getsMajorGreen((*link)->getTLIndex())) {
    1068              :                 // traffic light never turns 'G'?
    1069        19460 :                 errorMsg = "tlLogic '" + (*link)->getTLLogic()->getID() + "' link " + toString((*link)->getTLIndex()) + " never switches to 'G'";
    1070              :             }
    1071        50983 :             const double laneStopOffset = MAX2(getVehicleStopOffset(aVehicle),
    1072        50983 :                                                aVehicle->getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_STOPLINE_CROSSING_GAP, MSPModel::SAFETY_GAP) - (*link)->getDistToFoePedCrossing());
    1073        50983 :             const double remaining = seen - laneStopOffset;
    1074       101966 :             if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, remaining),
    1075              :                              patchSpeedSpecial, errorMsg, InsertionCheck::JUNCTION)) {
    1076              :                 // we may not drive with the given velocity - we cannot stop at the junction in time
    1077              : #ifdef DEBUG_INSERTION
    1078              :                 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
    1079              :                     std::cout << SIMTIME << " isInsertionSuccess lane=" << getID()
    1080              :                               << " veh=" << aVehicle->getID()
    1081              :                               << " patchSpeed=" << patchSpeed
    1082              :                               << " speed=" << speed
    1083              :                               << " remaining=" << remaining
    1084              :                               << " leader=" << currentLane->getLastVehicleInformation(aVehicle, 0, 0).toString()
    1085              :                               << " last=" << Named::getIDSecure(getLastAnyVehicle())
    1086              :                               << " meanSpeed=" << getMeanSpeed()
    1087              :                               << " failed (@926)!\n";
    1088              :                 }
    1089              : #endif
    1090              :                 return false;
    1091              :             }
    1092              : #ifdef DEBUG_INSERTION
    1093              :             if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
    1094              :                 std::cout << "trying insertion before minor link: "
    1095              :                           << "insertion speed = " << speed << " dist=" << dist
    1096              :                           << "\n";
    1097              :             }
    1098              : #endif
    1099        37974 :             if (seen >= aVehicle->getVehicleType().getMinGap()) {
    1100              :                 break;
    1101              :             }
    1102       446778 :         } else if (nextLane->isInternal()) {
    1103       245426 :             double tmp = 0;
    1104       245426 :             bool dummyReq = true;
    1105              : #ifdef DEBUG_INSERTION
    1106              :             if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
    1107              :                 std::cout << "checking linkLeader for lane '" << nextLane->getID() << "'\n";
    1108              :                 gDebugFlag1 = true;
    1109              :             }
    1110              : #endif
    1111       245426 :             double nSpeed = speed;
    1112       245426 :             aVehicle->checkLinkLeader(nextLane->getLinkCont()[0], nextLane, seen + nextLane->getLength(), nullptr, nSpeed, tmp, tmp, dummyReq);
    1113              : #ifdef DEBUG_INSERTION
    1114              :             gDebugFlag1 = false;
    1115              : #endif
    1116       490852 :             if (checkFailure(aVehicle, speed, dist, nSpeed, patchSpeed, "", InsertionCheck::LEADER_GAP)) {
    1117              :                 // we may not drive with the given velocity - there is a junction leader
    1118              : #ifdef DEBUG_INSERTION
    1119              :                 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
    1120              :                     std::cout << " linkLeader nSpeed=" << nSpeed << " failed (@1058)!\n";
    1121              :                 }
    1122              : #endif
    1123         2907 :                 return false;
    1124              :             }
    1125              :         }
    1126              :         // check how next lane affects the journey
    1127       453797 :         if (nextLane != nullptr) {
    1128              : 
    1129              :             // do not insert if the bidirectional edge is occupied before a railSignal has been encountered
    1130       453797 :             if (firstRailSignal == nullptr && nextLane->getBidiLane() != nullptr && nextLane->getBidiLane()->getVehicleNumberWithPartials() > 0) {
    1131            0 :                 if ((insertionChecks & (int)InsertionCheck::ONCOMING_TRAIN) != 0) {
    1132              : #ifdef DEBUG_INSERTION
    1133              :                     if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
    1134              :                         std::cout << " nextLane=" << nextLane->getID() << " occupiedBidi\n";
    1135              :                     }
    1136              : #endif
    1137        43988 :                     return false;
    1138              :                 }
    1139              :             }
    1140              : 
    1141              :             // check if there are stops on the next lane that should be regarded
    1142              :             // (this block is duplicated before the loop to deal with the insertion lane)
    1143       453797 :             if (aVehicle->hasStops()) {
    1144        17347 :                 const MSStop& nextStop = aVehicle->getNextStop();
    1145        17347 :                 if (nextStop.lane == nextLane) {
    1146          538 :                     std::stringstream msg;
    1147          538 :                     msg << "scheduled stop on lane '" << nextStop.lane->getID() << "' too close";
    1148          538 :                     const double distToStop = seen + nextStop.pars.endPos;
    1149          538 :                     if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, distToStop),
    1150          538 :                                      patchSpeedSpecial, msg.str(), InsertionCheck::STOP)) {
    1151              :                         // we may not drive with the given velocity - we cannot stop at the stop
    1152              :                         return false;
    1153              :                     }
    1154          538 :                 }
    1155              :             }
    1156              : 
    1157              :             // check leader on next lane
    1158       453797 :             const MSLeaderInfo nextLeaders = nextLane->getLastVehicleInformation(aVehicle, 0, 0);
    1159       453797 :             if (nextLeaders.hasVehicles()) {
    1160       158711 :                 const double nextLaneSpeed = nextLane->safeInsertionSpeed(aVehicle, seen, nextLeaders, speed);
    1161              : #ifdef DEBUG_INSERTION
    1162              :                 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
    1163              :                     std::cout << SIMTIME << " leader on lane '" << nextLane->getID() << "': " << nextLeaders.toString() << " nspeed=" << nextLaneSpeed << "\n";
    1164              :                 }
    1165              : #endif
    1166       308700 :                 if (nextLaneSpeed == INVALID_SPEED || checkFailure(aVehicle, speed, dist, nextLaneSpeed, patchSpeed, "", InsertionCheck::LEADER_GAP)) {
    1167              :                     // we may not drive with the given velocity - we crash into the leader
    1168              : #ifdef DEBUG_INSERTION
    1169              :                     if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
    1170              :                         std::cout << " isInsertionSuccess lane=" << getID()
    1171              :                                   << " veh=" << aVehicle->getID()
    1172              :                                   << " pos=" << pos
    1173              :                                   << " posLat=" << posLat
    1174              :                                   << " patchSpeed=" << patchSpeed
    1175              :                                   << " speed=" << speed
    1176              :                                   << " nspeed=" << nextLaneSpeed
    1177              :                                   << " nextLane=" << nextLane->getID()
    1178              :                                   << " lead=" << nextLeaders.toString()
    1179              :                                   << " failed (@641)!\n";
    1180              :                     }
    1181              : #endif
    1182              :                     return false;
    1183              :                 }
    1184              :             }
    1185       412313 :             if (!nextLane->checkForPedestrians(aVehicle, speed, dist, -seen, patchSpeed)) {
    1186              :                 return false;
    1187              :             }
    1188              :             // check next lane's maximum velocity
    1189       412288 :             const double freeSpeed = cfModel.freeSpeed(aVehicle, speed, seen, nextLane->getVehicleMaxSpeed(aVehicle), true, MSCFModel::CalcReason::FUTURE);
    1190       412287 :             if (freeSpeed < speed) {
    1191        59015 :                 if (patchSpeedSpecial) {
    1192        58605 :                     speed = freeSpeed;
    1193        58605 :                     dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
    1194              :                 } else {
    1195          410 :                     if ((insertionChecks & (int)InsertionCheck::SPEED_LIMIT) != 0) {
    1196          410 :                         if (!MSGlobals::gCheckRoutes) {
    1197           15 :                             WRITE_WARNINGF(TL("Vehicle '%' is inserted too fast and will violate the speed limit on a lane '%', time=%."),
    1198              :                                            aVehicle->getID(), nextLane->getID(), time2string(SIMSTEP));
    1199              :                         } else {
    1200              :                             // we may not drive with the given velocity - we would be too fast on the next lane
    1201         1215 :                             WRITE_ERRORF(TL("Vehicle '%' will not be able to depart using the given velocity (slow lane ahead), time=%."), aVehicle->getID(), time2string(SIMSTEP));
    1202          405 :                             MSNet::getInstance()->getInsertionControl().descheduleDeparture(aVehicle);
    1203              :                             return false;
    1204              :                         }
    1205              :                     }
    1206              :                 }
    1207              :             }
    1208              :             // check traffic on next junction
    1209              :             // we cannot use (*link)->opened because a vehicle without priority
    1210              :             // may already be comitted to blocking the link and unable to stop
    1211       411882 :             const SUMOTime leaveTime = (*link)->getLeaveTime(arrivalTime, speed, speed, aVehicle->getVehicleType().getLength());
    1212       411882 :             if ((*link)->hasApproachingFoe(arrivalTime, leaveTime, speed, cfModel.getMaxDecel())) {
    1213        17926 :                 if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, seen), patchSpeed, "", InsertionCheck::JUNCTION)) {
    1214              :                     // we may not drive with the given velocity - we crash at the junction
    1215              :                     return false;
    1216              :                 }
    1217              :             }
    1218       445708 :             arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
    1219       409808 :             seen += nextLane->getLength();
    1220              :             currentLane = nextLane;
    1221       409808 :             if ((*link)->getViaLane() == nullptr) {
    1222       191148 :                 nRouteSuccs++;
    1223              :                 ++ce;
    1224              :                 ++ri;
    1225              :             }
    1226       453797 :         }
    1227              :     }
    1228              : 
    1229      4501800 :     const MSLeaderDistanceInfo& followers = getFollowersOnConsecutive(aVehicle, aVehicle->getBackPositionOnLane(), false);
    1230      9850216 :     for (int i = 0; i < followers.numSublanes(); ++i) {
    1231      6329273 :         const MSVehicle* follower = followers[i].first;
    1232      6329273 :         if (follower != nullptr) {
    1233      1282059 :             const double backGapNeeded = follower->getCarFollowModel().getSecureGap(follower, aVehicle, follower->getSpeed(), speed, cfModel.getMaxDecel());
    1234      1282059 :             if (followers[i].second < backGapNeeded
    1235      1282059 :                     && ((insertionChecks & (int)InsertionCheck::FOLLOWER_GAP) != 0
    1236           80 :                         || (followers[i].second < 0 && (insertionChecks & (int)InsertionCheck::COLLISION) != 0))) {
    1237              :                 // too close to the follower on this lane
    1238              : #ifdef DEBUG_INSERTION
    1239              :                 if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
    1240              :                     std::cout << SIMTIME << " isInsertionSuccess lane=" << getID()
    1241              :                               << " veh=" << aVehicle->getID()
    1242              :                               << " pos=" << pos
    1243              :                               << " posLat=" << posLat
    1244              :                               << " speed=" << speed
    1245              :                               << " nspeed=" << nspeed
    1246              :                               << " follower=" << follower->getID()
    1247              :                               << " backGapNeeded=" << backGapNeeded
    1248              :                               << " gap=" << followers[i].second
    1249              :                               << " failure (@719)!\n";
    1250              :                 }
    1251              : #endif
    1252       980857 :                 return false;
    1253              :             }
    1254              :         }
    1255              :     }
    1256              : 
    1257      3520943 :     if (!checkForPedestrians(aVehicle, speed, dist, pos, patchSpeed)) {
    1258              :         return false;
    1259              :     }
    1260              : 
    1261      3520396 :     MSLane* shadowLane = aVehicle->getLaneChangeModel().getShadowLane(this);
    1262              : #ifdef DEBUG_INSERTION
    1263              :     if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
    1264              :         std::cout << "    shadowLane=" << Named::getIDSecure(shadowLane) << "\n";
    1265              :     }
    1266              : #endif
    1267      3520396 :     if (shadowLane != nullptr) {
    1268          875 :         const MSLeaderDistanceInfo& shadowFollowers = shadowLane->getFollowersOnConsecutive(aVehicle, aVehicle->getBackPositionOnLane(), false);
    1269         3829 :         for (int i = 0; i < shadowFollowers.numSublanes(); ++i) {
    1270         2971 :             const MSVehicle* follower = shadowFollowers[i].first;
    1271         2971 :             if (follower != nullptr) {
    1272           25 :                 const double backGapNeeded = follower->getCarFollowModel().getSecureGap(follower, aVehicle, follower->getSpeed(), speed, cfModel.getMaxDecel());
    1273           25 :                 if (shadowFollowers[i].second < backGapNeeded
    1274           25 :                         && ((insertionChecks & (int)InsertionCheck::FOLLOWER_GAP) != 0
    1275            0 :                             || (shadowFollowers[i].second < 0 && (insertionChecks & (int)InsertionCheck::COLLISION) != 0))) {
    1276              :                     // too close to the follower on this lane
    1277              : #ifdef DEBUG_INSERTION
    1278              :                     if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
    1279              :                         std::cout << SIMTIME
    1280              :                                   << " isInsertionSuccess shadowlane=" << shadowLane->getID()
    1281              :                                   << " veh=" << aVehicle->getID()
    1282              :                                   << " pos=" << pos
    1283              :                                   << " posLat=" << posLat
    1284              :                                   << " speed=" << speed
    1285              :                                   << " nspeed=" << nspeed
    1286              :                                   << " follower=" << follower->getID()
    1287              :                                   << " backGapNeeded=" << backGapNeeded
    1288              :                                   << " gap=" << shadowFollowers[i].second
    1289              :                                   << " failure (@812)!\n";
    1290              :                     }
    1291              : #endif
    1292           17 :                     return false;
    1293              :                 }
    1294              :             }
    1295              :         }
    1296          858 :         const MSLeaderInfo& ahead = shadowLane->getLastVehicleInformation(nullptr, 0, aVehicle->getPositionOnLane(), false);
    1297         2852 :         for (int i = 0; i < ahead.numSublanes(); ++i) {
    1298         2087 :             const MSVehicle* veh = ahead[i];
    1299         2087 :             if (veh != nullptr) {
    1300          342 :                 const double gap = veh->getBackPositionOnLane(shadowLane) - aVehicle->getPositionOnLane() - aVehicle->getVehicleType().getMinGap();
    1301          342 :                 const double gapNeeded = aVehicle->getCarFollowModel().getSecureGap(aVehicle, veh, speed, veh->getSpeed(), veh->getCarFollowModel().getMaxDecel());
    1302          342 :                 if (gap <  gapNeeded
    1303           93 :                         && ((insertionChecks & (int)InsertionCheck::LEADER_GAP) != 0
    1304            0 :                             || (gap < 0 && (insertionChecks & (int)InsertionCheck::COLLISION) != 0))) {
    1305              :                     // too close to the shadow leader
    1306              : #ifdef DEBUG_INSERTION
    1307              :                     if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
    1308              :                         std::cout << SIMTIME
    1309              :                                   << " isInsertionSuccess shadowlane=" << shadowLane->getID()
    1310              :                                   << " veh=" << aVehicle->getID()
    1311              :                                   << " pos=" << pos
    1312              :                                   << " posLat=" << posLat
    1313              :                                   << " speed=" << speed
    1314              :                                   << " nspeed=" << nspeed
    1315              :                                   << " leader=" << veh->getID()
    1316              :                                   << " gapNeeded=" << gapNeeded
    1317              :                                   << " gap=" << gap
    1318              :                                   << " failure (@842)!\n";
    1319              :                     }
    1320              : #endif
    1321              :                     return false;
    1322              :                 }
    1323              :             }
    1324              :         }
    1325          875 :     }
    1326      3520286 :     if (followers.numFreeSublanes() > 0) {
    1327              :         // check approaching vehicles to prevent rear-end collisions
    1328      3340485 :         const double backOffset = pos - aVehicle->getVehicleType().getLength();
    1329      3340485 :         const double missingRearGap = getMissingRearGap(aVehicle, backOffset, speed);
    1330      3340485 :         if (missingRearGap > 0
    1331            0 :                 && (insertionChecks & (int)InsertionCheck::LEADER_GAP) != 0) {
    1332              :             // too close to a follower
    1333              : #ifdef DEBUG_INSERTION
    1334              :             if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
    1335              :                 std::cout << SIMTIME
    1336              :                           << " isInsertionSuccess lane=" << getID()
    1337              :                           << " veh=" << aVehicle->getID()
    1338              :                           << " pos=" << pos
    1339              :                           << " posLat=" << posLat
    1340              :                           << " speed=" << speed
    1341              :                           << " nspeed=" << nspeed
    1342              :                           << " missingRearGap=" << missingRearGap
    1343              :                           << " failure (@728)!\n";
    1344              :             }
    1345              : #endif
    1346              :             return false;
    1347              :         }
    1348              :     }
    1349      3520286 :     if (insertionChecks == (int)InsertionCheck::NONE) {
    1350         2340 :         speed = MAX2(0.0, speed);
    1351              :     }
    1352              :     // may got negative while adaptation
    1353      3520286 :     if (speed < 0) {
    1354              : #ifdef DEBUG_INSERTION
    1355              :         if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
    1356              :             std::cout << SIMTIME
    1357              :                       << " isInsertionSuccess lane=" << getID()
    1358              :                       << " veh=" << aVehicle->getID()
    1359              :                       << " pos=" << pos
    1360              :                       << " posLat=" << posLat
    1361              :                       << " speed=" << speed
    1362              :                       << " nspeed=" << nspeed
    1363              :                       << " failed (@733)!\n";
    1364              :         }
    1365              : #endif
    1366              :         return false;
    1367              :     }
    1368      3520285 :     const int bestLaneOffset = aVehicle->getBestLaneOffset();
    1369      3520285 :     const double extraReservation = aVehicle->getLaneChangeModel().getExtraReservation(bestLaneOffset);
    1370      3520285 :     if (extraReservation > 0) {
    1371        23253 :         std::stringstream msg;
    1372        23253 :         msg << "too many lane changes required on lane '" << myID << "'";
    1373              :         // we need to take into acount one extra actionStep of delay due to #3665
    1374        23253 :         double distToStop = aVehicle->getBestLaneDist() - pos - extraReservation - speed * aVehicle->getActionStepLengthSecs();
    1375        23253 :         if (distToStop >= 0) {
    1376              :             double stopSpeed = cfModel.stopSpeed(aVehicle, speed, distToStop, MSCFModel::CalcReason::FUTURE);
    1377              : #ifdef DEBUG_INSERTION
    1378              :             if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
    1379              :                 std::cout << "\nIS_INSERTION_SUCCESS\n"
    1380              :                           << SIMTIME << " veh=" << aVehicle->getID() << " bestLaneOffset=" << bestLaneOffset << " bestLaneDist=" << aVehicle->getBestLaneDist() << " extraReservation=" << extraReservation
    1381              :                           << " distToStop=" << distToStop << " v=" << speed << " v2=" << stopSpeed << "\n";
    1382              :             }
    1383              : #endif
    1384        44712 :             if (checkFailure(aVehicle, speed, distToStop, MAX2(0.0, stopSpeed),
    1385        22360 :                              patchSpeedSpecial, msg.str(), InsertionCheck::LANECHANGE)) {
    1386              :                 // we may not drive with the given velocity - we cannot reserve enough space for lane changing
    1387              :                 return false;
    1388              :             }
    1389              :         }
    1390        23253 :     }
    1391              :     // enter
    1392      3520275 :     incorporateVehicle(aVehicle, pos, speed, posLat, find_if(myVehicles.begin(), myVehicles.end(), [&](MSVehicle * const v) {
    1393      2964044 :         return v->getPositionOnLane() >= pos;
    1394              :     }), notification);
    1395              : #ifdef DEBUG_INSERTION
    1396              :     if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
    1397              :         std::cout << SIMTIME
    1398              :                   << " isInsertionSuccess lane=" << getID()
    1399              :                   << " veh=" << aVehicle->getID()
    1400              :                   << " pos=" << pos
    1401              :                   << " posLat=" << posLat
    1402              :                   << " speed=" << speed
    1403              :                   << " nspeed=" << nspeed
    1404              :                   << "\n myVehicles=" << toString(myVehicles)
    1405              :                   << " myPartial=" << toString(myPartialVehicles)
    1406              :                   << " myManeuverReservations=" << toString(myManeuverReservations)
    1407              :                   << "\n success!\n";
    1408              :     }
    1409              : #endif
    1410      3520275 :     if (isRail) {
    1411         5770 :         unsetParameter("insertionConstraint:" + aVehicle->getID());
    1412         5770 :         unsetParameter("insertionOrder:" + aVehicle->getID());
    1413         5770 :         unsetParameter("insertionBlocked:" + aVehicle->getID());
    1414              :         // rail_signal (not traffic_light) requires approach information for
    1415              :         // switching correctly at the start of the next simulation step
    1416         5770 :         if (firstRailSignal != nullptr && firstRailSignal->getJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
    1417         1860 :             aVehicle->registerInsertionApproach(firstRailSignal, firstRailSignalDist);
    1418              :         }
    1419              :     }
    1420              :     return true;
    1421     14044652 : }
    1422              : 
    1423              : 
    1424              : void
    1425        48256 : MSLane::forceVehicleInsertion(MSVehicle* veh, double pos, MSMoveReminder::Notification notification, double posLat) {
    1426        48256 :     veh->updateBestLanes(true, this);
    1427              :     bool dummy;
    1428        48256 :     const double speed = veh->hasDeparted() ? veh->getSpeed() : getDepartSpeed(*veh, dummy);
    1429        48256 :     incorporateVehicle(veh, pos, speed, posLat, find_if(myVehicles.begin(), myVehicles.end(), [&](MSVehicle * const v) {
    1430       125519 :         return v->getPositionOnLane() >= pos;
    1431              :     }), notification);
    1432        48256 : }
    1433              : 
    1434              : 
    1435              : double
    1436     14203363 : MSLane::safeInsertionSpeed(const MSVehicle* veh, double seen, const MSLeaderInfo& leaders, double speed) {
    1437              :     double nspeed = speed;
    1438              : #ifdef DEBUG_INSERTION
    1439              :     if (DEBUG_COND2(veh)) {
    1440              :         std::cout << SIMTIME << " safeInsertionSpeed veh=" << veh->getID() << " speed=" << speed << "\n";
    1441              :     }
    1442              : #endif
    1443     25108735 :     for (int i = 0; i < leaders.numSublanes(); ++i) {
    1444     17807246 :         const MSVehicle* leader = leaders[i];
    1445     17807246 :         if (leader != nullptr) {
    1446     15531100 :             double gap = leader->getBackPositionOnLane(this) + seen - veh->getVehicleType().getMinGap();
    1447     15531100 :             if (leader->getLane() == getBidiLane()) {
    1448              :                 // use distance to front position and account for movement
    1449        10210 :                 gap -= (leader->getLength() + leader->getBrakeGap(true));
    1450              :             }
    1451     15531100 :             if (gap < 0) {
    1452              : #ifdef DEBUG_INSERTION
    1453              :                 if (DEBUG_COND2(veh)) {
    1454              :                     std::cout << "    leader=" << leader->getID() << " bPos=" << leader->getBackPositionOnLane(this) << " gap=" << gap << "\n";
    1455              :                 }
    1456              : #endif
    1457      6901874 :                 if ((veh->getInsertionChecks() & (int)InsertionCheck::COLLISION) != 0) {
    1458              :                     return INVALID_SPEED;
    1459              :                 } else {
    1460            0 :                     return 0;
    1461              :                 }
    1462              :             }
    1463      8629226 :             nspeed = MIN2(nspeed,
    1464      8629226 :                           veh->getCarFollowModel().insertionFollowSpeed(veh, speed, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), leader));
    1465              : #ifdef DEBUG_INSERTION
    1466              :             if (DEBUG_COND2(veh)) {
    1467              :                 std::cout << "    leader=" << leader->getID() << " bPos=" << leader->getBackPositionOnLane(this) << " gap=" << gap << " nspeed=" << nspeed << "\n";
    1468              :             }
    1469              : #endif
    1470              :         }
    1471              :     }
    1472              :     return nspeed;
    1473              : }
    1474              : 
    1475              : 
    1476              : // ------ Handling vehicles lapping into lanes ------
    1477              : const MSLeaderInfo
    1478    765144152 : MSLane::getLastVehicleInformation(const MSVehicle* ego, double latOffset, double minPos, bool allowCached, const MSVehicle* ignore) const {
    1479              : #ifdef DEBUG_SURROUNDING
    1480              :     if (DEBUG_COND2(ego) || DEBUG_COND) {
    1481              :         std::cout << "    getLastVehicleInformation lane=" << getID() << " ego=" << Named::getIDSecure(ego) << " latOffset=" << latOffset << " minPos=" << minPos << " allowCached=" << allowCached
    1482              :         << " hasCache=" << (myLeaderInfoTime >= MSNet::getInstance()->getCurrentTimeStep()) << "\n";
    1483              :     }
    1484              : #endif
    1485    765144152 :     if (myLeaderInfoTime < MSNet::getInstance()->getCurrentTimeStep() || ego != nullptr || minPos > 0 || !allowCached) {
    1486    271750647 :         MSLeaderInfo leaderTmp(myWidth, ego, latOffset);
    1487              :         AnyVehicleIterator last = anyVehiclesBegin();
    1488              :         int freeSublanes = 1; // number of sublanes for which no leader was found
    1489              :         //if (ego->getID() == "disabled" && SIMTIME == 58) {
    1490              :         //    std::cout << "DEBUG\n";
    1491              :         //}
    1492    271750647 :         const MSVehicle* veh = *last;
    1493   2041043185 :         while (freeSublanes > 0 && veh != nullptr) {
    1494              : #ifdef DEBUG_PLAN_MOVE
    1495              :             if (DEBUG_COND2(ego) || DEBUG_COND) {
    1496              :                 gDebugFlag1 = true;
    1497              :                 std::cout << "      getLastVehicleInformation lane=" << getID() << " minPos=" << minPos << " veh=" << veh->getID() << " pos=" << veh->getPositionOnLane(this)  << "\n";
    1498              :             }
    1499              : #endif
    1500   3451338749 :             if (veh != ego && veh != ignore && MAX2(0.0, veh->getPositionOnLane(this)) >= minPos) {
    1501    253866903 :                 const double vehLatOffset = veh->getLatOffset(this);
    1502    253866903 :                 freeSublanes = leaderTmp.addLeader(veh, true, vehLatOffset);
    1503              : #ifdef DEBUG_PLAN_MOVE
    1504              :                 if (DEBUG_COND2(ego) || DEBUG_COND) {
    1505              :                     std::cout << "         latOffset=" << vehLatOffset << " newLeaders=" << leaderTmp.toString() << "\n";
    1506              :                 }
    1507              : #endif
    1508              :             }
    1509   1769292538 :             veh = *(++last);
    1510              :         }
    1511    271750647 :         if (ego == nullptr && minPos == 0) {
    1512              : #ifdef HAVE_FOX
    1513    126061198 :             ScopedLocker<> lock(myLeaderInfoMutex, MSGlobals::gNumSimThreads > 1);
    1514              : #endif
    1515              :             // update cached value
    1516              :             myLeaderInfo = leaderTmp;
    1517    126061198 :             myLeaderInfoTime = MSNet::getInstance()->getCurrentTimeStep();
    1518              :         }
    1519              : #ifdef DEBUG_PLAN_MOVE
    1520              :         //if (DEBUG_COND2(ego)) std::cout << SIMTIME
    1521              :         //    << " getLastVehicleInformation lane=" << getID()
    1522              :         //        << " ego=" << Named::getIDSecure(ego)
    1523              :         //        << "\n"
    1524              :         //        << "    vehicles=" << toString(myVehicles)
    1525              :         //        << "    partials=" << toString(myPartialVehicles)
    1526              :         //        << "\n"
    1527              :         //        << "    result=" << leaderTmp.toString()
    1528              :         //        << "    cached=" << myLeaderInfo.toString()
    1529              :         //        << "    myLeaderInfoTime=" << myLeaderInfoTime
    1530              :         //        << "\n";
    1531              :         gDebugFlag1 = false;
    1532              : #endif
    1533              :         return leaderTmp;
    1534    271750647 :     }
    1535              :     return myLeaderInfo;
    1536              : }
    1537              : 
    1538              : 
    1539              : const MSLeaderInfo
    1540    447740885 : MSLane::getFirstVehicleInformation(const MSVehicle* ego, double latOffset, bool onlyFrontOnLane, double maxPos, bool allowCached) const {
    1541              : #ifdef HAVE_FOX
    1542    447740885 :     ScopedLocker<> lock(myFollowerInfoMutex, MSGlobals::gNumSimThreads > 1);
    1543              : #endif
    1544    447740885 :     if (myFollowerInfoTime < MSNet::getInstance()->getCurrentTimeStep() || ego != nullptr || maxPos < myLength || !allowCached || onlyFrontOnLane) {
    1545              :         // XXX separate cache for onlyFrontOnLane = true
    1546    447740885 :         MSLeaderInfo followerTmp(myWidth, ego, latOffset);
    1547              :         AnyVehicleIterator first = anyVehiclesUpstreamBegin();
    1548              :         int freeSublanes = 1; // number of sublanes for which no leader was found
    1549    447740885 :         const MSVehicle* veh = *first;
    1550    707797501 :         while (freeSublanes > 0 && veh != nullptr) {
    1551              : #ifdef DEBUG_PLAN_MOVE
    1552              :             if (DEBUG_COND2(ego)) {
    1553              :                 std::cout << "       veh=" << veh->getID() << " pos=" << veh->getPositionOnLane(this) << " maxPos=" << maxPos << "\n";
    1554              :             }
    1555              : #endif
    1556    260056617 :             if (veh != ego && veh->getPositionOnLane(this) <= maxPos
    1557    520113234 :                     && (!onlyFrontOnLane || veh->isFrontOnLane(this))) {
    1558              :                 //const double vehLatOffset = veh->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
    1559    237364404 :                 const double vehLatOffset = veh->getLatOffset(this);
    1560              : #ifdef DEBUG_PLAN_MOVE
    1561              :                 if (DEBUG_COND2(ego)) {
    1562              :                     std::cout << "          veh=" << veh->getID() << " latOffset=" << vehLatOffset << "\n";
    1563              :                 }
    1564              : #endif
    1565    237364403 :                 freeSublanes = followerTmp.addLeader(veh, true, vehLatOffset);
    1566              :             }
    1567    260056616 :             veh = *(++first);
    1568              :         }
    1569    447740884 :         if (ego == nullptr && maxPos == std::numeric_limits<double>::max()) {
    1570              :             // update cached value
    1571              :             myFollowerInfo = followerTmp;
    1572    447740884 :             myFollowerInfoTime = MSNet::getInstance()->getCurrentTimeStep();
    1573              :         }
    1574              : #ifdef DEBUG_PLAN_MOVE
    1575              :         //if (DEBUG_COND2(ego)) std::cout << SIMTIME
    1576              :         //    << " getFirstVehicleInformation lane=" << getID()
    1577              :         //        << " ego=" << Named::getIDSecure(ego)
    1578              :         //        << "\n"
    1579              :         //        << "    vehicles=" << toString(myVehicles)
    1580              :         //        << "    partials=" << toString(myPartialVehicles)
    1581              :         //        << "\n"
    1582              :         //        << "    result=" << followerTmp.toString()
    1583              :         //        //<< "    cached=" << myFollowerInfo.toString()
    1584              :         //        << "    myLeaderInfoTime=" << myLeaderInfoTime
    1585              :         //        << "\n";
    1586              : #endif
    1587              :         return followerTmp;
    1588    447740885 :     }
    1589              :     return myFollowerInfo;
    1590              : }
    1591              : 
    1592              : 
    1593              : // ------  ------
    1594              : void
    1595     97498558 : MSLane::planMovements(SUMOTime t) {
    1596              :     assert(myVehicles.size() != 0);
    1597              :     double cumulatedVehLength = 0.;
    1598     97498558 :     MSLeaderInfo leaders(myWidth);
    1599              : 
    1600              :     // iterate over myVehicles, myPartialVehicles, and myManeuverReservations merge-sort style
    1601              :     VehCont::reverse_iterator veh = myVehicles.rbegin();
    1602              :     VehCont::reverse_iterator vehPart = myPartialVehicles.rbegin();
    1603              :     VehCont::reverse_iterator vehRes = myManeuverReservations.rbegin();
    1604              : #ifdef DEBUG_PLAN_MOVE
    1605              :     if (DEBUG_COND) std::cout
    1606              :                 << "\n"
    1607              :                 << SIMTIME
    1608              :                 << " planMovements() lane=" << getID()
    1609              :                 << "\n    vehicles=" << toString(myVehicles)
    1610              :                 << "\n    partials=" << toString(myPartialVehicles)
    1611              :                 << "\n    reservations=" << toString(myManeuverReservations)
    1612              :                 << "\n";
    1613              : #endif
    1614              :     assert(MSGlobals::gLateralResolution || myManeuverReservations.size() == 0);
    1615    806696054 :     for (; veh != myVehicles.rend(); ++veh) {
    1616              : #ifdef DEBUG_PLAN_MOVE
    1617              :         if (DEBUG_COND2((*veh))) {
    1618              :             std::cout << "   plan move for: " << (*veh)->getID();
    1619              :         }
    1620              : #endif
    1621    709197496 :         updateLeaderInfo(*veh, vehPart, vehRes, leaders); // 36ns with 8 threads, 9ns with 1
    1622              : #ifdef DEBUG_PLAN_MOVE
    1623              :         if (DEBUG_COND2((*veh))) {
    1624              :             std::cout << " leaders=" << leaders.toString() << "\n";
    1625              :         }
    1626              : #endif
    1627    709197496 :         (*veh)->planMove(t, leaders, cumulatedVehLength); // 4800ns with 8 threads, 3100 with 1
    1628    709197496 :         cumulatedVehLength += (*veh)->getVehicleType().getLengthWithGap();
    1629    709197496 :         leaders.addLeader(*veh, false, 0);
    1630              :     }
    1631     97498558 : }
    1632              : 
    1633              : 
    1634              : void
    1635     97498558 : MSLane::setJunctionApproaches() const {
    1636    806696054 :     for (MSVehicle* const veh : myVehicles) {
    1637    709197496 :         veh->setApproachingForAllLinks();
    1638              :     }
    1639     97498558 : }
    1640              : 
    1641              : 
    1642              : void
    1643    709197496 : MSLane::updateLeaderInfo(const MSVehicle* veh, VehCont::reverse_iterator& vehPart, VehCont::reverse_iterator& vehRes, MSLeaderInfo& ahead) const {
    1644              :     bool morePartialVehsAhead = vehPart != myPartialVehicles.rend();
    1645              :     bool moreReservationsAhead = vehRes != myManeuverReservations.rend();
    1646              :     bool nextToConsiderIsPartial;
    1647              : 
    1648              :     // Determine relevant leaders for veh
    1649    719621687 :     while (moreReservationsAhead || morePartialVehsAhead) {
    1650      1200717 :         if ((!moreReservationsAhead || (*vehRes)->getPositionOnLane(this) <= veh->getPositionOnLane())
    1651     20379011 :                 && (!morePartialVehsAhead || (*vehPart)->getPositionOnLane(this) <= veh->getPositionOnLane())) {
    1652              :             // All relevant downstream vehicles have been collected.
    1653              :             break;
    1654              :         }
    1655              : 
    1656              :         // Check whether next farthest relevant vehicle downstream is a partial vehicle or a maneuver reservation
    1657     10424191 :         if (moreReservationsAhead && !morePartialVehsAhead) {
    1658              :             nextToConsiderIsPartial = false;
    1659     10332460 :         } else if (morePartialVehsAhead && !moreReservationsAhead) {
    1660              :             nextToConsiderIsPartial = true;
    1661              :         } else {
    1662              :             assert(morePartialVehsAhead && moreReservationsAhead);
    1663              :             // Add farthest downstream vehicle first
    1664       150848 :             nextToConsiderIsPartial = (*vehPart)->getPositionOnLane(this) > (*vehRes)->getPositionOnLane(this);
    1665              :         }
    1666              :         // Add appropriate leader information
    1667       150848 :         if (nextToConsiderIsPartial) {
    1668     10286092 :             const double latOffset = (*vehPart)->getLatOffset(this);
    1669              : #ifdef DEBUG_PLAN_MOVE
    1670              :             if (DEBUG_COND) {
    1671              :                 std::cout << "        partial ahead: " << (*vehPart)->getID() << " latOffset=" << latOffset << "\n";
    1672              :             }
    1673              : #endif
    1674     10353187 :             if (!(MSGlobals::gLaneChangeDuration > 0 && (*vehPart)->getLaneChangeModel().isOpposite()
    1675        67095 :                     && !(*vehPart)->getLaneChangeModel().isChangingLanes())) {
    1676     10236329 :                 ahead.addLeader(*vehPart, false, latOffset);
    1677              :             }
    1678              :             ++vehPart;
    1679              :             morePartialVehsAhead = vehPart != myPartialVehicles.rend();
    1680              :         } else {
    1681       138099 :             const double latOffset = (*vehRes)->getLatOffset(this);
    1682              : #ifdef DEBUG_PLAN_MOVE
    1683              :             if (DEBUG_COND) {
    1684              :                 std::cout << "    reservation ahead: " << (*vehRes)->getID() << " latOffset=" << latOffset << "\n";
    1685              :             }
    1686              : #endif
    1687       138099 :             ahead.addLeader(*vehRes, false, latOffset);
    1688              :             ++vehRes;
    1689              :             moreReservationsAhead = vehRes != myManeuverReservations.rend();
    1690              :         }
    1691              :     }
    1692    709197496 : }
    1693              : 
    1694              : 
    1695              : void
    1696    105682062 : MSLane::detectCollisions(SUMOTime timestep, const std::string& stage) {
    1697    105682062 :     myNeedsCollisionCheck = false;
    1698              : #ifdef DEBUG_COLLISIONS
    1699              :     if (DEBUG_COND) {
    1700              :         std::vector<const MSVehicle*> all;
    1701              :         for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
    1702              :             all.push_back(*last);
    1703              :         }
    1704              :         std::cout << SIMTIME << " detectCollisions stage=" << stage << " lane=" << getID() << ":\n"
    1705              :                   << "   vehs=" << toString(myVehicles) << "\n"
    1706              :                   << "   part=" << toString(myPartialVehicles) << "\n"
    1707              :                   << "   all=" << toString(all) << "\n"
    1708              :                   << "\n";
    1709              :     }
    1710              : #endif
    1711              : 
    1712    105682062 :     if (myCollisionAction == COLLISION_ACTION_NONE) {
    1713       882632 :         return;
    1714              :     }
    1715              : 
    1716              :     std::set<const MSVehicle*, ComparatorNumericalIdLess> toRemove;
    1717              :     std::set<const MSVehicle*, ComparatorNumericalIdLess> toTeleport;
    1718    105669194 :     if (mustCheckJunctionCollisions()) {
    1719      1410680 :         myNeedsCollisionCheck = true; // always check
    1720              : #ifdef DEBUG_JUNCTION_COLLISIONS
    1721              :         if (DEBUG_COND) {
    1722              :             std::cout << SIMTIME << " detect junction Collisions stage=" << stage << " lane=" << getID() << ":\n"
    1723              :                       << "   vehs=" << toString(myVehicles) << "\n"
    1724              :                       << "   part=" << toString(myPartialVehicles) << "\n"
    1725              :                       << "\n";
    1726              :         }
    1727              : #endif
    1728              :         assert(myLinks.size() == 1);
    1729      1410680 :         const std::vector<const MSLane*>& foeLanes = myLinks.front()->getFoeLanes();
    1730              :         // save the iterator, it might get modified, see #8842
    1731              :         MSLane::AnyVehicleIterator end = anyVehiclesEnd();
    1732      2510961 :         for (AnyVehicleIterator veh = anyVehiclesBegin(); veh != end; ++veh) {
    1733      2510961 :             const MSVehicle* const collider = *veh;
    1734              :             //std::cout << "   collider " << collider->getID() << "\n";
    1735      2510961 :             PositionVector colliderBoundary = collider->getBoundingBox(myCheckJunctionCollisionMinGap);
    1736     34614367 :             for (const MSLane* const foeLane : foeLanes) {
    1737              : #ifdef DEBUG_JUNCTION_COLLISIONS
    1738              :                 if (DEBUG_COND) {
    1739              :                     std::cout << "     foeLane " << foeLane->getID()
    1740              :                               << " foeVehs=" << toString(foeLane->myVehicles)
    1741              :                               << " foePart=" << toString(foeLane->myPartialVehicles) << "\n";
    1742              :                 }
    1743              : #endif
    1744              :                 MSLane::AnyVehicleIterator foeEnd = foeLane->anyVehiclesEnd();
    1745      4143634 :                 for (MSLane::AnyVehicleIterator it_veh = foeLane->anyVehiclesBegin(); it_veh != foeEnd; ++it_veh) {
    1746      4143634 :                     const MSVehicle* const victim = *it_veh;
    1747      4143634 :                     if (victim == collider) {
    1748              :                         // may happen if the vehicles lane and shadow lane are siblings
    1749         7389 :                         continue;
    1750              :                     }
    1751              : #ifdef DEBUG_JUNCTION_COLLISIONS
    1752              :                     if (DEBUG_COND && DEBUG_COND2(collider)) {
    1753              :                         std::cout << SIMTIME << " foe=" << victim->getID()
    1754              :                                   << " bound=" << colliderBoundary << " foeBound=" << victim->getBoundingBox()
    1755              :                                   << " overlaps=" << colliderBoundary.overlapsWith(victim->getBoundingBox())
    1756              :                                   << " poly=" << collider->getBoundingPoly()
    1757              :                                   << " foePoly=" << victim->getBoundingPoly()
    1758              :                                   << " overlaps2=" << collider->getBoundingPoly().overlapsWith(victim->getBoundingPoly())
    1759              :                                   << "\n";
    1760              :                     }
    1761              : #endif
    1762      4136245 :                     if (MSGlobals::gIgnoreJunctionBlocker < std::numeric_limits<SUMOTime>::max()) {
    1763         7280 :                         if (collider->getWaitingTime() >= MSGlobals::gIgnoreJunctionBlocker
    1764         7280 :                                 || victim->getWaitingTime() >= MSGlobals::gIgnoreJunctionBlocker) {
    1765              :                             // ignored vehicles should not tigger collision
    1766         5904 :                             continue;
    1767              :                         }
    1768              :                     }
    1769              : 
    1770      4130341 :                     if (colliderBoundary.overlapsWith(victim->getBoundingBox())) {
    1771              :                         // make a detailed check
    1772        20740 :                         PositionVector boundingPoly = collider->getBoundingPoly();
    1773        20740 :                         if (collider->getBoundingPoly(myCheckJunctionCollisionMinGap).overlapsWith(victim->getBoundingPoly())) {
    1774              :                             // junction leader is the victim (collider must still be on junction)
    1775              :                             assert(isInternal());
    1776        12521 :                             if (victim->getLane()->isInternal() && victim->isLeader(myLinks.front(), collider, -1)) {
    1777         5691 :                                 foeLane->handleCollisionBetween(timestep, stage, victim, collider, -1, 0, toRemove, toTeleport);
    1778              :                             } else {
    1779         6830 :                                 handleCollisionBetween(timestep, stage, collider, victim, -1, 0, toRemove, toTeleport);
    1780              :                             }
    1781              :                         }
    1782        20740 :                     }
    1783              :                 }
    1784     32103406 :                 detectPedestrianJunctionCollision(collider, colliderBoundary, foeLane, timestep, stage, toRemove, toTeleport);
    1785              :             }
    1786      2510961 :             if (myLinks.front()->getWalkingAreaFoe() != nullptr) {
    1787        57555 :                 detectPedestrianJunctionCollision(collider, colliderBoundary, myLinks.front()->getWalkingAreaFoe(), timestep, stage, toRemove, toTeleport);
    1788              :             }
    1789      2510961 :             if (myLinks.front()->getWalkingAreaFoeExit() != nullptr) {
    1790        53603 :                 detectPedestrianJunctionCollision(collider, colliderBoundary, myLinks.front()->getWalkingAreaFoeExit(), timestep, stage, toRemove, toTeleport);
    1791              :             }
    1792      2510961 :         }
    1793              :     }
    1794              : 
    1795              : 
    1796    105669194 :     if (myIntermodalCollisionAction != COLLISION_ACTION_NONE && myEdge->getPersons().size() > 0 && hasPedestrians()) {
    1797              : #ifdef DEBUG_PEDESTRIAN_COLLISIONS
    1798              :         if (DEBUG_COND) {
    1799              :             std::cout << SIMTIME << " detect pedestrian collisions stage=" << stage << " lane=" << getID() << "\n";
    1800              :         }
    1801              : #endif
    1802              :         AnyVehicleIterator v_end = anyVehiclesEnd();
    1803       145417 :         for (AnyVehicleIterator it_v = anyVehiclesBegin(); it_v != v_end; ++it_v) {
    1804       145417 :             const MSVehicle* v = *it_v;
    1805       145417 :             double back = v->getBackPositionOnLane(this);
    1806       145417 :             const double length = v->getVehicleType().getLength();
    1807       145417 :             const double right = v->getRightSideOnEdge(this) - getRightSideOnEdge();
    1808       145417 :             if (v->getLane() == getBidiLane()) {
    1809              :                 // use the front position for checking
    1810          611 :                 back -= length;
    1811              :             }
    1812       145417 :             PersonDist leader = nextBlocking(back, right, right + v->getVehicleType().getWidth());
    1813              : #ifdef DEBUG_PEDESTRIAN_COLLISIONS
    1814              :             if (DEBUG_COND && DEBUG_COND2(v)) {
    1815              :                 std::cout << SIMTIME << " back=" << back << " right=" << right << " person=" << Named::getIDSecure(leader.first)
    1816              :                           << " dist=" << leader.second << " jammed=" << (leader.first == nullptr ? false : leader.first->isJammed()) << "\n";
    1817              :             }
    1818              : #endif
    1819       145417 :             if (leader.first != 0 && leader.second < length && !leader.first->isJammed()) {
    1820          109 :                 if (v->getVehicleType().getGuiShape() == SUMOVehicleShape::AIRCRAFT) {
    1821              :                     // aircraft wings and body are above walking level
    1822              :                     continue;
    1823              :                 }
    1824          109 :                 const double gap = leader.second - length;
    1825          218 :                 handleIntermodalCollisionBetween(timestep, stage, v, leader.first, gap, "sharedLane", toRemove, toTeleport);
    1826              :             }
    1827              :         }
    1828              :     }
    1829              : 
    1830    105669194 :     if (myVehicles.size() == 0) {
    1831              :         return;
    1832              :     }
    1833    104799430 :     if (!MSGlobals::gSublane) {
    1834              :         // no sublanes
    1835              :         VehCont::reverse_iterator lastVeh = myVehicles.rend() - 1;
    1836    643219531 :         for (VehCont::reverse_iterator pred = myVehicles.rbegin(); pred != lastVeh; ++pred) {
    1837              :             VehCont::reverse_iterator veh = pred + 1;
    1838    559861297 :             detectCollisionBetween(timestep, stage, *veh, *pred, toRemove, toTeleport);
    1839              :         }
    1840     83358234 :         if (myPartialVehicles.size() > 0) {
    1841      7048653 :             detectCollisionBetween(timestep, stage, *lastVeh, myPartialVehicles.front(), toRemove, toTeleport);
    1842              :         }
    1843     83358234 :         if (getBidiLane() != nullptr) {
    1844              :             // bidirectional railway
    1845       481661 :             MSLane* bidiLane = getBidiLane();
    1846       481661 :             if (bidiLane->getVehicleNumberWithPartials() > 0) {
    1847       320065 :                 for (auto veh = myVehicles.begin(); veh != myVehicles.end(); ++veh) {
    1848       221885 :                     double high = (*veh)->getPositionOnLane(this);
    1849       221885 :                     double low = (*veh)->getBackPositionOnLane(this);
    1850       221885 :                     if (stage == MSNet::STAGE_MOVEMENTS) {
    1851              :                         // use previous back position to catch trains that
    1852              :                         // "jump" through each other
    1853       199733 :                         low -= SPEED2DIST((*veh)->getSpeed());
    1854              :                     }
    1855       968207 :                     for (AnyVehicleIterator veh2 = bidiLane->anyVehiclesBegin(); veh2 != bidiLane->anyVehiclesEnd(); ++veh2) {
    1856              :                         // self-collisions might legitemately occur when a long train loops back on itself
    1857       968207 :                         if (*veh == *veh2 && !(*veh)->isRail()) {
    1858       220980 :                             continue;
    1859              :                         }
    1860       868075 :                         if ((*veh)->getLane() == (*veh2)->getLane() ||
    1861       835384 :                                 (*veh)->getLane() == (*veh2)->getBackLane() ||
    1862        88157 :                                 (*veh)->getBackLane() == (*veh2)->getLane()) {
    1863              :                             // vehicles are not in a bidi relation
    1864       659070 :                             continue;
    1865              :                         }
    1866        88157 :                         double low2 = myLength - (*veh2)->getPositionOnLane(bidiLane);
    1867        88157 :                         double high2 = myLength - (*veh2)->getBackPositionOnLane(bidiLane);
    1868        88157 :                         if (stage == MSNet::STAGE_MOVEMENTS) {
    1869              :                             // use previous back position to catch trains that
    1870              :                             // "jump" through each other
    1871        74654 :                             high2 += SPEED2DIST((*veh2)->getSpeed());
    1872              :                         }
    1873        88157 :                         if (!(high < low2 || high2 < low)) {
    1874              : #ifdef DEBUG_COLLISIONS
    1875              :                             if (DEBUG_COND) {
    1876              :                                 std::cout << SIMTIME << " bidi-collision veh=" << (*veh)->getID() << " bidiVeh=" << (*veh2)->getID()
    1877              :                                           << " vehFurther=" << toString((*veh)->getFurtherLanes())
    1878              :                                           << " high=" << high << " low=" << low << " high2=" << high2 << " low2=" << low2 << "\n";
    1879              :                             }
    1880              : #endif
    1881              :                             // the faster vehicle is at fault
    1882           41 :                             MSVehicle* collider = const_cast<MSVehicle*>(*veh);
    1883           41 :                             MSVehicle* victim = const_cast<MSVehicle*>(*veh2);
    1884           41 :                             if (collider->getSpeed() < victim->getSpeed()) {
    1885              :                                 std::swap(victim, collider);
    1886              :                             }
    1887           41 :                             handleCollisionBetween(timestep, stage, collider, victim, -1, 0, toRemove, toTeleport);
    1888              :                         }
    1889              :                     }
    1890              :                 }
    1891              :             }
    1892              :         }
    1893              :     } else {
    1894              :         // in the sublane-case it is insufficient to check the vehicles ordered
    1895              :         // by their front position as there might be more than 2 vehicles next to each
    1896              :         // other on the same lane
    1897              :         // instead, a moving-window approach is used where all vehicles that
    1898              :         // overlap in the longitudinal direction receive pairwise checks
    1899              :         // XXX for efficiency, all lanes of an edge should be checked together
    1900              :         // (lanechanger-style)
    1901              : 
    1902              :         // XXX quick hack: check each in myVehicles against all others
    1903    145341931 :         for (AnyVehicleIterator veh = anyVehiclesBegin(); veh != anyVehiclesEnd(); ++veh) {
    1904    145341931 :             MSVehicle* follow = (MSVehicle*)*veh;
    1905   3935720106 :             for (AnyVehicleIterator veh2 = anyVehiclesBegin(); veh2 != anyVehiclesEnd(); ++veh2) {
    1906   3935792806 :                 MSVehicle* lead = (MSVehicle*)*veh2;
    1907   3935792806 :                 if (lead == follow) {
    1908    145332250 :                     continue;
    1909              :                 }
    1910   3790460556 :                 if (lead->getPositionOnLane(this) < follow->getPositionOnLane(this)) {
    1911   1894159235 :                     continue;
    1912              :                 }
    1913   1896301321 :                 if (detectCollisionBetween(timestep, stage, follow, lead, toRemove, toTeleport)) {
    1914              :                     // XXX what about collisions with multiple leaders at once?
    1915              :                     break;
    1916              :                 }
    1917              :             }
    1918              :         }
    1919              :     }
    1920              : 
    1921              : 
    1922    104803353 :     for (std::set<const MSVehicle*, ComparatorNumericalIdLess>::iterator it = toRemove.begin(); it != toRemove.end(); ++it) {
    1923         3923 :         MSVehicle* veh = const_cast<MSVehicle*>(*it);
    1924              :         MSLane* vehLane = veh->getMutableLane();
    1925         3923 :         vehLane->removeVehicle(veh, MSMoveReminder::NOTIFICATION_TELEPORT, false);
    1926              :         if (toTeleport.count(veh) > 0) {
    1927         3538 :             MSVehicleTransfer::getInstance()->add(timestep, veh);
    1928              :         } else {
    1929          385 :             veh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_VAPORIZED_COLLISION);
    1930          385 :             MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(veh);
    1931              :         }
    1932              :     }
    1933              : }
    1934              : 
    1935              : 
    1936              : void
    1937     32214564 : MSLane::detectPedestrianJunctionCollision(const MSVehicle* collider, const PositionVector& colliderBoundary, const MSLane* foeLane,
    1938              :         SUMOTime timestep, const std::string& stage,
    1939              :         std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,
    1940              :         std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) {
    1941     32214564 :     if (myIntermodalCollisionAction != COLLISION_ACTION_NONE && foeLane->getEdge().getPersons().size() > 0 && foeLane->hasPedestrians()) {
    1942              : #ifdef DEBUG_PEDESTRIAN_COLLISIONS
    1943              :         if (DEBUG_COND) {
    1944              :             std::cout << SIMTIME << " detect pedestrian junction collisions stage=" << stage << " lane=" << getID() << " foeLane=" << foeLane->getID() << "\n";
    1945              :         }
    1946              : #endif
    1947       108434 :         const std::vector<MSTransportable*>& persons = foeLane->getEdge().getSortedPersons(timestep);
    1948      1204972 :         for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
    1949              : #ifdef DEBUG_PEDESTRIAN_COLLISIONS
    1950              :             if (DEBUG_COND) {
    1951              :                 std::cout << "    collider=" << collider->getID()
    1952              :                           << " ped=" << (*it_p)->getID()
    1953              :                           << " jammed=" << (*it_p)->isJammed()
    1954              :                           << " colliderBoundary=" << colliderBoundary
    1955              :                           << " pedBoundary=" << (*it_p)->getBoundingBox()
    1956              :                           << "\n";
    1957              :             }
    1958              : #endif
    1959      1096538 :             if ((*it_p)->isJammed()) {
    1960         1576 :                 continue;
    1961              :             }
    1962      2189924 :             if (colliderBoundary.overlapsWith((*it_p)->getBoundingBox())
    1963      1094962 :                     && collider->getBoundingPoly().overlapsWith((*it_p)->getBoundingBox())) {
    1964         4222 :                 std::string collisionType = "junctionPedestrian";
    1965         4222 :                 if (foeLane->isCrossing()) {
    1966              :                     collisionType = "crossing";
    1967         4006 :                 } else if (foeLane->isWalkingArea()) {
    1968              :                     collisionType = "walkingarea";
    1969              :                 }
    1970         4222 :                 handleIntermodalCollisionBetween(timestep, stage, collider, *it_p, 0, collisionType, toRemove, toTeleport);
    1971              :             }
    1972              :         }
    1973       108434 :     }
    1974     32214564 : }
    1975              : 
    1976              : 
    1977              : bool
    1978   2463211271 : MSLane::detectCollisionBetween(SUMOTime timestep, const std::string& stage, MSVehicle* collider, MSVehicle* victim,
    1979              :                                std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,
    1980              :                                std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) const {
    1981   4899853080 :     if (myCollisionAction == COLLISION_ACTION_TELEPORT && ((victim->hasInfluencer() && victim->getInfluencer().isRemoteAffected(timestep)) ||
    1982   2436901311 :             (collider->hasInfluencer() && collider->getInfluencer().isRemoteAffected(timestep)))) {
    1983           37 :         return false;
    1984              :     }
    1985              : 
    1986              :     // No self-collisions! (This is assumed to be ensured at caller side)
    1987   2463211234 :     if (collider == victim) {
    1988              :         return false;
    1989              :     }
    1990              : 
    1991   2463210118 :     const bool colliderOpposite = collider->getLaneChangeModel().isOpposite() || collider->isBidiOn(this);
    1992   2463210118 :     const bool victimOpposite = victim->getLaneChangeModel().isOpposite() || victim->isBidiOn(this);
    1993   2463210118 :     const bool bothOpposite = victimOpposite && colliderOpposite;
    1994   2463210118 :     if (bothOpposite) {
    1995              :         std::swap(victim, collider);
    1996              :     }
    1997   2463210118 :     const double colliderPos = colliderOpposite && !bothOpposite ? collider->getBackPositionOnLane(this) : collider->getPositionOnLane(this);
    1998   2463210118 :     const double minGapFactor = myCollisionMinGapFactor >= 0 ? myCollisionMinGapFactor : collider->getCarFollowModel().getCollisionMinGapFactor();
    1999   2463210118 :     double victimBack = victimOpposite && !bothOpposite ? victim->getPositionOnLane(this) : victim->getBackPositionOnLane(this);
    2000   2463210118 :     if (victim->getLateralOverlap() > 0 || collider->getLateralOverlap() > 0) {
    2001    141078684 :         if (&collider->getLane()->getEdge() == myEdge && collider->getLane()->getLength() > getLength()) {
    2002              :             // interpret victim position on the longer lane
    2003          762 :             victimBack *= collider->getLane()->getLength() / getLength();
    2004              :         }
    2005              :     }
    2006   2463210118 :     double gap = victimBack - colliderPos - minGapFactor * collider->getVehicleType().getMinGap();
    2007   2463210118 :     if (bothOpposite) {
    2008      1511058 :         gap = colliderPos - victimBack - minGapFactor * collider->getVehicleType().getMinGap();
    2009   2461699060 :     } else if (colliderOpposite) {
    2010              :         // vehicles are back to back so (frontal) minGap doesn't apply
    2011      3577307 :         gap += minGapFactor * collider->getVehicleType().getMinGap();
    2012              :     }
    2013              : #ifdef DEBUG_COLLISIONS
    2014              :     if (DEBUG_COND && (DEBUG_COND2(collider) || DEBUG_COND2(victim))) {
    2015              :         std::cout << SIMTIME
    2016              :                   << " thisLane=" << getID()
    2017              :                   << " collider=" << collider->getID()
    2018              :                   << " victim=" << victim->getID()
    2019              :                   << " colOpposite=" << colliderOpposite
    2020              :                   << " vicOpposite=" << victimOpposite
    2021              :                   << " colLane=" << collider->getLane()->getID()
    2022              :                   << " vicLane=" << victim->getLane()->getID()
    2023              :                   << " colPos=" << colliderPos
    2024              :                   << " vicBack=" << victimBack
    2025              :                   << " colLat=" << collider->getCenterOnEdge(this)
    2026              :                   << " vicLat=" << victim->getCenterOnEdge(this)
    2027              :                   << " minGap=" << collider->getVehicleType().getMinGap()
    2028              :                   << " minGapFactor=" << minGapFactor
    2029              :                   << " gap=" << gap
    2030              :                   << "\n";
    2031              :     }
    2032              : #endif
    2033   2463210118 :     if (victimOpposite && gap < -(collider->getLength() + victim->getLength())) {
    2034              :         // already past each other
    2035              :         return false;
    2036              :     }
    2037   2463191982 :     if (gap < -NUMERICAL_EPS) {
    2038              :         double latGap = 0;
    2039     11968172 :         if (MSGlobals::gSublane) {
    2040     11961668 :             latGap = (fabs(victim->getCenterOnEdge(this) - collider->getCenterOnEdge(this))
    2041     11961668 :                       - 0.5 * fabs(victim->getVehicleType().getWidth() + collider->getVehicleType().getWidth()));
    2042     11961668 :             if (latGap + NUMERICAL_EPS > 0) {
    2043              :                 return false;
    2044              :             }
    2045              :             // account for ambiguous gap computation related to partial
    2046              :             // occupation of lanes with different lengths
    2047        72704 :             if (isInternal() && getEdge().getNumLanes() > 1 && victim->getLane() != collider->getLane()) {
    2048              :                 double gapDelta = 0;
    2049         2426 :                 const MSVehicle* otherLaneVeh = collider->getLane() == this ? victim : collider;
    2050         2426 :                 if (otherLaneVeh->getLaneChangeModel().getShadowLane() == this) {
    2051          689 :                     gapDelta = getLength() - otherLaneVeh->getLane()->getLength();
    2052              :                 } else {
    2053         1737 :                     for (const MSLane* cand : otherLaneVeh->getFurtherLanes()) {
    2054         1737 :                         if (&cand->getEdge() == &getEdge()) {
    2055         1737 :                             gapDelta = getLength() - cand->getLength();
    2056         1737 :                             break;
    2057              :                         }
    2058              :                     }
    2059              :                 }
    2060         2426 :                 if (gap + gapDelta >= 0) {
    2061              :                     return false;
    2062              :                 }
    2063              :             }
    2064              :         }
    2065        79204 :         if (MSGlobals::gLaneChangeDuration > DELTA_T
    2066           42 :                 && collider->getLaneChangeModel().isChangingLanes()
    2067           27 :                 && victim->getLaneChangeModel().isChangingLanes()
    2068        79204 :                 && victim->getLane() != this) {
    2069              :             // synchroneous lane change maneuver
    2070              :             return false;
    2071              :         }
    2072              : #ifdef DEBUG_COLLISIONS
    2073              :         if (DEBUG_COND && (DEBUG_COND2(collider) || DEBUG_COND2(victim))) {
    2074              :             std::cout << SIMTIME << " detectedCollision gap=" << gap << " latGap=" << latGap << "\n";
    2075              :         }
    2076              : #endif
    2077        79204 :         handleCollisionBetween(timestep, stage, collider, victim, gap, latGap, toRemove, toTeleport);
    2078        79204 :         return true;
    2079              :     }
    2080              :     return false;
    2081              : }
    2082              : 
    2083              : 
    2084              : void
    2085        91766 : MSLane::handleCollisionBetween(SUMOTime timestep, const std::string& stage, const MSVehicle* collider, const MSVehicle* victim,
    2086              :                                double gap, double latGap, std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,
    2087              :                                std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) const {
    2088        91766 :     if (collider->ignoreCollision() || victim->ignoreCollision()) {
    2089        73373 :         return;
    2090              :     }
    2091              :     std::string collisionType;
    2092              :     std::string collisionText;
    2093        89165 :     if (isFrontalCollision(collider, victim)) {
    2094              :         collisionType = "frontal";
    2095         3454 :         collisionText = TL("frontal collision");
    2096        85711 :     } else if (stage == MSNet::STAGE_LANECHANGE) {
    2097              :         collisionType = "side";
    2098        12358 :         collisionText = TL("side collision");
    2099        73353 :     } else if (isInternal()) {
    2100              :         collisionType = "junction";
    2101        11957 :         collisionText = TL("junction collision");
    2102              :     } else {
    2103              :         collisionType = "collision";
    2104        61396 :         collisionText = TL("collision");
    2105              :     }
    2106              : 
    2107              :     // in frontal collisions the opposite vehicle is the collider
    2108        89165 :     if (victim->getLaneChangeModel().isOpposite() && !collider->getLaneChangeModel().isOpposite()) {
    2109              :         std::swap(collider, victim);
    2110              :     }
    2111       356660 :     std::string prefix = TLF("Vehicle '%'; % with vehicle '%", collider->getID(), collisionText, victim->getID());
    2112        89165 :     if (myCollisionStopTime > 0) {
    2113        73043 :         if (collider->collisionStopTime() >= 0 && victim->collisionStopTime() >= 0) {
    2114        70772 :             return;
    2115              :         }
    2116              :         std::string dummyError;
    2117         2271 :         SUMOVehicleParameter::Stop stop;
    2118         2271 :         stop.duration = myCollisionStopTime;
    2119         2271 :         stop.parametersSet |= STOP_DURATION_SET;
    2120         2271 :         const double collisionAngle = RAD2DEG(fabs(GeomHelper::angleDiff(victim->getAngle(), collider->getAngle())));
    2121              :         // determine new speeds from collision angle (@todo account for vehicle mass)
    2122         2271 :         double victimSpeed = victim->getSpeed();
    2123         2271 :         double colliderSpeed = collider->getSpeed();
    2124              :         // double victimOrigSpeed = victim->getSpeed();
    2125              :         // double colliderOrigSpeed = collider->getSpeed();
    2126         2271 :         if (collisionAngle < 45) {
    2127              :             // rear-end collisions
    2128              :             colliderSpeed = MIN2(colliderSpeed, victimSpeed);
    2129          327 :         } else if (collisionAngle < 135) {
    2130              :             // side collision
    2131          316 :             colliderSpeed /= 2;
    2132          316 :             victimSpeed /= 2;
    2133              :         } else {
    2134              :             // frontal collision
    2135              :             colliderSpeed = 0;
    2136              :             victimSpeed = 0;
    2137              :         }
    2138         2271 :         const double victimStopPos = MIN2(victim->getLane()->getLength(),
    2139         2271 :                                           victim->getPositionOnLane() + victim->getCarFollowModel().brakeGap(victimSpeed, victim->getCarFollowModel().getEmergencyDecel(), 0));
    2140         2271 :         if (victim->collisionStopTime() < 0) {
    2141         1488 :             stop.collision = true;
    2142         1488 :             stop.lane = victim->getLane()->getID();
    2143              :             // @todo: push victim forward?
    2144         1488 :             stop.startPos = victimStopPos;
    2145         1488 :             stop.endPos = stop.startPos;
    2146         1488 :             stop.parametersSet |= STOP_START_SET | STOP_END_SET;
    2147         1488 :             ((MSBaseVehicle*)victim)->addStop(stop, dummyError, 0);
    2148              :         }
    2149         2271 :         if (collider->collisionStopTime() < 0) {
    2150         1721 :             stop.collision = true;
    2151         1721 :             stop.lane = collider->getLane()->getID();
    2152         1721 :             stop.startPos = MIN2(collider->getPositionOnLane() + collider->getCarFollowModel().brakeGap(colliderSpeed, collider->getCarFollowModel().getEmergencyDecel(), 0),
    2153         1721 :                                  MAX3(0.0, victimStopPos - 0.75 * victim->getVehicleType().getLength(),
    2154         1721 :                                       collider->getPositionOnLane() - SPEED2DIST(collider->getSpeed())));
    2155         1721 :             stop.endPos = stop.startPos;
    2156         1721 :             stop.parametersSet |= STOP_START_SET | STOP_END_SET;
    2157         1721 :             ((MSBaseVehicle*)collider)->addStop(stop, dummyError, 0);
    2158              :         }
    2159              :         //std::cout << " collisionAngle=" << collisionAngle
    2160              :         //    << "\n    vPos=" << victim->getPositionOnLane()   << " vStop=" << victimStopPos  << " vSpeed=" << victimOrigSpeed     << " vSpeed2=" << victimSpeed   << " vSpeed3=" << victim->getSpeed()
    2161              :         //    << "\n    cPos=" << collider->getPositionOnLane() << " cStop=" << stop.startPos  << " cSpeed=" << colliderOrigSpeed   << " cSpeed2=" << colliderSpeed << " cSpeed3=" << collider->getSpeed()
    2162              :         //    << "\n";
    2163         2271 :     } else {
    2164        16122 :         switch (myCollisionAction) {
    2165              :             case COLLISION_ACTION_WARN:
    2166              :                 break;
    2167         3526 :             case COLLISION_ACTION_TELEPORT:
    2168         7052 :                 prefix = TLF("Teleporting vehicle '%'; % with vehicle '%", collider->getID(), collisionText, victim->getID());
    2169              :                 toRemove.insert(collider);
    2170              :                 toTeleport.insert(collider);
    2171              :                 break;
    2172          210 :             case COLLISION_ACTION_REMOVE: {
    2173          420 :                 prefix = TLF("Removing % participants: vehicle '%', vehicle '%", collisionText, collider->getID(), victim->getID());
    2174              :                 bool removeCollider = true;
    2175              :                 bool removeVictim = true;
    2176          210 :                 removeVictim = !(victim->hasInfluencer() && victim->getInfluencer()->isRemoteAffected(timestep));
    2177          210 :                 removeCollider = !(collider->hasInfluencer() && collider->getInfluencer()->isRemoteAffected(timestep));
    2178          210 :                 if (removeVictim) {
    2179              :                     toRemove.insert(victim);
    2180              :                 }
    2181          210 :                 if (removeCollider) {
    2182              :                     toRemove.insert(collider);
    2183              :                 }
    2184          210 :                 if (!removeVictim) {
    2185            0 :                     if (!removeCollider) {
    2186            0 :                         prefix = TLF("Keeping remote-controlled % participants: vehicle '%', vehicle '%", collisionText, collider->getID(), victim->getID());
    2187              :                     } else {
    2188            0 :                         prefix = TLF("Removing % participant: vehicle '%', keeping remote-controlled vehicle '%", collisionText, collider->getID(), victim->getID());
    2189              :                     }
    2190          210 :                 } else if (!removeCollider) {
    2191            0 :                     prefix = TLF("Keeping remote-controlled % participant: vehicle '%', removing vehicle '%", collisionText, collider->getID(), victim->getID());
    2192              :                 }
    2193              :                 break;
    2194              :             }
    2195              :             default:
    2196              :                 break;
    2197              :         }
    2198              :     }
    2199        18393 :     const bool newCollision = MSNet::getInstance()->registerCollision(collider, victim, collisionType, this, collider->getPositionOnLane(this));
    2200        18393 :     if (newCollision) {
    2201        31662 :         WRITE_WARNINGF(prefix + "', lane='%', gap=%%, time=%, stage=%.",
    2202              :                        getID(), toString(gap), (MSGlobals::gSublane ? TL(", latGap=") + toString(latGap) : ""),
    2203              :                        time2string(timestep), stage);
    2204         6348 :         MSNet::getInstance()->informVehicleStateListener(victim, MSNet::VehicleState::COLLISION);
    2205         6348 :         MSNet::getInstance()->informVehicleStateListener(collider, MSNet::VehicleState::COLLISION);
    2206         6348 :         MSNet::getInstance()->getVehicleControl().countCollision(myCollisionAction == COLLISION_ACTION_TELEPORT);
    2207              :     }
    2208              : #ifdef DEBUG_COLLISIONS
    2209              :     if (DEBUG_COND2(collider)) {
    2210              :         toRemove.erase(collider);
    2211              :         toTeleport.erase(collider);
    2212              :     }
    2213              :     if (DEBUG_COND2(victim)) {
    2214              :         toRemove.erase(victim);
    2215              :         toTeleport.erase(victim);
    2216              :     }
    2217              : #endif
    2218              : }
    2219              : 
    2220              : 
    2221              : void
    2222         4331 : MSLane::handleIntermodalCollisionBetween(SUMOTime timestep, const std::string& stage, const MSVehicle* collider, const MSTransportable* victim,
    2223              :         double gap, const std::string& collisionType,
    2224              :         std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,
    2225              :         std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) const {
    2226         4331 :     if (collider->ignoreCollision()) {
    2227         3304 :         return;
    2228              :     }
    2229         8662 :     std::string prefix = TLF("Vehicle '%'", collider->getID());
    2230         4331 :     if (myIntermodalCollisionStopTime > 0) {
    2231         3344 :         if (collider->collisionStopTime() >= 0) {
    2232         3304 :             return;
    2233              :         }
    2234              :         std::string dummyError;
    2235           40 :         SUMOVehicleParameter::Stop stop;
    2236           40 :         stop.duration = myIntermodalCollisionStopTime;
    2237           40 :         stop.parametersSet |= STOP_DURATION_SET;
    2238              :         // determine new speeds from collision angle (@todo account for vehicle mass)
    2239           40 :         double colliderSpeed = collider->getSpeed();
    2240           40 :         const double victimStopPos = victim->getEdgePos();
    2241              :         // double victimOrigSpeed = victim->getSpeed();
    2242              :         // double colliderOrigSpeed = collider->getSpeed();
    2243           40 :         if (collider->collisionStopTime() < 0) {
    2244           40 :             stop.collision = true;
    2245           40 :             stop.lane = collider->getLane()->getID();
    2246           40 :             stop.startPos = MIN2(collider->getPositionOnLane() + collider->getCarFollowModel().brakeGap(colliderSpeed, collider->getCarFollowModel().getEmergencyDecel(), 0),
    2247           40 :                                  MAX3(0.0, victimStopPos - 0.75 * victim->getVehicleType().getLength(),
    2248           40 :                                       collider->getPositionOnLane() - SPEED2DIST(collider->getSpeed())));
    2249           40 :             stop.endPos = stop.startPos;
    2250           40 :             stop.parametersSet |= STOP_START_SET | STOP_END_SET;
    2251           40 :             ((MSBaseVehicle*)collider)->addStop(stop, dummyError, 0);
    2252              :         }
    2253           40 :     } else {
    2254          987 :         switch (myIntermodalCollisionAction) {
    2255              :             case COLLISION_ACTION_WARN:
    2256              :                 break;
    2257           15 :             case COLLISION_ACTION_TELEPORT:
    2258           30 :                 prefix = TLF("Teleporting vehicle '%' after", collider->getID());
    2259              :                 toRemove.insert(collider);
    2260              :                 toTeleport.insert(collider);
    2261              :                 break;
    2262           15 :             case COLLISION_ACTION_REMOVE: {
    2263           30 :                 prefix = TLF("Removing vehicle '%' after", collider->getID());
    2264              :                 bool removeCollider = true;
    2265           15 :                 removeCollider = !(collider->hasInfluencer() && collider->getInfluencer()->isRemoteAffected(timestep));
    2266              :                 if (!removeCollider) {
    2267            0 :                     prefix = TLF("Keeping remote-controlled vehicle '%' after", collider->getID());
    2268              :                 } else {
    2269              :                     toRemove.insert(collider);
    2270              :                 }
    2271              :                 break;
    2272              :             }
    2273              :             default:
    2274              :                 break;
    2275              :         }
    2276              :     }
    2277         1027 :     const bool newCollision = MSNet::getInstance()->registerCollision(collider, victim, collisionType, this, victim->getEdgePos());
    2278         1027 :     if (newCollision) {
    2279          292 :         if (gap != 0) {
    2280          520 :             WRITE_WARNING(prefix + TLF(" collision with person '%', lane='%', gap=%, time=%, stage=%.",
    2281              :                                        victim->getID(), getID(), gap, time2string(timestep), stage));
    2282              :         } else {
    2283          940 :             WRITE_WARNING(prefix + TLF(" collision with person '%', lane='%', time=%, stage=%.",
    2284              :                                        victim->getID(), getID(), time2string(timestep), stage));
    2285              :         }
    2286          292 :         MSNet::getInstance()->informVehicleStateListener(collider, MSNet::VehicleState::COLLISION);
    2287          292 :         MSNet::getInstance()->getVehicleControl().countCollision(myIntermodalCollisionAction == COLLISION_ACTION_TELEPORT);
    2288              :     }
    2289              : #ifdef DEBUG_COLLISIONS
    2290              :     if (DEBUG_COND2(collider)) {
    2291              :         toRemove.erase(collider);
    2292              :         toTeleport.erase(collider);
    2293              :     }
    2294              : #endif
    2295              : }
    2296              : 
    2297              : 
    2298              : bool
    2299        89165 : MSLane::isFrontalCollision(const MSVehicle* collider, const MSVehicle* victim) {
    2300        89165 :     if (collider->getLaneChangeModel().isOpposite() != victim->getLaneChangeModel().isOpposite()) {
    2301              :         return true;
    2302              :     } else {
    2303        89151 :         const MSEdge* victimBidi = victim->getLane()->getEdge().getBidiEdge();
    2304        89151 :         if (&collider->getLane()->getEdge() == victimBidi) {
    2305              :             return true;
    2306              :         } else {
    2307       128894 :             for (MSLane* further : collider->getFurtherLanes()) {
    2308        43183 :                 if (&further->getEdge() == victimBidi) {
    2309              :                     return true;
    2310              :                 }
    2311              :             }
    2312              :         }
    2313              :     }
    2314              :     return false;
    2315              : }
    2316              : 
    2317              : void
    2318     97498558 : MSLane::executeMovements(const SUMOTime t) {
    2319              :     // multithreading: there are concurrent writes to myNeedsCollisionCheck but all of them should set it to true
    2320     97498558 :     myNeedsCollisionCheck = true;
    2321     97498558 :     MSLane* bidi = getBidiLane();
    2322     97498558 :     if (bidi != nullptr && bidi->getVehicleNumber() == 0) {
    2323       655049 :         MSNet::getInstance()->getEdgeControl().checkCollisionForInactive(bidi);
    2324              :     }
    2325     97498558 :     MSVehicle* firstNotStopped = nullptr;
    2326              :     // iterate over vehicles in reverse so that move reminders will be called in the correct order
    2327    802602248 :     for (VehCont::reverse_iterator i = myVehicles.rbegin(); i != myVehicles.rend();) {
    2328    709197496 :         MSVehicle* veh = *i;
    2329              :         // length is needed later when the vehicle may not exist anymore
    2330    709197496 :         const double length = veh->getVehicleType().getLengthWithGap();
    2331    709197496 :         const double nettoLength = veh->getVehicleType().getLength();
    2332    709197496 :         const bool moved = veh->executeMove();
    2333              :         MSLane* const target = veh->getMutableLane();
    2334    705103690 :         if (veh->hasArrived()) {
    2335              :             // vehicle has reached its arrival position
    2336              : #ifdef DEBUG_EXEC_MOVE
    2337              :             if DEBUG_COND2(veh) {
    2338              :                 std::cout << SIMTIME << " veh " << veh->getID() << " has arrived." << std::endl;
    2339              :             }
    2340              : #endif
    2341      3344447 :             veh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_ARRIVED);
    2342      3344447 :             MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(veh);
    2343    701759243 :         } else if (target != nullptr && moved) {
    2344     16972446 :             if (target->getEdge().isVaporizing()) {
    2345              :                 // vehicle has reached a vaporizing edge
    2346          756 :                 veh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_VAPORIZED_VAPORIZER);
    2347          756 :                 MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(veh);
    2348              :             } else {
    2349              :                 // vehicle has entered a new lane (leaveLane and workOnMoveReminders were already called in MSVehicle::executeMove)
    2350     16971690 :                 target->myVehBuffer.push_back(veh);
    2351     16971690 :                 MSNet::getInstance()->getEdgeControl().needsVehicleIntegration(target);
    2352     16971690 :                 if (MSGlobals::gSublane && veh->getLaneChangeModel().getShadowLane() != nullptr) {
    2353              :                     // trigger sorting of partial vehicles as their order may have changed (lane might not be active and only contain partial vehicles)
    2354        58273 :                     MSNet::getInstance()->getEdgeControl().needsVehicleIntegration(veh->getLaneChangeModel().getShadowLane());
    2355              :                 }
    2356              :             }
    2357    684786797 :         } else if (veh->isParking()) {
    2358              :             // vehicle started to park
    2359        16503 :             MSVehicleTransfer::getInstance()->add(t, veh);
    2360        16503 :             myParkingVehicles.insert(veh);
    2361    684770294 :         } else if (veh->brokeDown()) {
    2362           12 :             veh->resumeFromStopping();
    2363           36 :             WRITE_WARNINGF(TL("Removing vehicle '%' after breaking down, lane='%', time=%."),
    2364              :                            veh->getID(), veh->getLane()->getID(), time2string(t));
    2365           12 :             veh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_VAPORIZED_BREAKDOWN);
    2366           12 :             MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(veh);
    2367    684770282 :         } else if (veh->isJumping()) {
    2368              :             // vehicle jumps to next route edge
    2369          953 :             MSVehicleTransfer::getInstance()->add(t, veh);
    2370    684769329 :         } else if (veh->getPositionOnLane() > getLength()) {
    2371              :             // for any reasons the vehicle is beyond its lane...
    2372              :             // this should never happen because it is handled in MSVehicle::executeMove
    2373              :             assert(false);
    2374            0 :             WRITE_WARNINGF(TL("Teleporting vehicle '%'; beyond end of lane, target lane='%', time=%."),
    2375              :                            veh->getID(), getID(), time2string(t));
    2376            0 :             MSNet::getInstance()->getVehicleControl().countCollision(true);
    2377            0 :             MSVehicleTransfer::getInstance()->add(t, veh);
    2378              : 
    2379    684769329 :         } else if (veh->collisionStopTime() == 0) {
    2380         3438 :             veh->resumeFromStopping();
    2381         3438 :             if (getCollisionAction() == COLLISION_ACTION_REMOVE) {
    2382          531 :                 WRITE_WARNINGF(TL("Removing vehicle '%' after earlier collision, lane='%', time=%."),
    2383              :                                veh->getID(), veh->getLane()->getID(), time2string(t));
    2384          177 :                 veh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_VAPORIZED_COLLISION);
    2385          177 :                 MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(veh);
    2386         3261 :             } else if (getCollisionAction() == COLLISION_ACTION_TELEPORT) {
    2387         7473 :                 WRITE_WARNINGF(TL("Teleporting vehicle '%' after earlier collision, lane='%', time=%."),
    2388              :                                veh->getID(), veh->getLane()->getID(), time2string(t));
    2389         2491 :                 MSVehicleTransfer::getInstance()->add(t, veh);
    2390              :             } else {
    2391          770 :                 if (firstNotStopped == nullptr && !(*i)->isStopped() && (*i)->getLane() == this) {
    2392          499 :                     firstNotStopped = *i;
    2393              :                 }
    2394              :                 ++i;
    2395          770 :                 continue;
    2396              :             }
    2397              :         } else {
    2398    684765891 :             if (firstNotStopped == nullptr && !(*i)->isStopped() && (*i)->getLane() == this) {
    2399     81494553 :                 firstNotStopped = *i;
    2400              :             }
    2401              :             ++i;
    2402    684765891 :             continue;
    2403              :         }
    2404     20337029 :         myBruttoVehicleLengthSumToRemove += length;
    2405     20337029 :         myNettoVehicleLengthSumToRemove += nettoLength;
    2406              :         ++i;
    2407     20337029 :         i = VehCont::reverse_iterator(myVehicles.erase(i.base()));
    2408              :     }
    2409     93404752 :     if (firstNotStopped != nullptr) {
    2410     81495052 :         const SUMOTime ttt = firstNotStopped->getVehicleType().getParameter().getTimeToTeleport(MSGlobals::gTimeToGridlock);
    2411     81495052 :         const SUMOTime tttb = firstNotStopped->getVehicleType().getParameter().getTimeToTeleportBidi(MSGlobals::gTimeToTeleportBidi);
    2412     81495052 :         if (ttt > 0 || MSGlobals::gTimeToGridlockHighways > 0 || MSGlobals::gTimeToTeleportDisconnected >= 0 || tttb > 0 || MSGlobals::gTimeToTeleportRSDeadlock > 0) {
    2413     78473822 :             const bool wrongLane = !appropriate(firstNotStopped);
    2414     78473822 :             const bool disconnected = (MSGlobals::gTimeToTeleportDisconnected >= 0
    2415        40907 :                                        && firstNotStopped->succEdge(1) != nullptr
    2416     78510894 :                                        && firstNotStopped->getEdge()->allowedLanes(*firstNotStopped->succEdge(1), firstNotStopped->getVClass()) == nullptr);
    2417              : 
    2418     78464732 :             const bool r1 = ttt > 0 && firstNotStopped->getWaitingTime() > ttt && !disconnected
    2419              :                             // never teleport a taxi on the last edge of it's route (where it would exit the simulation)
    2420     78482076 :                             && (firstNotStopped->getDevice(typeid(MSDevice_Taxi)) == nullptr || firstNotStopped->getRoutePosition() < (firstNotStopped->getRoute().size() - 1));
    2421     78465952 :             const bool r2 = !r1 && MSGlobals::gTimeToGridlockHighways > 0
    2422         1011 :                             && firstNotStopped->getWaitingTime() > MSGlobals::gTimeToGridlockHighways
    2423          602 :                             && getSpeedLimit() > MSGlobals::gGridlockHighwaysSpeed && wrongLane
    2424          602 :                             && !disconnected;
    2425     78473810 :             const bool r3 = disconnected && firstNotStopped->getWaitingTime() > MSGlobals::gTimeToTeleportDisconnected;
    2426     78465940 :             const bool r4 = !r1 && !r2 && !r3 && tttb > 0
    2427     78474266 :                             && firstNotStopped->getWaitingTime() > tttb && getBidiLane() && !disconnected;
    2428       539918 :             const bool r5 = MSGlobals::gTimeToTeleportRSDeadlock > 0 && MSRailSignalControl::hasInstance() && !r1 && !r2 && !r3 && !r4
    2429     78965341 :                             && firstNotStopped->getWaitingTime() > MSGlobals::gTimeToTeleportRSDeadlock && MSRailSignalControl::getInstance().haveDeadlock(firstNotStopped);
    2430     78473822 :             if (r1 || r2 || r3 || r4 || r5) {
    2431         7990 :                 const std::vector<MSLink*>::const_iterator link = succLinkSec(*firstNotStopped, 1, *this, firstNotStopped->getBestLanesContinuation());
    2432         7990 :                 const bool minorLink = !wrongLane && (link != myLinks.end()) && !((*link)->havePriority());
    2433         9918 :                 std::string reason = (wrongLane ? " (wrong lane" : (minorLink ? " (yield" : " (jam"));
    2434         7990 :                 myBruttoVehicleLengthSumToRemove += firstNotStopped->getVehicleType().getLengthWithGap();
    2435         7990 :                 myNettoVehicleLengthSumToRemove += firstNotStopped->getVehicleType().getLength();
    2436         7990 :                 if (firstNotStopped == myVehicles.back()) {
    2437              :                     myVehicles.pop_back();
    2438              :                 } else {
    2439          311 :                     myVehicles.erase(std::find(myVehicles.begin(), myVehicles.end(), firstNotStopped));
    2440              :                     reason = " (blocked";
    2441              :                 }
    2442        71790 :                 WRITE_WARNINGF("Teleporting vehicle '%'; waited too long" + reason
    2443              :                                + (r2 ? ", highway" : "")
    2444              :                                + (r3 ? ", disconnected" : "")
    2445              :                                + (r4 ? ", bidi" : "")
    2446              :                                + (r5 ? ", railSignal" : "")
    2447              :                                + "), lane='%', time=%.", firstNotStopped->getID(), getID(), time2string(t));
    2448         7990 :                 if (wrongLane) {
    2449         1147 :                     MSNet::getInstance()->getVehicleControl().registerTeleportWrongLane();
    2450         6843 :                 } else if (minorLink) {
    2451         4915 :                     MSNet::getInstance()->getVehicleControl().registerTeleportYield();
    2452              :                 } else {
    2453         1928 :                     MSNet::getInstance()->getVehicleControl().registerTeleportJam();
    2454              :                 }
    2455         7990 :                 if (MSGlobals::gRemoveGridlocked) {
    2456           14 :                     firstNotStopped->onRemovalFromNet(MSMoveReminder::NOTIFICATION_TELEPORT_ARRIVED);
    2457           14 :                     MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(firstNotStopped);
    2458              :                 } else {
    2459         7976 :                     MSVehicleTransfer::getInstance()->add(t, firstNotStopped);
    2460              :                 }
    2461              :             }
    2462              :         }
    2463              :     }
    2464     93404752 :     if (MSGlobals::gSublane) {
    2465              :         // trigger sorting of vehicles as their order may have changed
    2466     17488858 :         MSNet::getInstance()->getEdgeControl().needsVehicleIntegration(this);
    2467              :     }
    2468     93404752 : }
    2469              : 
    2470              : 
    2471              : void
    2472          236 : MSLane::markRecalculateBruttoSum() {
    2473          236 :     myRecalculateBruttoSum = true;
    2474          236 : }
    2475              : 
    2476              : 
    2477              : void
    2478     97498555 : MSLane::updateLengthSum() {
    2479     97498555 :     myBruttoVehicleLengthSum -= myBruttoVehicleLengthSumToRemove;
    2480     97498555 :     myNettoVehicleLengthSum -= myNettoVehicleLengthSumToRemove;
    2481     97498555 :     myBruttoVehicleLengthSumToRemove = 0;
    2482     97498555 :     myNettoVehicleLengthSumToRemove = 0;
    2483     97498555 :     if (myVehicles.empty()) {
    2484              :         // avoid numerical instability
    2485      7805467 :         myBruttoVehicleLengthSum = 0;
    2486      7805467 :         myNettoVehicleLengthSum = 0;
    2487     89693088 :     } else if (myRecalculateBruttoSum) {
    2488          175 :         myBruttoVehicleLengthSum = 0;
    2489          646 :         for (VehCont::const_iterator i = myVehicles.begin(); i != myVehicles.end(); ++i) {
    2490          471 :             myBruttoVehicleLengthSum += (*i)->getVehicleType().getLengthWithGap();
    2491              :         }
    2492          175 :         myRecalculateBruttoSum = false;
    2493              :     }
    2494     97498555 : }
    2495              : 
    2496              : 
    2497              : void
    2498            0 : MSLane::changeLanes(const SUMOTime t) {
    2499            0 :     myEdge->changeLanes(t);
    2500            0 : }
    2501              : 
    2502              : 
    2503              : const MSEdge*
    2504      5554202 : MSLane::getNextNormal() const {
    2505      5554202 :     return myEdge->getNormalSuccessor();
    2506              : }
    2507              : 
    2508              : 
    2509              : const MSLane*
    2510       130838 : MSLane::getFirstInternalInConnection(double& offset) const {
    2511       130838 :     if (!this->isInternal()) {
    2512              :         return nullptr;
    2513              :     }
    2514       130838 :     offset = 0.;
    2515              :     const MSLane* firstInternal = this;
    2516       130838 :     MSLane* pred = getCanonicalPredecessorLane();
    2517       130886 :     while (pred != nullptr && pred->isInternal()) {
    2518              :         firstInternal = pred;
    2519           48 :         offset += pred->getLength();
    2520           48 :         pred = firstInternal->getCanonicalPredecessorLane();
    2521              :     }
    2522              :     return firstInternal;
    2523              : }
    2524              : 
    2525              : 
    2526              : // ------ Static (sic!) container methods  ------
    2527              : bool
    2528      2157015 : MSLane::dictionary(const std::string& id, MSLane* ptr) {
    2529              :     const DictType::iterator it = myDict.lower_bound(id);
    2530      2157015 :     if (it == myDict.end() || it->first != id) {
    2531              :         // id not in myDict
    2532      2157007 :         myDict.emplace_hint(it, id, ptr);
    2533      2157007 :         return true;
    2534              :     }
    2535              :     return false;
    2536              : }
    2537              : 
    2538              : 
    2539              : MSLane*
    2540      9370621 : MSLane::dictionary(const std::string& id) {
    2541              :     const DictType::iterator it = myDict.find(id);
    2542      9370621 :     if (it == myDict.end()) {
    2543              :         // id not in myDict
    2544              :         return nullptr;
    2545              :     }
    2546      9370163 :     return it->second;
    2547              : }
    2548              : 
    2549              : 
    2550              : void
    2551        42795 : MSLane::clear() {
    2552      2181293 :     for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
    2553      2138498 :         delete (*i).second;
    2554              :     }
    2555              :     myDict.clear();
    2556        42795 : }
    2557              : 
    2558              : 
    2559              : void
    2560          242 : MSLane::insertIDs(std::vector<std::string>& into) {
    2561         8196 :     for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
    2562         7954 :         into.push_back((*i).first);
    2563              :     }
    2564          242 : }
    2565              : 
    2566              : 
    2567              : template<class RTREE> void
    2568          618 : MSLane::fill(RTREE& into) {
    2569        26181 :     for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
    2570        25563 :         MSLane* l = (*i).second;
    2571        25563 :         Boundary b = l->getShape().getBoxBoundary();
    2572        25563 :         b.grow(3.);
    2573        25563 :         const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
    2574        25563 :         const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
    2575        25563 :         into.Insert(cmin, cmax, l);
    2576              :     }
    2577          618 : }
    2578              : 
    2579              : template void MSLane::fill<NamedRTree>(NamedRTree& into);
    2580              : template void MSLane::fill<LANE_RTREE_QUAL>(LANE_RTREE_QUAL& into);
    2581              : 
    2582              : // ------   ------
    2583              : bool
    2584     78473822 : MSLane::appropriate(const MSVehicle* veh) const {
    2585     78473822 :     if (veh->getLaneChangeModel().isOpposite()) {
    2586              :         return false;
    2587              :     }
    2588     78362524 :     if (myEdge->isInternal()) {
    2589              :         return true;
    2590              :     }
    2591     73072454 :     if (veh->succEdge(1) == nullptr) {
    2592              :         assert((int)veh->getBestLanes().size() > veh->getLaneIndex());
    2593     19663221 :         if (veh->getBestLanes()[veh->getLaneIndex()].bestLaneOffset == 0) {
    2594              :             return true;
    2595              :         } else {
    2596              :             return false;
    2597              :         }
    2598              :     }
    2599     53409233 :     std::vector<MSLink*>::const_iterator link = succLinkSec(*veh, 1, *this, veh->getBestLanesContinuation());
    2600              :     return (link != myLinks.end());
    2601              : }
    2602              : 
    2603              : 
    2604              : void
    2605     34518821 : MSLane::integrateNewVehicles() {
    2606     34518821 :     myNeedsCollisionCheck = true;
    2607              :     std::vector<MSVehicle*>& buffered = myVehBuffer.getContainer();
    2608     34518821 :     sort(buffered.begin(), buffered.end(), vehicle_position_sorter(this));
    2609     51490511 :     for (MSVehicle* const veh : buffered) {
    2610              :         assert(veh->getLane() == this);
    2611     16971690 :         myVehicles.insert(myVehicles.begin(), veh);
    2612     16971690 :         myBruttoVehicleLengthSum += veh->getVehicleType().getLengthWithGap();
    2613     16971690 :         myNettoVehicleLengthSum += veh->getVehicleType().getLength();
    2614              :         //if (true) std::cout << SIMTIME << " integrateNewVehicle lane=" << getID() << " veh=" << veh->getID() << " (on lane " << veh->getLane()->getID() << ") into lane=" << getID() << " myBrutto=" << myBruttoVehicleLengthSum << "\n";
    2615     16971690 :         myEdge->markDelayed();
    2616              :     }
    2617              :     buffered.clear();
    2618              :     myVehBuffer.unlock();
    2619              :     //std::cout << SIMTIME << " integrateNewVehicle lane=" << getID() << " myVehicles1=" << toString(myVehicles);
    2620     34518821 :     if (MSGlobals::gLateralResolution > 0 || myOpposite != nullptr) {
    2621     20028518 :         sort(myVehicles.begin(), myVehicles.end(), vehicle_natural_position_sorter(this));
    2622              :     }
    2623     34518821 :     sortPartialVehicles();
    2624              : #ifdef DEBUG_VEHICLE_CONTAINER
    2625              :     if (DEBUG_COND) std::cout << SIMTIME << " integrateNewVehicle lane=" << getID()
    2626              :                                   << " vehicles=" << toString(myVehicles) << " partials=" << toString(myPartialVehicles) << "\n";
    2627              : #endif
    2628     34518821 : }
    2629              : 
    2630              : 
    2631              : void
    2632    120572653 : MSLane::sortPartialVehicles() {
    2633    120572653 :     if (myPartialVehicles.size() > 1) {
    2634      1728798 :         sort(myPartialVehicles.begin(), myPartialVehicles.end(), vehicle_natural_position_sorter(this));
    2635              :     }
    2636    120572653 : }
    2637              : 
    2638              : 
    2639              : void
    2640     21018921 : MSLane::sortManeuverReservations() {
    2641     21018921 :     if (myManeuverReservations.size() > 1) {
    2642              : #ifdef DEBUG_CONTEXT
    2643              :         if (DEBUG_COND) {
    2644              :             std::cout << "sortManeuverReservations on lane " << getID()
    2645              :                       << "\nBefore sort: " << toString(myManeuverReservations) << std::endl;
    2646              :         }
    2647              : #endif
    2648        22892 :         sort(myManeuverReservations.begin(), myManeuverReservations.end(), vehicle_natural_position_sorter(this));
    2649              : #ifdef DEBUG_CONTEXT
    2650              :         if (DEBUG_COND) {
    2651              :             std::cout << "After sort: " << toString(myManeuverReservations) << std::endl;
    2652              :         }
    2653              : #endif
    2654              :     }
    2655     21018921 : }
    2656              : 
    2657              : 
    2658              : bool
    2659   7591913776 : MSLane::isInternal() const {
    2660   7591913776 :     return myEdge->isInternal();
    2661              : }
    2662              : 
    2663              : 
    2664              : bool
    2665     56373917 : MSLane::isNormal() const {
    2666     56373917 :     return myEdge->isNormal();
    2667              : }
    2668              : 
    2669              : 
    2670              : bool
    2671    101969277 : MSLane::isCrossing() const {
    2672    101969277 :     return myEdge->isCrossing();
    2673              : }
    2674              : 
    2675              : 
    2676              : bool
    2677       845820 : MSLane::isPriorityCrossing() const {
    2678       845820 :     return isCrossing() && getIncomingLanes()[0].viaLink->getOffState() == LINKSTATE_MAJOR;
    2679              : }
    2680              : 
    2681              : 
    2682              : bool
    2683    425269603 : MSLane::isWalkingArea() const {
    2684    425269603 :     return myEdge->isWalkingArea();
    2685              : }
    2686              : 
    2687              : 
    2688              : MSVehicle*
    2689   1084414498 : MSLane::getLastFullVehicle() const {
    2690   1084414498 :     if (myVehicles.size() == 0) {
    2691              :         return nullptr;
    2692              :     }
    2693   1066853175 :     return myVehicles.front();
    2694              : }
    2695              : 
    2696              : 
    2697              : MSVehicle*
    2698       276363 : MSLane::getFirstFullVehicle() const {
    2699       276363 :     if (myVehicles.size() == 0) {
    2700              :         return nullptr;
    2701              :     }
    2702       113288 :     return myVehicles.back();
    2703              : }
    2704              : 
    2705              : 
    2706              : MSVehicle*
    2707    419698410 : MSLane::getLastAnyVehicle() const {
    2708              :     // all vehicles in myVehicles should have positions smaller or equal to
    2709              :     // those in myPartialVehicles (unless we're on a bidi-lane)
    2710    419698410 :     if (myVehicles.size() > 0) {
    2711    329356276 :         if (myBidiLane != nullptr && myPartialVehicles.size() > 0) {
    2712       113035 :             if (myVehicles.front()->getPositionOnLane() > myPartialVehicles.front()->getPositionOnLane(this)) {
    2713        18356 :                 return myPartialVehicles.front();
    2714              :             }
    2715              :         }
    2716    329337920 :         return myVehicles.front();
    2717              :     }
    2718     90342134 :     if (myPartialVehicles.size() > 0) {
    2719      4945328 :         return myPartialVehicles.front();
    2720              :     }
    2721              :     return nullptr;
    2722              : }
    2723              : 
    2724              : 
    2725              : MSVehicle*
    2726       136739 : MSLane::getFirstAnyVehicle() const {
    2727              :     MSVehicle* result = nullptr;
    2728       136739 :     if (myVehicles.size() > 0) {
    2729       136739 :         result = myVehicles.back();
    2730              :     }
    2731              :     if (myPartialVehicles.size() > 0
    2732       136739 :             && (result == nullptr || result->getPositionOnLane(this) < myPartialVehicles.back()->getPositionOnLane(this))) {
    2733          146 :         result = myPartialVehicles.back();
    2734              :     }
    2735       136739 :     return result;
    2736              : }
    2737              : 
    2738              : 
    2739              : std::vector<MSLink*>::const_iterator
    2740   2045795708 : MSLane::succLinkSec(const SUMOVehicle& veh, int nRouteSuccs,
    2741              :                     const MSLane& succLinkSource, const std::vector<MSLane*>& conts) {
    2742   2045795708 :     const MSEdge* nRouteEdge = veh.succEdge(nRouteSuccs);
    2743              :     // check whether the vehicle tried to look beyond its route
    2744   2045795708 :     if (nRouteEdge == nullptr) {
    2745              :         // return end (no succeeding link) if so
    2746              :         return succLinkSource.myLinks.end();
    2747              :     }
    2748              :     // if we are on an internal lane there should only be one link and it must be allowed
    2749   1444793113 :     if (succLinkSource.isInternal()) {
    2750              :         assert(succLinkSource.myLinks.size() == 1);
    2751              :         // could have been disallowed dynamically with a rerouter or via TraCI
    2752              :         // assert(succLinkSource.myLinks[0]->getLane()->allowsVehicleClass(veh.getVehicleType().getVehicleClass()));
    2753              :         return succLinkSource.myLinks.begin();
    2754              :     }
    2755              :     // a link may be used if
    2756              :     //  1) there is a destination lane ((*link)->getLane()!=0)
    2757              :     //  2) the destination lane belongs to the next edge in route ((*link)->getLane()->myEdge == nRouteEdge)
    2758              :     //  3) the destination lane allows the vehicle's class ((*link)->getLane()->allowsVehicleClass(veh.getVehicleClass()))
    2759              : 
    2760              :     // there should be a link which leads to the next desired lane our route in "conts" (built in "getBestLanes")
    2761              :     // "conts" stores the best continuations of our current lane
    2762              :     // we should never return an arbitrary link since this may cause collisions
    2763              : 
    2764   1130115279 :     if (nRouteSuccs < (int)conts.size()) {
    2765              :         // we go through the links in our list and return the matching one
    2766   1258501334 :         for (std::vector<MSLink*>::const_iterator link = succLinkSource.myLinks.begin(); link != succLinkSource.myLinks.end(); ++link) {
    2767   1257764141 :             if ((*link)->getLane() != nullptr && (*link)->getLane()->myEdge == nRouteEdge
    2768   1124151870 :                     && (*link)->getLane()->allowsVehicleClass(veh.getVClass())
    2769   2381473360 :                     && ((*link)->getViaLane() == nullptr || (*link)->getViaLane()->allowsVehicleClass(veh.getVClass()))) {
    2770              :                 // we should use the link if it connects us to the best lane
    2771   1123709133 :                 if ((*link)->getLane() == conts[nRouteSuccs]) {
    2772   1109264248 :                     return link;
    2773              :                 }
    2774              :             }
    2775              :         }
    2776              :     } else {
    2777              :         // the source lane is a dead end (no continuations exist)
    2778              :         return succLinkSource.myLinks.end();
    2779              :     }
    2780              :     // the only case where this should happen is for a disconnected route (deliberately ignored)
    2781              : #ifdef DEBUG_NO_CONNECTION
    2782              :     // the "'" around the ids are missing intentionally in the message below because it slows messaging down, resulting in test timeouts
    2783              :     WRITE_WARNING("Could not find connection between lane " + succLinkSource.getID() + " and lane " + conts[nRouteSuccs]->getID() +
    2784              :                   " for vehicle " + veh.getID() + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
    2785              : #endif
    2786              :     return succLinkSource.myLinks.end();
    2787              : }
    2788              : 
    2789              : 
    2790              : const MSLink*
    2791    634731971 : MSLane::getLinkTo(const MSLane* const target) const {
    2792    634731971 :     const bool internal = target->isInternal();
    2793    846325983 :     for (const MSLink* const l : myLinks) {
    2794    812415596 :         if ((internal && l->getViaLane() == target) || (!internal && l->getLane() == target)) {
    2795              :             return l;
    2796              :         }
    2797              :     }
    2798              :     return nullptr;
    2799              : }
    2800              : 
    2801              : 
    2802              : const MSLane*
    2803        76991 : MSLane::getInternalFollowingLane(const MSLane* const target) const {
    2804       125975 :     for (const MSLink* const l : myLinks) {
    2805       117140 :         if (l->getLane() == target) {
    2806              :             return l->getViaLane();
    2807              :         }
    2808              :     }
    2809              :     return nullptr;
    2810              : }
    2811              : 
    2812              : 
    2813              : const MSLink*
    2814    117376515 : MSLane::getEntryLink() const {
    2815    117376515 :     if (!isInternal()) {
    2816              :         return nullptr;
    2817              :     }
    2818              :     const MSLane* internal = this;
    2819    117077529 :     const MSLane* lane = this->getCanonicalPredecessorLane();
    2820              :     assert(lane != nullptr);
    2821    118404089 :     while (lane->isInternal()) {
    2822              :         internal = lane;
    2823      1326560 :         lane = lane->getCanonicalPredecessorLane();
    2824              :         assert(lane != nullptr);
    2825              :     }
    2826    117077529 :     return lane->getLinkTo(internal);
    2827              : }
    2828              : 
    2829              : 
    2830              : void
    2831         1026 : MSLane::setMaxSpeed(const double val, const bool modified, const double jamThreshold) {
    2832         1026 :     myMaxSpeed = val;
    2833         1026 :     mySpeedModified = modified;
    2834         1026 :     myEdge->recalcCache();
    2835         1026 :     if (MSGlobals::gUseMesoSim) {
    2836          222 :         MESegment* first = MSGlobals::gMesoNet->getSegmentForEdge(*myEdge);
    2837         1266 :         while (first != nullptr) {
    2838         1044 :             first->setSpeed(val, SIMSTEP, jamThreshold, myIndex);
    2839              :             first = first->getNextSegment();
    2840              :         }
    2841              :     }
    2842         1026 : }
    2843              : 
    2844              : 
    2845              : void
    2846           85 : MSLane::setFrictionCoefficient(double val) {
    2847           85 :     myFrictionCoefficient = val;
    2848           85 :     myEdge->recalcCache();
    2849           85 : }
    2850              : 
    2851              : 
    2852              : void
    2853           15 : MSLane::setLength(double val) {
    2854           15 :     myLength = val;
    2855           15 :     myEdge->recalcCache();
    2856           15 : }
    2857              : 
    2858              : 
    2859              : void
    2860     85051588 : MSLane::swapAfterLaneChange(SUMOTime) {
    2861              :     //if (getID() == "disabled_lane") std::cout << SIMTIME << " swapAfterLaneChange lane=" << getID() << " myVehicles=" << toString(myVehicles) << " myTmpVehicles=" << toString(myTmpVehicles) << "\n";
    2862     85051588 :     myVehicles = myTmpVehicles;
    2863              :     myTmpVehicles.clear();
    2864              :     // this needs to be done after finishing lane-changing for all lanes on the
    2865              :     // current edge (MSLaneChanger::updateLanes())
    2866     85051588 :     sortPartialVehicles();
    2867     85051588 :     if (MSGlobals::gSublane && getOpposite() != nullptr) {
    2868       426084 :         getOpposite()->sortPartialVehicles();
    2869              :     }
    2870     85051588 :     if (myBidiLane != nullptr) {
    2871       576160 :         myBidiLane->sortPartialVehicles();
    2872              :     }
    2873     85051588 : }
    2874              : 
    2875              : 
    2876              : MSVehicle*
    2877        25727 : MSLane::removeVehicle(MSVehicle* remVehicle, MSMoveReminder::Notification notification, bool notify) {
    2878              :     assert(remVehicle->getLane() == this);
    2879        54890 :     for (MSLane::VehCont::iterator it = myVehicles.begin(); it < myVehicles.end(); it++) {
    2880        54874 :         if (remVehicle == *it) {
    2881        25711 :             if (notify) {
    2882        17565 :                 remVehicle->leaveLane(notification);
    2883              :             }
    2884        25711 :             myVehicles.erase(it);
    2885        25711 :             myBruttoVehicleLengthSum -= remVehicle->getVehicleType().getLengthWithGap();
    2886        25711 :             myNettoVehicleLengthSum -= remVehicle->getVehicleType().getLength();
    2887        25711 :             break;
    2888              :         }
    2889              :     }
    2890        25727 :     return remVehicle;
    2891              : }
    2892              : 
    2893              : 
    2894              : MSLane*
    2895     84322663 : MSLane::getParallelLane(int offset, bool includeOpposite) const {
    2896     84322663 :     return myEdge->parallelLane(this, offset, includeOpposite);
    2897              : }
    2898              : 
    2899              : 
    2900              : void
    2901      2967056 : MSLane::addIncomingLane(MSLane* lane, MSLink* viaLink) {
    2902              :     IncomingLaneInfo ili;
    2903      2967056 :     ili.lane = lane;
    2904      2967056 :     ili.viaLink = viaLink;
    2905      2967056 :     ili.length = lane->getLength();
    2906      2967056 :     myIncomingLanes.push_back(ili);
    2907      2967056 : }
    2908              : 
    2909              : 
    2910              : void
    2911      2967056 : MSLane::addApproachingLane(MSLane* lane, bool warnMultiCon) {
    2912      2967056 :     MSEdge* approachingEdge = &lane->getEdge();
    2913      2967056 :     if (myApproachingLanes.find(approachingEdge) == myApproachingLanes.end()) {
    2914      2935431 :         myApproachingLanes[approachingEdge] = std::vector<MSLane*>();
    2915        31625 :     } else if (!approachingEdge->isInternal() && warnMultiCon) {
    2916              :         // whenever a normal edge connects twice, there is a corresponding
    2917              :         // internal edge wich connects twice, one warning is sufficient
    2918           18 :         WRITE_WARNINGF(TL("Lane '%' is approached multiple times from edge '%'. This may cause collisions."),
    2919              :                        getID(), approachingEdge->getID());
    2920              :     }
    2921      2967056 :     myApproachingLanes[approachingEdge].push_back(lane);
    2922      2967056 : }
    2923              : 
    2924              : 
    2925              : bool
    2926    102510033 : MSLane::isApproachedFrom(MSLane* const lane, SUMOVehicleClass svc) {
    2927    150843947 :     for (MSLink* link : lane->getLinkCont()) {
    2928    115014155 :         if (link->getLane() == this && (link->getPermissions() & svc) == svc) {
    2929              :             return true;
    2930              :         }
    2931              :     }
    2932              :     return false;
    2933              : }
    2934              : 
    2935              : 
    2936      3353196 : double MSLane::getMissingRearGap(const MSVehicle* leader, double backOffset, double leaderSpeed) const {
    2937              :     // this follows the same logic as getFollowerOnConsecutive. we do a tree
    2938              :     // search and check for the vehicle with the largest missing rear gap within
    2939              :     // relevant range
    2940              :     double result = 0;
    2941              :     const double leaderDecel = leader->getCarFollowModel().getMaxDecel();
    2942      3353196 :     CLeaderDist followerInfo = getFollowersOnConsecutive(leader, backOffset, false)[0];
    2943      3353196 :     const MSVehicle* v = followerInfo.first;
    2944      3353196 :     if (v != nullptr) {
    2945         2991 :         result = v->getCarFollowModel().getSecureGap(v, leader, v->getSpeed(), leaderSpeed, leaderDecel) - followerInfo.second;
    2946              :     }
    2947      3353196 :     return result;
    2948              : }
    2949              : 
    2950              : 
    2951              : double
    2952    366509511 : MSLane::getMaximumBrakeDist() const {
    2953    366509511 :     const MSVehicleControl& vc = MSNet::getInstance()->getVehicleControl();
    2954    366509511 :     const double maxSpeed = getSpeedLimit() * vc.getMaxSpeedFactor();
    2955              :     // NOTE: For the euler update this is an upper bound on the actual braking distance (see ticket #860)
    2956              :     // impose a hard bound due to visibility / common sense to avoid unnecessary computation if there are strange vehicles in the fleet
    2957    366509511 :     const double minDecel = isRailway(myPermissions) ? vc.getMinDecelerationRail() : vc.getMinDeceleration();
    2958    366509511 :     return MIN2(maxSpeed * maxSpeed * 0.5 / minDecel + vc.getMaxMinGap(),
    2959    366509511 :                 myPermissions == SVC_SHIP ? 10000.0 : 1000.0);
    2960              : }
    2961              : 
    2962              : 
    2963              : std::pair<MSVehicle* const, double>
    2964     39885492 : MSLane::getLeader(const MSVehicle* veh, const double vehPos, const std::vector<MSLane*>& bestLaneConts, double dist, bool checkTmpVehicles) const {
    2965              :     // get the leading vehicle for (shadow) veh
    2966              :     // XXX this only works as long as all lanes of an edge have equal length
    2967              : #ifdef DEBUG_CONTEXT
    2968              :     if (DEBUG_COND2(veh)) {
    2969              :         std::cout << "   getLeader lane=" << getID() << " ego=" << veh->getID() << " vehs=" << toString(myVehicles) << " tmpVehs=" << toString(myTmpVehicles) << "\n";
    2970              :     }
    2971              : #endif
    2972     39885492 :     if (checkTmpVehicles) {
    2973    242423019 :         for (VehCont::const_iterator last = myTmpVehicles.begin(); last != myTmpVehicles.end(); ++last) {
    2974              :             // XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
    2975    240070012 :             MSVehicle* pred = (MSVehicle*)*last;
    2976    240070012 :             if (pred == veh) {
    2977              :                 continue;
    2978              :             }
    2979              : #ifdef DEBUG_CONTEXT
    2980              :             if (DEBUG_COND2(veh)) {
    2981              :                 std::cout << std::setprecision(gPrecision) << "   getLeader lane=" << getID() << " ego=" << veh->getID() << " egoPos=" << vehPos << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane() << "\n";
    2982              :             }
    2983              : #endif
    2984    205064698 :             if (pred->getPositionOnLane() >= vehPos) {
    2985     32716834 :                 return std::pair<MSVehicle* const, double>(pred, pred->getBackPositionOnLane(this) - veh->getVehicleType().getMinGap() - vehPos);
    2986              :             }
    2987              :         }
    2988              :     } else {
    2989     47090869 :         for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
    2990              :             // XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
    2991     51027991 :             MSVehicle* pred = (MSVehicle*)*last;
    2992     51027991 :             if (pred == veh) {
    2993      3783226 :                 continue;
    2994              :             }
    2995              : #ifdef DEBUG_CONTEXT
    2996              :             if (DEBUG_COND2(veh)) {
    2997              :                 std::cout << "   getLeader lane=" << getID() << " ego=" << veh->getID() << " egoPos=" << vehPos
    2998              :                           << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane(this) << " predBack=" << pred->getBackPositionOnLane(this) << "\n";
    2999              :             }
    3000              : #endif
    3001     47244765 :             if (pred->getPositionOnLane(this) >= vehPos) {
    3002      4053918 :                 if (MSGlobals::gLaneChangeDuration > 0
    3003       332915 :                         && pred->getLaneChangeModel().isOpposite()
    3004        89310 :                         && !pred->getLaneChangeModel().isChangingLanes()
    3005      4066735 :                         && pred->getLaneChangeModel().getShadowLane() == this) {
    3006              :                     // skip non-overlapping shadow
    3007        58398 :                     continue;
    3008              :                 }
    3009      3937122 :                 return std::pair<MSVehicle* const, double>(pred, pred->getBackPositionOnLane(this) - veh->getVehicleType().getMinGap() - vehPos);
    3010              :             }
    3011              :         }
    3012              :     }
    3013              :     // XXX from here on the code mirrors MSLaneChanger::getRealLeader
    3014      3231536 :     if (bestLaneConts.size() > 0) {
    3015      2895730 :         double seen = getLength() - vehPos;
    3016      2895730 :         double speed = veh->getSpeed();
    3017      2895730 :         if (dist < 0) {
    3018        32827 :             dist = veh->getCarFollowModel().brakeGap(speed) + veh->getVehicleType().getMinGap();
    3019              :         }
    3020              : #ifdef DEBUG_CONTEXT
    3021              :         if (DEBUG_COND2(veh)) {
    3022              :             std::cout << "   getLeader lane=" << getID() << " seen=" << seen << " dist=" << dist << "\n";
    3023              :         }
    3024              : #endif
    3025      2895730 :         if (seen > dist) {
    3026      1110691 :             return std::pair<MSVehicle* const, double>(static_cast<MSVehicle*>(nullptr), -1);
    3027              :         }
    3028      1785039 :         return getLeaderOnConsecutive(dist, seen, speed, *veh, bestLaneConts);
    3029              :     } else {
    3030       335806 :         return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
    3031              :     }
    3032              : }
    3033              : 
    3034              : 
    3035              : std::pair<MSVehicle* const, double>
    3036     39351868 : MSLane::getLeaderOnConsecutive(double dist, double seen, double speed, const MSVehicle& veh,
    3037              :                                const std::vector<MSLane*>& bestLaneConts, bool considerCrossingFoes) const {
    3038              : #ifdef DEBUG_CONTEXT
    3039              :     if (DEBUG_COND2(&veh)) {
    3040              :         std::cout << "   getLeaderOnConsecutive lane=" << getID() << " ego=" << veh.getID() << " seen=" << seen << " dist=" << dist << " conts=" << toString(bestLaneConts) << "\n";
    3041              :     }
    3042              : #endif
    3043     39351868 :     if (seen > dist && !isInternal()) {
    3044       122955 :         return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
    3045              :     }
    3046              :     int view = 1;
    3047              :     // loop over following lanes
    3048     39228913 :     if (myPartialVehicles.size() > 0) {
    3049              :         // XXX
    3050      1132410 :         MSVehicle* pred = myPartialVehicles.front();
    3051      1132410 :         const double gap = seen - (getLength() - pred->getBackPositionOnLane(this)) - veh.getVehicleType().getMinGap();
    3052              : #ifdef DEBUG_CONTEXT
    3053              :         if (DEBUG_COND2(&veh)) {
    3054              :             std::cout << "    predGap=" << gap << " partials=" << toString(myPartialVehicles) << "\n";
    3055              :         }
    3056              : #endif
    3057              :         // make sure pred is really a leader and not doing continous lane-changing behind ego
    3058      1132410 :         if (gap > 0) {
    3059       766641 :             return std::pair<MSVehicle* const, double>(pred, gap);
    3060              :         }
    3061              :     }
    3062              : #ifdef DEBUG_CONTEXT
    3063              :     if (DEBUG_COND2(&veh)) {
    3064              :         gDebugFlag1 = true;
    3065              :     }
    3066              : #endif
    3067              :     const MSLane* nextLane = this;
    3068              :     do {
    3069     55104061 :         nextLane->getVehiclesSecure(); // lock against running sim when called from GUI for time gap coloring
    3070              :         // get the next link used
    3071     55104061 :         std::vector<MSLink*>::const_iterator link = succLinkSec(veh, view, *nextLane, bestLaneConts);
    3072     55104061 :         if (nextLane->isLinkEnd(link) && view < veh.getRoute().size() - veh.getRoutePosition()) {
    3073      5192501 :             const MSEdge* nextEdge = *(veh.getCurrentRouteEdge() + view);
    3074      5192501 :             if (nextEdge->getNumLanes() == 1) {
    3075              :                 // lanes are unambiguous on the next route edge, continue beyond bestLaneConts
    3076      5624633 :                 for (link = nextLane->getLinkCont().begin(); link < nextLane->getLinkCont().end(); link++) {
    3077      3493454 :                     if ((*link)->getLane() == nextEdge->getLanes().front()) {
    3078              :                         break;
    3079              :                     }
    3080              :                 }
    3081              :             }
    3082              :         }
    3083     55104061 :         if (nextLane->isLinkEnd(link)) {
    3084              : #ifdef DEBUG_CONTEXT
    3085              :             if (DEBUG_COND2(&veh)) {
    3086              :                 std::cout << "    cannot continue after nextLane=" << nextLane->getID() << "\n";
    3087              :             }
    3088              : #endif
    3089     14730710 :             nextLane->releaseVehicles();
    3090     14730710 :             break;
    3091              :         }
    3092              :         // check for link leaders
    3093     40373351 :         const bool laneChanging = veh.getLane() != this;
    3094     40373351 :         const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(&veh, seen);
    3095     40373351 :         nextLane->releaseVehicles();
    3096     40373351 :         if (linkLeaders.size() > 0) {
    3097              :             std::pair<MSVehicle*, double> result;
    3098              :             double shortestGap = std::numeric_limits<double>::max();
    3099      2345474 :             for (auto ll : linkLeaders) {
    3100              :                 double gap = ll.vehAndGap.second;
    3101              :                 MSVehicle* lVeh = ll.vehAndGap.first;
    3102      1293657 :                 if (lVeh != nullptr) {
    3103              :                     // leader is a vehicle, not a pedestrian
    3104      1197877 :                     gap += lVeh->getCarFollowModel().brakeGap(lVeh->getSpeed(), lVeh->getCarFollowModel().getMaxDecel(), 0);
    3105              :                 }
    3106              : #ifdef DEBUG_CONTEXT
    3107              :                 if (DEBUG_COND2(&veh)) {
    3108              :                     std::cout << "      linkLeader candidate " << Named::getIDSecure(lVeh)
    3109              :                               << " isLeader=" << veh.isLeader(*link, lVeh, ll.vehAndGap.second)
    3110              :                               << " gap=" << ll.vehAndGap.second
    3111              :                               << " gap+brakeing=" << gap
    3112              :                               << "\n";
    3113              :                 }
    3114              : #endif
    3115              :                 // skip vehicles which do not share the outgoing edge (to get only real leader vehicles in TraCI #13842)
    3116      1293657 :                 if (!considerCrossingFoes && !ll.sameTarget()) {
    3117           35 :                     continue;
    3118              :                 }
    3119              :                 // in the context of lane-changing, all candidates are leaders
    3120      1293622 :                 if (lVeh != nullptr && !laneChanging && !veh.isLeader(*link, lVeh, ll.vehAndGap.second)) {
    3121        11257 :                     continue;
    3122              :                 }
    3123      1282365 :                 if (gap < shortestGap) {
    3124              :                     shortestGap = gap;
    3125      1094091 :                     if (ll.vehAndGap.second < 0 && !MSGlobals::gComputeLC) {
    3126              :                         // can always continue up to the stop line or crossing point
    3127              :                         // @todo: figure out whether this should also impact lane changing
    3128        74275 :                         ll.vehAndGap.second = MAX2(seen - nextLane->getLength(), ll.distToCrossing);
    3129              :                     }
    3130              :                     result = ll.vehAndGap;
    3131              :                 }
    3132              :             }
    3133      1051817 :             if (shortestGap != std::numeric_limits<double>::max()) {
    3134              : #ifdef DEBUG_CONTEXT
    3135              :                 if (DEBUG_COND2(&veh)) {
    3136              :                     std::cout << "    found linkLeader after nextLane=" << nextLane->getID() << "\n";
    3137              :                     gDebugFlag1 = false;
    3138              :                 }
    3139              : #endif
    3140      1042492 :                 return result;
    3141              :             }
    3142              :         }
    3143     39330859 :         bool nextInternal = (*link)->getViaLane() != nullptr;
    3144              :         nextLane = (*link)->getViaLaneOrLane();
    3145     19491702 :         if (nextLane == nullptr) {
    3146              :             break;
    3147              :         }
    3148     39330859 :         nextLane->getVehiclesSecure(); // lock against running sim when called from GUI for time gap coloring
    3149     39330859 :         MSVehicle* leader = nextLane->getLastAnyVehicle();
    3150     39330859 :         if (leader != nullptr) {
    3151              : #ifdef DEBUG_CONTEXT
    3152              :             if (DEBUG_COND2(&veh)) {
    3153              :                 std::cout << "    found leader " << leader->getID() << " on nextLane=" << nextLane->getID() << "\n";
    3154              :             }
    3155              : #endif
    3156     15391111 :             const double leaderDist = seen + leader->getBackPositionOnLane(nextLane) - veh.getVehicleType().getMinGap();
    3157     15391111 :             nextLane->releaseVehicles();
    3158     15391111 :             return std::make_pair(leader, leaderDist);
    3159              :         }
    3160     23939748 :         nextLane->releaseVehicles();
    3161     23939748 :         if (nextLane->getVehicleMaxSpeed(&veh) < speed) {
    3162      2359900 :             dist = veh.getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(&veh));
    3163              :         }
    3164     23939748 :         seen += nextLane->getLength();
    3165     23939748 :         if (!nextInternal) {
    3166      8063715 :             view++;
    3167              :         }
    3168     57015140 :     } while (seen <= dist || nextLane->isInternal());
    3169              : #ifdef DEBUG_CONTEXT
    3170              :     gDebugFlag1 = false;
    3171              : #endif
    3172     22028669 :     return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
    3173              : }
    3174              : 
    3175              : 
    3176              : std::pair<MSVehicle* const, double>
    3177       103997 : MSLane::getCriticalLeader(double dist, double seen, double speed, const MSVehicle& veh) const {
    3178              : #ifdef DEBUG_CONTEXT
    3179              :     if (DEBUG_COND2(&veh)) {
    3180              :         std::cout << SIMTIME << " getCriticalLeader. lane=" << getID() << " veh=" << veh.getID() << "\n";
    3181              :     }
    3182              : #endif
    3183       103997 :     const std::vector<MSLane*>& bestLaneConts = veh.getBestLanesContinuation(this);
    3184              :     std::pair<MSVehicle*, double> result = std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
    3185              :     double safeSpeed = std::numeric_limits<double>::max();
    3186              :     int view = 1;
    3187              :     // loop over following lanes
    3188              :     // @note: we don't check the partial occupator for this lane since it was
    3189              :     // already checked in MSLaneChanger::getRealLeader()
    3190              :     const MSLane* nextLane = this;
    3191       207994 :     SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / MAX2(speed, NUMERICAL_EPS));
    3192              :     do {
    3193              :         // get the next link used
    3194       187841 :         std::vector<MSLink*>::const_iterator link = succLinkSec(veh, view, *nextLane, bestLaneConts);
    3195       184966 :         if (nextLane->isLinkEnd(link) || !(*link)->opened(arrivalTime, speed, speed, veh.getVehicleType().getLength(),
    3196       367838 :                 veh.getImpatience(), veh.getCarFollowModel().getMaxDecel(), 0, veh.getLateralPositionOnLane(), nullptr, false, &veh) || (*link)->haveRed()) {
    3197         7844 :             return result;
    3198              :         }
    3199              :         // check for link leaders
    3200              : #ifdef DEBUG_CONTEXT
    3201              :         if (DEBUG_COND2(&veh)) {
    3202              :             gDebugFlag1 = true;    // See MSLink::getLeaderInfo
    3203              :         }
    3204              : #endif
    3205       179997 :         const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(&veh, seen);
    3206              : #ifdef DEBUG_CONTEXT
    3207              :         if (DEBUG_COND2(&veh)) {
    3208              :             gDebugFlag1 = false;    // See MSLink::getLeaderInfo
    3209              :         }
    3210              : #endif
    3211       197783 :         for (MSLink::LinkLeaders::const_iterator it = linkLeaders.begin(); it != linkLeaders.end(); ++it) {
    3212        17786 :             const MSVehicle* leader = (*it).vehAndGap.first;
    3213        17786 :             if (leader != nullptr && leader != result.first) {
    3214              :                 // XXX ignoring pedestrians here!
    3215              :                 // XXX ignoring the fact that the link leader may alread by following us
    3216              :                 // XXX ignoring the fact that we may drive up to the crossing point
    3217        17701 :                 double tmpSpeed = safeSpeed;
    3218        17701 :                 veh.adaptToJunctionLeader((*it).vehAndGap, seen, nullptr, nextLane, tmpSpeed, tmpSpeed, (*it).distToCrossing);
    3219              : #ifdef DEBUG_CONTEXT
    3220              :                 if (DEBUG_COND2(&veh)) {
    3221              :                     std::cout << "    linkLeader=" << leader->getID() << " gap=" << result.second << " tmpSpeed=" << tmpSpeed << " safeSpeed=" << safeSpeed << "\n";
    3222              :                 }
    3223              : #endif
    3224        17701 :                 if (tmpSpeed < safeSpeed) {
    3225              :                     safeSpeed = tmpSpeed;
    3226              :                     result = (*it).vehAndGap;
    3227              :                 }
    3228              :             }
    3229              :         }
    3230       179997 :         bool nextInternal = (*link)->getViaLane() != nullptr;
    3231              :         nextLane = (*link)->getViaLaneOrLane();
    3232       100055 :         if (nextLane == nullptr) {
    3233              :             break;
    3234              :         }
    3235       179997 :         MSVehicle* leader = nextLane->getLastAnyVehicle();
    3236       179997 :         if (leader != nullptr && leader != result.first) {
    3237       101083 :             const double gap = seen + leader->getBackPositionOnLane(nextLane) - veh.getVehicleType().getMinGap();
    3238       101083 :             const double tmpSpeed = veh.getCarFollowModel().insertionFollowSpeed(&veh, speed, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), leader);
    3239       101083 :             if (tmpSpeed < safeSpeed) {
    3240              :                 safeSpeed = tmpSpeed;
    3241              :                 result = std::make_pair(leader, gap);
    3242              :             }
    3243              :         }
    3244       179997 :         if (nextLane->getVehicleMaxSpeed(&veh) < speed) {
    3245        27968 :             dist = veh.getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(&veh));
    3246              :         }
    3247       179997 :         seen += nextLane->getLength();
    3248       179997 :         if (seen <= dist) {
    3249              :             // delaying the update of arrivalTime and making it conditional to avoid possible integer overflows
    3250        37732 :             arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
    3251              :         }
    3252       179997 :         if (!nextInternal) {
    3253       100055 :             view++;
    3254              :         }
    3255       263841 :     } while (seen <= dist || nextLane->isInternal());
    3256        96153 :     return result;
    3257              : }
    3258              : 
    3259              : 
    3260              : MSLane*
    3261   1434783950 : MSLane::getLogicalPredecessorLane() const {
    3262   1434783950 :     if (myLogicalPredecessorLane == nullptr) {
    3263      5467186 :         MSEdgeVector pred = myEdge->getPredecessors();
    3264              :         // get only those edges which connect to this lane
    3265     10981890 :         for (MSEdgeVector::iterator i = pred.begin(); i != pred.end();) {
    3266      5514704 :             std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(*i));
    3267      5514704 :             if (j == myIncomingLanes.end()) {
    3268              :                 i = pred.erase(i);
    3269              :             } else {
    3270              :                 ++i;
    3271              :             }
    3272              :         }
    3273              :         // get the lane with the "straightest" connection
    3274      5467186 :         if (pred.size() != 0) {
    3275      2135722 :             std::sort(pred.begin(), pred.end(), by_connections_to_sorter(&getEdge()));
    3276      1067861 :             MSEdge* best = *pred.begin();
    3277      1067861 :             std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(best));
    3278      1067861 :             myLogicalPredecessorLane = j->lane;
    3279              :         }
    3280      5467186 :     }
    3281   1434783950 :     return myLogicalPredecessorLane;
    3282              : }
    3283              : 
    3284              : 
    3285              : const MSLane*
    3286   1117344838 : MSLane::getNormalPredecessorLane() const {
    3287   2276655419 :     if (isInternal()) {
    3288   1159310581 :         return getLogicalPredecessorLane()->getNormalPredecessorLane();
    3289              :     } else {
    3290              :         return this;
    3291              :     }
    3292              : }
    3293              : 
    3294              : 
    3295              : const MSLane*
    3296    125851456 : MSLane::getNormalSuccessorLane() const {
    3297    131271972 :     if (isInternal()) {
    3298      5420516 :         return getCanonicalSuccessorLane()->getNormalSuccessorLane();
    3299              :     } else {
    3300              :         return this;
    3301              :     }
    3302              : }
    3303              : 
    3304              : 
    3305              : MSLane*
    3306        84359 : MSLane::getLogicalPredecessorLane(const MSEdge& fromEdge) const {
    3307       147949 :     for (const IncomingLaneInfo& cand : myIncomingLanes) {
    3308        99786 :         if (&(cand.lane->getEdge()) == &fromEdge) {
    3309              :             return cand.lane;
    3310              :         }
    3311              :     }
    3312              :     return nullptr;
    3313              : }
    3314              : 
    3315              : 
    3316              : MSLane*
    3317    120185910 : MSLane::getCanonicalPredecessorLane() const {
    3318    120185910 :     if (myCanonicalPredecessorLane != nullptr) {
    3319              :         return myCanonicalPredecessorLane;
    3320              :     }
    3321      1032966 :     if (myIncomingLanes.empty()) {
    3322              :         return nullptr;
    3323              :     }
    3324              :     // myCanonicalPredecessorLane has not yet been determined and there exist incoming lanes
    3325              :     // get the lane with the priorized (or if this does not apply the "straightest") connection
    3326      1032634 :     const auto bestLane = std::min_element(myIncomingLanes.begin(), myIncomingLanes.end(), incoming_lane_priority_sorter(this));
    3327              :     {
    3328              : #ifdef HAVE_FOX
    3329      1032634 :         ScopedLocker<> lock(myLeaderInfoMutex, MSGlobals::gNumSimThreads > 1);
    3330              : #endif
    3331      1032634 :         myCanonicalPredecessorLane = bestLane->lane;
    3332              :     }
    3333              : #ifdef DEBUG_LANE_SORTER
    3334              :     std::cout << "\nBest predecessor lane for lane '" << myID << "': '" << myCanonicalPredecessorLane->getID() << "'" << std::endl;
    3335              : #endif
    3336      1032634 :     return myCanonicalPredecessorLane;
    3337              : }
    3338              : 
    3339              : 
    3340              : MSLane*
    3341      7774702 : MSLane::getCanonicalSuccessorLane() const {
    3342      7774702 :     if (myCanonicalSuccessorLane != nullptr) {
    3343              :         return myCanonicalSuccessorLane;
    3344              :     }
    3345        74539 :     if (myLinks.empty()) {
    3346              :         return nullptr;
    3347              :     }
    3348              :     // myCanonicalSuccessorLane has not yet been determined and there exist outgoing links
    3349        14014 :     std::vector<MSLink*> candidateLinks = myLinks;
    3350              :     // get the lane with the priorized (or if this does not apply the "straightest") connection
    3351        28028 :     std::sort(candidateLinks.begin(), candidateLinks.end(), outgoing_lane_priority_sorter(this));
    3352        14014 :     MSLane* best = (*candidateLinks.begin())->getViaLaneOrLane();
    3353              : #ifdef DEBUG_LANE_SORTER
    3354              :     std::cout << "\nBest successor lane for lane '" << myID << "': '" << best->getID() << "'" << std::endl;
    3355              : #endif
    3356        14014 :     myCanonicalSuccessorLane = best;
    3357              :     return myCanonicalSuccessorLane;
    3358        14014 : }
    3359              : 
    3360              : 
    3361              : LinkState
    3362      4736094 : MSLane::getIncomingLinkState() const {
    3363      4736094 :     const MSLane* const pred = getLogicalPredecessorLane();
    3364      4736094 :     if (pred == nullptr) {
    3365              :         return LINKSTATE_DEADEND;
    3366              :     } else {
    3367      4736094 :         return pred->getLinkTo(this)->getState();
    3368              :     }
    3369              : }
    3370              : 
    3371              : 
    3372              : const std::vector<std::pair<const MSLane*, const MSEdge*> >
    3373       284703 : MSLane::getOutgoingViaLanes() const {
    3374              :     std::vector<std::pair<const MSLane*, const MSEdge*> > result;
    3375       641036 :     for (const MSLink* link : myLinks) {
    3376              :         assert(link->getLane() != nullptr);
    3377       712666 :         result.push_back(std::make_pair(link->getLane(), link->getViaLane() == nullptr ? nullptr : &link->getViaLane()->getEdge()));
    3378              :     }
    3379       284703 :     return result;
    3380            0 : }
    3381              : 
    3382              : std::vector<const MSLane*>
    3383           76 : MSLane::getNormalIncomingLanes() const {
    3384           76 :     std::vector<const MSLane*> result = {};
    3385          226 :     for (std::map<MSEdge*, std::vector<MSLane*> >::const_iterator it = myApproachingLanes.begin(); it != myApproachingLanes.end(); ++it) {
    3386          328 :         for (std::vector<MSLane*>::const_iterator it_lane = (*it).second.begin(); it_lane != (*it).second.end(); ++it_lane) {
    3387          178 :             if (!((*it_lane)->isInternal())) {
    3388          146 :                 result.push_back(*it_lane);
    3389              :             }
    3390              :         }
    3391              :     }
    3392           76 :     return result;
    3393            0 : }
    3394              : 
    3395              : 
    3396              : void
    3397      1137238 : MSLane::leftByLaneChange(MSVehicle* v) {
    3398      1137238 :     myBruttoVehicleLengthSum -= v->getVehicleType().getLengthWithGap();
    3399      1137238 :     myNettoVehicleLengthSum -= v->getVehicleType().getLength();
    3400      1137238 : }
    3401              : 
    3402              : 
    3403              : void
    3404      1093115 : MSLane::enteredByLaneChange(MSVehicle* v) {
    3405      1093115 :     myBruttoVehicleLengthSum += v->getVehicleType().getLengthWithGap();
    3406      1093115 :     myNettoVehicleLengthSum += v->getVehicleType().getLength();
    3407      1093115 : }
    3408              : 
    3409              : 
    3410              : int
    3411            0 : MSLane::getCrossingIndex() const {
    3412            0 :     for (std::vector<MSLink*>::const_iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
    3413            0 :         if ((*i)->getLane()->isCrossing()) {
    3414            0 :             return (int)(i - myLinks.begin());
    3415              :         }
    3416              :     }
    3417              :     return -1;
    3418              : }
    3419              : 
    3420              : // ------------ Current state retrieval
    3421              : double
    3422   2090367082 : MSLane::getFractionalVehicleLength(bool brutto) const {
    3423              :     double sum = 0;
    3424   2090367082 :     if (myPartialVehicles.size() > 0) {
    3425    405698524 :         const MSLane* bidi = getBidiLane();
    3426    827780761 :         for (MSVehicle* cand : myPartialVehicles) {
    3427    422082237 :             if (MSGlobals::gSublane && cand->getLaneChangeModel().getShadowLane() == this) {
    3428     23751147 :                 continue;
    3429              :             }
    3430    398331090 :             if (cand->getLane() == bidi) {
    3431       207846 :                 sum += (brutto ? cand->getVehicleType().getLengthWithGap() : cand->getVehicleType().getLength());
    3432              :             } else {
    3433    398227167 :                 sum += myLength - cand->getBackPositionOnLane(this);
    3434              :             }
    3435              :         }
    3436              :     }
    3437   2090367082 :     return sum;
    3438              : }
    3439              : 
    3440              : double
    3441   2090310362 : MSLane::getBruttoOccupancy() const {
    3442   2090310362 :     getVehiclesSecure();
    3443   2090310362 :     double fractions = getFractionalVehicleLength(true);
    3444   2090310362 :     if (myVehicles.size() != 0) {
    3445   1548408788 :         MSVehicle* lastVeh = myVehicles.front();
    3446   1548408788 :         if (lastVeh->getPositionOnLane() < lastVeh->getVehicleType().getLength()) {
    3447     48960173 :             fractions -= (lastVeh->getVehicleType().getLength() - lastVeh->getPositionOnLane());
    3448              :         }
    3449              :     }
    3450   2090310362 :     releaseVehicles();
    3451   2090310362 :     return MIN2(1., (myBruttoVehicleLengthSum + fractions) / myLength);
    3452              : }
    3453              : 
    3454              : 
    3455              : double
    3456        56720 : MSLane::getNettoOccupancy() const {
    3457        56720 :     getVehiclesSecure();
    3458        56720 :     double fractions = getFractionalVehicleLength(false);
    3459        56720 :     if (myVehicles.size() != 0) {
    3460          504 :         MSVehicle* lastVeh = myVehicles.front();
    3461          504 :         if (lastVeh->getPositionOnLane() < lastVeh->getVehicleType().getLength()) {
    3462            4 :             fractions -= (lastVeh->getVehicleType().getLength() - lastVeh->getPositionOnLane());
    3463              :         }
    3464              :     }
    3465        56720 :     releaseVehicles();
    3466        56720 :     return (myNettoVehicleLengthSum + fractions) / myLength;
    3467              : }
    3468              : 
    3469              : 
    3470              : double
    3471           46 : MSLane::getWaitingSeconds() const {
    3472           46 :     if (myVehicles.size() == 0) {
    3473              :         return 0;
    3474              :     }
    3475              :     double wtime = 0;
    3476           48 :     for (VehCont::const_iterator i = myVehicles.begin(); i != myVehicles.end(); ++i) {
    3477           24 :         wtime += (*i)->getWaitingSeconds();
    3478              :     }
    3479              :     return wtime;
    3480              : }
    3481              : 
    3482              : 
    3483              : double
    3484    167769044 : MSLane::getMeanSpeed() const {
    3485    167769044 :     if (myVehicles.size() == 0) {
    3486    138760647 :         return myMaxSpeed;
    3487              :     }
    3488              :     double v = 0;
    3489              :     int numVehs = 0;
    3490    174885889 :     for (const MSVehicle* const veh : getVehiclesSecure()) {
    3491    145877492 :         if (!veh->isStopped() || !myEdge->hasLaneChanger()) {
    3492    145366055 :             v += veh->getSpeed();
    3493    145366055 :             numVehs++;
    3494              :         }
    3495              :     }
    3496     29008397 :     releaseVehicles();
    3497     29008397 :     if (numVehs == 0) {
    3498       246209 :         return myMaxSpeed;
    3499              :     }
    3500     28762188 :     return v / numVehs;
    3501              : }
    3502              : 
    3503              : 
    3504              : double
    3505         2095 : MSLane::getMeanSpeedBike() const {
    3506              :     // @note: redundant code with getMeanSpeed to avoid extra checks in a function that is called very often
    3507         2095 :     if (myVehicles.size() == 0) {
    3508         1480 :         return myMaxSpeed;
    3509              :     }
    3510              :     double v = 0;
    3511              :     int numBikes = 0;
    3512         2260 :     for (MSVehicle* veh : getVehiclesSecure()) {
    3513         1645 :         if (veh->getVClass() == SVC_BICYCLE) {
    3514         1150 :             v += veh->getSpeed();
    3515         1150 :             numBikes++;
    3516              :         }
    3517              :     }
    3518              :     double ret;
    3519          615 :     if (numBikes > 0) {
    3520          335 :         ret = v / (double) myVehicles.size();
    3521              :     } else {
    3522          280 :         ret = myMaxSpeed;
    3523              :     }
    3524          615 :     releaseVehicles();
    3525          615 :     return ret;
    3526              : }
    3527              : 
    3528              : 
    3529              : double
    3530        56723 : MSLane::getHarmonoise_NoiseEmissions() const {
    3531              :     double ret = 0;
    3532        56723 :     const MSLane::VehCont& vehs = getVehiclesSecure();
    3533        56723 :     if (vehs.size() == 0) {
    3534        56223 :         releaseVehicles();
    3535        56223 :         return 0;
    3536              :     }
    3537         1216 :     for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
    3538          716 :         double sv = (*i)->getHarmonoise_NoiseEmissions();
    3539          716 :         ret += (double) pow(10., (sv / 10.));
    3540              :     }
    3541          500 :     releaseVehicles();
    3542          500 :     return HelpersHarmonoise::sum(ret);
    3543              : }
    3544              : 
    3545              : 
    3546              : int
    3547       273083 : MSLane::vehicle_position_sorter::operator()(MSVehicle* v1, MSVehicle* v2) const {
    3548       273083 :     const double pos1 = v1->getBackPositionOnLane(myLane);
    3549       273083 :     const double pos2 = v2->getBackPositionOnLane(myLane);
    3550       273083 :     if (pos1 != pos2) {
    3551       269040 :         return pos1 > pos2;
    3552              :     } else {
    3553         4043 :         return v1->getNumericalID() > v2->getNumericalID();
    3554              :     }
    3555              : }
    3556              : 
    3557              : 
    3558              : int
    3559    365609064 : MSLane::vehicle_natural_position_sorter::operator()(MSVehicle* v1, MSVehicle* v2) const {
    3560    365609064 :     const double pos1 = v1->getBackPositionOnLane(myLane);
    3561    365609064 :     const double pos2 = v2->getBackPositionOnLane(myLane);
    3562    365609064 :     if (pos1 != pos2) {
    3563    365063275 :         return pos1 < pos2;
    3564              :     } else {
    3565       545789 :         return v1->getLateralPositionOnLane() < v2->getLateralPositionOnLane();
    3566              :     }
    3567              : }
    3568              : 
    3569              : 
    3570      1067861 : MSLane::by_connections_to_sorter::by_connections_to_sorter(const MSEdge* const e) :
    3571      1067861 :     myEdge(e),
    3572      1067861 :     myLaneDir(e->getLanes()[0]->getShape().angleAt2D(0)) {
    3573      1067861 : }
    3574              : 
    3575              : 
    3576              : int
    3577        22271 : MSLane::by_connections_to_sorter::operator()(const MSEdge* const e1, const MSEdge* const e2) const {
    3578              : //    std::cout << "\nby_connections_to_sorter()";
    3579              : 
    3580        22271 :     const std::vector<MSLane*>* ae1 = e1->allowedLanes(*myEdge);
    3581        22271 :     const std::vector<MSLane*>* ae2 = e2->allowedLanes(*myEdge);
    3582              :     double s1 = 0;
    3583        22271 :     if (ae1 != nullptr && ae1->size() != 0) {
    3584              : //        std::cout << "\nsize 1 = " << ae1->size()
    3585              : //        << " anglediff 1 = " << fabs(GeomHelper::angleDiff((*ae1)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.
    3586              : //        << "\nallowed lanes: ";
    3587              : //        for (std::vector<MSLane*>::const_iterator j = ae1->begin(); j != ae1->end(); ++j){
    3588              : //            std::cout << "\n" << (*j)->getID();
    3589              : //        }
    3590        22271 :         s1 = (double) ae1->size() + fabs(GeomHelper::angleDiff((*ae1)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.;
    3591              :     }
    3592              :     double s2 = 0;
    3593        22271 :     if (ae2 != nullptr && ae2->size() != 0) {
    3594              : //        std::cout << "\nsize 2 = " << ae2->size()
    3595              : //        << " anglediff 2 = " << fabs(GeomHelper::angleDiff((*ae2)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.
    3596              : //        << "\nallowed lanes: ";
    3597              : //        for (std::vector<MSLane*>::const_iterator j = ae2->begin(); j != ae2->end(); ++j){
    3598              : //            std::cout << "\n" << (*j)->getID();
    3599              : //        }
    3600        22271 :         s2 = (double) ae2->size() + fabs(GeomHelper::angleDiff((*ae2)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.;
    3601              :     }
    3602              : 
    3603              : //    std::cout << "\ne1 = " << e1->getID() << " e2 = " << e2->getID()
    3604              : //            << "\ns1 = " << s1 << " s2 = " << s2
    3605              : //            << std::endl;
    3606              : 
    3607        22271 :     return s1 < s2;
    3608              : }
    3609              : 
    3610              : 
    3611      1032634 : MSLane::incoming_lane_priority_sorter::incoming_lane_priority_sorter(const MSLane* const targetLane) :
    3612      1032634 :     myLane(targetLane),
    3613      1032634 :     myLaneDir(targetLane->getShape().angleAt2D(0)) {}
    3614              : 
    3615              : int
    3616         1370 : MSLane::incoming_lane_priority_sorter::operator()(const IncomingLaneInfo& laneInfo1, const IncomingLaneInfo& laneInfo2) const {
    3617         1370 :     const MSLane* noninternal1 = laneInfo1.lane;
    3618         3371 :     while (noninternal1->isInternal()) {
    3619              :         assert(noninternal1->getIncomingLanes().size() == 1);
    3620         2001 :         noninternal1 = noninternal1->getIncomingLanes()[0].lane;
    3621              :     }
    3622         1370 :     MSLane* noninternal2 = laneInfo2.lane;
    3623         3045 :     while (noninternal2->isInternal()) {
    3624              :         assert(noninternal2->getIncomingLanes().size() == 1);
    3625         1675 :         noninternal2 = noninternal2->getIncomingLanes()[0].lane;
    3626              :     }
    3627              : 
    3628         1370 :     const MSLink* link1 = noninternal1->getLinkTo(myLane);
    3629         1370 :     const MSLink* link2 = noninternal2->getLinkTo(myLane);
    3630              : 
    3631              : #ifdef DEBUG_LANE_SORTER
    3632              :     std::cout << "\nincoming_lane_priority sorter()\n"
    3633              :               << "noninternal predecessor for lane '" << laneInfo1.lane->getID()
    3634              :               << "': '" << noninternal1->getID() << "'\n"
    3635              :               << "noninternal predecessor for lane '" << laneInfo2.lane->getID()
    3636              :               << "': '" << noninternal2->getID() << "'\n";
    3637              : #endif
    3638              : 
    3639              :     assert(laneInfo1.lane->isInternal() || link1 == laneInfo1.viaLink);
    3640              :     assert(link1 != 0);
    3641              :     assert(link2 != 0);
    3642              : 
    3643              :     // check priority between links
    3644              :     bool priorized1 = true;
    3645              :     bool priorized2 = true;
    3646              : 
    3647              : #ifdef DEBUG_LANE_SORTER
    3648              :     std::cout << "FoeLinks of '" << noninternal1->getID() << "'" << std::endl;
    3649              : #endif
    3650         2704 :     for (const MSLink* const foeLink : link1->getFoeLinks()) {
    3651              : #ifdef DEBUG_LANE_SORTER
    3652              :         std::cout << foeLink->getLaneBefore()->getID() << std::endl;
    3653              : #endif
    3654         2409 :         if (foeLink == link2) {
    3655              :             priorized1 = false;
    3656              :             break;
    3657              :         }
    3658              :     }
    3659              : 
    3660              : #ifdef DEBUG_LANE_SORTER
    3661              :     std::cout << "FoeLinks of '" << noninternal2->getID() << "'" << std::endl;
    3662              : #endif
    3663         3717 :     for (const MSLink* const foeLink : link2->getFoeLinks()) {
    3664              : #ifdef DEBUG_LANE_SORTER
    3665              :         std::cout << foeLink->getLaneBefore()->getID() << std::endl;
    3666              : #endif
    3667              :         // either link1 is priorized, or it should not appear in link2's foes
    3668         2859 :         if (foeLink == link1) {
    3669              :             priorized2 = false;
    3670              :             break;
    3671              :         }
    3672              :     }
    3673              :     // if one link is subordinate, the other must be priorized (except for
    3674              :     // traffic lights where mutual response is permitted to handle stuck-on-red
    3675              :     // situation)
    3676         1370 :     if (priorized1 != priorized2) {
    3677         1145 :         return priorized1;
    3678              :     }
    3679              : 
    3680              :     // both are priorized, compare angle difference
    3681          225 :     double d1 = fabs(GeomHelper::angleDiff(noninternal1->getShape().angleAt2D(0), myLaneDir));
    3682          225 :     double d2 = fabs(GeomHelper::angleDiff(noninternal2->getShape().angleAt2D(0), myLaneDir));
    3683              : 
    3684          225 :     return d2 > d1;
    3685              : }
    3686              : 
    3687              : 
    3688              : 
    3689        14014 : MSLane::outgoing_lane_priority_sorter::outgoing_lane_priority_sorter(const MSLane* const sourceLane) :
    3690        14014 :     myLaneDir(sourceLane->getShape().angleAt2D(0)) {}
    3691              : 
    3692              : int
    3693        13675 : MSLane::outgoing_lane_priority_sorter::operator()(const MSLink* link1, const MSLink* link2) const {
    3694              :     const MSLane* target1 = link1->getLane();
    3695              :     const MSLane* target2 = link2->getLane();
    3696        13675 :     if (target2 == nullptr) {
    3697              :         return true;
    3698              :     }
    3699        13675 :     if (target1 == nullptr) {
    3700              :         return false;
    3701              :     }
    3702              : 
    3703              : #ifdef DEBUG_LANE_SORTER
    3704              :     std::cout << "\noutgoing_lane_priority sorter()\n"
    3705              :               << "noninternal successors for lane '" << myLane->getID()
    3706              :               << "': '" << target1->getID() << "' and "
    3707              :               << "'" << target2->getID() << "'\n";
    3708              : #endif
    3709              : 
    3710              :     // priority of targets
    3711              :     int priority1 = target1->getEdge().getPriority();
    3712              :     int priority2 = target2->getEdge().getPriority();
    3713              : 
    3714        13675 :     if (priority1 != priority2) {
    3715          131 :         return priority1 > priority2;
    3716              :     }
    3717              : 
    3718              :     // if priority of targets coincides, use angle difference
    3719              : 
    3720              :     // both are priorized, compare angle difference
    3721        13544 :     double d1 = fabs(GeomHelper::angleDiff(target1->getShape().angleAt2D(0), myLaneDir));
    3722        13544 :     double d2 = fabs(GeomHelper::angleDiff(target2->getShape().angleAt2D(0), myLaneDir));
    3723              : 
    3724        13544 :     return d2 > d1;
    3725              : }
    3726              : 
    3727              : void
    3728         6287 : MSLane::addParking(MSBaseVehicle* veh) {
    3729              :     myParkingVehicles.insert(veh);
    3730         6287 : }
    3731              : 
    3732              : 
    3733              : void
    3734        18403 : MSLane::removeParking(MSBaseVehicle* veh) {
    3735              :     myParkingVehicles.erase(veh);
    3736        18403 : }
    3737              : 
    3738              : bool
    3739           73 : MSLane::hasApproaching() const {
    3740          146 :     for (const MSLink* link : myLinks) {
    3741           79 :         if (link->getApproaching().size() > 0) {
    3742              :             return true;
    3743              :         }
    3744              :     }
    3745              :     return false;
    3746              : }
    3747              : 
    3748              : void
    3749        12626 : MSLane::saveState(OutputDevice& out) {
    3750        12626 :     const bool toRailJunction = myLinks.size() > 0 && (
    3751        12172 :                                     myEdge->getToJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL
    3752        12088 :                                     || myEdge->getToJunction()->getType() == SumoXMLNodeType::RAIL_CROSSING);
    3753              :     const bool hasVehicles = myVehicles.size() > 0;
    3754        12626 :     if (hasVehicles || (toRailJunction && hasApproaching())) {
    3755          519 :         out.openTag(SUMO_TAG_LANE);
    3756          519 :         out.writeAttr(SUMO_ATTR_ID, getID());
    3757          519 :         if (hasVehicles) {
    3758          513 :             out.openTag(SUMO_TAG_VIEWSETTINGS_VEHICLES);
    3759          513 :             out.writeAttr(SUMO_ATTR_VALUE, myVehicles);
    3760         1026 :             out.closeTag();
    3761              :         }
    3762          519 :         if (toRailJunction) {
    3763           37 :             for (const MSLink* link : myLinks) {
    3764           20 :                 if (link->getApproaching().size() > 0) {
    3765           17 :                     out.openTag(SUMO_TAG_LINK);
    3766           17 :                     out.writeAttr(SUMO_ATTR_TO, link->getViaLaneOrLane()->getID());
    3767           34 :                     for (auto item : link->getApproaching()) {
    3768           17 :                         out.openTag(SUMO_TAG_APPROACHING);
    3769           17 :                         out.writeAttr(SUMO_ATTR_ID, item.first->getID());
    3770           17 :                         out.writeAttr(SUMO_ATTR_ARRIVALTIME, item.second.arrivalTime);
    3771           17 :                         out.writeAttr(SUMO_ATTR_ARRIVALSPEED, item.second.arrivalSpeed);
    3772           17 :                         out.writeAttr(SUMO_ATTR_DEPARTSPEED, item.second.leaveSpeed);
    3773           17 :                         out.writeAttr(SUMO_ATTR_REQUEST, item.second.willPass);
    3774           17 :                         out.writeAttr(SUMO_ATTR_ARRIVALSPEEDBRAKING, item.second.arrivalSpeedBraking);
    3775           17 :                         out.writeAttr(SUMO_ATTR_WAITINGTIME, item.second.waitingTime);
    3776           17 :                         out.writeAttr(SUMO_ATTR_DISTANCE, item.second.dist);
    3777           17 :                         if (item.second.latOffset != 0) {
    3778            0 :                             out.writeAttr(SUMO_ATTR_POSITION_LAT, item.second.latOffset);
    3779              :                         }
    3780           34 :                         out.closeTag();
    3781              :                     }
    3782           34 :                     out.closeTag();
    3783              :                 }
    3784              :             }
    3785              :         }
    3786         1038 :         out.closeTag();
    3787              :     }
    3788        12626 : }
    3789              : 
    3790              : void
    3791         8448 : MSLane::clearState() {
    3792              :     myVehicles.clear();
    3793              :     myParkingVehicles.clear();
    3794              :     myPartialVehicles.clear();
    3795              :     myManeuverReservations.clear();
    3796         8448 :     myBruttoVehicleLengthSum = 0;
    3797         8448 :     myNettoVehicleLengthSum = 0;
    3798         8448 :     myBruttoVehicleLengthSumToRemove = 0;
    3799         8448 :     myNettoVehicleLengthSumToRemove = 0;
    3800         8448 :     myLeaderInfoTime = SUMOTime_MIN;
    3801         8448 :     myFollowerInfoTime = SUMOTime_MIN;
    3802        19632 :     for (MSLink* link : myLinks) {
    3803        11184 :         link->clearState();
    3804              :     }
    3805         8448 : }
    3806              : 
    3807              : void
    3808          588 : MSLane::loadState(const std::vector<SUMOVehicle*>& vehs) {
    3809         2045 :     for (SUMOVehicle* veh : vehs) {
    3810         1457 :         MSVehicle* v = dynamic_cast<MSVehicle*>(veh);
    3811         1457 :         v->updateBestLanes(false, this);
    3812              :         // incorporateVehicle resets the lastActionTime (which has just been loaded from state) so we must restore it
    3813         1457 :         const SUMOTime lastActionTime = v->getLastActionTime();
    3814         1457 :         incorporateVehicle(v, v->getPositionOnLane(), v->getSpeed(), v->getLateralPositionOnLane(), myVehicles.end(),
    3815              :                            MSMoveReminder::NOTIFICATION_LOAD_STATE);
    3816         1457 :         v->resetActionOffset(lastActionTime - MSNet::getInstance()->getCurrentTimeStep());
    3817              :     }
    3818          588 : }
    3819              : 
    3820              : 
    3821              : double
    3822   2490477435 : MSLane::getVehicleStopOffset(const MSVehicle* veh) const {
    3823   2490477435 :     if (!myLaneStopOffset.isDefined()) {
    3824              :         return 0;
    3825              :     }
    3826        93844 :     if ((myLaneStopOffset.getPermissions() & veh->getVClass()) != 0) {
    3827        31828 :         return myLaneStopOffset.getOffset();
    3828              :     } else {
    3829              :         return 0;
    3830              :     }
    3831              : }
    3832              : 
    3833              : 
    3834              : const StopOffset&
    3835         2980 : MSLane::getLaneStopOffsets() const {
    3836         2980 :     return myLaneStopOffset;
    3837              : }
    3838              : 
    3839              : 
    3840              : void
    3841         2152 : MSLane::setLaneStopOffset(const StopOffset& stopOffset) {
    3842         2152 :     myLaneStopOffset = stopOffset;
    3843         2152 : }
    3844              : 
    3845              : 
    3846              : MSLeaderDistanceInfo
    3847    312472376 : MSLane::getFollowersOnConsecutive(const MSVehicle* ego, double backOffset,
    3848              :                                   bool allSublanes, double searchDist, MinorLinkMode mLinkMode, bool maxSearchDist) const {
    3849              :     assert(ego != 0);
    3850              :     // get the follower vehicle on the lane to change to
    3851    312472376 :     const double egoPos = backOffset + ego->getVehicleType().getLength();
    3852    312472376 :     const double egoLatDist = ego->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
    3853    313415539 :     const bool getOppositeLeaders = ((ego->getLaneChangeModel().isOpposite() && ego->getLane() == this)
    3854    312599614 :                                      || (!ego->getLaneChangeModel().isOpposite() && &ego->getLane()->getEdge() != &getEdge()));
    3855              : #ifdef DEBUG_CONTEXT
    3856              :     if (DEBUG_COND2(ego)) {
    3857              :         std::cout << SIMTIME << " getFollowers lane=" << getID() << " ego=" << ego->getID()
    3858              :                   << " backOffset=" << backOffset << " pos=" << egoPos
    3859              :                   << " allSub=" << allSublanes << " searchDist=" << searchDist << " ignoreMinor=" << mLinkMode
    3860              :                   << " maxSearchDist=" << maxSearchDist
    3861              :                   << " egoLatDist=" << egoLatDist
    3862              :                   << " getOppositeLeaders=" << getOppositeLeaders
    3863              :                   << "\n";
    3864              :     }
    3865              : #endif
    3866    320328247 :     MSCriticalFollowerDistanceInfo result(myWidth, allSublanes ? nullptr : ego, allSublanes ? 0 : egoLatDist, getOppositeLeaders);
    3867    312472376 :     if (MSGlobals::gLateralResolution > 0 && egoLatDist == 0) {
    3868              :         // check whether ego is outside lane bounds far enough so that another vehicle might
    3869              :         // be between itself and the first "actual" sublane
    3870              :         // shift the offset so that we "see" this vehicle
    3871    202666954 :         if (ego->getLeftSideOnLane() < -MSGlobals::gLateralResolution) {
    3872        35929 :             result.setSublaneOffset(int(-ego->getLeftSideOnLane() / MSGlobals::gLateralResolution));
    3873    202631025 :         } else if (ego->getRightSideOnLane() > getWidth() + MSGlobals::gLateralResolution) {
    3874       127797 :             result.setSublaneOffset(-int((ego->getRightSideOnLane() - getWidth()) / MSGlobals::gLateralResolution));
    3875              :         }
    3876              : #ifdef DEBUG_CONTEXT
    3877              :         if (DEBUG_COND2(ego)) {
    3878              :             std::cout << SIMTIME << " getFollowers lane=" << getID() << " ego=" << ego->getID()
    3879              :                       << " egoPosLat=" << ego->getLateralPositionOnLane()
    3880              :                       << " egoLatDist=" << ego->getLane()->getRightSideOnEdge() - getRightSideOnEdge()
    3881              :                       << " extraOffset=" << result.getSublaneOffset()
    3882              :                       << "\n";
    3883              :         }
    3884              : #endif
    3885              :     }
    3886              :     /// XXX iterate in reverse and abort when there are no more freeSublanes
    3887   6361458688 :     for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
    3888   6361458688 :         const MSVehicle* veh = *last;
    3889              : #ifdef DEBUG_CONTEXT
    3890              :         if (DEBUG_COND2(ego)) {
    3891              :             std::cout << "  veh=" << veh->getID() << " lane=" << veh->getLane()->getID() << " pos=" << veh->getPositionOnLane(this) << "\n";
    3892              :         }
    3893              : #endif
    3894   6361458688 :         if (veh != ego && veh->getPositionOnLane(this) < egoPos) {
    3895              :             //const double latOffset = veh->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
    3896   2816166596 :             const double latOffset = veh->getLatOffset(this);
    3897   2816166596 :             double dist = backOffset - veh->getPositionOnLane(this) - veh->getVehicleType().getMinGap();
    3898   2816166596 :             if (veh->isBidiOn(this)) {
    3899       544943 :                 dist -= veh->getLength();
    3900              :             }
    3901   2816166596 :             result.addFollower(veh, ego, dist, latOffset);
    3902              : #ifdef DEBUG_CONTEXT
    3903              :             if (DEBUG_COND2(ego)) {
    3904              :                 std::cout << "  (1) added veh=" << veh->getID() << " latOffset=" << latOffset << " result=" << result.toString() << "\n";
    3905              :             }
    3906              : #endif
    3907              :         }
    3908              :     }
    3909              : #ifdef DEBUG_CONTEXT
    3910              :     if (DEBUG_COND2(ego)) {
    3911              :         std::cout << "  result.numFreeSublanes=" << result.numFreeSublanes() << "\n";
    3912              :     }
    3913              : #endif
    3914    312472376 :     if (result.numFreeSublanes() > 0) {
    3915              :         // do a tree search among all follower lanes and check for the most
    3916              :         // important vehicle (the one requiring the largest reargap)
    3917              :         // to get a safe bound on the necessary search depth, we need to consider the maximum speed and minimum
    3918              :         // deceleration of potential follower vehicles
    3919    143350548 :         if (searchDist == -1) {
    3920    141937453 :             searchDist = getMaximumBrakeDist() - backOffset;
    3921              : #ifdef DEBUG_CONTEXT
    3922              :             if (DEBUG_COND2(ego)) {
    3923              :                 std::cout << "   computed searchDist=" << searchDist << "\n";
    3924              :             }
    3925              : #endif
    3926              :         }
    3927              :         std::set<const MSEdge*> egoFurther;
    3928    155419915 :         for (MSLane* further : ego->getFurtherLanes()) {
    3929     12069367 :             egoFurther.insert(&further->getEdge());
    3930              :         }
    3931    155150175 :         if (ego->getPositionOnLane() < ego->getVehicleType().getLength() && egoFurther.size() == 0
    3932    144841349 :                 && ego->getLane()->getLogicalPredecessorLane() != nullptr) {
    3933              :             // on insertion
    3934       986559 :             egoFurther.insert(&ego->getLane()->getLogicalPredecessorLane()->getEdge());
    3935              :         }
    3936              : 
    3937              :         // avoid loops
    3938    143350548 :         std::set<const MSLane*> visited(myEdge->getLanes().begin(), myEdge->getLanes().end());
    3939    143350548 :         if (myEdge->getBidiEdge() != nullptr) {
    3940              :             visited.insert(myEdge->getBidiEdge()->getLanes().begin(), myEdge->getBidiEdge()->getLanes().end());
    3941              :         }
    3942              :         std::vector<MSLane::IncomingLaneInfo> newFound;
    3943    143350548 :         std::vector<MSLane::IncomingLaneInfo> toExamine = myIncomingLanes;
    3944    310813303 :         while (toExamine.size() != 0) {
    3945    391333198 :             for (std::vector<MSLane::IncomingLaneInfo>::iterator it = toExamine.begin(); it != toExamine.end(); ++it) {
    3946    223870443 :                 MSLane* next = (*it).lane;
    3947              :                 searchDist = maxSearchDist
    3948    223870443 :                     ? MAX2(searchDist, next->getMaximumBrakeDist() - backOffset)
    3949    217738190 :                     : MIN2(searchDist, next->getMaximumBrakeDist() - backOffset);
    3950    223870443 :                 MSLeaderInfo first = next->getFirstVehicleInformation(nullptr, 0, false, std::numeric_limits<double>::max(), false);
    3951    223870442 :                 MSLeaderInfo firstFront = next->getFirstVehicleInformation(nullptr, 0, true);
    3952              : #ifdef DEBUG_CONTEXT
    3953              :                 if (DEBUG_COND2(ego)) {
    3954              :                     std::cout << "   next=" << next->getID() << " seen=" << (*it).length << " first=" << first.toString() << " firstFront=" << firstFront.toString() << " backOffset=" << backOffset << "\n";
    3955              :                     gDebugFlag1 = true; // for calling getLeaderInfo
    3956              :                 }
    3957              : #endif
    3958    223870442 :                 if (backOffset + (*it).length - next->getLength() < 0
    3959    223870442 :                         && egoFurther.count(&next->getEdge()) != 0
    3960              :                    )  {
    3961              :                     // check for junction foes that would interfere with lane changing
    3962              :                     // @note: we are passing the back of ego as its front position so
    3963              :                     //        we need to add this back to the returned gap
    3964     12581055 :                     const MSLink::LinkLeaders linkLeaders = (*it).viaLink->getLeaderInfo(ego, -backOffset);
    3965     12949571 :                     for (const auto& ll : linkLeaders) {
    3966       368516 :                         if (ll.vehAndGap.first != nullptr) {
    3967       368504 :                             const bool bidiFoe = (*it).viaLink->getLane() == ll.vehAndGap.first->getLane()->getNormalPredecessorLane()->getBidiLane();
    3968       368504 :                             const bool egoIsLeader = !bidiFoe && ll.vehAndGap.first->isLeader((*it).viaLink, ego, ll.vehAndGap.second);
    3969              :                             // if ego is leader the returned gap still assumes that ego follows the leader
    3970              :                             // if the foe vehicle follows ego we need to deduce that gap
    3971              :                             const double gap = (egoIsLeader
    3972       368504 :                                                 ? -ll.vehAndGap.second - ll.vehAndGap.first->getVehicleType().getLengthWithGap() - ego->getVehicleType().getMinGap()
    3973         1009 :                                                 : ll.vehAndGap.second + ego->getVehicleType().getLength());
    3974       368504 :                             result.addFollower(ll.vehAndGap.first, ego, gap);
    3975              : #ifdef DEBUG_CONTEXT
    3976              :                             if (DEBUG_COND2(ego)) {
    3977              :                                 std::cout << SIMTIME << " ego=" << ego->getID() << "    link=" << (*it).viaLink->getViaLaneOrLane()->getID()
    3978              :                                           << " (3) added veh=" << Named::getIDSecure(ll.vehAndGap.first)
    3979              :                                           << " gap=" << ll.vehAndGap.second << " dtC=" << ll.distToCrossing
    3980              :                                           << " bidiFoe=" << bidiFoe
    3981              :                                           << " egoIsLeader=" << egoIsLeader << " gap2=" << gap
    3982              :                                           << "\n";
    3983              :                             }
    3984              : #endif
    3985              :                         }
    3986              :                     }
    3987     12581055 :                 }
    3988              : #ifdef DEBUG_CONTEXT
    3989              :                 if (DEBUG_COND2(ego)) {
    3990              :                     gDebugFlag1 = false;
    3991              :                 }
    3992              : #endif
    3993              : 
    3994   1068478288 :                 for (int i = 0; i < first.numSublanes(); ++i) {
    3995    844607846 :                     const MSVehicle* v = first[i] == ego ? firstFront[i] : first[i];
    3996              :                     double agap = 0;
    3997              : 
    3998    844607846 :                     if (v != nullptr && v != ego) {
    3999    192020935 :                         if (!v->isFrontOnLane(next)) {
    4000              :                             // the front of v is already on divergent trajectory from the ego vehicle
    4001              :                             // for which this method is called (in the context of MSLaneChanger).
    4002              :                             // Therefore, technically v is not a follower but only an obstruction and
    4003              :                             // the gap is not between the front of v and the back of ego
    4004              :                             // but rather between the flank of v and the back of ego.
    4005     27893781 :                             agap = (*it).length - next->getLength() + backOffset;
    4006     27893781 :                             if (MSGlobals::gUsingInternalLanes) {
    4007              :                                 // ego should have left the intersection still occupied by v
    4008     27884511 :                                 agap -= v->getVehicleType().getMinGap();
    4009              :                             }
    4010              : #ifdef DEBUG_CONTEXT
    4011              :                             if (DEBUG_COND2(ego)) {
    4012              :                                 std::cout << "    agap1=" << agap << "\n";
    4013              :                             }
    4014              : #endif
    4015     27893781 :                             const bool differentEdge = &v->getLane()->getEdge() != &ego->getLane()->getEdge();
    4016     27893781 :                             if (agap > 0 && differentEdge) {
    4017              :                                 // Only if ego overlaps we treat v as if it were a real follower
    4018              :                                 // Otherwise we ignore it and look for another follower
    4019     16970274 :                                 if (!getOppositeLeaders) {
    4020              :                                     // even if the vehicle is not a real
    4021              :                                     // follower, it still forms a real
    4022              :                                     // obstruction in opposite direction driving
    4023     16789549 :                                     v = firstFront[i];
    4024     16789549 :                                     if (v != nullptr && v != ego) {
    4025     13970161 :                                         agap = (*it).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
    4026              :                                     } else {
    4027              :                                         v = nullptr;
    4028              :                                     }
    4029              :                                 }
    4030     10923507 :                             } else if (differentEdge && result.hasVehicle(v)) {
    4031              :                                 // ignore this vehicle as it was already seen on another lane
    4032              :                                 agap = 0;
    4033              :                             }
    4034              :                         } else {
    4035    164127154 :                             if (next->getBidiLane() != nullptr && v->isBidiOn(next)) {
    4036       100989 :                                 agap = v->getPositionOnLane() + backOffset - v->getVehicleType().getLengthWithGap();
    4037              :                             } else {
    4038    164026165 :                                 agap = (*it).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
    4039              :                             }
    4040    164127154 :                             if (!(*it).viaLink->havePriority() && egoFurther.count(&(*it).lane->getEdge()) == 0
    4041      7087506 :                                     && ego->isOnRoad() // during insertion, this can lead to collisions because ego's further lanes are not set (see #3053)
    4042      7030022 :                                     && !ego->getLaneChangeModel().isOpposite()
    4043    171156646 :                                     && v->getSpeed() < SUMO_const_haltingSpeed
    4044              :                                ) {
    4045              :                                 // if v is stopped on a minor side road it should not block lane changing
    4046              :                                 agap = MAX2(agap, 0.0);
    4047              :                             }
    4048              :                         }
    4049    192020935 :                         result.addFollower(v, ego, agap, 0, i);
    4050              : #ifdef DEBUG_CONTEXT
    4051              :                         if (DEBUG_COND2(ego)) {
    4052              :                             std::cout << " (2) added veh=" << Named::getIDSecure(v) << " agap=" << agap << " next=" << next->getID() << " result=" << result.toString() << "\n";
    4053              :                         }
    4054              : #endif
    4055              :                     }
    4056              :                 }
    4057    223870442 :                 if ((*it).length < searchDist) {
    4058              :                     const std::vector<MSLane::IncomingLaneInfo>& followers = next->getIncomingLanes();
    4059    201294702 :                     for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j = followers.begin(); j != followers.end(); ++j) {
    4060    104635373 :                         if (visited.find((*j).lane) == visited.end() && (((*j).viaLink->havePriority() && !(*j).viaLink->isTurnaround())
    4061     25801664 :                                 || mLinkMode == MinorLinkMode::FOLLOW_ALWAYS
    4062      1507964 :                                 || (mLinkMode == MinorLinkMode::FOLLOW_ONCOMING && (*j).viaLink->getDirection() == LinkDirection::STRAIGHT))) {
    4063     94586358 :                             visited.insert((*j).lane);
    4064              :                             MSLane::IncomingLaneInfo ili;
    4065     94586358 :                             ili.lane = (*j).lane;
    4066     94586358 :                             ili.length = (*j).length + (*it).length;
    4067     94586358 :                             ili.viaLink = (*j).viaLink;
    4068     94586358 :                             newFound.push_back(ili);
    4069              :                         }
    4070              :                     }
    4071              :                 }
    4072    223870442 :             }
    4073              :             toExamine.clear();
    4074              :             swap(newFound, toExamine);
    4075              :         }
    4076              :         //return result;
    4077              : 
    4078    143350549 :     }
    4079    624944750 :     return result;
    4080    312472376 : }
    4081              : 
    4082              : 
    4083              : void
    4084     17219841 : MSLane::getLeadersOnConsecutive(double dist, double seen, double speed, const MSVehicle* ego,
    4085              :                                 const std::vector<MSLane*>& bestLaneConts, MSLeaderDistanceInfo& result,
    4086              :                                 bool oppositeDirection) const {
    4087              : #ifdef DEBUG_CONTEXT
    4088              :     if (DEBUG_COND2(ego)) {
    4089              :         std::cout << "   getLeadersOnConsecutive " << getID() << " ego=" << Named::getIDSecure(ego) << " dist=" << dist << " seen=" << seen << "\n";
    4090              :     }
    4091              : #endif
    4092     17219841 :     if (seen > dist && !(isInternal() && MSGlobals::gComputeLC)) {
    4093              :         return;
    4094              :     }
    4095              :     // check partial vehicles (they might be on a different route and thus not
    4096              :     // found when iterating along bestLaneConts)
    4097     18197718 :     for (VehCont::const_iterator it = myPartialVehicles.begin(); it != myPartialVehicles.end(); ++it) {
    4098      2876984 :         MSVehicle* veh = *it;
    4099      2876984 :         if (!veh->isFrontOnLane(this)) {
    4100       977877 :             result.addLeader(veh, seen, veh->getLatOffset(this));
    4101              :         } else {
    4102              :             break;
    4103              :         }
    4104              :     }
    4105              : #ifdef DEBUG_CONTEXT
    4106              :     if (DEBUG_COND2(ego)) {
    4107              :         gDebugFlag1 = true;
    4108              :     }
    4109              : #endif
    4110              :     const MSLane* nextLane = this;
    4111              :     int view = 1;
    4112              :     // loop over following lanes
    4113     40526289 :     while ((seen < dist && result.numFreeSublanes() > 0) || nextLane->isInternal()) {
    4114     29476580 :         if (nextLane != this) {
    4115     12256765 :             seen += nextLane->getLength();
    4116              :         }
    4117              :         // get the next link used
    4118              :         bool nextInternal = false;
    4119     29476580 :         if (oppositeDirection) {
    4120         7031 :             if (view >= (int)bestLaneConts.size()) {
    4121              :                 break;
    4122              :             }
    4123         1521 :             nextLane = bestLaneConts[view];
    4124              :         } else {
    4125     29469549 :             std::vector<MSLink*>::const_iterator link = succLinkSec(*ego, view, *nextLane, bestLaneConts);
    4126     29469549 :             if (nextLane->isLinkEnd(link)) {
    4127              :                 break;
    4128              :             }
    4129              : #ifdef DEBUG_CONTEXT
    4130              :             if (DEBUG_COND2(ego)) {
    4131              :                 std::cout << "    link=" << (*link)->getDescription() << " debugflag=" << gDebugFlag1 << "\n";
    4132              :             }
    4133              : #endif
    4134              :             // check for link leaders
    4135     23304927 :             const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(ego, seen);
    4136     23304927 :             if (DEBUG_COND2(ego)) {
    4137            0 :                 std::cout << "    numLinkLeaders=" << linkLeaders.size() << "\n";
    4138              :             }
    4139     25405245 :             for (const MSLink::LinkLeader& ll : linkLeaders) {
    4140      2100318 :                 MSVehicle* veh = ll.vehAndGap.first;
    4141              :                 // in the context of lane changing all junction leader candidates must be respected
    4142              : #ifdef DEBUG_CONTEXT
    4143              :                 if (DEBUG_COND2(ego)) {
    4144              :                     std::cout << "   linkleader=" << veh->getID() << " gap=" << ll.vehAndGap.second << " leaderOffset=" << ll.latOffset << " flags=" << ll.llFlags << "\n";
    4145              :                 }
    4146              : #endif
    4147      2100318 :                 if (veh != 0 && (ego->isLeader(*link, veh, ll.vehAndGap.second)
    4148       183995 :                                  || (MSGlobals::gComputeLC
    4149      2284313 :                                      && veh->getPosition().distanceTo2D(ego->getPosition()) - veh->getVehicleType().getMinGap() - ego->getVehicleType().getLength()
    4150       183995 :                                      < veh->getCarFollowModel().brakeGap(veh->getSpeed())))) {
    4151      1947279 :                     if (ll.sameTarget() || ll.sameSource()) {
    4152      1325132 :                         result.addLeader(veh, ll.vehAndGap.second, ll.latOffset);
    4153              : #ifdef DEBUG_CONTEXT
    4154              :                         if (DEBUG_COND2(ego)) {
    4155              :                             std::cout << "   added selective: result=" << result.toString() << "\n";
    4156              :                         }
    4157              : #endif
    4158              :                     } else {
    4159              :                         // add link leader to all sublanes and return
    4160      3262119 :                         for (int i = 0; i < result.numSublanes(); ++i) {
    4161      2639972 :                             result.addLeader(veh, ll.vehAndGap.second, 0, i);
    4162              :                         }
    4163              : #ifdef DEBUG_CONTEXT
    4164              :                         if (DEBUG_COND2(ego)) {
    4165              :                             std::cout << "   added allSublanes: result=" << result.toString() << "\n";
    4166              :                         }
    4167              : #endif
    4168              :                     }
    4169              :                 } // XXX else, deal with pedestrians
    4170              :             }
    4171     23304927 :             nextInternal = (*link)->getViaLane() != nullptr;
    4172              :             nextLane = (*link)->getViaLaneOrLane();
    4173     14385728 :             if (nextLane == nullptr) {
    4174              :                 break;
    4175              :             }
    4176     23304927 :         }
    4177              : 
    4178     23306448 :         MSLeaderInfo leaders = nextLane->getLastVehicleInformation(nullptr, 0, 0, false);
    4179              : #ifdef DEBUG_CONTEXT
    4180              :         if (DEBUG_COND2(ego)) {
    4181              :             std::cout << SIMTIME << " getLeadersOnConsecutive lane=" << getID() << " nextLane=" << nextLane->getID() << " leaders=" << leaders.toString() << "\n";
    4182              :         }
    4183              : #endif
    4184              :         // @todo check alignment issues if the lane width changes
    4185              :         const int iMax = MIN2(leaders.numSublanes(), result.numSublanes());
    4186    125434787 :         for (int i = 0; i < iMax; ++i) {
    4187    102128339 :             const MSVehicle* veh = leaders[i];
    4188    102128339 :             if (veh != nullptr) {
    4189              : #ifdef DEBUG_CONTEXT
    4190              :                 if (DEBUG_COND2(ego)) std::cout << "   lead=" << veh->getID()
    4191              :                                                     << " seen=" << seen
    4192              :                                                     << " minGap=" << ego->getVehicleType().getMinGap()
    4193              :                                                     << " backPos=" << veh->getBackPositionOnLane(nextLane)
    4194              :                                                     << " gap=" << seen - ego->getVehicleType().getMinGap() + veh->getBackPositionOnLane(nextLane)
    4195              :                                                     << "\n";
    4196              : #endif
    4197     42000119 :                 result.addLeader(veh, seen - ego->getVehicleType().getMinGap() + veh->getBackPositionOnLane(nextLane), 0, i);
    4198              :             }
    4199              :         }
    4200              : 
    4201     23306448 :         if (nextLane->getVehicleMaxSpeed(ego) < speed) {
    4202      1096271 :             dist = ego->getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(ego));
    4203              :         }
    4204              : #ifdef DEBUG_CONTEXT
    4205              :         if (DEBUG_COND2(ego)) std::cout << "   newDist=" << dist << " newSeen=" << seen << "\n";
    4206              : #endif
    4207     23306448 :         if (!nextInternal) {
    4208     14387249 :             view++;
    4209              :         }
    4210     23306448 :     }
    4211              : #ifdef DEBUG_CONTEXT
    4212              :     gDebugFlag1 = false;
    4213              : #endif
    4214              : }
    4215              : 
    4216              : 
    4217              : void
    4218    126746823 : MSLane::addLeaders(const MSVehicle* vehicle, double vehPos, MSLeaderDistanceInfo& result, bool opposite) {
    4219              :     // if there are vehicles on the target lane with the same position as ego,
    4220              :     // they may not have been added to 'ahead' yet
    4221              : #ifdef DEBUG_SURROUNDING
    4222              :     if (DEBUG_COND || DEBUG_COND2(vehicle)) {
    4223              :         std::cout << " addLeaders lane=" << getID() << " veh=" << vehicle->getID() << " vehPos=" << vehPos << " opposite=" << opposite << "\n";
    4224              :     }
    4225              : #endif
    4226    126746823 :     const MSLeaderInfo& aheadSamePos = getLastVehicleInformation(nullptr, 0, vehPos, false, vehicle);
    4227    657466830 :     for (int i = 0; i < aheadSamePos.numSublanes(); ++i) {
    4228    530720007 :         const MSVehicle* veh = aheadSamePos[i];
    4229    530720007 :         if (veh != nullptr && veh != vehicle) {
    4230    395803421 :             const double gap = veh->getBackPositionOnLane(this) - vehPos - vehicle->getVehicleType().getMinGap();
    4231              : #ifdef DEBUG_SURROUNDING
    4232              :             if (DEBUG_COND || DEBUG_COND2(vehicle)) {
    4233              :                 std::cout << " further lead=" << veh->getID() << " leadBack=" << veh->getBackPositionOnLane(this) << " gap=" << gap << "\n";
    4234              :             }
    4235              : #endif
    4236    395803421 :             result.addLeader(veh, gap, 0, i);
    4237              :         }
    4238              :     }
    4239              : 
    4240              :     // we must consider linkLeaders (via getLeadersOnConsecutive) while on a junction
    4241    126746823 :     if (result.numFreeSublanes() > 0 || isInternal()) {
    4242     37994775 :         double seen = vehicle->getLane()->getLength() - vehPos;
    4243     37994775 :         double speed = vehicle->getSpeed();
    4244              :         // leader vehicle could be link leader on the next junction
    4245     37994775 :         double dist = MAX2(vehicle->getCarFollowModel().brakeGap(speed), 10.0) + vehicle->getVehicleType().getMinGap();
    4246     37994775 :         if (getBidiLane() != nullptr) {
    4247       245343 :             dist = MAX2(dist, myMaxSpeed * 20);
    4248              :         }
    4249              :         // check for link leaders when on internal
    4250     37994775 :         if (seen > dist && !(isInternal() && MSGlobals::gComputeLC)) {
    4251              : #ifdef DEBUG_SURROUNDING
    4252              :             if (DEBUG_COND || DEBUG_COND2(vehicle)) {
    4253              :                 std::cout << " aborting forward search. dist=" << dist << " seen=" << seen << "\n";
    4254              :             }
    4255              : #endif
    4256              :             return;
    4257              :         }
    4258              : #ifdef DEBUG_SURROUNDING
    4259              :         if (DEBUG_COND || DEBUG_COND2(vehicle)) {
    4260              :             std::cout << " add consecutive before=" << result.toString() << " seen=" << seen << " dist=" << dist;
    4261              :         }
    4262              : #endif
    4263     17219841 :         if (opposite) {
    4264         5721 :             const std::vector<MSLane*> bestLaneConts = vehicle->getUpstreamOppositeLanes();
    4265              : #ifdef DEBUG_SURROUNDING
    4266              :             if (DEBUG_COND || DEBUG_COND2(vehicle)) {
    4267              :                 std::cout << " upstreamOpposite=" << toString(bestLaneConts);
    4268              :             }
    4269              : #endif
    4270         5721 :             getLeadersOnConsecutive(dist, seen, speed, vehicle, bestLaneConts, result, opposite);
    4271         5721 :         } else {
    4272     17214120 :             const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation(this);
    4273     17214120 :             getLeadersOnConsecutive(dist, seen, speed, vehicle, bestLaneConts, result);
    4274              :         }
    4275              : #ifdef DEBUG_SURROUNDING
    4276              :         if (DEBUG_COND || DEBUG_COND2(vehicle)) {
    4277              :             std::cout << " after=" << result.toString() << "\n";
    4278              :         }
    4279              : #endif
    4280              :     }
    4281    126746823 : }
    4282              : 
    4283              : 
    4284              : MSVehicle*
    4285    482063624 : MSLane::getPartialBehind(const MSVehicle* ego) const {
    4286    508558185 :     for (VehCont::const_reverse_iterator i = myPartialVehicles.rbegin(); i != myPartialVehicles.rend(); ++i) {
    4287     28177531 :         MSVehicle* veh = *i;
    4288     28177531 :         if (veh->isFrontOnLane(this)
    4289      3284877 :                 && veh != ego
    4290     31462408 :                 && veh->getPositionOnLane() <= ego->getPositionOnLane()) {
    4291              : #ifdef DEBUG_CONTEXT
    4292              :             if (DEBUG_COND2(ego)) {
    4293              :                 std::cout << SIMTIME << " getPartialBehind lane=" << getID() << " ego=" << ego->getID() << " found=" << veh->getID() << "\n";
    4294              :             }
    4295              : #endif
    4296              :             return veh;
    4297              :         }
    4298              :     }
    4299              : #ifdef DEBUG_CONTEXT
    4300              :     if (DEBUG_COND2(ego)) {
    4301              :         std::cout << SIMTIME << " getPartialBehind lane=" << getID() << " ego=" << ego->getID() << " nothing found. partials=" << toString(myPartialVehicles) << "\n";
    4302              :     }
    4303              : #endif
    4304              :     return nullptr;
    4305              : }
    4306              : 
    4307              : MSLeaderInfo
    4308     21018921 : MSLane::getPartialBeyond() const {
    4309     21018921 :     MSLeaderInfo result(myWidth);
    4310     22548181 :     for (VehCont::const_iterator it = myPartialVehicles.begin(); it != myPartialVehicles.end(); ++it) {
    4311      3107489 :         MSVehicle* veh = *it;
    4312      3107489 :         if (!veh->isFrontOnLane(this)) {
    4313      1529260 :             result.addLeader(veh, false, veh->getLatOffset(this));
    4314              :         } else {
    4315              :             break;
    4316              :         }
    4317              :     }
    4318     21018921 :     return result;
    4319            0 : }
    4320              : 
    4321              : 
    4322              : std::set<MSVehicle*>
    4323        11180 : MSLane::getSurroundingVehicles(double startPos, double downstreamDist, double upstreamDist, std::shared_ptr<LaneCoverageInfo> checkedLanes) const {
    4324              :     assert(checkedLanes != nullptr);
    4325        11180 :     if (checkedLanes->find(this) != checkedLanes->end()) {
    4326              : #ifdef DEBUG_SURROUNDING
    4327              :         std::cout << "Skipping previously scanned lane: " << getID() << std::endl;
    4328              : #endif
    4329         2266 :         return std::set<MSVehicle*>();
    4330              :     } else {
    4331              :         // Add this lane's coverage to the lane coverage info
    4332        18841 :         (*checkedLanes)[this] = std::make_pair(MAX2(0.0, startPos - upstreamDist), MIN2(startPos + downstreamDist, getLength()));
    4333              :     }
    4334              : #ifdef DEBUG_SURROUNDING
    4335              :     std::cout << "Scanning on lane " << myID << "(downstr. " << downstreamDist << ", upstr. " << upstreamDist << ", startPos " << startPos << "): " << std::endl;
    4336              : #endif
    4337        14492 :     std::set<MSVehicle*> foundVehicles = getVehiclesInRange(MAX2(0., startPos - upstreamDist), MIN2(myLength, startPos + downstreamDist));
    4338         8914 :     if (startPos < upstreamDist) {
    4339              :         // scan incoming lanes
    4340        10886 :         for (const IncomingLaneInfo& incomingInfo : getIncomingLanes()) {
    4341         5412 :             MSLane* incoming = incomingInfo.lane;
    4342              : #ifdef DEBUG_SURROUNDING
    4343              :             std::cout << "Checking on incoming: " << incoming->getID() << std::endl;
    4344              :             if (checkedLanes->find(incoming) != checkedLanes->end()) {
    4345              :                 std::cout << "Skipping previous: " << incoming->getID() << std::endl;
    4346              :             }
    4347              : #endif
    4348        10824 :             std::set<MSVehicle*> newVehs = incoming->getSurroundingVehicles(incoming->getLength(), 0.0, upstreamDist - startPos, checkedLanes);
    4349         5412 :             foundVehicles.insert(newVehs.begin(), newVehs.end());
    4350              :         }
    4351              :     }
    4352              : 
    4353         8914 :     if (getLength() < startPos + downstreamDist) {
    4354              :         // scan successive lanes
    4355              :         const std::vector<MSLink*>& lc = getLinkCont();
    4356         6130 :         for (MSLink* l : lc) {
    4357              : #ifdef DEBUG_SURROUNDING
    4358              :             std::cout << "Checking on outgoing: " << l->getViaLaneOrLane()->getID() << std::endl;
    4359              : #endif
    4360         5588 :             std::set<MSVehicle*> newVehs = l->getViaLaneOrLane()->getSurroundingVehicles(0.0, downstreamDist - (myLength - startPos), upstreamDist, checkedLanes);
    4361         2794 :             foundVehicles.insert(newVehs.begin(), newVehs.end());
    4362              :         }
    4363              :     }
    4364              : #ifdef DEBUG_SURROUNDING
    4365              :     std::cout << "On lane (2) " << myID << ": \nFound vehicles: " << std::endl;
    4366              :     for (MSVehicle* v : foundVehicles) {
    4367              :         std::cout << v->getID() << " pos = " << v->getPositionOnLane() << std::endl;
    4368              :     }
    4369              : #endif
    4370              :     return foundVehicles;
    4371              : }
    4372              : 
    4373              : 
    4374              : std::set<MSVehicle*>
    4375        11749 : MSLane::getVehiclesInRange(const double a, const double b) const {
    4376              :     std::set<MSVehicle*> res;
    4377        11749 :     const VehCont& vehs = getVehiclesSecure();
    4378              : 
    4379        11749 :     if (!vehs.empty()) {
    4380        12545 :         for (MSVehicle* const veh : vehs) {
    4381         8356 :             if (veh->getPositionOnLane() >= a) {
    4382         7012 :                 if (veh->getBackPositionOnLane() > b) {
    4383              :                     break;
    4384              :                 }
    4385              :                 res.insert(veh);
    4386              :             }
    4387              :         }
    4388              :     }
    4389        11749 :     releaseVehicles();
    4390        11749 :     return res;
    4391              : }
    4392              : 
    4393              : 
    4394              : std::vector<const MSJunction*>
    4395            0 : MSLane::getUpcomingJunctions(double pos, double range, const std::vector<MSLane*>& contLanes) const {
    4396              :     // set of upcoming junctions and the corresponding conflict links
    4397              :     std::vector<const MSJunction*> junctions;
    4398            0 :     for (auto l : getUpcomingLinks(pos, range, contLanes)) {
    4399            0 :         junctions.insert(junctions.end(), l->getJunction());
    4400            0 :     }
    4401            0 :     return junctions;
    4402            0 : }
    4403              : 
    4404              : 
    4405              : std::vector<const MSLink*>
    4406          761 : MSLane::getUpcomingLinks(double pos, double range, const std::vector<MSLane*>& contLanes) const {
    4407              : #ifdef DEBUG_SURROUNDING
    4408              :     std::cout << "getUpcoming links on lane '" << getID() << "' with pos=" << pos
    4409              :               << " range=" << range << std::endl;
    4410              : #endif
    4411              :     // set of upcoming junctions and the corresponding conflict links
    4412              :     std::vector<const MSLink*> links;
    4413              : 
    4414              :     // Currently scanned lane
    4415              :     const MSLane* lane = this;
    4416              : 
    4417              :     // continuation lanes for the vehicle
    4418              :     std::vector<MSLane*>::const_iterator contLanesIt = contLanes.begin();
    4419              :     // scanned distance so far
    4420              :     double dist = 0.0;
    4421              :     // link to be crossed by the vehicle
    4422          761 :     const MSLink* link = nullptr;
    4423          761 :     if (lane->isInternal()) {
    4424              :         assert(*contLanesIt == nullptr); // is called with vehicle's bestLane structure
    4425          116 :         link = lane->getEntryLink();
    4426          116 :         links.insert(links.end(), link);
    4427          116 :         dist += link->getInternalLengthsAfter();
    4428              :         // next non-internal lane behind junction
    4429              :         lane = link->getLane();
    4430              :         pos = 0.0;
    4431              :         assert(*(contLanesIt + 1) == lane);
    4432              :     }
    4433         1266 :     while (++contLanesIt != contLanes.end()) {
    4434              :         assert(!lane->isInternal());
    4435          969 :         dist += lane->getLength() - pos;
    4436              :         pos = 0.;
    4437              : #ifdef DEBUG_SURROUNDING
    4438              :         std::cout << "Distance until end of lane '" << lane->getID() << "' is " << dist << "." << std::endl;
    4439              : #endif
    4440          969 :         if (dist > range) {
    4441              :             break;
    4442              :         }
    4443          505 :         link = lane->getLinkTo(*contLanesIt);
    4444          505 :         if (link != nullptr) {
    4445          493 :             links.insert(links.end(), link);
    4446              :         }
    4447          505 :         lane = *contLanesIt;
    4448              :     }
    4449          761 :     return links;
    4450            0 : }
    4451              : 
    4452              : 
    4453              : MSLane*
    4454    254127745 : MSLane::getOpposite() const {
    4455    254127745 :     return myOpposite;
    4456              : }
    4457              : 
    4458              : 
    4459              : MSLane*
    4460    193503521 : MSLane::getParallelOpposite() const {
    4461    193503521 :     return myEdge->getLanes().back()->getOpposite();
    4462              : }
    4463              : 
    4464              : 
    4465              : double
    4466      7552141 : MSLane::getOppositePos(double pos) const {
    4467      7552141 :     return MAX2(0., myLength - pos);
    4468              : }
    4469              : 
    4470              : std::pair<MSVehicle* const, double>
    4471      9340536 : MSLane::getFollower(const MSVehicle* ego, double egoPos, double dist, MinorLinkMode mLinkMode, bool maxSearchDist) const {
    4472     33686352 :     for (AnyVehicleIterator first = anyVehiclesUpstreamBegin(); first != anyVehiclesUpstreamEnd(); ++first) {
    4473              :         // XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
    4474     41340064 :         MSVehicle* pred = (MSVehicle*)*first;
    4475              : #ifdef DEBUG_CONTEXT
    4476              :         if (DEBUG_COND2(ego)) {
    4477              :             std::cout << "   getFollower lane=" << getID() << " egoPos=" << egoPos << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane(this) << "\n";
    4478              :         }
    4479              : #endif
    4480     41340064 :         if (pred != ego && pred->getPositionOnLane(this) < egoPos) {
    4481      7653712 :             return std::pair<MSVehicle* const, double>(pred, egoPos - pred->getPositionOnLane(this) - ego->getVehicleType().getLength() - pred->getVehicleType().getMinGap());
    4482              :         }
    4483              :     }
    4484      1686824 :     const double backOffset = egoPos - ego->getVehicleType().getLength();
    4485      1686824 :     if (dist > 0 && backOffset > dist) {
    4486       322750 :         return std::make_pair(nullptr, -1);
    4487              :     }
    4488      1364074 :     const MSLeaderDistanceInfo followers = getFollowersOnConsecutive(ego, backOffset, true,  dist, mLinkMode, maxSearchDist);
    4489      1364073 :     CLeaderDist result = followers.getClosest();
    4490      1364073 :     return std::make_pair(const_cast<MSVehicle*>(result.first), result.second);
    4491      1364073 : }
    4492              : 
    4493              : std::pair<MSVehicle* const, double>
    4494      5132971 : MSLane::getOppositeLeader(const MSVehicle* ego, double dist, bool oppositeDir, MinorLinkMode mLinkMode) const {
    4495              : #ifdef DEBUG_OPPOSITE
    4496              :     if (DEBUG_COND2(ego)) std::cout << SIMTIME << " getOppositeLeader lane=" << getID()
    4497              :                                         << " ego=" << ego->getID()
    4498              :                                         << " pos=" << ego->getPositionOnLane()
    4499              :                                         << " posOnOpposite=" << getOppositePos(ego->getPositionOnLane())
    4500              :                                         << " dist=" << dist
    4501              :                                         << " oppositeDir=" << oppositeDir
    4502              :                                         << "\n";
    4503              : #endif
    4504      5132971 :     if (!oppositeDir) {
    4505       383710 :         return getLeader(ego, getOppositePos(ego->getPositionOnLane()), ego->getBestLanesContinuation(this));
    4506              :     } else {
    4507      4749261 :         const double egoLength = ego->getVehicleType().getLength();
    4508      4749261 :         const double egoPos = ego->getLaneChangeModel().isOpposite() ? ego->getPositionOnLane() : getOppositePos(ego->getPositionOnLane());
    4509      4749261 :         std::pair<MSVehicle* const, double> result = getFollower(ego, egoPos + egoLength, dist, mLinkMode, true);
    4510      4749261 :         if (result.first != nullptr) {
    4511      4106648 :             result.second -= ego->getVehicleType().getMinGap();
    4512      4106648 :             if (result.first->getLaneChangeModel().isOpposite()) {
    4513      1306082 :                 result.second -= result.first->getVehicleType().getLength();
    4514              :             }
    4515              :         }
    4516      4749261 :         return result;
    4517              :     }
    4518              : }
    4519              : 
    4520              : 
    4521              : std::pair<MSVehicle* const, double>
    4522       698834 : MSLane::getOppositeFollower(const MSVehicle* ego) const {
    4523              : #ifdef DEBUG_OPPOSITE
    4524              :     if (DEBUG_COND2(ego)) std::cout << SIMTIME << " getOppositeFollower lane=" << getID()
    4525              :                                         << " ego=" << ego->getID()
    4526              :                                         << " backPos=" << ego->getBackPositionOnLane()
    4527              :                                         << " posOnOpposite=" << getOppositePos(ego->getBackPositionOnLane())
    4528              :                                         << "\n";
    4529              : #endif
    4530       698834 :     if (ego->getLaneChangeModel().isOpposite()) {
    4531       414100 :         std::pair<MSVehicle* const, double> result = getFollower(ego, getOppositePos(ego->getPositionOnLane()), -1, MinorLinkMode::FOLLOW_NEVER);
    4532       414100 :         return result;
    4533              :     } else {
    4534       284734 :         double vehPos = getOppositePos(ego->getPositionOnLane() - ego->getVehicleType().getLength());
    4535       284734 :         std::pair<MSVehicle*, double> result = getLeader(ego, vehPos, std::vector<MSLane*>());
    4536       284734 :         double dist = getMaximumBrakeDist() + getOppositePos(ego->getPositionOnLane() - getLength());
    4537              :         MSLane* next = const_cast<MSLane*>(this);
    4538       522851 :         while (result.first == nullptr && dist > 0) {
    4539              :             // cannot call getLeadersOnConsecutive because succLinkSec doesn't
    4540              :             // uses the vehicle's route and doesn't work on the opposite side
    4541       298579 :             vehPos -= next->getLength();
    4542       298579 :             next = next->getCanonicalSuccessorLane();
    4543       298579 :             if (next == nullptr) {
    4544              :                 break;
    4545              :             }
    4546       238117 :             dist -= next->getLength();
    4547       238117 :             result = next->getLeader(ego, vehPos, std::vector<MSLane*>());
    4548              :         }
    4549       284734 :         if (result.first != nullptr) {
    4550       219840 :             if (result.first->getLaneChangeModel().isOpposite()) {
    4551        80762 :                 result.second -= result.first->getVehicleType().getLength();
    4552              :             } else {
    4553       139078 :                 if (result.second > POSITION_EPS) {
    4554              :                     // follower can be safely ignored since it is going the other way
    4555       130968 :                     return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
    4556              :                 }
    4557              :             }
    4558              :         }
    4559       153766 :         return result;
    4560              :     }
    4561              : }
    4562              : 
    4563              : void
    4564        85892 : MSLane::initCollisionAction(const OptionsCont& oc, const std::string& option, CollisionAction& myAction) {
    4565        85892 :     const std::string action = oc.getString(option);
    4566        85892 :     if (action == "none") {
    4567           15 :         myAction = COLLISION_ACTION_NONE;
    4568        85877 :     } else if (action == "warn") {
    4569        43753 :         myAction = COLLISION_ACTION_WARN;
    4570        42124 :     } else if (action == "teleport") {
    4571        42089 :         myAction = COLLISION_ACTION_TELEPORT;
    4572           35 :     } else if (action == "remove") {
    4573           35 :         myAction = COLLISION_ACTION_REMOVE;
    4574              :     } else {
    4575            0 :         WRITE_ERROR(TLF("Invalid % '%'.", option, action));
    4576              :     }
    4577        85892 : }
    4578              : 
    4579              : void
    4580        42946 : MSLane::initCollisionOptions(const OptionsCont& oc) {
    4581        42946 :     initCollisionAction(oc, "collision.action", myCollisionAction);
    4582        42946 :     initCollisionAction(oc, "intermodal-collision.action", myIntermodalCollisionAction);
    4583        42946 :     myCheckJunctionCollisions = oc.getBool("collision.check-junctions");
    4584        42946 :     myCheckJunctionCollisionMinGap = oc.getFloat("collision.check-junctions.mingap");
    4585        42946 :     myCollisionStopTime = string2time(oc.getString("collision.stoptime"));
    4586        42946 :     myIntermodalCollisionStopTime = string2time(oc.getString("intermodal-collision.stoptime"));
    4587        42946 :     myCollisionMinGapFactor = oc.getFloat("collision.mingap-factor");
    4588        42946 :     myExtrapolateSubstepDepart = oc.getBool("extrapolate-departpos");
    4589        42946 : }
    4590              : 
    4591              : 
    4592              : void
    4593          986 : MSLane::setPermissions(SVCPermissions permissions, long long transientID) {
    4594          986 :     if (transientID == CHANGE_PERMISSIONS_PERMANENT) {
    4595           83 :         myPermissions = permissions;
    4596           83 :         myOriginalPermissions = permissions;
    4597              :     } else {
    4598          903 :         myPermissionChanges[transientID] = permissions;
    4599          903 :         resetPermissions(CHANGE_PERMISSIONS_PERMANENT);
    4600              :     }
    4601          986 : }
    4602              : 
    4603              : 
    4604              : void
    4605         1184 : MSLane::resetPermissions(long long transientID) {
    4606              :     myPermissionChanges.erase(transientID);
    4607         1184 :     if (myPermissionChanges.empty()) {
    4608          267 :         myPermissions = myOriginalPermissions;
    4609              :     } else {
    4610              :         // combine all permission changes
    4611          917 :         myPermissions = SVCAll;
    4612         1848 :         for (const auto& item : myPermissionChanges) {
    4613          931 :             myPermissions &= item.second;
    4614              :         }
    4615              :     }
    4616         1184 : }
    4617              : 
    4618              : 
    4619              : bool
    4620     12368868 : MSLane::hadPermissionChanges() const {
    4621     12368868 :     return !myPermissionChanges.empty();
    4622              : }
    4623              : 
    4624              : 
    4625              : void
    4626            9 : MSLane::setChangeLeft(SVCPermissions permissions) {
    4627            9 :     myChangeLeft = permissions;
    4628            9 : }
    4629              : 
    4630              : 
    4631              : void
    4632            9 : MSLane::setChangeRight(SVCPermissions permissions) {
    4633            9 :     myChangeRight = permissions;
    4634            9 : }
    4635              : 
    4636              : 
    4637              : bool
    4638     52914745 : MSLane::hasPedestrians() const {
    4639     52914745 :     MSNet* const net = MSNet::getInstance();
    4640     52914745 :     return net->hasPersons() && net->getPersonControl().getMovementModel()->hasPedestrians(this);
    4641              : }
    4642              : 
    4643              : 
    4644              : PersonDist
    4645       694727 : MSLane::nextBlocking(double minPos, double minRight, double maxLeft, double stopTime, bool bidi) const {
    4646       694727 :     return MSNet::getInstance()->getPersonControl().getMovementModel()->nextBlocking(this, minPos, minRight, maxLeft, stopTime, bidi);
    4647              : }
    4648              : 
    4649              : 
    4650              : bool
    4651      3933256 : MSLane::checkForPedestrians(const MSVehicle* aVehicle, double& speed, double& dist,  double pos, bool patchSpeed) const {
    4652      3933256 :     if (getEdge().getPersons().size() > 0 && hasPedestrians()) {
    4653              : #ifdef DEBUG_INSERTION
    4654              :         if (DEBUG_COND2(aVehicle)) {
    4655              :             std::cout << SIMTIME << " check for pedestrians on lane=" << getID() << " pos=" << pos << "\n";
    4656              :         }
    4657              : #endif
    4658         3914 :         PersonDist leader = nextBlocking(pos - aVehicle->getVehicleType().getLength(),
    4659         1957 :                                          aVehicle->getRightSideOnLane(), aVehicle->getRightSideOnLane() + aVehicle->getVehicleType().getWidth(), ceil(speed / aVehicle->getCarFollowModel().getMaxDecel()));
    4660         1957 :         if (leader.first != 0) {
    4661          846 :             const double gap = leader.second - aVehicle->getVehicleType().getLengthWithGap();
    4662          846 :             const double stopSpeed = aVehicle->getCarFollowModel().stopSpeed(aVehicle, speed, gap, MSCFModel::CalcReason::FUTURE);
    4663          325 :             if ((gap < 0 && (aVehicle->getInsertionChecks() & ((int)InsertionCheck::COLLISION | (int)InsertionCheck::PEDESTRIAN)) != 0)
    4664         1692 :                     || checkFailure(aVehicle, speed, dist, stopSpeed, patchSpeed, "", InsertionCheck::PEDESTRIAN)) {
    4665              :                 // we may not drive with the given velocity - we crash into the pedestrian
    4666              : #ifdef DEBUG_INSERTION
    4667              :                 if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
    4668              :                                                          << " isInsertionSuccess lane=" << getID()
    4669              :                                                          << " veh=" << aVehicle->getID()
    4670              :                                                          << " pos=" << pos
    4671              :                                                          << " posLat=" << aVehicle->getLateralPositionOnLane()
    4672              :                                                          << " patchSpeed=" << patchSpeed
    4673              :                                                          << " speed=" << speed
    4674              :                                                          << " stopSpeed=" << stopSpeed
    4675              :                                                          << " pedestrianLeader=" << leader.first->getID()
    4676              :                                                          << " failed (@796)!\n";
    4677              : #endif
    4678          539 :                 return false;
    4679              :             }
    4680              :         }
    4681              :     }
    4682      3932717 :     double backLength = aVehicle->getLength() - pos;
    4683      3932717 :     if (backLength > 0 && MSNet::getInstance()->hasPersons()) {
    4684              :         // look upstream for pedestrian crossings
    4685         6962 :         const MSLane* prev = getLogicalPredecessorLane();
    4686              :         const MSLane* cur = this;
    4687        98894 :         while (backLength > 0 && prev != nullptr) {
    4688        91965 :             const MSLink* link = prev->getLinkTo(cur);
    4689        91965 :             if (link->hasFoeCrossing()) {
    4690         2273 :                 for (const MSLane* foe : link->getFoeLanes()) {
    4691         1760 :                     if (foe->isCrossing() && (foe->hasPedestrians() ||
    4692          707 :                                               (foe->getIncomingLanes()[0].viaLink->getApproachingPersons() != nullptr
    4693           47 :                                                && foe->getIncomingLanes()[0].viaLink->getApproachingPersons()->size() > 0))) {
    4694              : #ifdef DEBUG_INSERTION
    4695              :                         if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
    4696              :                                                                  << " isInsertionSuccess lane=" << getID()
    4697              :                                                                  << " veh=" << aVehicle->getID()
    4698              :                                                                  << " pos=" << pos
    4699              :                                                                  << " backCrossing=" << foe->getID()
    4700              :                                                                  << " peds=" << joinNamedToString(foe->getEdge().getPersons(), " ")
    4701              :                                                                  << " approaching=" << foe->getIncomingLanes()[0].viaLink->getApproachingPersons()->size()
    4702              :                                                                  << " failed (@4550)!\n";
    4703              : #endif
    4704              :                         return false;
    4705              :                     }
    4706              :                 }
    4707              :             }
    4708        91932 :             backLength -= prev->getLength();
    4709              :             cur = prev;
    4710        91932 :             prev = prev->getLogicalPredecessorLane();
    4711              :         }
    4712              :     }
    4713              :     return true;
    4714              : }
    4715              : 
    4716              : 
    4717              : void
    4718        42948 : MSLane::initRNGs(const OptionsCont& oc) {
    4719              :     myRNGs.clear();
    4720        42948 :     const int numRNGs = oc.getInt("thread-rngs");
    4721        42948 :     const bool random = oc.getBool("random");
    4722        42948 :     int seed = oc.getInt("seed");
    4723        42948 :     myRNGs.reserve(numRNGs); // this is needed for stable pointers on debugging
    4724      2791620 :     for (int i = 0; i < numRNGs; i++) {
    4725      5497344 :         myRNGs.push_back(SumoRNG("lanes_" + toString(i)));
    4726      2748672 :         RandHelper::initRand(&myRNGs.back(), random, seed++);
    4727              :     }
    4728        42948 : }
    4729              : 
    4730              : void
    4731           46 : MSLane::saveRNGStates(OutputDevice& out) {
    4732         2990 :     for (int i = 0; i < getNumRNGs(); i++) {
    4733         2944 :         out.openTag(SUMO_TAG_RNGLANE);
    4734         2944 :         out.writeAttr(SUMO_ATTR_INDEX, i);
    4735         2944 :         out.writeAttr(SUMO_ATTR_STATE, RandHelper::saveState(&myRNGs[i]));
    4736         5888 :         out.closeTag();
    4737              :     }
    4738           46 : }
    4739              : 
    4740              : void
    4741         2944 : MSLane::loadRNGState(int index, const std::string& state) {
    4742         2944 :     if (index >= getNumRNGs()) {
    4743            0 :         throw ProcessError(TLF("State was saved with more than % threads. Change the number of threads or do not load RNG state", toString(getNumRNGs())));
    4744              :     }
    4745         2944 :     RandHelper::loadState(state, &myRNGs[index]);
    4746         2944 : }
    4747              : 
    4748              : 
    4749              : MSLane*
    4750  18570917711 : MSLane::getBidiLane() const {
    4751  18570917711 :     return myBidiLane;
    4752              : }
    4753              : 
    4754              : 
    4755              : bool
    4756    125367581 : MSLane::mustCheckJunctionCollisions() const {
    4757    125367581 :     return myCheckJunctionCollisions && myEdge->isInternal() && (
    4758      1483066 :                myLinks.front()->getFoeLanes().size() > 0
    4759         6581 :                || myLinks.front()->getWalkingAreaFoe() != nullptr
    4760         5673 :                || myLinks.front()->getWalkingAreaFoeExit() != nullptr);
    4761              : }
    4762              : 
    4763              : 
    4764              : double
    4765    620907247 : MSLane::getSpaceTillLastStanding(const MSVehicle* ego, bool& foundStopped) const {
    4766              :     /// @todo if ego isn't on this lane, we could use a cached value
    4767              :     double lengths = 0;
    4768   5004310461 :     for (const MSVehicle* last : myVehicles) {
    4769   4446542978 :         if (last->getSpeed() < SUMO_const_haltingSpeed && !last->getLane()->getEdge().isRoundabout()
    4770     30949343 :                 && last != ego
    4771              :                 // @todo recheck
    4772   4445275838 :                 && last->isFrontOnLane(this)) {
    4773     30936312 :             foundStopped = true;
    4774     30936312 :             const double lastBrakeGap = last->getCarFollowModel().brakeGap(last->getSpeed());
    4775     30936312 :             const double ret = last->getBackPositionOnLane() + lastBrakeGap - lengths;
    4776              :             return ret;
    4777              :         }
    4778   4383403214 :         if (MSGlobals::gSublane && ego->getVehicleType().getWidth() + last->getVehicleType().getWidth() < getWidth()) {
    4779     30859735 :             lengths += last->getVehicleType().getLengthWithGap() * (last->getVehicleType().getWidth() + last->getVehicleType().getMinGapLat()) / getWidth();
    4780              :         } else {
    4781   4352543479 :             lengths += last->getVehicleType().getLengthWithGap();
    4782              :         }
    4783              :     }
    4784    589970935 :     return getLength() - lengths;
    4785              : }
    4786              : 
    4787              : 
    4788              : bool
    4789    500507267 : MSLane::allowsVehicleClass(SUMOVehicleClass vclass, int routingMode) const {
    4790    500507267 :     return (((routingMode & libsumo::ROUTING_MODE_IGNORE_TRANSIENT_PERMISSIONS) ? myOriginalPermissions : myPermissions) & vclass) == vclass;
    4791              : }
    4792              : 
    4793              : 
    4794              : const MSJunction*
    4795       113097 : MSLane::getFromJunction() const {
    4796       113097 :     return myEdge->getFromJunction();
    4797              : }
    4798              : 
    4799              : 
    4800              : const MSJunction*
    4801       211965 : MSLane::getToJunction() const {
    4802       211965 :     return myEdge->getToJunction();
    4803              : }
    4804              : 
    4805              : 
    4806              : bool
    4807        11019 : MSLane::mayContinue(const MSVehicle* veh) const {
    4808        11019 :     if (veh->getDevice(typeid(MSDevice_Taxi)) != nullptr) {
    4809              :         // taxi device may assign a new route that continues past the end of the initial route
    4810              :         return true;
    4811              :     }
    4812        21815 :     for (const MSMoveReminder* rem : myMoveReminders) {
    4813        12504 :         if (dynamic_cast<const MSTriggeredRerouter*>(rem) != nullptr) {
    4814              :             return true;
    4815              :         }
    4816              :     }
    4817              :     return false;
    4818              : }
    4819              : 
    4820              : 
    4821              : bool
    4822         1708 : MSLane::hasUnsafeLink() const {
    4823         3365 :     for (const MSLink* link : myLinks) {
    4824         3200 :         if (!link->havePriority() || link->getState() == LINKSTATE_ZIPPER) {
    4825              :             return true;
    4826              :         }
    4827              :     }
    4828              :     return false;
    4829              : }
    4830              : 
    4831              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1