LCOV - code coverage report
Current view: top level - src/microsim - MSLane.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 97.5 % 1847 1801
Test Date: 2026-03-02 16:00:03 Functions: 96.7 % 152 147

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

Generated by: LCOV version 2.0-1