/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2025 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 MSEdgeControl.h14/// @author Christian Roessel15/// @author Daniel Krajzewicz16/// @author Jakob Erdmann17/// @author Christoph Sommer18/// @author Sascha Krieg19/// @author Michael Behrisch20/// @date Mon, 09 Apr 200121///22// Stores edges and lanes, performs moving of vehicle23/****************************************************************************/24#pragma once25#include <config.h>2627#include <vector>28#include <map>29#include <string>30#include <iostream>31#include <list>32#include <set>33#include <queue>34#include <utils/common/SUMOTime.h>35#include <utils/common/Named.h>36#include <utils/common/StopWatch.h>37#include <utils/router/SUMOAbstractRouter.h>38#include <utils/router/RouterProvider.h>39#include <utils/vehicle/SUMOVehicle.h>40#include <microsim/MSRouterDefs.h>4142#include <utils/foxtools/MFXSynchQue.h>43#include <utils/foxtools/MFXSynchSet.h>44//#define THREAD_POOL45#ifdef THREAD_POOL46#include <utils/threadpool/WorkStealingThreadPool.h>47#else48#ifdef HAVE_FOX49#include <utils/foxtools/MFXWorkerThread.h>50#endif51#endif525354// ===========================================================================55// class declarations56// ===========================================================================57class OutputDevice;585960// ===========================================================================61// class definitions62// ===========================================================================63/**64* @class MSEdgeControl65* @brief Stores edges and lanes, performs moving of vehicle66*67* In order to avoid touching all lanes, even the empty ones, this class stores68* and updates the information about "active" lanes, those that have at least69* one vehicle on them. During longitudinal movement, this can be simply70* achieved through return values of the MSLane-methods, signalling either71* that the lane got active or inactive. This is but not possible when72* changing lanes, we have to go through the lanes, here. Also, we have to73* add lanes on which a vehicle was inserted, separately, doing this into74* ("myChangedStateLanes") which entries are integrated at the begin of is step75* in "patchActiveLanes".76*/77class MSEdgeControl {7879public:80/** @brief Constructor81*82* Builds LaneUsage information for each lane and assigns them to lanes.83*84* @param[in] edges The loaded edges85* @todo Assure both containers are not 086*/87MSEdgeControl(const std::vector< MSEdge* >& edges);888990/// @brief Destructor.91~MSEdgeControl();929394/** @brief Resets information whether a lane is active for all lanes95*96* For each lane in "myChangedStateLanes": if the lane has at least one vehicle97* and is not marked as being active, it is added to the list og active lanes98* and marked as being active.99*/100void patchActiveLanes();101102103/// @name Interfaces for longitudinal vehicle movement104/// @{105106/** @brief Compute safe velocities for all vehicles based on positions and107* speeds from the last time step. Also registers108* ApproachingVehicleInformation for all links109*110* This method goes through all active lanes calling their "planMovements" method.111* @see MSLane::planMovements112*/113void planMovements(SUMOTime t);114115/** @brief Register junction approaches for all vehicles after velocities116* have been planned. This is a prerequisite for executeMovements117*118* This method goes through all active lanes calling their "setJunctionApproaches" method.119*/120void setJunctionApproaches();121122123/** @brief Executes planned vehicle movements with regards to right-of-way124*125* This method goes through all active lanes calling their executeMovements126* method which causes vehicles to update their positions and speeds.127* Lanes which receive new vehicles are stored in myWithVehicles2Integrate128* After movements are executed the vehicles in myWithVehicles2Integrate are129* put onto their new lanes130* This method also updates the "active" status of lanes131*132* @see MSLane::executeMovements133* @see MSLane::integrateNewVehicle134*/135void executeMovements(SUMOTime t);136137void needsVehicleIntegration(MSLane* const l) {138myWithVehicles2Integrate.push_back(l);139}140/// @}141142143/** @brief Moves (precomputes) critical vehicles144*145* Calls "changeLanes" of each of the multi-lane edges. Check then for this146* edge whether a lane got active, adding it to "myActiveLanes" and marking147* it as active in such cases.148*149* @see MSEdge::changeLanes150*/151void changeLanes(const SUMOTime t);152153154/** @brief Detect collisions155*156* Calls "detectCollisions" of each lane.157* Shouldn't be necessary if model-implementation is correct.158* The parameter is simply passed to the lane-instance for reporting.159*160* @param[in] timestep The current time step161* @param[in] stage The current stage within the simulation step162* @note see MSNet::simulationStep163*/164void detectCollisions(SUMOTime timestep, const std::string& stage);165166167/** @brief Returns loaded edges168*169* @return the container storing one-lane edges170* @todo Check: Is this secure?171*/172const MSEdgeVector& getEdges() const {173return myEdges;174}175176177/** @brief Informs the control that the given lane got active178*179* @param[in] l The activated lane180* @todo Check for l==0?181*/182void gotActive(MSLane* l);183184/// @brief trigger collision checking for inactive lane185void checkCollisionForInactive(MSLane* l);186187/// @brief apply additional restrictions188void setAdditionalRestrictions();189190/// @brief update meso edge type parameters191void setMesoTypes();192193/** @brief Saves the current state into the given stream194*/195void saveState(OutputDevice& out);196197/** @brief Reconstruct the current state198*/199void setActiveLanes(std::list<MSLane*> lanes);200201202#ifndef THREAD_POOL203#ifdef HAVE_FOX204MFXWorkerThread::Pool& getThreadPool() {205return myThreadPool;206}207#endif208#endif209210public:211/**212* @struct LaneUsage213* @brief A structure holding some basic information about a simulated lane214*215* To fasten up speed, this structure holds the number of vehicles using216* a lane and the lane's neighbours. Only lanes that are occupied are217* forced to compute the vehicles longitunidal movement.218*219* The information about a lane's neighbours speed up the computation220* of the lane changing.221*/222struct LaneUsage {223/// @brief The described lane224MSLane* lane;225/// @brief Information whether this lane is active226bool amActive;227/// @brief Information whether this lane belongs to a multi-lane edge228bool haveNeighbors;229};230231#ifdef HAVE_FOX232/**233* @class WorkerThread234* @brief the thread which provides the router instance as context235*/236class WorkerThread : public MFXWorkerThread {237public:238WorkerThread(MFXWorkerThread::Pool& pool)239: MFXWorkerThread(pool), myRouterProvider(nullptr) {}240241bool setRouterProvider(MSRouterProvider* routerProvider) {242if (myRouterProvider == nullptr) {243myRouterProvider = routerProvider;244return true;245}246return false;247}248MSVehicleRouter& getRouter(SUMOVehicleClass svc) const {249return myRouterProvider->getVehicleRouter(svc);250}251MSTransportableRouter& getIntermodalRouter() const {252return myRouterProvider->getIntermodalRouter();253}254virtual ~WorkerThread() {255stop();256delete myRouterProvider;257}258private:259MSRouterProvider* myRouterProvider;260};261#endif262263private:264/// @brief Loaded edges265MSEdgeVector myEdges;266267/// @brief Definition of a container about a lane's number of vehicles and neighbors268typedef std::vector<LaneUsage> LaneUsageVector;269270/// @brief Information about lanes' number of vehicles and neighbors271LaneUsageVector myLanes;272273/// @brief The list of active (not empty) lanes274std::list<MSLane*> myActiveLanes;275276/// @brief A storage for lanes which shall be integrated because vehicles have moved onto them277MFXSynchQue<MSLane*, std::vector<MSLane*> > myWithVehicles2Integrate;278279/// @brief Lanes which changed the state without informing the control280std::set<MSLane*, ComparatorNumericalIdLess> myChangedStateLanes;281282/// @brief The list of active (not empty) lanes283std::vector<SUMOTime> myLastLaneChange;284285/// @brief Additional lanes for which collision checking must be performed286MFXSynchSet<MSLane*, std::set<MSLane*, ComparatorNumericalIdLess> > myInactiveCheckCollisions;287288double myMinLengthGeometryFactor;289290#ifdef THREAD_POOL291WorkStealingThreadPool<> myThreadPool;292#else293#ifdef HAVE_FOX294MFXWorkerThread::Pool myThreadPool;295#endif296#endif297298std::vector<StopWatch<std::chrono::nanoseconds> > myStopWatch;299300private:301/// @brief Copy constructor.302MSEdgeControl(const MSEdgeControl&);303304/// @brief Assignment operator.305MSEdgeControl& operator=(const MSEdgeControl&);306307};308309310