LCOV - code coverage report
Current view: top level - src/microsim/traffic_lights - MSSwarmTrafficLightLogic.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 70 76 92.1 %
Date: 2024-05-19 15:37:39 Functions: 17 20 85.0 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2010-2024 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    MSSwarmTrafficLightLogic.h
      15             : /// @author  Gianfilippo Slager
      16             : /// @author  Federico Caselli
      17             : /// @date    Mar 2010
      18             : ///
      19             : // The class for Swarm-based logics
      20             : /****************************************************************************/
      21             : #pragma once
      22             : #include <config.h>
      23             : 
      24             : #include "MSSOTLHiLevelTrafficLightLogic.h"
      25             : #include "MSSOTLPhasePolicy.h"
      26             : #include "MSSOTLPlatoonPolicy.h"
      27             : #include "MSSOTLMarchingPolicy.h"
      28             : #include "MSSOTLCongestionPolicy.h"
      29             : #include "MSSOTLPolicy3DStimulus.h"
      30             : #include "MSSOTLPolicy5DFamilyStimulus.h"
      31             : 
      32             : template<class T>
      33             : class CircularBuffer {
      34             : public:
      35         256 :     CircularBuffer(int size) :
      36         256 :         m_size(size), m_currentIndex(0), m_firstTime(true) {
      37         256 :         m_buffer = new T[m_size];
      38         256 :     }
      39             : 
      40         256 :     virtual ~CircularBuffer() {
      41         256 :         delete[] m_buffer;
      42         512 :     }
      43             : 
      44             :     bool addValue(const T newValue, T& replacedValue) {
      45             :         bool result = !m_firstTime;
      46             :         if (result) {
      47             :             replacedValue = m_buffer[m_currentIndex];
      48             :         }
      49             :         insert(newValue);
      50             :         return result;
      51             :     }
      52             : 
      53             :     void push_front(const T value) {
      54             :         insert(value);
      55             :     }
      56             : 
      57             :     T at(const int index) const {
      58      626192 :         int idx = (m_currentIndex - 1 - index + m_size) % m_size;
      59      458744 :         return m_buffer[idx];
      60             :     }
      61             : 
      62             :     T front() const {
      63             :         return at(0);
      64             :     }
      65             : 
      66             :     T back() const {
      67             :         return at(size() - 1);
      68             :     }
      69             : 
      70             :     int size() const {
      71      937400 :         if (m_firstTime) {
      72       28304 :             return m_currentIndex;
      73             :         }
      74      909096 :         return m_size;
      75             :     }
      76             : 
      77             :     void clear() {
      78       33656 :         m_currentIndex = 0;
      79       16828 :         m_firstTime = true;
      80             :     }
      81             : 
      82             : private:
      83             :     T* m_buffer;
      84             :     int m_size;
      85             :     int m_currentIndex;
      86             :     bool m_firstTime;
      87             : 
      88             :     inline void insert(const T& value) {
      89      108020 :         m_buffer[m_currentIndex++] = value;
      90      108020 :         if (m_currentIndex == m_size) {
      91       30366 :             m_currentIndex = 0;
      92       30366 :             m_firstTime = false;
      93             :         }
      94             :     }
      95             : };
      96             : 
      97             : class MSSwarmTrafficLightLogic: public MSSOTLHiLevelTrafficLightLogic {
      98             : public:
      99             :     //****************************************************
     100             :     /**
     101             :      * @brief Constructor without sensors passed
     102             :      * @param[in] tlcontrol The tls control responsible for this tls
     103             :      * @param[in] id This tls' id
     104             :      * @param[in] programID This tls' sub-id (program id)
     105             :      * @param[in] phases Definitions of the phases
     106             :      * @param[in] step The initial phase index
     107             :      * @param[in] delay The time to wait before the first switch
     108             :      * @param[in] parameters Parameters defined for the tll
     109             :      */
     110             :     MSSwarmTrafficLightLogic(MSTLLogicControl& tlcontrol, const std::string& id,
     111             :                              const std::string& programID, const Phases& phases, int step,
     112             :                              SUMOTime delay,
     113             :                              const Parameterised::Map& parameters);
     114             : 
     115             :     ~MSSwarmTrafficLightLogic();
     116             : 
     117             :     /**
     118             :      * @brief Initialises the tls with sensors on incoming and outgoing lanes
     119             :      * Sensors are built in the simulation according to the type of sensor specified in the simulation parameter
     120             :      * @param[in] nb The detector builder
     121             :      * @exception ProcessError If something fails on initialisation
     122             :      */
     123             :     void init(NLDetectorBuilder& nb);
     124             : 
     125           0 :     SUMOTime getMaxCongestionDuration() {
     126           0 :         return StringUtils::toInt(getParameter("MAX_CONGESTION_DUR", "120"));
     127             :     }
     128             : 
     129      255808 :     double getPheroMaxVal() {
     130      511616 :         return StringUtils::toDouble(getParameter("PHERO_MAXVAL", "10"));
     131             :     }
     132             : 
     133       31952 :     double getBetaNo() {
     134       63904 :         return StringUtils::toDouble(getParameter("BETA_NO", "0.99"));
     135             :     }
     136             : 
     137       31952 :     double getGammaNo() {
     138       63904 :         return StringUtils::toDouble(getParameter("GAMMA_NO", "1.0"));
     139             :     }
     140             : 
     141       31952 :     double getBetaSp() {
     142       63904 :         return StringUtils::toDouble(getParameter("BETA_SP", "0.99"));
     143             :     }
     144             : 
     145       31952 :     double getGammaSp() {
     146       63904 :         return StringUtils::toDouble(getParameter("GAMMA_SP", "1.0"));
     147             :     }
     148             : 
     149         306 :     double getChangePlanProbability() {
     150         918 :         return StringUtils::toDouble(getParameter("CHANGE_PLAN_PROBABILITY", "0.003"));
     151             :     }
     152             : 
     153        1128 :     double getThetaMax() {
     154        2256 :         return StringUtils::toDouble(getParameter("THETA_MAX", "0.8"));
     155             :     }
     156             : 
     157        1128 :     double getThetaMin() {
     158        2256 :         return StringUtils::toDouble(getParameter("THETA_MIN", "0.2"));
     159             :     }
     160             : 
     161           0 :     double getThetaInit() {
     162           0 :         return StringUtils::toDouble(getParameter("THETA_INIT", "0.5"));
     163             :     }
     164             : 
     165         282 :     double getLearningCox() {
     166         564 :         return StringUtils::toDouble(getParameter("LEARNING_COX", "0.0005"));
     167             :     }
     168             : 
     169         846 :     double getForgettingCox() {
     170        1692 :         return StringUtils::toDouble(getParameter("FORGETTING_COX", "0.0005"));
     171             :     }
     172             : 
     173             :     double getScaleFactorDispersionIn() {
     174           0 :         return scaleFactorDispersionIn;
     175             :     }
     176             : 
     177             :     double getScaleFactorDispersionOut() {
     178           0 :         return scaleFactorDispersionOut;
     179             :     }
     180             : 
     181             :     /** @brief Returns the type of the logic as a string
     182             :      * @return The type of the logic
     183             :      */
     184             :     const std::string getLogicType() const {
     185             :         return "swarmBasedTrafficLogic";
     186             :     }
     187             :     /// @}
     188             : 
     189             : protected:
     190             :     /**
     191             :      * @brief This pheronome is an indicator of congestion on input lanes.\n
     192             :      * Its levels refer to the average speed of vehicles passing the input lane:
     193             :      * the lower the speed the higher the pheromone.\n
     194             :      * These levels are updated on every input lane, independently on lights state.
     195             :      */
     196             :     MSLaneId_PheromoneMap pheromoneInputLanes;
     197             : 
     198             :     /**
     199             :      * \brief This pheromone is an indicator of congestion on output lanes.\n
     200             :      * Its levels refer to the average speed of vehicles passing the output lane:
     201             :      * the lower the speed the higher the pheromone.\n
     202             :      * These levels are updated on every output lane, independently on lights state.
     203             :      */
     204             :     MSLaneId_PheromoneMap pheromoneOutputLanes;
     205             : 
     206             :     /**
     207             :      * This member keeps track of the last thresholds update, s.t.
     208             :      * updates can be correctly performed even on time-variable interations.
     209             :      * @see MSSwarmTrafficLightLogic::updateSensitivities()
     210             :      */
     211             :     SUMOTime lastThetaSensitivityUpdate;
     212             : 
     213             :     /*
     214             :      * This member has to contain the switching logic for SOTL policies
     215             :      */
     216             : 
     217             :     int decideNextPhase();
     218             : 
     219             :     bool canRelease();
     220             : 
     221             :     /*
     222             :      * Computes how much time will pass after decideNextPhase will be executed again
     223             :      */
     224       31952 :     virtual SUMOTime computeReturnTime() {
     225             : 
     226       31952 :         return DELTA_T;
     227             : 
     228             :     }
     229             : 
     230             :     /**
     231             :      * @brief Resets pheromone levels
     232             :      */
     233             :     void resetPheromone();
     234             : 
     235             :     /*
     236             :      * @return The average pheromone level regarding congestion on input lanes
     237             :      */
     238             :     double getPheromoneForInputLanes();
     239             : 
     240             :     /*
     241             :      * @return The average pheromone level regarding congestion on output lanes
     242             :      */
     243             :     double getPheromoneForOutputLanes();
     244             : 
     245             :     /*
     246             :      * @return The dispersion level regarding congestion on input lanes
     247             :      */
     248             :     double getDispersionForInputLanes(double average_phero_in);
     249             : 
     250             :     /*
     251             :      * @return The dispersion level regarding congestion on output lanes
     252             :      */
     253             :     double getDispersionForOutputLanes(double average_phero_out);
     254             : 
     255             :     /*
     256             :      * @return The difference between the current max phero value and the average phero of the other lanes
     257             :      */
     258             :     double getDistanceOfMaxPheroForInputLanes();
     259             : 
     260             :     /*
     261             :      * @return The difference between the current max phero value and the average phero of the other lanes
     262             :      */
     263             :     double getDistanceOfMaxPheroForOutputLanes();
     264             :     /**
     265             :      * @brief Update pheromone levels
     266             :      * Pheromone on input lanes is costantly updated
     267             :      * Pheromone follows a discrete-time dynamic law "pheromone(k+1) = beta*pheromone(k) + gamma * sensed_val(k)"
     268             :      */
     269             :     void updatePheromoneLevels();
     270             : 
     271             :     /**
     272             :      * @brief Utility method to avoid code duplication
     273             :      */
     274             :     void updatePheromoneLevels(MSLaneId_PheromoneMap&, std::string, const double, const double);
     275             : 
     276             :     /**
     277             :      * After a policy has been chosen, for every iteration thresholds has to be updated.
     278             :      * Thresholds reinforcement lowers the theta_sensitivity for the current policy and raises the ones for currently unused policies.
     279             :      * Thresholds belongs to the interval [THETA_MIN THETA_MAX]
     280             :      */
     281             :     void updateSensitivities();
     282             : 
     283             :     /**
     284             :      * @brief Decide the current policy according to pheromone levels
     285             :      * The decision reflects on currentPolicy value
     286             :      */
     287             :     void decidePolicy();
     288             : 
     289             :     /**
     290             :      * \brief Method that should calculate the valor of phi a coefficient to amplify/attenuate eta based on a factor.
     291             :      * The factor depends on the situation when the function is called; should be the number of cars in the target lanes
     292             :      * or the number of cars in the lanes with a red tl.
     293             :      * @param[in] factor - the value to consider to compute this coefficient.
     294             :      */
     295             :     double calculatePhi(int factor);
     296             : 
     297             :     /**
     298             :      * \brief Method that should calculate the valor of eta a coefficient to evaluate the current
     299             :      * policy's work. This eta is based on the difference between the number of vehicles that enters a tl
     300             :      * and the ones that exit it. It consider vehicles on a lane with a tl set to red as well to determinate
     301             :      * policy work.
     302             :      */
     303             :     double calculateEtaDiff();
     304             : 
     305             :     double calculateEtaRatio();
     306             : 
     307             :     /*
     308             :      * \brief Method to reset the map that stores if a lane is already been checked during the
     309             :      * evaluation of eta.
     310             :      */
     311             :     void resetLaneCheck();
     312             :     void choosePolicy(double phero_in, double phero_out, double dispersion_in, double dispersion_out);
     313             :     void choosePolicy(double phero_in, double phero_out);
     314             : 
     315          32 :     std::string getPoliciesParam() {
     316          96 :         return getParameter("POLICIES", "Platoon;Phase;Marching;Congestion");
     317             :     }
     318             : 
     319             :     /*
     320             :      * Reinforcement modes:
     321             :      * 0-> elapsed time
     322             :      * 1-> diff
     323             :      * 2-> ratio
     324             :      */
     325         306 :     int getReinforcementMode() {
     326         612 :         return StringUtils::toInt(getParameter("REIMODE", "0"));
     327             :     }
     328             : 
     329          32 :     void initScaleFactorDispersionIn(int lanes_in) {
     330             :         std::vector<double> phero_values;
     331             : 
     332          96 :         for (int i = 0; i < lanes_in / 2; i++) {
     333          64 :             phero_values.push_back(getPheroMaxVal());
     334             :         }
     335          96 :         for (int i = lanes_in / 2; i < lanes_in; i++) {
     336          64 :             phero_values.push_back(0.0);
     337             :         }
     338             : 
     339             :         double sum_avg_tmp = 0;
     340             : 
     341         160 :         for (int i = 0; i < (int)phero_values.size(); i++) {
     342         128 :             sum_avg_tmp += phero_values[i];
     343             :         }
     344             : 
     345          32 :         const double mean = sum_avg_tmp / (double)phero_values.size();
     346             : 
     347             :         double sum_dev_tmp = 0;
     348         160 :         for (int i = 0; i < (int)phero_values.size(); i++) {
     349         128 :             sum_dev_tmp += pow(phero_values[i] - mean, 2);
     350             :         }
     351             : 
     352          32 :         const double deviation = sqrt(sum_dev_tmp / (double)phero_values.size());
     353             : 
     354          32 :         scaleFactorDispersionIn = getPheroMaxVal() / deviation;
     355          32 :     }
     356             : 
     357          32 :     void initScaleFactorDispersionOut(int lanes_out) {
     358             :         std::vector<double> phero_values;
     359             : 
     360          96 :         for (int i = 0; i < lanes_out / 2; i++) {
     361          64 :             phero_values.push_back(getPheroMaxVal());
     362             :         }
     363          96 :         for (int i = lanes_out / 2; i < lanes_out; i++) {
     364          64 :             phero_values.push_back(0.0);
     365             :         }
     366             : 
     367             :         double sum_avg_tmp = 0;
     368         160 :         for (int i = 0; i < (int)phero_values.size(); i++) {
     369         128 :             sum_avg_tmp += phero_values[i];
     370             :         }
     371          32 :         const double mean = sum_avg_tmp / (double)phero_values.size();
     372             : 
     373             :         double sum_dev_tmp = 0;
     374             : 
     375         160 :         for (int i = 0; i < (int)phero_values.size(); i++) {
     376         128 :             sum_dev_tmp += pow(phero_values[i] - mean, 2);
     377             :         }
     378             : 
     379          32 :         const double deviation = sqrt(sum_dev_tmp / (double)phero_values.size());
     380             : 
     381          32 :         scaleFactorDispersionOut = getPheroMaxVal() / deviation;
     382          32 :     }
     383             : 
     384             :     /**
     385             :      * @brief Check if a lane is allowed to be added to the maps pheromoneInputLanes and pheromoneOutputLanes
     386             :      * Control in this function if the lane is a walking area, a crossing, or if only pedestrian are allowed.
     387             :      * Return true if the lane has to be added, false otherwise.
     388             :      */
     389             :     bool allowLine(MSLane*);
     390             : 
     391             :     bool logData;
     392             :     std::ofstream swarmLogFile;
     393             :     /**
     394             :      * \brief When true, indicates that the current policy MUST be changed.\n
     395             :      * It's used to force the exit from the congestion policy
     396             :      */
     397             :     bool mustChange;
     398             :     SUMOTime congestion_steps;
     399             : 
     400             :     /**
     401             :      * \brief Map to check if a lane was already controlled during the elaboration of eta.
     402             :      */
     403             :     LaneCheckMap laneCheck;
     404             :     /**
     405             :      * \brief A copy of the target lanes of this phase.
     406             :      */
     407             :     LaneIdVector targetLanes;
     408             :     /**
     409             :      * \brief When true indicates that we can skip the evaluation of eta since we've
     410             :      * a congestion policy that is lasting too much.
     411             :      */
     412             :     bool skipEta;
     413             :     /**
     414             :      * \brief When true indicates that we've already acquired the target lanes for this
     415             :      * particular phase.
     416             :      */
     417             :     bool gotTargetLane;
     418             : 
     419             :     int carsIn;
     420             :     int carsOut;
     421             :     int inTarget;
     422             :     int notTarget;
     423             :     /**
     424             :      * \factors to scale pheromoneDispersion in range [0, 10]
     425             :      */
     426             :     double scaleFactorDispersionIn;
     427             :     double scaleFactorDispersionOut;
     428             : 
     429             : //      For every lane its index. Esed to get the current lane state for the lane
     430             :     std::map<std::string, std::vector<int> > m_laneIndexMap;
     431             :     std::string getLaneLightState(const std::string& laneId);
     432             : //      store the last message logged. if equal do not log it again
     433             :     Parameterised::Map m_pheroLevelLog;
     434             : 
     435             :     //derivative
     436             :     std::map<std::string, CircularBuffer<double>* > m_meanSpeedHistory;
     437             :     std::map<std::string, CircularBuffer<double>* > m_derivativeHistory;
     438             :     double m_derivativeAlpha;
     439             :     int m_losCounter;//los: loss of signal
     440             :     int m_losMaxLimit;
     441             :     bool m_useVehicleTypesWeights;
     442             : 
     443             : //      double pheroBegin;
     444             : };

Generated by: LCOV version 1.14