/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file MSLane.h14/// @author Christian Roessel15/// @author Daniel Krajzewicz16/// @author Jakob Erdmann17/// @author Christoph Sommer18/// @author Tino Morenz19/// @author Michael Behrisch20/// @author Mario Krumnow21/// @author Leonhard Luecken22/// @date Mon, 12 Mar 200123///24// Representation of a lane in the micro simulation25/****************************************************************************/26#pragma once27#include <config.h>2829#include <memory>30#include <vector>31#include <map>32#include <deque>33#include <cassert>34#include <utils/common/Named.h>35#include <utils/common/Parameterised.h>36#include <utils/common/SUMOVehicleClass.h>37#include <utils/vehicle/SUMOVehicle.h>38#include <utils/common/NamedRTree.h>39#include <utils/emissions/PollutantsInterface.h>40#include <utils/geom/PositionVector.h>41#include "MSGlobals.h"42#include "MSLeaderInfo.h"43#include "MSMoveReminder.h"44#include "MSVehicle.h"4546#include <utils/foxtools/MFXSynchQue.h>47#ifdef HAVE_FOX48#include <utils/foxtools/MFXWorkerThread.h>49#endif50#include <utils/common/StopWatch.h>515253// ===========================================================================54// class declarations55// ===========================================================================56class MSEdge;57class MSBaseVehicle;58class MSLaneChanger;59class MSLink;60class MSVehicleTransfer;61class MSVehicleControl;62class OutputDevice;63class MSLeaderInfo;64class MSJunction;656667// ===========================================================================68// type definitions69// ===========================================================================70/// Coverage info71typedef std::map<const MSLane*, std::pair<double, double> > LaneCoverageInfo;7273// ===========================================================================74// class definitions75// ===========================================================================76/**77* @class MSLane78* @brief Representation of a lane in the micro simulation79*80* Class which represents a single lane. Somekind of the main class of the81* simulation. Allows moving vehicles.82*/83class MSLane : public Named, public Parameterised {84public:85class StoringVisitor {86public:87/// @brief Constructor88StoringVisitor(std::set<const Named*>& objects, const PositionVector& shape,89const double range, const int domain)90: myObjects(objects), myShape(shape), myRange(range), myDomain(domain) {}9192/// @brief Adds the given object to the container93void add(const MSLane* const l) const;9495private:96/// @brief The container97std::set<const Named*>& myObjects;98const PositionVector& myShape;99const double myRange;100const int myDomain;101102private:103/// @brief invalidated copy constructor104StoringVisitor(const StoringVisitor& src);105106/// @brief invalidated assignment operator107StoringVisitor& operator=(const StoringVisitor& src);108};109110/// needs access to myTmpVehicles (this maybe should be done via double-buffering!!!)111friend class MSLaneChanger;112friend class MSLaneChangerSublane;113114friend class MSQueueExport;115friend class AnyVehicleIterator;116117/// Container for vehicles.118typedef std::vector<MSVehicle*> VehCont;119120// TODO: Better documentation121/// @brief AnyVehicleIterator is a structure, which manages the iteration through all vehicles on the lane,122/// that may be of importance for the car-following dynamics along that lane. The relevant types of vehicles are:123/// 1) vehicles with their front on the lane (myVehicles),124/// 2) vehicles intersecting the lane but with front on another lane (myPartialVehicles)125///126/// In the context of retrieving linkLeaders during lane changing a third group of vehicles is checked:127/// 3) vehicles processed during lane changing (myTmpVehicles)128class AnyVehicleIterator {129public:130AnyVehicleIterator(131const MSLane* lane,132int i1,133int i2,134int i3,135const int i1End,136const int i2End,137const int i3End,138bool downstream = true) :139myLane(lane),140myI1(i1),141myI2(i2),142myI3(i3),143myI1End(i1End),144myI2End(i2End),145myI3End(i3End),146myDownstream(downstream),147myDirection(downstream ? 1 : -1) {148}149150bool operator== (AnyVehicleIterator const& other) const {151return (myI1 == other.myI1152&& myI2 == other.myI2153&& myI3 == other.myI3154&& myI1End == other.myI1End155&& myI2End == other.myI2End156&& myI3End == other.myI3End);157}158159bool operator!= (AnyVehicleIterator const& other) const {160return !(*this == other);161}162163const MSVehicle* operator->() {164return **this;165}166167const MSVehicle* operator*();168169AnyVehicleIterator& operator++();170171private:172bool nextIsMyVehicles() const;173174/// @brief the lane that is being iterated175const MSLane* myLane;176/// @brief index for myVehicles177int myI1;178/// @brief index for myPartialVehicles179int myI2;180/// @brief index for myTmpVehicles181int myI3;182/// @brief end index for myVehicles183int myI1End;184/// @brief end index for myPartialVehicles185int myI2End;186/// @brief end index for myTmpVehicles187int myI3End;188/// @brief iteration direction189bool myDownstream;190/// @brief index delta191int myDirection;192193};194195196public:197/** @enum ChangeRequest198* @brief Requests set via TraCI199*/200enum CollisionAction {201COLLISION_ACTION_NONE,202COLLISION_ACTION_WARN,203COLLISION_ACTION_TELEPORT,204COLLISION_ACTION_REMOVE205};206207/** @brief Constructor208*209* @param[in] id The lane's id210* @param[in] maxSpeed The speed allowed on this lane211* @param[in] friction The friction of this lane212* @param[in] length The lane's length213* @param[in] edge The edge this lane belongs to214* @param[in] numericalID The numerical id of the lane215* @param[in] shape The shape of the lane216* @param[in] width The width of the lane217* @param[in] permissions Encoding of the Vehicle classes that may drive on this lane218* @param[in] index The index of this lane within its parent edge219* @param[in] isRampAccel Whether this lane is an acceleration lane220* @see SUMOVehicleClass221*/222MSLane(const std::string& id, double maxSpeed, double friction, double length, MSEdge* const edge,223int numericalID, const PositionVector& shape, double width,224SVCPermissions permissions,225SVCPermissions changeLeft, SVCPermissions changeRight,226int index, bool isRampAccel,227const std::string& type,228const PositionVector& outlineShape);229230231/// @brief Destructor232virtual ~MSLane();233234/// @brief returns the associated thread index235inline int getThreadIndex() const {236return myRNGIndex % MSGlobals::gNumSimThreads;237}238239/// @brief returns the associated RNG index240inline int getRNGIndex() const {241return myRNGIndex;242}243244/// @brief return the associated RNG245SumoRNG* getRNG() const {246return &myRNGs[myRNGIndex];247}248249/// @brief return the number of RNGs250static int getNumRNGs() {251return (int)myRNGs.size();252}253254/// @brief save random number generator states to the given output device255static void saveRNGStates(OutputDevice& out);256257/// @brief load random number generator state for the given rng index258static void loadRNGState(int index, const std::string& state);259260/// @name Additional initialisation261/// @{262263/** @brief Delayed initialization264*265* Not all lane-members are known at the time the lane is born, above all the pointers266* to other lanes, so we have to add them later.267*268* @param[in] link An outgoing link269*/270void addLink(MSLink* link);271272/** @brief Adds a neighbor to this lane273*274* @param[in] id The lane's id275*/276void setOpposite(MSLane* oppositeLane);277278/** @brief Adds the (overlapping) reverse direction lane to this lane279*280* @param[in] id The lane's id281*/282void setBidiLane(MSLane* bidyLane);283///@}284285/// @name Used by the GUI for secondary shape visualization286/// @{287virtual void addSecondaryShape(const PositionVector& /*shape*/) {}288289virtual double getLengthGeometryFactor(bool /*secondaryShape*/) const {290return myLengthGeometryFactor;291}292293virtual const PositionVector& getShape(bool /*secondaryShape*/) const {294return myShape;295}296///@}297298virtual void updateMesoGUISegments() {}299300/// @name interaction with MSMoveReminder301/// @{302303/** @brief Add a move-reminder to move-reminder container304*305* The move reminder will not be deleted by the lane.306*307* @param[in] rem The move reminder to add308*/309virtual void addMoveReminder(MSMoveReminder* rem, bool addToVehicles = true);310311312/** @brief Remove a move-reminder from move-reminder container313*314* The move reminder will not be deleted by the lane.315* @param[in] rem The move reminder to remvoe316*/317virtual void removeMoveReminder(MSMoveReminder* rem);318319320/** @brief Return the list of this lane's move reminders321* @return Previously added move reminder322*/323inline const std::vector< MSMoveReminder* >& getMoveReminders() const {324return myMoveReminders;325}326///@}327328329330/// @name Vehicle insertion331///@{332333/** @brief Tries to insert the given vehicle334*335* The insertion position and speed are determined in dependence336* to the vehicle's departure definition, first.337*338* Then, the vehicle is tried to be inserted into the lane339* using these values by a call to "isInsertionSuccess". The result of340* "isInsertionSuccess" is returned.341*342* @param[in] v The vehicle to insert343* @return Whether the vehicle could be inserted344* @see isInsertionSuccess345* @see MSVehicle::getDepartureDefinition346* @see MSVehicle::DepartArrivalDefinition347*/348bool insertVehicle(MSVehicle& v);349350351/** @brief Tries to insert the given vehicle with the given state (speed and pos)352*353* Checks whether the vehicle can be inserted at the given position with the354* given speed so that no collisions with leader/follower occur and the speed355* does not cause unexpected behaviour on consecutive lanes. Returns false356* if the vehicle can not be inserted.357*358* If the insertion can take place, incorporateVehicle() is called and true is returned.359*360* @param[in] vehicle The vehicle to insert361* @param[in] speed The speed with which it shall be inserted362* @param[in] pos The position at which it shall be inserted363* @param[in] posLat The lateral position at which it shall be inserted364* @param[in] recheckNextLanes Forces patching the speed for not being too fast on next lanes365* @param[in] notification The cause of insertion (i.e. departure, teleport, parking) defaults to departure366* @return Whether the vehicle could be inserted367* @see MSVehicle::enterLaneAtInsertion368*/369bool isInsertionSuccess(MSVehicle* vehicle, double speed, double pos, double posLat,370bool recheckNextLanes,371MSMoveReminder::Notification notification);372373// XXX: Documentation?374bool checkFailure(const MSVehicle* aVehicle, double& speed, double& dist, const double nspeed, const bool patchSpeed, const std::string errorMsg, InsertionCheck check) const;375376/** @brief inserts vehicle as close as possible to the last vehicle on this377* lane (or at the end of the lane if there is no leader)378*/379bool lastInsertion(MSVehicle& veh, double mspeed, double posLat, bool patchSpeed);380381/** @brief Tries to insert the given vehicle on any place382*383* @param[in] veh The vehicle to insert384* @param[in] speed The maximum insertion speed385* @param[in] notification The cause of insertion (i.e. departure, teleport, parking) defaults to departure386* @return Whether the vehicle could be inserted387*/388bool freeInsertion(MSVehicle& veh, double speed, double posLat,389MSMoveReminder::Notification notification = MSMoveReminder::NOTIFICATION_DEPARTED);390391392/** @brief Inserts the given vehicle at the given position393*394* No checks are done, vehicle insertion using this method may395* generate collisions (possibly delayed).396* @param[in] veh The vehicle to insert397* @param[in] pos The position at which the vehicle shall be inserted398* @param[in] notification The cause of insertion (i.e. departure, teleport, parking) defaults to departure399* @param[in] posLat The lateral position at which the vehicle shall be inserted400*/401void forceVehicleInsertion(MSVehicle* veh, double pos, MSMoveReminder::Notification notification, double posLat = 0);402/// @}403404405406/// @name Handling vehicles lapping into several lanes (-> partial occupation)407/// or which committed a maneuver that will lead them into another (sublane case -> maneuver reservations)408/// @{409/** @brief Sets the information about a vehicle lapping into this lane410*411* This vehicle is added to myVehicles and may be distinguished from regular412* vehicles by the disparity between this lane and v->getLane()413* @param[in] v The vehicle which laps into this lane414* @return This lane's length415*/416virtual double setPartialOccupation(MSVehicle* v);417418/** @brief Removes the information about a vehicle lapping into this lane419* @param[in] v The vehicle which laps into this lane420*/421virtual void resetPartialOccupation(MSVehicle* v);422423/** @brief Registers the lane change intentions (towards this lane) for the given vehicle424*/425virtual void setManeuverReservation(MSVehicle* v);426427/** @brief Unregisters a vehicle, which previously registered for maneuvering into this lane428* @param[in] v The vehicle429*/430virtual void resetManeuverReservation(MSVehicle* v);431432/** @brief Returns the last vehicles on the lane433*434* The information about the last vehicles in this lanes in all sublanes435* occupied by ego are436* returned. Partial occupators are included437* @param[in] ego The vehicle for which to restrict the returned leaderInfo438* @param[in] minPos The minimum position from which to start search for leaders439* @param[in] allowCached Whether the cached value may be used440* @return Information about the last vehicles441*/442const MSLeaderInfo getLastVehicleInformation(const MSVehicle* ego, double latOffset, double minPos = 0, bool allowCached = true) const;443444/// @brief analogue to getLastVehicleInformation but in the upstream direction445const MSLeaderInfo getFirstVehicleInformation(const MSVehicle* ego, double latOffset, bool onlyFrontOnLane, double maxPos = std::numeric_limits<double>::max(), bool allowCached = true) const;446447/// @}448449/// @name Access to vehicles450/// @{451452/** @brief Returns the number of vehicles on this lane (for which this lane453* is responsible)454* @return The number of vehicles with their front on this lane455*/456int getVehicleNumber() const {457return (int)myVehicles.size();458}459460/** @brief Returns the number of vehicles on this lane (including partial461* occupators)462* @return The number of vehicles with intersecting this lane463*/464int getVehicleNumberWithPartials() const {465return (int)myVehicles.size() + (int)myPartialVehicles.size();466}467468/** @brief Returns the number of vehicles partially on this lane (for which this lane469* is not responsible)470* @return The number of vehicles touching this lane but with their front on another lane471*/472int getPartialVehicleNumber() const {473return (int)myPartialVehicles.size();474}475476477/** @brief Returns the vehicles container; locks it for microsimulation478*479* Please note that it is necessary to release the vehicles container480* afterwards using "releaseVehicles".481* @return The vehicles on this lane482*/483virtual const VehCont& getVehiclesSecure() const {484return myVehicles;485}486487488/// @brief begin iterator for iterating over all vehicles touching this lane in downstream direction489AnyVehicleIterator anyVehiclesBegin() const {490return AnyVehicleIterator(this, 0, 0, 0,491(int)myVehicles.size(), (int)myPartialVehicles.size(), (int)myTmpVehicles.size(), true);492}493494/// @brief end iterator for iterating over all vehicles touching this lane in downstream direction495AnyVehicleIterator anyVehiclesEnd() const {496return AnyVehicleIterator(this, (int)myVehicles.size(), (int)myPartialVehicles.size(), (int)myTmpVehicles.size(),497(int)myVehicles.size(), (int)myPartialVehicles.size(), (int)myTmpVehicles.size(), true);498}499500/// @brief begin iterator for iterating over all vehicles touching this lane in upstream direction501AnyVehicleIterator anyVehiclesUpstreamBegin() const {502return AnyVehicleIterator(this, (int)myVehicles.size() - 1, (int)myPartialVehicles.size() - 1, (int)myTmpVehicles.size() - 1,503-1, -1, -1, false);504}505506/// @brief end iterator for iterating over all vehicles touching this lane in upstream direction507AnyVehicleIterator anyVehiclesUpstreamEnd() const {508return AnyVehicleIterator(this, -1, -1, -1, -1, -1, -1, false);509}510511/** @brief Allows to use the container for microsimulation again512*/513virtual void releaseVehicles() const { }514/// @}515516517518/// @name Atomar value getter519/// @{520521522/** @brief Returns this lane's numerical id523* @return This lane's numerical id524*/525inline int getNumericalID() const {526return myNumericalID;527}528529530/** @brief Returns this lane's shape531* @return This lane's shape532*/533inline const PositionVector& getShape() const {534return myShape;535}536537/// @brief return shape.length() / myLength538inline double getLengthGeometryFactor() const {539return myLengthGeometryFactor;540}541542/// @brief return whether this lane is an acceleration lane543inline bool isAccelLane() const {544return myIsRampAccel;545}546547/// @brief return the type of this lane548const std::string& getLaneType() const {549return myLaneType;550}551552/* @brief fit the given lane position to a visibly suitable geometry position553* (lane length might differ from geometry length) */554inline double interpolateLanePosToGeometryPos(double lanePos) const {555return lanePos * myLengthGeometryFactor;556}557558/* @brief fit the given lane position to a visibly suitable geometry position559* and return the coordinates */560inline const Position geometryPositionAtOffset(double offset, double lateralOffset = 0) const {561return myShape.positionAtOffset(interpolateLanePosToGeometryPos(offset), lateralOffset);562}563564/* @brief fit the given geometry position to a valid lane position565* (lane length might differ from geometry length) */566inline double interpolateGeometryPosToLanePos(double geometryPos) const {567return geometryPos / myLengthGeometryFactor;568}569570/** @brief Returns the lane's maximum speed, given a vehicle's speed limit adaptation571* @param[in] The vehicle to return the adapted speed limit for572* @return This lane's resulting max. speed573*/574inline double getVehicleMaxSpeed(const SUMOTrafficObject* const veh) const {575return getVehicleMaxSpeed(veh, veh->getMaxSpeed());576}577578579inline double getVehicleMaxSpeed(const SUMOTrafficObject* const veh, double vehMaxSpeed) const {580if (myRestrictions != nullptr) {581std::map<SUMOVehicleClass, double>::const_iterator r = myRestrictions->find(veh->getVClass());582if (r != myRestrictions->end()) {583if (mySpeedByVSS || mySpeedByTraCI) {584return MIN2(myMaxSpeed, MIN2(vehMaxSpeed, r->second * veh->getChosenSpeedFactor()));585} else {586return MIN2(vehMaxSpeed, r->second * veh->getChosenSpeedFactor());587}588}589}590return MIN2(vehMaxSpeed, myMaxSpeed * veh->getChosenSpeedFactor());591}592593594/** @brief Returns the lane's maximum allowed speed595* @return This lane's maximum allowed speed596*/597inline double getSpeedLimit() const {598return myMaxSpeed;599}600601/** @brief Returns the lane's friction coefficient602* @return This lane's friction coefficient603*/604inline double getFrictionCoefficient() const {605return myFrictionCoefficient;606}607608/** @brief Returns the lane's length609* @return This lane's length610*/611inline double getLength() const {612return myLength;613}614615616/** @brief Returns the vehicle class permissions for this lane617* @return This lane's allowed vehicle classes618*/619inline SVCPermissions getPermissions() const {620return myPermissions;621}622623/** @brief Returns the vehicle class permissions for changing to the left neighbour lane624* @return The vehicle classes allowed to change to the left neighbour lane625*/626inline SVCPermissions getChangeLeft() const {627return myChangeLeft;628}629630/** @brief Returns the vehicle class permissions for changing to the right neighbour lane631* @return The vehicle classes allowed to change to the right neighbour lane632*/633inline SVCPermissions getChangeRight() const {634return myChangeRight;635}636637/** @brief Returns the lane's width638* @return This lane's width639*/640double getWidth() const {641return myWidth;642}643644/** @brief Returns the lane's index645* @return This lane's index646*/647int getIndex() const {648return myIndex;649}650/// @}651652/// @brief return the index of the link to the next crossing if this is walkingArea, else -1653int getCrossingIndex() const;654655656/// @name Vehicle movement (longitudinal)657/// @{658659/** @brief Compute safe velocities for all vehicles based on positions and660* speeds from the last time step. Also registers661* ApproachingVehicleInformation for all links662*663* This method goes through all vehicles calling their "planMove" method.664* @see MSVehicle::planMove665*/666virtual void planMovements(const SUMOTime t);667668/** @brief Register junction approaches for all vehicles after velocities669* have been planned.670*671* This method goes through all vehicles calling their * "setApproachingForAllLinks" method.672*/673virtual void setJunctionApproaches() const;674675/** @brief This updates the MSLeaderInfo argument with respect to the given MSVehicle.676* All leader-vehicles on the same edge, which are relevant for the vehicle677* (i.e. with position > vehicle's position) and not already integrated into678* the LeaderInfo, are integrated.679* The given iterators vehPart and vehRes give access to these vehicles which are680* either partial occupators or have issued a maneuver reservation for the lane681* (the latter occurs only for the sublane model).682*/683void updateLeaderInfo(const MSVehicle* veh, VehCont::reverse_iterator& vehPart, VehCont::reverse_iterator& vehRes, MSLeaderInfo& ahead) const;684685/** @brief Executes planned vehicle movements with regards to right-of-way686*687* This method goes through all vehicles calling their executeMove method688* which causes vehicles to update their positions and speeds.689* Vehicles wich move to the next lane are stored in the targets lane buffer690*691* @return Returns true, if all vehicles left the lane.692*693* @see MSVehicle::executeMove694*/695virtual void executeMovements(const SUMOTime t);696697/// Insert buffered vehicle into the real lane.698virtual void integrateNewVehicles();699700/** @brief Set a flag to recalculate the brutto (including minGaps) occupancy of this lane (used if mingap is changed)701*/702void markRecalculateBruttoSum();703704/// @brief updated current vehicle length sum (delayed to avoid lane-order-dependency)705void updateLengthSum();706///@}707708709/// @brief short-circut collision check if nothing changed since the last check710inline bool needsCollisionCheck() const {711return myNeedsCollisionCheck;712}713714/// @brief require another collision check due to relevant changes in the simulation715inline void requireCollisionCheck() {716myNeedsCollisionCheck = true;717}718719/// Check if vehicles are too close.720virtual void detectCollisions(SUMOTime timestep, const std::string& stage);721722723/** Returns the information whether this lane may be used to continue724the current route */725virtual bool appropriate(const MSVehicle* veh) const;726727728/// returns the container with all links !!!729const std::vector<MSLink*>& getLinkCont() const {730return myLinks;731}732733/// returns the link to the given lane or nullptr, if it is not connected734const MSLink* getLinkTo(const MSLane* const) const;735736/// returns the internal lane leading to the given lane or nullptr, if there is none737const MSLane* getInternalFollowingLane(const MSLane* const) const;738739/// Returns the entry link if this is an internal lane, else nullptr740const MSLink* getEntryLink() const;741742743/// Returns true if there is not a single vehicle on the lane.744bool empty() const {745assert(myVehBuffer.size() == 0);746return myVehicles.empty();747}748749/** @brief Sets a new maximum speed for the lane (used by TraCI and MSCalibrator)750* @param[in] val the new speed in m/s751* @param[in] whether a variable speed sign (VSS) imposes the speed limit752* @param[in] whether TraCI imposes the speed limit753*/754void setMaxSpeed(double val, bool byVSS = false, bool byTraCI = false, double jamThreshold = -1);755756/** @brief Sets a new friction coefficient for the lane [*to be later (used by TraCI and MSCalibrator)*]757* @param[in] val the new friction coefficient [0..1]758*/759void setFrictionCoefficient(double val);760761/** @brief Sets a new length for the lane (used by TraCI only)762* @param[in] val the new length in m763*/764void setLength(double val);765766/** @brief Returns the lane's edge767* @return This lane's edge768*/769MSEdge& getEdge() const {770return *myEdge;771}772773const MSJunction* getFromJunction() const;774const MSJunction* getToJunction() const;775776/** @brief Returns the lane's follower if it is an internal lane, the edge of the lane otherwise777* @return This lane's follower778*/779const MSEdge* getNextNormal() const;780781782/** @brief Returns 0 if the lane is not internal. Otherwise the first part of the783* connection (sequence of internal lanes along junction) corresponding to the lane784* is returned and the offset is set to the distance of the begin of this lane785* to the begin of the returned.786*/787const MSLane* getFirstInternalInConnection(double& offset) const;788789790/// @brief Static (sic!) container methods791/// {792793/** @brief Inserts a MSLane into the static dictionary794*795* Returns true if the key id isn't already in the dictionary.796* Otherwise returns false.797* @param[in] id The id of the lane798* @param[in] lane The lane itself799* @return Whether the lane was added800* @todo make non-static801* @todo why is the id given? The lane is named802*/803static bool dictionary(const std::string& id, MSLane* lane);804805806/** @brief Returns the MSLane associated to the key id807*808* The lane is returned if exists, otherwise 0 is returned.809* @param[in] id The id of the lane810* @return The lane811*/812static MSLane* dictionary(const std::string& id);813814815/** @brief Clears the dictionary */816static void clear();817818819/** @brief Returns the number of stored lanes820* @return The number of stored lanes821*/822static int dictSize() {823return (int)myDict.size();824}825826827/** @brief Adds the ids of all stored lanes into the given vector828* @param[in, filled] into The vector to add the IDs into829*/830static void insertIDs(std::vector<std::string>& into);831832833/** @brief Fills the given RTree with lane instances834* @param[in, filled] into The RTree to fill835* @see TraCILaneRTree836*/837template<class RTREE>838static void fill(RTREE& into);839840841/// @brief initialize rngs842static void initRNGs(const OptionsCont& oc);843/// @}844845846847// XXX: succLink does not exist... Documentation?848/** Same as succLink, but does not throw any assertions when849the succeeding link could not be found;850Returns the myLinks.end() instead; Further, the number of edges to851look forward may be given */852static std::vector<MSLink*>::const_iterator succLinkSec(const SUMOVehicle& veh,853int nRouteSuccs,854const MSLane& succLinkSource,855const std::vector<MSLane*>& conts);856857858/** Returns the information whether the given link shows at the end859of the list of links (is not valid) */860inline bool isLinkEnd(std::vector<MSLink*>::const_iterator& i) const {861return i == myLinks.end();862}863864/** Returns the information whether the given link shows at the end865of the list of links (is not valid) */866inline bool isLinkEnd(std::vector<MSLink*>::iterator& i) {867return i == myLinks.end();868}869870/** Returns the information whether the lane is has no vehicle and no871partial occupation*/872inline bool isEmpty() const {873return myVehicles.empty() && myPartialVehicles.empty();874}875876/** Returns whether the lane pertains to an internal edge*/877bool isInternal() const;878879/** Returns whether the lane pertains to a normal edge*/880bool isNormal() const;881882/** Returns whether the lane pertains to a crossing edge*/883bool isCrossing() const;884885/** Returns whether the lane pertains to a crossing edge*/886bool isPriorityCrossing() const;887888/** Returns whether the lane pertains to a walkingarea*/889bool isWalkingArea() const;890891/// @brief returns the last vehicle for which this lane is responsible or 0892MSVehicle* getLastFullVehicle() const;893894/// @brief returns the first vehicle for which this lane is responsible or 0895MSVehicle* getFirstFullVehicle() const;896897/// @brief returns the last vehicle that is fully or partially on this lane898MSVehicle* getLastAnyVehicle() const;899900/// @brief returns the first vehicle that is fully or partially on this lane901MSVehicle* getFirstAnyVehicle() const;902903/* @brief remove the vehicle from this lane904* @param[notify] whether moveReminders of the vehicle shall be triggered905*/906virtual MSVehicle* removeVehicle(MSVehicle* remVehicle, MSMoveReminder::Notification notification, bool notify = true);907908void leftByLaneChange(MSVehicle* v);909void enteredByLaneChange(MSVehicle* v);910911/** @brief Returns the lane with the given offset parallel to this one or 0 if it does not exist912* @param[in] offset The offset of the result lane913*/914MSLane* getParallelLane(int offset, bool includeOpposite = true) const;915916917/** @brief Sets the permissions to the given value. If a transientID is given, the permissions are recored as temporary918* @param[in] permissions The new permissions919* @param[in] transientID The id of the permission-modification or the special value PERMANENT920*/921void setPermissions(SVCPermissions permissions, long long transientID);922void resetPermissions(long long transientID);923bool hadPermissionChanges() const;924925/** @brief Sets the permissions for changing to the left neighbour lane926* @param[in] permissions The new permissions927*/928void setChangeLeft(SVCPermissions permissions);929930/** @brief Sets the permissions for changing to the right neighbour lane931* @param[in] permissions The new permissions932*/933void setChangeRight(SVCPermissions permissions);934935inline bool allowsVehicleClass(SUMOVehicleClass vclass) const {936return (myPermissions & vclass) == vclass;937}938939bool allowsVehicleClass(SUMOVehicleClass vclass, int routingMode) const;940941/** @brief Returns whether the given vehicle class may change left from this lane */942inline bool allowsChangingLeft(SUMOVehicleClass vclass) const {943return (myChangeLeft & vclass) == vclass;944}945946/** @brief Returns whether the given vehicle class may change left from this lane */947inline bool allowsChangingRight(SUMOVehicleClass vclass) const {948return (myChangeRight & vclass) == vclass;949}950951void addIncomingLane(MSLane* lane, MSLink* viaLink);952953954struct IncomingLaneInfo {955MSLane* lane;956double length;957MSLink* viaLink;958};959960const std::vector<IncomingLaneInfo>& getIncomingLanes() const {961return myIncomingLanes;962}963964965void addApproachingLane(MSLane* lane, bool warnMultiCon);966inline bool isApproachedFrom(MSEdge* const edge) {967return myApproachingLanes.find(edge) != myApproachingLanes.end();968}969bool isApproachedFrom(MSEdge* const edge, MSLane* const lane);970971/// @brief Returns vehicle class specific stopOffset for the vehicle972double getVehicleStopOffset(const MSVehicle* veh) const;973974/// @brief Returns vehicle class specific stopOffsets975const StopOffset& getLaneStopOffsets() const;976977/// @brief Set vehicle class specific stopOffsets978void setLaneStopOffset(const StopOffset& stopOffset);979980/** @enum MinorLinkMode981* @brief determine whether/how getFollowers looks upstream beyond minor links982*/983enum MinorLinkMode {984FOLLOW_NEVER = 0,985FOLLOW_ALWAYS = 1,986FOLLOW_ONCOMING = 2,987};988989/// @brief return the sublane followers with the largest missing rear gap among all predecessor lanes (within dist)990MSLeaderDistanceInfo getFollowersOnConsecutive(const MSVehicle* ego, double backOffset,991bool allSublanes, double searchDist = -1, MinorLinkMode mLinkMode = FOLLOW_ALWAYS) const;992993/// @brief return by how much further the leader must be inserted to avoid rear end collisions994double getMissingRearGap(const MSVehicle* leader, double backOffset, double leaderSpeed) const;995996/** @brief Returns the immediate leader of veh and the distance to veh997* starting on this lane998*999* Iterates over the current lane to find a leader and then uses1000* getLeaderOnConsecutive()1001* @param[in] veh The vehicle for which the information shall be computed1002* @param[in] vehPos The vehicle position relative to this lane (may be negative)1003* @param[in] bestLaneConts The succeding lanes that shall be checked (if any)1004* @param[in] dist Optional distance to override default (ego stopDist)1005* @param[in] checkTmpVehicles Whether myTmpVehicles should be used instead of myVehicles1006* @return1007*/1008std::pair<MSVehicle* const, double> getLeader(const MSVehicle* veh, const double vehPos, const std::vector<MSLane*>& bestLaneConts, double dist = -1, bool checkTmpVehicles = false) const;10091010/** @brief Returns the immediate leader and the distance to him1011*1012* Goes along the vehicle's estimated used lanes (bestLaneConts). For each link,1013* it is determined whether the vehicle will pass it. If so, the subsequent lane1014* is investigated. If a vehicle (leader) is found, it is returned, together with the length1015* of the investigated lanes until this vehicle's end, including the already seen1016* place (seen).1017*1018* If no leading vehicle was found, <0, -1> is returned.1019*1020* Pretty slow, as it has to go along lanes.1021*1022* @todo: There are some oddities:1023* - what about crossing a link at red, or if a link is closed? Has a following vehicle to be regarded or not?1024*1025* @param[in] dist The distance to investigate1026* @param[in] seen The already seen place (normally the place in front on own lane)1027* @param[in] speed The speed of the vehicle used for determining whether a subsequent link will be opened at arrival time1028* @param[in] veh The vehicle for which the information shall be computed1029* @param[in] bestLaneConts The lanes the vehicle will use in future1030* @param[in] considerCrossingFoes Whether vehicles on crossing foe links should be considered1031* @return1032*/1033std::pair<MSVehicle* const, double> getLeaderOnConsecutive(double dist, double seen,1034double speed, const MSVehicle& veh, const std::vector<MSLane*>& bestLaneConts, bool considerCrossingFoes = true) const;10351036/// @brief Returns the immediate leaders and the distance to them (as getLeaderOnConsecutive but for the sublane case)1037void getLeadersOnConsecutive(double dist, double seen, double speed, const MSVehicle* ego,1038const std::vector<MSLane*>& bestLaneConts, MSLeaderDistanceInfo& result, bool oppositeDirection = false) const;103910401041/// @brief get leaders for ego on the given lane1042void addLeaders(const MSVehicle* vehicle, double vehPos, MSLeaderDistanceInfo& result, bool oppositeDirection = false);104310441045/** @brief Returns the most dangerous leader and the distance to him1046*1047* Goes along the vehicle's estimated used lanes (bestLaneConts). For each link,1048* it is determined whether the ego vehicle will pass it. If so, the subsequent lane1049* is investigated. Check all lanes up to the stopping distance of ego.1050* Return the leader vehicle (and the gap) which puts the biggest speed constraint on ego.1051*1052* If no leading vehicle was found, <0, -1> is returned.1053*1054* Pretty slow, as it has to go along lanes.1055*1056* @param[in] dist The distance to investigate1057* @param[in] seen The already seen place (normally the place in front on own lane)1058* @param[in] speed The speed of the vehicle used for determining whether a subsequent link will be opened at arrival time1059* @param[in] veh The (ego) vehicle for which the information shall be computed1060* @return1061*/1062std::pair<MSVehicle* const, double> getCriticalLeader(double dist, double seen, double speed, const MSVehicle& veh) const;10631064/* @brief return the partial vehicle closest behind ego or 01065* if no such vehicle exists */1066MSVehicle* getPartialBehind(const MSVehicle* ego) const;10671068/// @brief get all vehicles that are inlapping from consecutive edges1069MSLeaderInfo getPartialBeyond() const;10701071/// @brief Returns all vehicles closer than downstreamDist along the road network starting on the given1072/// position. Predecessor lanes are searched upstream for the given upstreamDistance.1073/// @note Re-implementation of the corresponding method in MSDevice_SSM, which cannot be easily adapted, as it gathers1074/// additional information for conflict lanes, etc.1075/// @param[in] startPos - start position of the search on the first lane1076/// @param[in] downstreamDist - distance to search downstream1077/// @param[in] upstreamDist - distance to search upstream1078/// @param[in/out] checkedLanes - lanes, which were already scanned (current lane is added, if not present,1079/// otherwise the scan is aborted; TODO: this may disregard unscanned parts of the lane in specific circular set ups.)1080/// @return vehs - List of vehicles found1081std::set<MSVehicle*> getSurroundingVehicles(double startPos, double downstreamDist, double upstreamDist, std::shared_ptr<LaneCoverageInfo> checkedLanes) const;10821083/// @brief Returns all vehicles on the lane overlapping with the interval [a,b]1084/// @note Does not consider vehs with front on subsequent lanes1085std::set<MSVehicle*> getVehiclesInRange(const double a, const double b) const;10861087/// @brief Returns all upcoming junctions within given range along the given (non-internal) continuation lanes measured from given position1088std::vector<const MSJunction*> getUpcomingJunctions(double pos, double range, const std::vector<MSLane*>& contLanes) const;10891090/// @brief Returns all upcoming links within given range along the given (non-internal) continuation lanes measured from given position1091std::vector<const MSLink*> getUpcomingLinks(double pos, double range, const std::vector<MSLane*>& contLanes) const;10921093/** @brief get the most likely precedecessor lane (sorted using by_connections_to_sorter).1094* The result is cached in myLogicalPredecessorLane1095*/1096MSLane* getLogicalPredecessorLane() const;10971098/** @brief get normal lane leading to this internal lane, for normal lanes,1099* the lane itself is returned1100*/1101const MSLane* getNormalPredecessorLane() const;11021103/** @brief get normal lane following this internal lane, for normal lanes,1104* the lane itself is returned1105*/1106const MSLane* getNormalSuccessorLane() const;11071108/** @brief return the (first) predecessor lane from the given edge1109*/1110MSLane* getLogicalPredecessorLane(const MSEdge& fromEdge) const;111111121113/** Return the main predecessor lane for the current.1114* If there are several incoming lanes, the first attempt is to return the priorized.1115* If this does not yield an unambiguous lane, the one with the least angle difference1116* to the current is selected.1117*/1118MSLane* getCanonicalPredecessorLane() const;111911201121/** Return the main successor lane for the current.1122* If there are several outgoing lanes, the first attempt is to return the priorized.1123* If this does not yield an unambiguous lane, the one with the least angle difference1124* to the current is selected.1125*/1126MSLane* getCanonicalSuccessorLane() const;11271128/// @brief get the state of the link from the logical predecessor to this lane1129LinkState getIncomingLinkState() const;11301131/// @brief get the list of outgoing lanes1132const std::vector<std::pair<const MSLane*, const MSEdge*> > getOutgoingViaLanes() const;11331134/// @brief get the list of all direct (disregarding internal predecessors) non-internal predecessor lanes of this lane1135std::vector<const MSLane*> getNormalIncomingLanes() const;11361137/// @name Current state retrieval1138//@{11391140/** @brief Returns the mean speed on this lane1141* @return The average speed of vehicles during the last step; default speed if no vehicle was on this lane1142*/1143double getMeanSpeed() const;11441145/// @brief get the mean speed of all bicycles on this lane1146double getMeanSpeedBike() const;11471148/** @brief Returns the overall waiting time on this lane1149* @return The sum of the waiting time of all vehicles during the last step;1150*/1151double getWaitingSeconds() const;115211531154/** @brief Returns the brutto (including minGaps) occupancy of this lane during the last step1155* @return The occupancy during the last step1156*/1157double getBruttoOccupancy() const;115811591160/** @brief Returns the netto (excluding minGaps) occupancy of this lane during the last step (including minGaps)1161* @return The occupancy during the last step1162*/1163double getNettoOccupancy() const;116411651166/** @brief Returns the sum of lengths of vehicles, including their minGaps, which were on the lane during the last step1167* @return The sum of vehicle lengths of vehicles in the last step1168*/1169inline double getBruttoVehLenSum() const {1170return myBruttoVehicleLengthSum;1171}117211731174/** @brief Returns the sum of last step emissions1175* The value is always per 1s, so multiply by step length if necessary.1176* @return emissions of vehicles on this lane during the last step1177*/1178template<PollutantsInterface::EmissionType ET>1179double getEmissions() const {1180double ret = 0;1181for (MSVehicle* const v : getVehiclesSecure()) {1182ret += v->getEmissions<ET>();1183}1184releaseVehicles();1185return ret;1186}118711881189/** @brief Returns the sum of last step noise emissions1190* @return noise emissions of vehicles on this lane during the last step1191*/1192double getHarmonoise_NoiseEmissions() const;1193/// @}11941195void setRightSideOnEdge(double value, int rightmostSublane) {1196myRightSideOnEdge = value;1197myRightmostSublane = rightmostSublane;1198}11991200/// @brief initialized vClass-specific speed limits1201void initRestrictions();12021203void checkBufferType();12041205double getRightSideOnEdge() const {1206return myRightSideOnEdge;1207}12081209int getRightmostSublane() const {1210return myRightmostSublane;1211}12121213double getCenterOnEdge() const {1214return myRightSideOnEdge + 0.5 * myWidth;1215}12161217/// @brief sorts myPartialVehicles1218void sortPartialVehicles();12191220/// @brief sorts myManeuverReservations1221void sortManeuverReservations();12221223/// @brief return the neighboring opposite direction lane for lane changing or nullptr1224MSLane* getOpposite() const;12251226/// @brief return the opposite direction lane of this lanes edge or nullptr1227MSLane* getParallelOpposite() const;12281229/// @brief return the corresponding position on the opposite lane1230double getOppositePos(double pos) const;12311232/* @brief find leader for a vehicle depending on the relative driving direction1233* @param[in] ego The ego vehicle1234* @param[in] dist The look-ahead distance when looking at consecutive lanes1235* @param[in] oppositeDir Whether the lane has the opposite driving direction of ego1236* @return the leader vehicle and its gap to ego1237*/1238std::pair<MSVehicle* const, double> getOppositeLeader(const MSVehicle* ego, double dist, bool oppositeDir, MinorLinkMode mLinkMode = MinorLinkMode::FOLLOW_NEVER) const;12391240/* @brief find follower for a vehicle that is located on the opposite of this lane1241* @param[in] ego The ego vehicle1242* @return the follower vehicle and its gap to ego1243*/1244std::pair<MSVehicle* const, double> getOppositeFollower(const MSVehicle* ego) const;124512461247/** @brief Find follower vehicle for the given ego vehicle (which may be on the opposite direction lane)1248* @param[in] ego The ego vehicle1249* @param[in] egoPos The ego position mapped to the current lane1250* @param[in] dist The look-back distance when looking at consecutive lanes1251* @param[in] ignoreMinorLinks Whether backward search should stop at minor links1252* @return the follower vehicle and its gap to ego1253*/1254std::pair<MSVehicle* const, double> getFollower(const MSVehicle* ego, double egoPos, double dist, MinorLinkMode mLinkMode) const;125512561257///@brief add parking vehicle. This should only used during state loading1258void addParking(MSBaseVehicle* veh);12591260///@brief remove parking vehicle. This must be syncrhonized when running with GUI1261virtual void removeParking(MSBaseVehicle* veh);12621263/// @brief retrieve the parking vehicles (see GUIParkingArea)1264const std::set<const MSBaseVehicle*>& getParkingVehicles() const {1265return myParkingVehicles;1266}12671268/// @brief whether this lane is selected in the GUI1269virtual bool isSelected() const {1270return false;1271}12721273/// @brief retrieve bidirectional lane or nullptr1274MSLane* getBidiLane() const;12751276/// @brief whether this lane must check for junction collisions1277bool mustCheckJunctionCollisions() const;12781279#ifdef HAVE_FOX1280MFXWorkerThread::Task* getPlanMoveTask(const SUMOTime time) {1281mySimulationTask.init(&MSLane::planMovements, time);1282return &mySimulationTask;1283}12841285MFXWorkerThread::Task* getExecuteMoveTask(const SUMOTime time) {1286mySimulationTask.init(&MSLane::executeMovements, time);1287return &mySimulationTask;1288}12891290MFXWorkerThread::Task* getLaneChangeTask(const SUMOTime time) {1291mySimulationTask.init(&MSLane::changeLanes, time);1292return &mySimulationTask;1293}1294#endif12951296std::vector<StopWatch<std::chrono::nanoseconds> >& getStopWatch() {1297return myStopWatch;1298}12991300void changeLanes(const SUMOTime time);13011302/// @name State saving/loading1303/// @{13041305/** @brief Saves the state of this lane into the given stream1306*1307* Basically, a list of vehicle ids1308*1309* @param[in, filled] out The (possibly binary) device to write the state into1310* @todo What about throwing an IOError?1311*/1312void saveState(OutputDevice& out);13131314/** @brief Remove all vehicles before quick-loading state */1315void clearState();13161317/** @brief Loads the state of this segment with the given parameters1318*1319* This method is called for every internal que the segment has.1320* Every vehicle is retrieved from the given MSVehicleControl and added to this1321* lane.1322*1323* @param[in] vehs The vehicles for the current lane1324* @todo What about throwing an IOError?1325* @todo What about throwing an error if something else fails (a vehicle can not be referenced)?1326*/1327void loadState(const std::vector<SUMOVehicle*>& vehs);132813291330/* @brief helper function for state saving: checks whether any outgoing1331* links are being approached */1332bool hasApproaching() const;13331334/// @}133513361337/** @brief Callback for visiting the lane when traversing an RTree1338*1339* This is used in the TraCIServerAPI_Lane for context subscriptions.1340*1341* @param[in] cont The context doing all the work1342* @see libsumo::Helper::LaneStoringVisitor::add1343*/1344void visit(const MSLane::StoringVisitor& cont) const {1345cont.add(this);1346}13471348/// @brief whether the lane has pedestrians on it1349bool hasPedestrians() const;13501351/// This is just a wrapper around MSPModel::nextBlocking. You should always check using hasPedestrians before calling this method.1352std::pair<const MSPerson*, double> nextBlocking(double minPos, double minRight, double maxLeft, double stopTime = 0, bool bidi = false) const;13531354/// @brief return the empty space up to the last standing vehicle or the empty space on the whole lane if no vehicle is standing1355double getSpaceTillLastStanding(const MSVehicle* ego, bool& foundStopped) const;13561357/// @brief compute maximum braking distance on this lane1358double getMaximumBrakeDist() const;13591360inline const PositionVector* getOutlineShape() const {1361return myOutlineShape;1362}13631364static void initCollisionOptions(const OptionsCont& oc);1365static void initCollisionAction(const OptionsCont& oc, const std::string& option, CollisionAction& myAction);13661367static CollisionAction getCollisionAction() {1368return myCollisionAction;1369}13701371static CollisionAction getIntermodalCollisionAction() {1372return myIntermodalCollisionAction;1373}13741375static DepartSpeedDefinition& getDefaultDepartSpeedDefinition() {1376return myDefaultDepartSpeedDefinition;1377}13781379static double& getDefaultDepartSpeed() {1380return myDefaultDepartSpeed;1381}138213831384static const long CHANGE_PERMISSIONS_PERMANENT = 0;1385static const long CHANGE_PERMISSIONS_GUI = 1;13861387protected:1388/// moves myTmpVehicles int myVehicles after a lane change procedure1389virtual void swapAfterLaneChange(SUMOTime t);13901391/** @brief Inserts the vehicle into this lane, and informs it about entering the network1392*1393* Calls the vehicles enterLaneAtInsertion function,1394* updates statistics and modifies the active state as needed1395* @param[in] veh The vehicle to be incorporated1396* @param[in] pos The position of the vehicle1397* @param[in] speed The speed of the vehicle1398* @param[in] posLat The lateral position of the vehicle1399* @param[in] at1400* @param[in] notification The cause of insertion (i.e. departure, teleport, parking) defaults to departure1401*/1402virtual void incorporateVehicle(MSVehicle* veh, double pos, double speed, double posLat,1403const MSLane::VehCont::iterator& at,1404MSMoveReminder::Notification notification = MSMoveReminder::NOTIFICATION_DEPARTED);14051406/// @brief detect whether a vehicle collids with pedestrians on the junction1407void detectPedestrianJunctionCollision(const MSVehicle* collider, const PositionVector& colliderBoundary, const MSLane* foeLane,1408SUMOTime timestep, const std::string& stage,1409std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,1410std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport);14111412/// @brief detect whether there is a collision between the two vehicles1413bool detectCollisionBetween(SUMOTime timestep, const std::string& stage, MSVehicle* collider, MSVehicle* victim,1414std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,1415std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) const;14161417/// @brief take action upon collision1418void handleCollisionBetween(SUMOTime timestep, const std::string& stage, const MSVehicle* collider, const MSVehicle* victim,1419double gap, double latGap,1420std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,1421std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) const;14221423void handleIntermodalCollisionBetween(SUMOTime timestep, const std::string& stage, const MSVehicle* collider, const MSTransportable* victim,1424double gap, const std::string& collisionType,1425std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,1426std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) const;14271428/* @brief determine depart speed and whether it may be patched1429* @param[in] veh The departing vehicle1430* @param[out] whether the speed may be patched to account for safety1431* @return the depart speed1432*/1433double getDepartSpeed(const MSVehicle& veh, bool& patchSpeed);14341435/* @brief determine the lateral depart position1436* @param[in] veh The departing vehicle1437* @return the lateral depart position1438*/1439double getDepartPosLat(const MSVehicle& veh);14401441/** @brief return the maximum safe speed for insertion behind leaders1442* (a negative value indicates that safe insertion is impossible) */1443double safeInsertionSpeed(const MSVehicle* veh, double seen, const MSLeaderInfo& leaders, double speed);14441445/// @brief check whether pedestrians on this lane interfere with vehicle insertion1446bool checkForPedestrians(const MSVehicle* aVehicle, double& speed, double& dist, double pos, bool patchSpeed) const;14471448/// @brief check whether any of the outgoing links are being approached1449bool hasApproaching(const std::vector<MSLink*>& links) const;14501451/// @brief return length of fractional vehicles on this lane1452double getFractionalVehicleLength(bool brutto) const;14531454/// @brief detect frontal collisions1455static bool isFrontalCollision(const MSVehicle* collider, const MSVehicle* victim);14561457/// Unique numerical ID (set on reading by netload)1458int myNumericalID;14591460/// The shape of the lane1461PositionVector myShape;14621463/// @brief the outline of the lane (optional)1464PositionVector* myOutlineShape = nullptr;14651466/// The lane index1467int myIndex;14681469/** @brief The lane's vehicles.1470This container holds all vehicles that have their front (longitudinally)1471and their center (laterally) on this lane.1472These are the vehicles that this lane is 'responsibly' for (i.e. when executing movements)14731474The entering vehicles are inserted at the front1475of this container and the leaving ones leave from the back, e.g. the1476vehicle in front of the junction (often called first) is1477myVehicles.back() (if it exists). And if it is an iterator at a1478vehicle, ++it points to the vehicle in front. This is the interaction1479vehicle. */1480VehCont myVehicles;14811482/** @brief The lane's partial vehicles.1483This container holds all vehicles that are partially on this lane but which are1484in myVehicles of another lane.1485Reasons for partial occupancies include the following1486- the back is still on this lane during regular movement1487- the vehicle is performing a continuous lane-change maneuver1488- sub-lane simulation where vehicles can freely move laterally among the lanes of an edge14891490The entering vehicles are inserted at the front1491of this container and the leaving ones leave from the back. */1492VehCont myPartialVehicles;14931494/** @brief Container for lane-changing vehicles. After completion of lane-change-1495process, the containers will be swapped with myVehicles. */1496VehCont myTmpVehicles;14971498/** @brief Buffer for vehicles that moved from their previous lane onto this one.1499* Integrated after all vehicles executed their moves*/1500MFXSynchQue<MSVehicle*, std::vector<MSVehicle*> > myVehBuffer;15011502/** @brief The vehicles which registered maneuvering into the lane within their current action step.1503* This is currently only relevant for sublane simulation, since continuous lanechanging1504* uses the partial vehicle mechanism.1505*1506* The entering vehicles are inserted at the front1507* of this container and the leaving ones leave from the back. */1508VehCont myManeuverReservations;15091510/* @brief list of vehicles that are parking near this lane1511* (not necessarily on the road but having reached their stop on this lane)1512* */1513std::set<const MSBaseVehicle*> myParkingVehicles;15141515/// Lane length [m]1516double myLength;15171518/// Lane width [m]1519const double myWidth;15201521/// Lane's vClass specific stop offset [m]. The map is either of length 0, which means no1522/// special stopOffset was set, or of length 1, where the key is a bitset representing a subset1523/// of the SUMOVehicleClass Enum and the value is the offset in meters.1524StopOffset myLaneStopOffset;15251526/// The lane's edge, for routing only.1527MSEdge* const myEdge;15281529/// Lane-wide speed limit [m/s]1530double myMaxSpeed;1531/// Lane-wide friction coefficient [0..1]1532double myFrictionCoefficient;15331534/// @brief Whether the current speed limit is set by a variable speed sign (VSS)1535bool mySpeedByVSS;15361537/// @brief Whether the current speed limit has been set through TraCI1538bool mySpeedByTraCI;15391540/// The vClass permissions for this lane1541SVCPermissions myPermissions;15421543/// The vClass permissions for changing from this lane1544SVCPermissions myChangeLeft;1545SVCPermissions myChangeRight;15461547/// The original vClass permissions for this lane (before temporary modifications)1548SVCPermissions myOriginalPermissions;15491550/// The vClass speed restrictions for this lane1551const std::map<SUMOVehicleClass, double>* myRestrictions;15521553/// All direct predecessor lanes1554std::vector<IncomingLaneInfo> myIncomingLanes;15551556///1557mutable MSLane* myLogicalPredecessorLane;15581559/// Similar to LogicalPredecessorLane, @see getCanonicalPredecessorLane()1560mutable MSLane* myCanonicalPredecessorLane;15611562/// Main successor lane, @see getCanonicalSuccessorLane()1563mutable MSLane* myCanonicalSuccessorLane;15641565/// @brief The current length of all vehicles on this lane, including their minGaps1566double myBruttoVehicleLengthSum;15671568/// @brief The current length of all vehicles on this lane, excluding their minGaps1569double myNettoVehicleLengthSum;15701571/// @brief The length of all vehicles that have left this lane in the current step (this lane, including their minGaps)1572double myBruttoVehicleLengthSumToRemove;15731574/// @brief The length of all vehicles that have left this lane in the current step (this lane, excluding their minGaps)1575double myNettoVehicleLengthSumToRemove;15761577/// @brief Flag to recalculate the occupancy (including minGaps) after a change in minGap1578bool myRecalculateBruttoSum;15791580/** The lane's Links to its succeeding lanes and the default1581right-of-way rule, i.e. blocked or not blocked. */1582std::vector<MSLink*> myLinks;15831584/// All direct internal and direct (disregarding internal predecessors) non-internal predecessor lanes of this lane1585std::map<MSEdge*, std::vector<MSLane*> > myApproachingLanes;15861587/// @brief leaders on all sublanes as seen by approaching vehicles (cached)1588mutable MSLeaderInfo myLeaderInfo;1589/// @brief followers on all sublanes as seen by vehicles on consecutive lanes (cached)1590mutable MSLeaderInfo myFollowerInfo;15911592/// @brief time step for which myLeaderInfo was last updated1593mutable SUMOTime myLeaderInfoTime;1594/// @brief time step for which myFollowerInfo was last updated1595mutable SUMOTime myFollowerInfoTime;15961597/// @brief precomputed myShape.length / myLength1598const double myLengthGeometryFactor;15991600/// @brief whether this lane is an acceleration lane1601const bool myIsRampAccel;16021603/// @brief the type of this lane1604const std::string myLaneType;16051606/// @brief the combined width of all lanes with lower index on myEdge1607double myRightSideOnEdge;1608/// @brief the index of the rightmost sublane of this lane on myEdge1609int myRightmostSublane;16101611/// @brief whether a collision check is currently needed1612bool myNeedsCollisionCheck;16131614// @brief the neighboring opposite direction or nullptr1615MSLane* myOpposite;16161617// @brief bidi lane or nullptr1618MSLane* myBidiLane;16191620// @brief transient changes in permissions1621std::map<long long, SVCPermissions> myPermissionChanges;16221623// @brief index of the associated thread-rng1624int myRNGIndex;16251626/// definition of the static dictionary type1627typedef std::map< std::string, MSLane* > DictType;16281629/// Static dictionary to associate string-ids with objects.1630static DictType myDict;16311632static std::vector<SumoRNG> myRNGs;16331634private:1635/// @brief This lane's move reminder1636std::vector< MSMoveReminder* > myMoveReminders;16371638/// @brief the action to take on collisions1639static CollisionAction myCollisionAction;1640static CollisionAction myIntermodalCollisionAction;1641static bool myCheckJunctionCollisions;1642static double myCheckJunctionCollisionMinGap;1643static SUMOTime myCollisionStopTime;1644static SUMOTime myIntermodalCollisionStopTime;1645static double myCollisionMinGapFactor;1646static bool myExtrapolateSubstepDepart;1647static DepartSpeedDefinition myDefaultDepartSpeedDefinition;1648static double myDefaultDepartSpeed;1649/**1650* @class vehicle_position_sorter1651* @brief Sorts vehicles by their position (descending)1652*/1653class vehicle_position_sorter {1654public:1655/// @brief Constructor1656explicit vehicle_position_sorter(const MSLane* lane) :1657myLane(lane) {1658}165916601661/** @brief Comparing operator1662* @param[in] v1 First vehicle to compare1663* @param[in] v2 Second vehicle to compare1664* @return Whether the first vehicle is further on the lane than the second1665*/1666int operator()(MSVehicle* v1, MSVehicle* v2) const;16671668const MSLane* myLane;16691670};16711672/**1673* @class vehicle_reverse_position_sorter1674* @brief Sorts vehicles by their position (ascending)1675*/1676class vehicle_natural_position_sorter {1677public:1678/// @brief Constructor1679explicit vehicle_natural_position_sorter(const MSLane* lane) :1680myLane(lane) {1681}168216831684/** @brief Comparing operator1685* @param[in] v1 First vehicle to compare1686* @param[in] v2 Second vehicle to compare1687* @return Whether the first vehicle is further on the lane than the second1688*/1689int operator()(MSVehicle* v1, MSVehicle* v2) const;16901691const MSLane* myLane;16921693};16941695/** @class by_connections_to_sorter1696* @brief Sorts edges by their angle relative to the given edge (straight comes first)1697*1698*/1699class by_connections_to_sorter {1700public:1701/// @brief constructor1702explicit by_connections_to_sorter(const MSEdge* const e);17031704/// @brief comparing operator1705int operator()(const MSEdge* const e1, const MSEdge* const e2) const;17061707private:1708const MSEdge* const myEdge;1709double myLaneDir;1710};1711171217131714/** @class incoming_lane_priority_sorter1715* @brief Sorts lanes (IncomingLaneInfos) by their priority or, if this doesn't apply,1716* wrt. the angle difference magnitude relative to the target lane's angle (straight comes first)1717*/1718class incoming_lane_priority_sorter {1719public:1720/// @brief constructor1721explicit incoming_lane_priority_sorter(const MSLane* targetLane);17221723/// @brief comparing operator1724int operator()(const IncomingLaneInfo& lane1, const IncomingLaneInfo& lane2) const;17251726private:1727const MSLane* const myLane;1728double myLaneDir;1729};173017311732/** @class outgoing_lane_priority_sorter1733* @brief Sorts lanes (their origin link) by the priority of their noninternal target edges or, if this doesn't yield an unambiguous result,1734* wrt. the angle difference magnitude relative to the target lane's angle (straight comes first)1735*/1736class outgoing_lane_priority_sorter {1737public:1738/// @brief constructor1739explicit outgoing_lane_priority_sorter(const MSLane* sourceLane);17401741/// @brief comparing operator1742int operator()(const MSLink* link1, const MSLink* link2) const;17431744private:1745double myLaneDir;1746};17471748/**1749* @class edge_finder1750*/1751class edge_finder {1752public:1753edge_finder(MSEdge* e) : myEdge(e) {}1754bool operator()(const IncomingLaneInfo& ili) const {1755return &(ili.lane->getEdge()) == myEdge;1756}1757private:1758const MSEdge* const myEdge;1759};17601761#ifdef HAVE_FOX1762/// Type of the function that is called for the simulation stage (e.g. planMovements).1763typedef void(MSLane::*Operation)(const SUMOTime);17641765/**1766* @class SimulationTask1767* @brief the routing task which mainly calls reroute of the vehicle1768*/1769class SimulationTask : public MFXWorkerThread::Task {1770public:1771SimulationTask(MSLane& l, const SUMOTime time)1772: myLane(l), myTime(time) {}1773void init(Operation operation, const SUMOTime time) {1774myOperation = operation;1775myTime = time;1776}1777void run(MFXWorkerThread* /*context*/) {1778try {1779(myLane.*(myOperation))(myTime);1780} catch (ProcessError& e) {1781WRITE_ERROR(e.what());1782}1783}1784private:1785Operation myOperation = nullptr;1786MSLane& myLane;1787SUMOTime myTime;1788private:1789/// @brief Invalidated assignment operator.1790SimulationTask& operator=(const SimulationTask&) = delete;1791};17921793SimulationTask mySimulationTask;1794/// @brief Mutex for access to the cached leader info value1795mutable FXMutex myLeaderInfoMutex;1796/// @brief Mutex for access to the cached follower info value1797mutable FXMutex myFollowerInfoMutex;1798/// @brief Mutex for access to the cached follower info value1799mutable FXMutex myPartialOccupatorMutex;1800#endif1801std::vector<StopWatch<std::chrono::nanoseconds> > myStopWatch;18021803private:1804/// @brief invalidated copy constructor1805MSLane(const MSLane&) = delete;18061807/// @brief invalidated assignment operator1808MSLane& operator=(const MSLane&) = delete;180918101811};18121813// specialized implementation for speedup and avoiding warnings1814#define LANE_RTREE_QUAL RTree<MSLane*, MSLane, float, 2, MSLane::StoringVisitor>18151816template<>1817inline float LANE_RTREE_QUAL::RectSphericalVolume(Rect* a_rect) {1818ASSERT(a_rect);1819const float extent0 = a_rect->m_max[0] - a_rect->m_min[0];1820const float extent1 = a_rect->m_max[1] - a_rect->m_min[1];1821return .78539816f * (extent0 * extent0 + extent1 * extent1);1822}18231824template<>1825inline LANE_RTREE_QUAL::Rect LANE_RTREE_QUAL::CombineRect(Rect* a_rectA, Rect* a_rectB) {1826ASSERT(a_rectA && a_rectB);1827Rect newRect;1828newRect.m_min[0] = rtree_min(a_rectA->m_min[0], a_rectB->m_min[0]);1829newRect.m_max[0] = rtree_max(a_rectA->m_max[0], a_rectB->m_max[0]);1830newRect.m_min[1] = rtree_min(a_rectA->m_min[1], a_rectB->m_min[1]);1831newRect.m_max[1] = rtree_max(a_rectA->m_max[1], a_rectB->m_max[1]);1832return newRect;1833}183418351836