LCOV - code coverage report
Current view: top level - src/microsim/traffic_lights - MSActuatedTrafficLightLogic.h (source / functions) Coverage Total Hit
Test: lcov.info Lines: 95.0 % 20 19
Test Date: 2026-04-16 16:39:47 Functions: 100.0 % 2 2

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2002-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    MSActuatedTrafficLightLogic.h
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Michael Behrisch
      17              : /// @author  Jakob Erdmann
      18              : /// @date    Sept 2002
      19              : ///
      20              : // An actuated (adaptive) traffic light logic
      21              : /****************************************************************************/
      22              : #pragma once
      23              : #include <config.h>
      24              : 
      25              : #include <utility>
      26              : #include <vector>
      27              : #include <bitset>
      28              : #include <map>
      29              : #include <microsim/MSEventControl.h>
      30              : #include <microsim/traffic_lights/MSTrafficLightLogic.h>
      31              : #include <microsim/output/MSDetectorControl.h>
      32              : #include <microsim/output/MSInductLoop.h>
      33              : #include "MSSimpleTrafficLightLogic.h"
      34              : 
      35              : 
      36              : // ===========================================================================
      37              : // class declarations
      38              : // ===========================================================================
      39              : class NLDetectorBuilder;
      40              : 
      41              : // ===========================================================================
      42              : // class definitions
      43              : // ===========================================================================
      44              : /**
      45              :  * @class MSActuatedTrafficLightLogic
      46              :  * @brief An actuated (adaptive) traffic light logic
      47              :  */
      48              : class MSActuatedTrafficLightLogic : public MSSimpleTrafficLightLogic {
      49              : public:
      50              : 
      51              :     typedef Parameterised::Map ConditionMap;
      52              :     typedef std::vector<std::tuple<std::string, std::string, std::string> > AssignmentMap;
      53              : 
      54        41785 :     struct Function {
      55        41785 :         Function(const std::string& _id = "", int _nArgs = -1):
      56        41785 :             id(_id), nArgs(_nArgs) {}
      57              :         std::string id;
      58              :         int nArgs;
      59              :         AssignmentMap assignments;
      60              :     };
      61              : 
      62              :     typedef std::map<std::string, Function> FunctionMap;
      63              : 
      64              : 
      65              :     /** @brief Constructor
      66              :      * @param[in] tlcontrol The tls control responsible for this tls
      67              :      * @param[in] id This tls' id
      68              :      * @param[in] programID This tls' sub-id (program id)
      69              :      * @param[in] phases Definitions of the phases
      70              :      * @param[in] step The initial phase index
      71              :      * @param[in] delay The time to wait before the first switch
      72              :      * @param[in] parameter The parameter to use for tls set-up
      73              :      */
      74              :     MSActuatedTrafficLightLogic(MSTLLogicControl& tlcontrol,
      75              :                                 const std::string& id, const std::string& programID,
      76              :                                 const SUMOTime offset,
      77              :                                 const MSSimpleTrafficLightLogic::Phases& phases,
      78              :                                 int step, SUMOTime delay,
      79              :                                 const Parameterised::Map& parameter,
      80              :                                 const std::string& basePath,
      81              :                                 const ConditionMap& conditions = ConditionMap(),
      82              :                                 const AssignmentMap& assignments = AssignmentMap(),
      83              :                                 const FunctionMap& functions = FunctionMap());
      84              : 
      85              : 
      86              :     /** @brief Initialises the tls with information about incoming lanes
      87              :      * @param[in] nb The detector builder
      88              :      * @exception ProcessError If something fails on initialisation
      89              :      */
      90              :     void init(NLDetectorBuilder& nb) override;
      91              : 
      92              : 
      93              :     /// @brief Destructor
      94              :     ~MSActuatedTrafficLightLogic();
      95              : 
      96              : 
      97              : 
      98              :     /// @name Switching and setting current rows
      99              :     /// @{
     100              : 
     101              :     /** @brief Switches to the next phase
     102              :      * @return The time of the next switch
     103              :      * @see MSTrafficLightLogic::trySwitch
     104              :      */
     105              :     SUMOTime trySwitch() override;
     106              :     /// @}
     107              : 
     108              :     SUMOTime getMinDur(int step = -1) const override;
     109              :     SUMOTime getMaxDur(int step = -1) const override;
     110              :     SUMOTime getEarliestEnd(int step = -1) const override;
     111              :     SUMOTime getLatestEnd(int step = -1) const override;
     112              : 
     113              :     /// @name Changing phases and phase durations
     114              :     /// @{
     115              : 
     116              :     /** @brief Changes the current phase and her duration
     117              :      * @param[in] tlcontrol The responsible traffic lights control
     118              :      * @param[in] simStep The current simulation step
     119              :      * @param[in] step Index of the phase to use
     120              :      * @param[in] stepDuration The left duration of the phase
     121              :      * @see MSTrafficLightLogic::changeStepAndDuration
     122              :      */
     123              :     void changeStepAndDuration(MSTLLogicControl& tlcontrol, SUMOTime simStep,
     124              :                                int step, SUMOTime stepDuration) override;
     125              : 
     126              :     /// @brief called when switching programs
     127              :     void activateProgram() override;
     128              :     void deactivateProgram() override;
     129              : 
     130              :     bool showDetectors() const {
     131            0 :         return myShowDetectors;
     132              :     }
     133              : 
     134              :     void setShowDetectors(bool show);
     135              : 
     136              :     void saveState(OutputDevice& out) const override;
     137              : 
     138              :     void loadExtraState(const std::string& state) override;
     139              : 
     140              :     /// @brief try to get the value of the given parameter (including prefixed parameters)
     141              :     const std::string getParameter(const std::string& key, const std::string defaultValue = "") const override;
     142              : 
     143              :     /**@brief Sets a parameter and updates internal constants */
     144              :     void setParameter(const std::string& key, const std::string& value) override;
     145              : 
     146              :     /// @brief retrieve all detectors used by this program
     147              :     std::map<std::string, double> getDetectorStates() const override;
     148              : 
     149              :     /// @brief retrieve a specific detector used by this program
     150              :     double getDetectorState(const std::string laneID) const override;
     151              : 
     152              :     /// @brief return all named conditions defined for this traffic light
     153              :     std::map<std::string, double> getConditions() const override;
     154              : 
     155              :     void loadState(MSTLLogicControl& tlcontrol, SUMOTime t, int step, SUMOTime spentDuration, bool active) override;
     156              : 
     157              : protected:
     158              :     /// @brief initialize custom switching rules
     159              :     void initAttributeOverride();
     160              :     void initSwitchingRules();
     161              : 
     162       125639 :     struct InductLoopInfo {
     163         4246 :         InductLoopInfo(MSInductLoop* _loop, const MSLane* _lane, int numPhases, double _maxGap, double _jamThreshold):
     164         4246 :             loop(_loop),
     165         4246 :             lane(_lane),
     166         8492 :             servedPhase(numPhases, false),
     167         4246 :             maxGap(_maxGap),
     168         4246 :             jamThreshold(_jamThreshold)
     169              :         {}
     170              : 
     171              : 
     172              :         bool isJammed() const {
     173       941291 :             return jamThreshold > 0 && loop->getOccupancyTime() >= jamThreshold;
     174              :         }
     175              : 
     176              :         MSInductLoop* loop;
     177              :         const MSLane* lane;
     178              :         SUMOTime lastGreenTime = 0;
     179              :         std::vector<bool> servedPhase;
     180              :         double maxGap;
     181              :         double jamThreshold;
     182              : 
     183              :     };
     184              : 
     185              :     /// @brief Definition of a map from phases to induct loops controlling them
     186              :     typedef std::vector<std::vector<InductLoopInfo*> > InductLoopMap;
     187              : 
     188              :     /// @name "actuated" algorithm methods
     189              :     /// @{
     190              : 
     191              :     /** @brief Returns the minimum duration of the current phase
     192              :      * @param[in] detectionGap The minimum detection gap for the current phase
     193              :      * @return The minimum duration of the current phase
     194              :      */
     195              :     SUMOTime duration(const double detectionGap) const;
     196              : 
     197              :     /// @brief get the minimum min duration for all stretchable phases that affect the given lane
     198              :     SUMOTime getMinimumMinDuration(MSLane* lane, const std::set<int>& multiNextTargets) const;
     199              : 
     200              :     /** @brief Return the minimum detection gap of all detectors if the current phase should be extended and double::max otherwise
     201              :      */
     202              :     double gapControl();
     203              : 
     204              : 
     205              :     /// @brief return whether there is a major link from the given lane in the given phase
     206              :     bool hasMajor(const std::string& state, const LaneVector& lanes) const;
     207              :     /// @}
     208              : 
     209              :     /// @brief select among candidate phases based on detector states
     210              :     int decideNextPhase();
     211              : 
     212              :     /// @brief select among candidate phases based on detector states and custom switching rules
     213              :     int decideNextPhaseCustom(bool mustSwitch);
     214              : 
     215              :     /// @brief evaluate custom switching condition
     216              :     double evalExpression(const std::string& condition) const;
     217              : 
     218              :     /// @brief evaluate atomic expression
     219              :     double evalTernaryExpression(double a, const std::string& o, double b, const std::string& condition) const;
     220              : 
     221              :     /// @brief evaluate atomic expression
     222              :     double evalAtomicExpression(const std::string& expr) const;
     223              : 
     224              :     /// @brief evaluate function expression
     225              :     double evalCustomFunction(const std::string& fun, const std::string& arg) const;
     226              : 
     227              :     /// @brief execute assignemnts of the logic or a custom function
     228              :     void executeAssignments(const AssignmentMap& assignments, ConditionMap& conditions, const ConditionMap& forbidden = ConditionMap()) const;
     229              : 
     230              :     int getDetectorPriority(const InductLoopInfo& loopInfo) const;
     231              : 
     232              :     /// @brief count the number of active detectors for the given step
     233              :     int getPhasePriority(int step) const;
     234              : 
     235              :     /// @brief get the green phase following step and the transition time
     236              :     std::pair<int, SUMOTime> getTarget(int step) const;
     237              : 
     238              :     /// @brief whether the current phase cannot be continued due to linkMaxDur constraints
     239              :     bool maxLinkDurationReached();
     240              : 
     241              :     /// @brief whether the target phase is acceptable in light of linkMaxDur constraints
     242              :     bool canExtendLinkGreen(int target);
     243              : 
     244              :     /// @brief the minimum duratin for keeping the current phase due to linkMinDur constraints
     245              :     SUMOTime getLinkMinDuration(int target) const;
     246              : 
     247              :     /// @brief whether a given link has only weak mode foes that are green in the given state
     248              :     bool weakConflict(int linkIndex, const std::string& state) const;
     249              : 
     250              :     template<typename T, SumoXMLTag Tag>
     251       106636 :     const T* retrieveDetExpression(const std::string& arg, const std::string& expr, bool tryPrefix) const {
     252        62012 :         const T* det = dynamic_cast<const T*>(
     253       106636 :                            MSNet::getInstance()->getDetectorControl().getTypedDetectors(Tag).get(
     254       106636 :                                (tryPrefix ? myDetectorPrefix : "") + arg));
     255       106636 :         if (det == nullptr) {
     256        44624 :             if (tryPrefix) {
     257              :                 // try again without prefix
     258        33902 :                 return retrieveDetExpression<T, Tag>(arg, expr, false);
     259              :             } else {
     260        32166 :                 throw ProcessError("Unknown detector '" + arg + "' in expression '" + expr + "'");
     261              :             }
     262              :         } else {
     263              :             return det;
     264              :         }
     265              :     }
     266              : 
     267              :     /// find green phases target by a next attribute
     268              :     std::set<int> getMultiNextTargets() const;
     269              : 
     270              :     void initTargets(int step);
     271              :     void findTargets(int origStep, int n, SUMOTime priorTransition, std::map<int, SUMOTime>& found);
     272              : 
     273              : protected:
     274              :     /// @brief A map from phase to induction loops to be used for gap control
     275              :     InductLoopMap myInductLoopsForPhase;
     276              :     std::vector<std::vector<const MSLink*> > myCrossingsForPhase;
     277              : 
     278              :     std::vector<InductLoopInfo> myInductLoops;
     279              : 
     280              :     /// @brief extra loops for output/tracking
     281              :     std::vector<const MSInductLoop*> myExtraLoops;
     282              :     std::vector<const MSE2Collector*> myExtraE2;
     283              : 
     284              :     /// The maximum gap to check in seconds
     285              :     double myMaxGap;
     286              : 
     287              :     /// The minimum continuous occupancy time to mark a detector as jammed
     288              :     double myJamThreshold;
     289              : 
     290              :     /// The passing time used in seconds
     291              :     double myPassingTime;
     292              : 
     293              :     /// The detector distance in seconds
     294              :     double myDetectorGap;
     295              : 
     296              :     /// The time threshold to avoid starved phases
     297              :     SUMOTime myInactiveThreshold;
     298              : 
     299              :     /// Whether the detectors shall be shown in the GUI
     300              :     bool myShowDetectors;
     301              : 
     302              :     /// Whether all detectors shall be built
     303              :     bool myBuildAllDetectors;
     304              : 
     305              :     /// Whether any of the phases has multiple targets
     306              :     bool myHasMultiTarget;
     307              : 
     308              :     /// The output file for generated detectors
     309              :     std::string myFile;
     310              : 
     311              :     /// The frequency for aggregating detector output
     312              :     SUMOTime myFreq;
     313              : 
     314              :     /// Whether detector output separates by vType
     315              :     std::string myVehicleTypes;
     316              : 
     317              :     /// @brief last time trySwitch was called
     318              :     SUMOTime myLastTrySwitchTime;
     319              : 
     320              :     /// @brief consecutive time that the given link index has been green
     321              :     std::vector<SUMOTime> myLinkGreenTimes;
     322              :     std::vector<SUMOTime> myLinkRedTimes;
     323              :     /// @brief maximum consecutive time that the given link may remain green
     324              :     std::vector<SUMOTime> myLinkMaxGreenTimes;
     325              :     /// @brief minimum consecutive time that the given link must remain green
     326              :     std::vector<SUMOTime> myLinkMinGreenTimes;
     327              : 
     328              :     /// @brief The custom switching conditions
     329              :     ConditionMap myConditions;
     330              : 
     331              :     /// @brief The condition assignments
     332              :     AssignmentMap myAssignments;
     333              : 
     334              :     /// @brief The loaded functions
     335              :     FunctionMap myFunctions;
     336              : 
     337              :     /// @brief The function call stack;
     338              :     mutable std::vector<std::map<std::string, double> > myStack;
     339              : 
     340              :     /// @brief the conditions which shall be listed in GUITLLogicPhasesTrackerWindow
     341              :     std::set<std::string> myListedConditions;
     342              : 
     343              :     /// @brief whether the next switch time was requested via TraCI
     344              :     bool myTraCISwitch;
     345              : 
     346              :     struct SwitchingRules {
     347              :         bool enabled = false;
     348              :     };
     349              : 
     350              :     std::vector<SwitchingRules> mySwitchingRules;
     351              : 
     352              :     const std::string myDetectorPrefix;
     353              : 
     354              :     /* @brief for every actuated phase,
     355              :      * then for every target phase,
     356              :      * provide the list of green phases that are reached quickest from the target phase
     357              :      */
     358              :     std::map<int, std::map<int, std::vector<int> > > myTargets;
     359              : 
     360              :     static const std::vector<std::string> OPERATOR_PRECEDENCE;
     361              : };
        

Generated by: LCOV version 2.0-1