LCOV - code coverage report
Current view: top level - src/microsim/traffic_lights - MSTrafficLightLogic.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 93.4 % 287 268
Test Date: 2025-11-13 15:38:19 Functions: 79.4 % 34 27

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2025 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    MSTrafficLightLogic.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Michael Behrisch
      18              : /// @date    Sept 2002
      19              : ///
      20              : // The parent class for traffic light logics
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #include <cassert>
      25              : #include <string>
      26              : #include <iostream>
      27              : #include <map>
      28              : #include <microsim/MSLink.h>
      29              : #include <microsim/MSLane.h>
      30              : #include <microsim/MSEventControl.h>
      31              : #include <microsim/MSJunctionLogic.h>
      32              : #include <microsim/MSNet.h>
      33              : #include <microsim/MSEdge.h>
      34              : #include <microsim/MSGlobals.h>
      35              : #include <mesosim/MESegment.h>
      36              : #include "MSTLLogicControl.h"
      37              : #include "MSTrafficLightLogic.h"
      38              : 
      39              : 
      40              : // ===========================================================================
      41              : // static value definitions
      42              : // ===========================================================================
      43              : const MSTrafficLightLogic::LaneVector MSTrafficLightLogic::myEmptyLaneVector;
      44              : 
      45              : 
      46              : #define SHORT_EDGE ((SUMOVTypeParameter::getDefault().length + SUMOVTypeParameter::getDefault().minGap) * 2)
      47              : 
      48              : // ===========================================================================
      49              : // member method definitions
      50              : // ===========================================================================
      51              : /* -------------------------------------------------------------------------
      52              :  * member method definitions
      53              :  * ----------------------------------------------------------------------- */
      54       116758 : MSTrafficLightLogic::SwitchCommand::SwitchCommand(MSTLLogicControl& tlcontrol,
      55       116758 :         MSTrafficLightLogic* tlLogic, SUMOTime nextSwitch) :
      56       116758 :     myTLControl(tlcontrol), myTLLogic(tlLogic),
      57       116758 :     myAssumedNextSwitch(nextSwitch), myAmValid(true) {
      58              :     // higher than default command priority of 0
      59       116758 :     priority = std::numeric_limits<int>::max();
      60       116758 : }
      61              : 
      62              : 
      63       232056 : MSTrafficLightLogic::SwitchCommand::~SwitchCommand() {}
      64              : 
      65              : 
      66              : 
      67              : SUMOTime
      68      6072808 : MSTrafficLightLogic::SwitchCommand::execute(SUMOTime t) {
      69              :     // check whether this command has been descheduled
      70      6072808 :     if (!myAmValid) {
      71              :         return 0;
      72              :     }
      73      6065147 :     int step1 = myTLLogic->getCurrentPhaseIndex();
      74      6065147 :     SUMOTime next = myTLLogic->trySwitch();
      75      6065462 :     while (next == 0) {
      76              :         // skip phase and switch again
      77          315 :         next = myTLLogic->trySwitch();
      78              :     }
      79      6065147 :     int step2 = myTLLogic->getCurrentPhaseIndex();
      80      6065147 :     if (step1 != step2) {
      81      4150966 :         if (myTLLogic->isActive()) {
      82              :             // execute any action connected to this tls
      83      3616285 :             const MSTLLogicControl::TLSLogicVariants& vars = myTLControl.get(myTLLogic->getID());
      84              :             // set link priorities
      85      3616285 :             myTLLogic->setTrafficLightSignals(t);
      86              :             // execute switch actions
      87      3616285 :             vars.executeOnSwitchActions();
      88              :         }
      89              :     }
      90      6065147 :     myAssumedNextSwitch += next;
      91      6065147 :     return next;
      92              : }
      93              : 
      94              : 
      95              : void
      96         8095 : MSTrafficLightLogic::SwitchCommand::deschedule(MSTrafficLightLogic* tlLogic) {
      97         8095 :     if (tlLogic == myTLLogic) {
      98         8095 :         myAmValid = false;
      99         8095 :         myAssumedNextSwitch = -1;
     100              :     }
     101         8095 : }
     102              : 
     103              : 
     104              : SUMOTime
     105         1013 : MSTrafficLightLogic::SwitchCommand::shiftTime(SUMOTime currentTime, SUMOTime execTime, SUMOTime newTime) {
     106              :     if (myTLLogic->getDefaultCycleTime() == DELTA_T) {
     107              :         // MSRailSignal
     108              :         return newTime;
     109              :     } else {
     110              :         UNUSED_PARAMETER(currentTime);
     111              :         UNUSED_PARAMETER(execTime);
     112              :         // XXX changeStepAndDuration (computed as in NLJunctionControlBuilder::closeTrafficLightLogic
     113              :         return newTime;
     114              :     }
     115              : }
     116              : 
     117              : /* -------------------------------------------------------------------------
     118              :  * member method definitions
     119              :  * ----------------------------------------------------------------------- */
     120       113264 : MSTrafficLightLogic::MSTrafficLightLogic(MSTLLogicControl& tlcontrol, const std::string& id,
     121              :         const std::string& programID, const SUMOTime offset, const TrafficLightType logicType, const SUMOTime delay,
     122       113264 :         const Parameterised::Map& parameters) :
     123              :     Named(id), Parameterised(parameters),
     124       113264 :     myProgramID(programID),
     125       113264 :     myOffset(offset),
     126       113264 :     myLogicType(logicType),
     127       113264 :     myCurrentDurationIncrement(-1),
     128       113264 :     myDefaultCycleTime(0),
     129       113264 :     myAmActive(true) {
     130       113264 :     mySwitchCommand = new SwitchCommand(tlcontrol, this, delay);
     131       113264 :     MSNet::getInstance()->getBeginOfTimestepEvents()->addEvent(mySwitchCommand, delay);
     132       113264 : }
     133              : 
     134              : 
     135              : void
     136       100230 : MSTrafficLightLogic::init(NLDetectorBuilder&) {
     137       100230 :     const Phases& phases = getPhases();
     138       100230 :     if (phases.size() > 0 && (MSGlobals::gUseMesoSim || MSGlobals::gTLSPenalty > 0)) {
     139        16649 :         initMesoTLSPenalties();
     140              :     }
     141       100230 :     if (phases.size() > 1) {
     142              :         bool haveWarnedAboutUnusedStates = false;
     143       586376 :         for (int i = 0; i < (int)phases.size(); ++i) {
     144              :             // warn about unused states
     145              :             std::vector<int> nextPhases;
     146       503901 :             nextPhases.push_back((i + 1) % phases.size());
     147              :             bool iNextDefault = true;
     148       503901 :             if (phases[i]->nextPhases.size() > 0) {
     149          248 :                 nextPhases = phases[i]->nextPhases;
     150              :                 iNextDefault = false;
     151              :             }
     152      1007944 :             for (int iNext : nextPhases) {
     153       504046 :                 if (iNext < 0 || iNext >= (int)phases.size()) {
     154            1 :                     throw ProcessError("Invalid nextPhase " + toString(iNext) + " in tlLogic '" + getID()
     155            4 :                                        + "', program '" + getProgramID() + "' with " + toString(phases.size()) + " phases");
     156              :                 }
     157       504045 :                 if (iNext == i && (int)nextPhases.size() == 1 && (int)phases.size() > 1) {
     158            3 :                     WRITE_WARNINGF("Phase % only loops backs to itself in tlLogic '%', program '%'.", i, getID(), getProgramID());
     159              :                 }
     160       504437 :                 const std::string optionalFrom = iNextDefault ? "" : " from phase " + toString(i);
     161       504045 :                 const std::string& state1 = phases[i]->getState();
     162       504045 :                 const std::string& state2 = phases[iNext]->getState();
     163       504045 :                 if (state1.size() != state2.size()) {
     164            1 :                     throw ProcessError("Mismatching phase state length in tlLogic '" + getID()
     165            4 :                                        + "', program '" + getProgramID() + "' in phases " + toString(i) + " and " + toString(iNext));
     166              :                 }
     167       504044 :                 if (!haveWarnedAboutUnusedStates && state1.size() > myLanes.size() + myIgnoredIndices.size()) {
     168          228 :                     WRITE_WARNINGF(TL("Unused states in tlLogic '%', program '%' in phase % after tl-index %"),
     169              :                                    getID(), getProgramID(), i, (int)myLanes.size() - 1);
     170              :                     haveWarnedAboutUnusedStates = true;
     171              :                 }
     172              :                 // detect illegal states
     173              :                 const std::string::size_type illegal = state1.find_first_not_of(SUMOXMLDefinitions::ALLOWED_TLS_LINKSTATES);
     174       504044 :                 if (std::string::npos != illegal) {
     175            1 :                     throw ProcessError("Illegal character '" + toString(state1[illegal]) + "' in tlLogic '" + getID()
     176            3 :                                        + "', program '" + getProgramID() + "' in phase " + toString(i));
     177              :                 }
     178              :                 // warn about transitions from green to red without intermediate yellow
     179              :                 bool haveWarned = false;
     180      6393431 :                 for (int j = 0; j < (int)MIN3(state1.size(), state2.size(), myLanes.size()) && !haveWarned; ++j) {
     181      5889388 :                     if ((LinkState)state2[j] == LINKSTATE_TL_RED
     182      5889388 :                             && ((LinkState)state1[j] == LINKSTATE_TL_GREEN_MAJOR
     183      3422222 :                                 || (LinkState)state1[j] == LINKSTATE_TL_GREEN_MINOR)) {
     184        27160 :                         for (LaneVector::const_iterator it = myLanes[j].begin(); it != myLanes[j].end(); ++it) {
     185        14188 :                             if ((*it)->getPermissions() != SVC_PEDESTRIAN) {
     186         1265 :                                 if (getLogicType() != TrafficLightType::NEMA) {
     187          980 :                                     WRITE_WARNINGF(TL("Missing yellow phase in tlLogic '%', program '%' for tl-index % when switching% to phase %."),
     188              :                                                    getID(), getProgramID(), j, optionalFrom, iNext);
     189              :                                     // one warning per program is enough
     190              :                                     haveWarned = true;
     191              :                                 }
     192              :                                 break;
     193              :                             }
     194              :                         }
     195              :                     }
     196              :                 }
     197              :             }
     198       503901 :         }
     199              :     }
     200              :     // warn about links that never get the green light
     201       100227 :     std::vector<bool> foundGreen(phases.front()->getState().size(), false);
     202       621869 :     for (int i = 0; i < (int)phases.size(); ++i) {
     203       521642 :         const std::string& state = phases[i]->getState();
     204      6475255 :         for (int j = 0; j < (int)state.size(); ++j) {
     205      5953613 :             LinkState ls = (LinkState)state[j];
     206      5953613 :             if (ls == LINKSTATE_TL_GREEN_MAJOR || ls == LINKSTATE_TL_GREEN_MINOR || ls == LINKSTATE_TL_OFF_BLINKING || ls == LINKSTATE_TL_OFF_NOSIGNAL || ls == LINKSTATE_STOP) {
     207              :                 foundGreen[j] = true;
     208              :             }
     209              :         }
     210              :     }
     211       100227 :     std::vector<bool> usedIndices(phases.front()->getState().size(), false);
     212       998112 :     for (auto lv : myLinks) {
     213      1794863 :         for (const MSLink* link : lv) {
     214       896978 :             if (link->getTLIndex() >= 0) {
     215              :                 usedIndices[link->getTLIndex()] = true;
     216              :             }
     217              :         }
     218       897885 :     }
     219      1987694 :     for (int j = 0; j < (int)foundGreen.size(); ++j) {
     220       893994 :         if (!foundGreen[j] && usedIndices[j]) {
     221         1122 :             WRITE_WARNINGF(TL("Missing green phase in tlLogic '%', program '%' for tl-index %."), getID(), getProgramID(), j);
     222          374 :             break;
     223              :         }
     224              :     }
     225              :     // check direct conflict (two green links targeting the same lane)
     226       100227 :     const int numLinks = (int)myLinks.size();
     227              :     std::set<const MSLane*> unsafeGreen;
     228              :     int firstUnsafePhase = -1;
     229              :     const MSLane* firstUnsafeLane = nullptr;
     230              :     int firstUnsafeOrigins = 0;
     231              :     int unsafeGreenPhases = 0;
     232       621869 :     for (int i = 0; i < (int)phases.size(); ++i) {
     233              :         std::map<const MSLane*, int, ComparatorNumericalIdLess> greenLanes;
     234       521642 :         const std::string& state = phases[i]->getState();
     235      6463932 :         for (int j = 0; j < numLinks; ++j) {
     236      5942290 :             if (state[j] == LINKSTATE_TL_GREEN_MAJOR) {
     237      1774971 :                 for (const MSLink* link : myLinks[j]) {
     238       887307 :                     if (link->isInternalJunctionLink()) {
     239              :                         // links from an internal junction have implicit priority in case of conflict
     240          158 :                         continue;
     241              :                     }
     242       887149 :                     greenLanes[link->getLane()] += 1;
     243              :                 }
     244              :             }
     245              :         }
     246              :         bool unsafe = false;
     247      1400530 :         for (auto item : greenLanes) {
     248       878888 :             if (item.second > 1) {
     249         3382 :                 if (unsafeGreenPhases == 0 && !unsafe) {
     250              :                     firstUnsafePhase = i;
     251          580 :                     firstUnsafeLane = item.first;
     252              :                     firstUnsafeOrigins = item.second;
     253              :                 }
     254              :                 unsafe = true;
     255              :                 unsafeGreen.insert(item.first);
     256              :             }
     257              :         }
     258       521642 :         if (unsafe) {
     259         1017 :             unsafeGreenPhases++;
     260              :         }
     261              :     }
     262       100227 :     if (unsafeGreenPhases > 0) {
     263          580 :         const std::string furtherAffected = unsafeGreen.size() > 1 || unsafeGreenPhases > 1 ? TLF(" Overall % lanes in % phases are unsafe.", unsafeGreen.size(), unsafeGreenPhases) : "";
     264         1740 :         WRITE_WARNINGF(TL("Unsafe green phase % in tlLogic '%', program '%'. Lane '%' is targeted by % 'G'-links. (use 'g' instead)%"),
     265              :                        firstUnsafePhase, getID(), getProgramID(), firstUnsafeLane->getID(), firstUnsafeOrigins, furtherAffected);
     266              :     }
     267              : 
     268              :     // check incompatible junction logic
     269              :     // this can happen if the network was built with a very different signal
     270              :     // plan from the one currently being used.
     271              :     // Connections that never had a common green phase during network building may
     272              :     // have a symmetric response relation to avoid certain kinds of jam but this
     273              :     // can lead to deadlock if a different program gives minor green to both
     274              :     // connections at the same time
     275              :     // Note: mutual conflict between 'g' and 'G' is expected for traffic_light_right_on_red
     276              : 
     277       100227 :     const bool mustCheck = MSNet::getInstance()->hasInternalLinks();
     278              :     // The checks only runs for definitions from additional file and this is sufficient.
     279              :     // The distinction is implicit because original logics are loaded earlier and at that time hasInternalLinks is always false
     280              :     // Also, when the network has no internal links, mutual conflicts are not built by netconvert
     281              :     //std::cout << "init tlLogic=" << getID() << " prog=" << getProgramID() << " links=" << myLinks.size() << " internal=" << MSNet::getInstance()->hasInternalLinks() << "\n";
     282       100227 :     if (mustCheck && phases.size() > 0) {
     283              :         // see NBNode::tlsConflict
     284              :         std::set<const MSJunction*> controlledJunctions;
     285       279437 :         for (int j = 0; j < numLinks; ++j) {
     286       487364 :             for (int k = 0; k < (int)myLinks[j].size(); ++k) {
     287       243228 :                 MSLink* link = myLinks[j][k];
     288              :                 assert(link->getJunction() != nullptr);
     289       243228 :                 controlledJunctions.insert(link->getJunction());
     290              :             }
     291              :         }
     292        35301 :         const std::string minor = "gos";
     293        71290 :         for (const MSJunction* junction : controlledJunctions) {
     294        35989 :             const MSJunctionLogic* logic = junction->getLogic();
     295        35989 :             if (logic != nullptr) {
     296              :                 // find symmetrical response
     297              :                 const int logicSize = logic->getLogicSize();
     298              :                 bool foundProblem = false;
     299              :                 std::vector<int> tlIndex;
     300       279786 :                 for (int u = 0; u < logicSize && !foundProblem; u++) {
     301       243856 :                     const MSLogicJunction::LinkBits& response = logic->getResponseFor(u);
     302      3641000 :                     for (int v = 0; v < logicSize && !foundProblem; v++) {
     303      3397144 :                         if (response.test(v)) {
     304       664256 :                             if (logic->getResponseFor(v).test(u)) {
     305              :                                 // get tls link index for links u and v
     306       151966 :                                 if (tlIndex.size() == 0) {
     307              :                                     // init tlindex for all links  once
     308         5267 :                                     tlIndex.resize(logicSize, -1);
     309       110339 :                                     for (int j = 0; j < numLinks; ++j) {
     310       210350 :                                         for (int k = 0; k < (int)myLinks[j].size(); ++k) {
     311       105278 :                                             MSLink* link = myLinks[j][k];
     312       105278 :                                             if (link->getJunction() == junction) {
     313       104517 :                                                 if (link->fromInternalLane()) {
     314              :                                                     // internal links may have their own control (i.e. for indirect left turn) but they also have their own conflict matrix
     315          174 :                                                     continue;
     316              :                                                 }
     317       104343 :                                                 if (link->isCont() && link->getViaLane() != nullptr && link->getViaLane()->getLinkCont()[0]->getTLIndex() >= 0) {
     318              :                                                     // if the internal junction link is controlled, the first-part indices are not deadlock-relevant
     319           98 :                                                     continue;
     320              :                                                 }
     321       104245 :                                                 tlIndex[link->getIndex()] = link->getTLIndex();
     322              :                                             }
     323              :                                         }
     324              :                                     }
     325              :                                 }
     326       151966 :                                 const int tlu = tlIndex[u];
     327       151966 :                                 const int tlv = tlIndex[v];
     328       151966 :                                 if (tlu >= 0 && tlv >= 0) {
     329              :                                     int phaseIndex = 0;
     330      1356638 :                                     for (MSPhaseDefinition* p : phases) {
     331      1205762 :                                         if (minor.find(p->getState()[tlu]) != std::string::npos
     332      1205762 :                                                 && minor.find(p->getState()[tlv]) != std::string::npos) {
     333           30 :                                             WRITE_WARNING(TLF("Program '%' at tlLogic '%' is incompatible with logic at junction '%' (mutual conflict between link indices %,% tl indices %,% phase %).\n"
     334              :                                                               "  To avoid deadlock/collisions, either: rebuild the signal plan with a newer version of netconvert/netedit\n"
     335              :                                                               "  or rebuild the network with option '--tls.ignore-internal-junction-jam' or include the program when building.",
     336              :                                                               getProgramID(), getID(), junction->getID(), u, v, tlu, tlv, phaseIndex));
     337              :                                             // only one warning per program
     338              :                                             foundProblem = true;
     339           10 :                                             break;
     340              :                                         }
     341      1205752 :                                         phaseIndex++;
     342              :                                     }
     343              :                                 }
     344              :                             }
     345              :                         }
     346              :                     }
     347              :                 }
     348        35930 :             }
     349              :         }
     350              :     }
     351       100227 :     myNumLinks = (int)myLinks.size();
     352       100227 : }
     353              : 
     354              : 
     355       226170 : MSTrafficLightLogic::~MSTrafficLightLogic() {
     356              :     // no need to do something about mySwitchCommand here,
     357              :     // it is handled by the event control
     358       226170 : }
     359              : 
     360              : 
     361              : // ----------- Handling of controlled links
     362              : void
     363       832576 : MSTrafficLightLogic::addLink(MSLink* link, MSLane* lane, int pos) {
     364              :     // !!! should be done within the loader (checking necessary)
     365       832576 :     myLinks.reserve(pos + 1);
     366      1666279 :     while ((int)myLinks.size() <= pos) {
     367       833703 :         myLinks.push_back(LinkVector());
     368              :     }
     369       832576 :     myLinks[pos].push_back(link);
     370              :     //
     371       832576 :     myLanes.reserve(pos + 1);
     372      1666279 :     while ((int)myLanes.size() <= pos) {
     373       833703 :         myLanes.push_back(LaneVector());
     374              :     }
     375       832576 :     myLanes[pos].push_back(lane);
     376       832576 :     link->setTLState((LinkState) getCurrentPhaseDef().getState()[pos], MSNet::getInstance()->getCurrentTimeStep());
     377       832576 : }
     378              : 
     379              : 
     380              : void
     381         9281 : MSTrafficLightLogic::adaptLinkInformationFrom(const MSTrafficLightLogic& logic) {
     382         9281 :     myLinks = logic.myLinks;
     383         9281 :     myLanes = logic.myLanes;
     384              :     myIgnoredIndices = logic.myIgnoredIndices;
     385         9281 : }
     386              : 
     387              : 
     388              : std::map<MSLink*, LinkState>
     389       103106 : MSTrafficLightLogic::collectLinkStates() const {
     390              :     std::map<MSLink*, LinkState> ret;
     391       928504 :     for (LinkVectorVector::const_iterator i1 = myLinks.begin(); i1 != myLinks.end(); ++i1) {
     392              :         const LinkVector& l = (*i1);
     393      1649666 :         for (LinkVector::const_iterator i2 = l.begin(); i2 != l.end(); ++i2) {
     394       824268 :             ret[*i2] = (*i2)->getState();
     395              :         }
     396              :     }
     397       103106 :     return ret;
     398              : }
     399              : 
     400              : 
     401              : bool
     402     11401578 : MSTrafficLightLogic::setTrafficLightSignals(SUMOTime t) const {
     403              :     // get the current traffic light signal combination
     404     11401578 :     const std::string& state = getCurrentPhaseDef().getState();
     405              :     // go through the links
     406     59611593 :     for (int i = 0; i < (int)myLinks.size(); i++) {
     407     48210015 :         const LinkVector& currGroup = myLinks[i];
     408     48210015 :         LinkState ls = (LinkState) state[i];
     409     96541468 :         for (LinkVector::const_iterator j = currGroup.begin(); j != currGroup.end(); j++) {
     410     48331453 :             (*j)->setTLState(ls, t);
     411              :         }
     412              :     }
     413     11401578 :     return true;
     414              : }
     415              : 
     416              : 
     417              : void
     418            0 : MSTrafficLightLogic::resetLinkStates(const std::map<MSLink*, LinkState>& vals) const {
     419            0 :     for (LinkVectorVector::const_iterator i1 = myLinks.begin(); i1 != myLinks.end(); ++i1) {
     420              :         const LinkVector& l = (*i1);
     421            0 :         for (LinkVector::const_iterator i2 = l.begin(); i2 != l.end(); ++i2) {
     422              :             assert(vals.find(*i2) != vals.end());
     423            0 :             (*i2)->setTLState(vals.find(*i2)->second, MSNet::getInstance()->getCurrentTimeStep());
     424              :         }
     425              :     }
     426            0 : }
     427              : 
     428              : 
     429              : // ----------- Static Information Retrieval
     430              : int
     431            0 : MSTrafficLightLogic::getLinkIndex(const MSLink* const link) const {
     432              :     int index = 0;
     433            0 :     for (LinkVectorVector::const_iterator i1 = myLinks.begin(); i1 != myLinks.end(); ++i1, ++index) {
     434              :         const LinkVector& l = (*i1);
     435            0 :         for (LinkVector::const_iterator i2 = l.begin(); i2 != l.end(); ++i2) {
     436            0 :             if ((*i2) == link) {
     437              :                 return index;
     438              :             }
     439              :         }
     440              :     }
     441              :     return -1;
     442              : }
     443              : 
     444              : 
     445              : 
     446              : // ----------- Dynamic Information Retrieval
     447              : SUMOTime
     448       109914 : MSTrafficLightLogic::getNextSwitchTime() const {
     449       109914 :     return mySwitchCommand != nullptr ? mySwitchCommand->getNextSwitchTime() : -1;
     450              : }
     451              : 
     452              : 
     453              : SUMOTime
     454         2853 : MSTrafficLightLogic::getSpentDuration(SUMOTime simStep) const {
     455         2853 :     if (simStep == -1) {
     456         2529 :         simStep = SIMSTEP;
     457              :     }
     458         2853 :     return simStep - getCurrentPhaseDef().myLastSwitch;
     459              : }
     460              : 
     461              : 
     462              : // ----------- Changing phases and phase durations
     463              : void
     464            0 : MSTrafficLightLogic::addOverridingDuration(SUMOTime duration) {
     465            0 :     myOverridingTimes.push_back(duration);
     466            0 : }
     467              : 
     468              : 
     469              : void
     470            0 : MSTrafficLightLogic::setCurrentDurationIncrement(SUMOTime delay) {
     471            0 :     myCurrentDurationIncrement = delay;
     472            0 : }
     473              : 
     474              : 
     475        16685 : void MSTrafficLightLogic::initMesoTLSPenalties() {
     476        16685 :     if (myLogicType == TrafficLightType::RAIL_SIGNAL) {
     477            4 :         return;
     478              :     }
     479              :     // set mesoscopic time penalties
     480        16681 :     const Phases& phases = getPhases();
     481        16681 :     const int numLinks = (int)myLinks.size();
     482              :     // warning already given if not all states are used
     483              :     assert(numLinks <= (int)phases.front()->getState().size());
     484              :     SUMOTime duration = 0;
     485        16681 :     std::vector<double> firstRedDuration(numLinks, 0);
     486        16681 :     std::vector<double> redDuration(numLinks, 0);
     487        16681 :     std::vector<double> totalRedDuration(numLinks, 0);
     488        16681 :     std::vector<double> penalty(numLinks, 0);
     489       120599 :     for (int i = 0; i < (int)phases.size(); ++i) {
     490       103918 :         const std::string& state = phases[i]->getState();
     491       103918 :         duration += phases[i]->duration;
     492              :         // warn about transitions from green to red without intermediate yellow
     493      1332440 :         for (int j = 0; j < numLinks; ++j) {
     494      1228522 :             double& red = redDuration[j];
     495      1228522 :             if ((LinkState)state[j] == LINKSTATE_TL_RED
     496      1228522 :                     || (LinkState)state[j] == LINKSTATE_TL_REDYELLOW) {
     497       709245 :                 red += STEPS2TIME(phases[i]->duration);
     498       709245 :                 totalRedDuration[j] += STEPS2TIME(phases[i]->duration);
     499       519277 :             } else if (red > 0) {
     500        81705 :                 if (firstRedDuration[j] == 0) {
     501              :                     // store for handling wrap-around
     502        81639 :                     firstRedDuration[j] = red;
     503              :                 } else {
     504              :                     // vehicle may arive in any second or the red duration
     505              :                     // compute the sum over [0,red]
     506           66 :                     penalty[j] += 0.5 * (red * red + red);
     507              :                 }
     508        81705 :                 red = 0;
     509              :             }
     510              :         }
     511              :     }
     512              :     // final phase and wrap-around to first phase
     513       194444 :     for (int j = 0; j < numLinks; ++j) {
     514       177763 :         double red = redDuration[j] + firstRedDuration[j];
     515       177763 :         if (red) {
     516       169145 :             penalty[j] += 0.5 * (red * red + red);
     517              :         }
     518              :     }
     519        16681 :     double tlsPenalty = MSGlobals::gTLSPenalty;
     520        16681 :     const double durationSeconds = STEPS2TIME(duration);
     521              :     std::set<const MSJunction*> controlledJunctions;
     522              :     std::set<const MSEdge*> shortEdges;;
     523       194444 :     for (int j = 0; j < numLinks; ++j) {
     524       355474 :         for (int k = 0; k < (int)myLinks[j].size(); ++k) {
     525       177711 :             MSLink* link = myLinks[j][k];
     526              :             MSEdge& edge = link->getLaneBefore()->getEdge();
     527       177711 :             if (MSGlobals::gUseMesoSim) {
     528       177551 :                 const MESegment::MesoEdgeType& edgeType = MSNet::getInstance()->getMesoType(edge.getEdgeType());
     529       177551 :                 tlsPenalty = edgeType.tlsPenalty;
     530       177551 :                 double greenFraction = (durationSeconds - totalRedDuration[j]) / durationSeconds;
     531       177551 :                 if (edgeType.tlsFlowPenalty == 0) {
     532              :                     greenFraction = 1;
     533              :                 } else {
     534          648 :                     greenFraction = MAX2(MIN2(greenFraction / edgeType.tlsFlowPenalty, 1.0), 0.01);
     535              :                 }
     536              :                 if (greenFraction == 0.01) {
     537           48 :                     WRITE_WARNINGF(TL("Green fraction is only 1% for link % in tlLogic '%', program '%'."), "%", j, getID(), getProgramID());
     538              :                 }
     539              :                 link->setGreenFraction(greenFraction);
     540       177551 :                 if (tlsPenalty > 0 && edge.getLength() < SHORT_EDGE && shortEdges.count(&edge) == 0) {
     541            4 :                     shortEdges.insert(&edge);
     542           12 :                     WRITE_WARNINGF(TL("Edge '%' is shorter than %m (%m) and will cause incorrect flow reduction with option --meso-tls-penalty"), edge.getID(), SHORT_EDGE, edge.getLength());
     543              :                 }
     544              :             }
     545       177711 :             link->setMesoTLSPenalty(TIME2STEPS(tlsPenalty * penalty[j] / durationSeconds));
     546       177711 :             controlledJunctions.insert(link->getLane()->getEdge().getFromJunction()); // MSLink::myJunction is not yet initialized
     547              :             //std::cout << " tls=" << getID() << " i=" << j << " link=" << link->getDescription() << " p=" << penalty[j] << " fr=" << firstRedDuration[j] << " r=" << redDuration[j] << " tr=" << totalRedDuration[j] << " durSecs=" << durationSeconds << " tlsPen=" << STEPS2TIME(link->getMesoTLSPenalty()) << " gF=" << myLinks[j][k]->getGreenFraction() << "\n";
     548              :         }
     549              :     }
     550              :     // initialize empty-net travel times
     551              :     // XXX refactor after merging sharps (links know their incoming edge)
     552        33394 :     for (std::set<const MSJunction*>::iterator it = controlledJunctions.begin(); it != controlledJunctions.end(); ++it) {
     553        16713 :         const ConstMSEdgeVector incoming = (*it)->getIncoming();
     554       100391 :         for (ConstMSEdgeVector::const_iterator it_e = incoming.begin(); it_e != incoming.end(); ++it_e) {
     555        83678 :             const_cast<MSEdge*>(*it_e)->recalcCache();
     556              :         }
     557        16713 :     }
     558              : 
     559        16681 : }
     560              : 
     561              : 
     562              : void
     563          924 : MSTrafficLightLogic::ignoreLinkIndex(int pos) {
     564              :     myIgnoredIndices.insert(pos);
     565          924 : }
     566              : 
     567              : SUMOTime
     568       145594 : MSTrafficLightLogic::getTimeInCycle() const {
     569       145594 :     return mapTimeInCycle(SIMSTEP);
     570              : }
     571              : 
     572              : 
     573              : SUMOTime
     574            0 : MSTrafficLightLogic::mapTimeInCycle(SUMOTime t) const {
     575            0 :     return (t - myOffset) % myDefaultCycleTime;
     576              : }
     577              : 
     578              : 
     579              : bool
     580            0 : MSTrafficLightLogic::isSelected() const {
     581            0 :     return MSNet::getInstance()->isSelected(this);
     582              : }
     583              : 
     584              : 
     585              : void
     586       113495 : MSTrafficLightLogic::activateProgram() {
     587       113495 :     myAmActive = true;
     588              :     // updated the traffic light logic stored in the link
     589       263742 :     for (const LinkVector& currGroup : myLinks) {
     590       300578 :         for (MSLink* link : currGroup) {
     591       150331 :             link->setTLLogic(this);
     592              :         }
     593              :     }
     594       113495 : }
     595              : 
     596              : 
     597              : void
     598         9624 : MSTrafficLightLogic::deactivateProgram() {
     599         9624 :     myAmActive = false;
     600         9624 : }
     601              : 
     602              : bool
     603        18942 : MSTrafficLightLogic::getsMajorGreen(int linkIndex) const {
     604        18942 :     if (linkIndex >= 0 && linkIndex < getNumLinks()) {
     605        44461 :         for (const MSPhaseDefinition* p : getPhases()) {
     606              :             const std::string& s = p->getState();
     607              :             assert(linkIndex < (int)s.size());
     608        39800 :             if (s[linkIndex] == LINKSTATE_TL_GREEN_MAJOR) {
     609              :                 return true;
     610              :             }
     611              :         }
     612              :     }
     613              :     return false;
     614              : 
     615              : }
     616              : 
     617              : 
     618              : SUMOTime
     619          849 : MSTrafficLightLogic::getMinDur(int step) const {
     620          849 :     const MSPhaseDefinition& p = step < 0 ? getCurrentPhaseDef() : getPhase(step);
     621          849 :     return p.minDuration;
     622              : }
     623              : 
     624              : SUMOTime
     625         1468 : MSTrafficLightLogic::getMaxDur(int step) const {
     626         1468 :     const MSPhaseDefinition& p = step < 0 ? getCurrentPhaseDef() : getPhase(step);
     627         1468 :     return p.maxDuration;
     628              : }
     629              : 
     630              : SUMOTime
     631       211856 : MSTrafficLightLogic::getEarliestEnd(int step) const {
     632       211856 :     const MSPhaseDefinition& p = step < 0 ? getCurrentPhaseDef() : getPhase(step);
     633       211856 :     return p.earliestEnd;
     634              : }
     635              : 
     636              : SUMOTime
     637       623842 : MSTrafficLightLogic::getLatestEnd(int step) const {
     638       623842 :     const MSPhaseDefinition& p = step < 0 ? getCurrentPhaseDef() : getPhase(step);
     639       623842 :     return p.latestEnd;
     640              : }
     641              : 
     642              : 
     643              : void
     644         1687 : MSTrafficLightLogic::loadState(MSTLLogicControl& tlcontrol, SUMOTime t, int step, SUMOTime spentDuration) {
     645         1687 :     const SUMOTime remaining = getPhase(step).duration - spentDuration;
     646         1687 :     changeStepAndDuration(tlcontrol, t, step, remaining);
     647         1687 :     setTrafficLightSignals(t - spentDuration);
     648         1687 : }
     649              : 
     650              : 
     651              : SUMOTime
     652       108528 : MSTrafficLightLogic::computeCycleTime(const Phases& phases) {
     653              :     SUMOTime result = 0;
     654       677130 :     for (const MSPhaseDefinition* p : phases) {
     655       568602 :         result += p->duration;
     656              :     }
     657       108528 :     return result;
     658              : }
     659              : 
     660              : 
     661              : 
     662              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1