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

            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          128 :     CircularBuffer(int size) :
      36          128 :         m_size(size), m_currentIndex(0), m_firstTime(true) {
      37          128 :         m_buffer = new T[m_size];
      38          128 :     }
      39              : 
      40          128 :     virtual ~CircularBuffer() {
      41          128 :         delete[] m_buffer;
      42          256 :     }
      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       313096 :         int idx = (m_currentIndex - 1 - index + m_size) % m_size;
      59       229372 :         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       468700 :         if (m_firstTime) {
      72        14152 :             return m_currentIndex;
      73              :         }
      74       454548 :         return m_size;
      75              :     }
      76              : 
      77              :     void clear() {
      78        16828 :         m_currentIndex = 0;
      79         8414 :         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        54010 :         m_buffer[m_currentIndex++] = value;
      90        54010 :         if (m_currentIndex == m_size) {
      91        15183 :             m_currentIndex = 0;
      92        15183 :             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       127904 :     double getPheroMaxVal() {
     130       255808 :         return StringUtils::toDouble(getParameter("PHERO_MAXVAL", "10"));
     131              :     }
     132              : 
     133        15976 :     double getBetaNo() {
     134        31952 :         return StringUtils::toDouble(getParameter("BETA_NO", "0.99"));
     135              :     }
     136              : 
     137        15976 :     double getGammaNo() {
     138        31952 :         return StringUtils::toDouble(getParameter("GAMMA_NO", "1.0"));
     139              :     }
     140              : 
     141        15976 :     double getBetaSp() {
     142        31952 :         return StringUtils::toDouble(getParameter("BETA_SP", "0.99"));
     143              :     }
     144              : 
     145        15976 :     double getGammaSp() {
     146        31952 :         return StringUtils::toDouble(getParameter("GAMMA_SP", "1.0"));
     147              :     }
     148              : 
     149          153 :     double getChangePlanProbability() {
     150          306 :         return StringUtils::toDouble(getParameter("CHANGE_PLAN_PROBABILITY", "0.003"));
     151              :     }
     152              : 
     153          564 :     double getThetaMax() {
     154         1128 :         return StringUtils::toDouble(getParameter("THETA_MAX", "0.8"));
     155              :     }
     156              : 
     157          564 :     double getThetaMin() {
     158         1128 :         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          141 :     double getLearningCox() {
     166          282 :         return StringUtils::toDouble(getParameter("LEARNING_COX", "0.0005"));
     167              :     }
     168              : 
     169          423 :     double getForgettingCox() {
     170          846 :         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        15976 :     virtual SUMOTime computeReturnTime() {
     225              : 
     226        15976 :         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           16 :     std::string getPoliciesParam() {
     316           32 :         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          153 :     int getReinforcementMode() {
     326          306 :         return StringUtils::toInt(getParameter("REIMODE", "0"));
     327              :     }
     328              : 
     329           16 :     void initScaleFactorDispersionIn(int lanes_in) {
     330              :         std::vector<double> phero_values;
     331              : 
     332           48 :         for (int i = 0; i < lanes_in / 2; i++) {
     333           32 :             phero_values.push_back(getPheroMaxVal());
     334              :         }
     335           48 :         for (int i = lanes_in / 2; i < lanes_in; i++) {
     336           32 :             phero_values.push_back(0.0);
     337              :         }
     338              : 
     339              :         double sum_avg_tmp = 0;
     340              : 
     341           80 :         for (int i = 0; i < (int)phero_values.size(); i++) {
     342           64 :             sum_avg_tmp += phero_values[i];
     343              :         }
     344              : 
     345           16 :         const double mean = sum_avg_tmp / (double)phero_values.size();
     346              : 
     347              :         double sum_dev_tmp = 0;
     348           80 :         for (int i = 0; i < (int)phero_values.size(); i++) {
     349           64 :             sum_dev_tmp += pow(phero_values[i] - mean, 2);
     350              :         }
     351              : 
     352           16 :         const double deviation = sqrt(sum_dev_tmp / (double)phero_values.size());
     353              : 
     354           16 :         scaleFactorDispersionIn = getPheroMaxVal() / deviation;
     355           16 :     }
     356              : 
     357           16 :     void initScaleFactorDispersionOut(int lanes_out) {
     358              :         std::vector<double> phero_values;
     359              : 
     360           48 :         for (int i = 0; i < lanes_out / 2; i++) {
     361           32 :             phero_values.push_back(getPheroMaxVal());
     362              :         }
     363           48 :         for (int i = lanes_out / 2; i < lanes_out; i++) {
     364           32 :             phero_values.push_back(0.0);
     365              :         }
     366              : 
     367              :         double sum_avg_tmp = 0;
     368           80 :         for (int i = 0; i < (int)phero_values.size(); i++) {
     369           64 :             sum_avg_tmp += phero_values[i];
     370              :         }
     371           16 :         const double mean = sum_avg_tmp / (double)phero_values.size();
     372              : 
     373              :         double sum_dev_tmp = 0;
     374              : 
     375           80 :         for (int i = 0; i < (int)phero_values.size(); i++) {
     376           64 :             sum_dev_tmp += pow(phero_values[i] - mean, 2);
     377              :         }
     378              : 
     379           16 :         const double deviation = sqrt(sum_dev_tmp / (double)phero_values.size());
     380              : 
     381           16 :         scaleFactorDispersionOut = getPheroMaxVal() / deviation;
     382           16 :     }
     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 2.0-1