LCOV - code coverage report
Current view: top level - src/microsim/traffic_lights - MSTLLogicControl.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 65.4 % 402 263
Test Date: 2024-11-22 15:46:21 Functions: 81.7 % 60 49

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-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    MSTLLogicControl.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Friedemann Wesner
      18              : /// @author  Laura Bieker
      19              : /// @author  Julia Ringel
      20              : /// @author  Michael Behrisch
      21              : /// @author  Sascha Krieg
      22              : /// @date    Sept 2002
      23              : ///
      24              : // A class that stores and controls tls and switching of their programs
      25              : /****************************************************************************/
      26              : #include <config.h>
      27              : 
      28              : #include <vector>
      29              : #include <algorithm>
      30              : #include <cassert>
      31              : #include <iterator>
      32              : #include "MSTrafficLightLogic.h"
      33              : #include "MSSimpleTrafficLightLogic.h"
      34              : #include "MSTLLogicControl.h"
      35              : #include "MSOffTrafficLightLogic.h"
      36              : #include "MSRailSignalConstraint.h"
      37              : #include "MSDriveWay.h"
      38              : #include <microsim/MSEventControl.h>
      39              : #include <microsim/MSNet.h>
      40              : #include <utils/common/StringUtils.h>
      41              : #include <utils/common/ToString.h>
      42              : #include <utils/common/MsgHandler.h>
      43              : 
      44              : #define TRACI_PROGRAM "online"
      45              : 
      46              : // ===========================================================================
      47              : // method definitions
      48              : // ===========================================================================
      49              : /* -------------------------------------------------------------------------
      50              :  * MSTLLogicControl::TLSLogicVariants - methods
      51              :  * ----------------------------------------------------------------------- */
      52        99298 : MSTLLogicControl::TLSLogicVariants::TLSLogicVariants() :
      53        99298 :     myCurrentProgram(nullptr),
      54        99298 :     myDefaultProgram(nullptr) {
      55        99298 : }
      56              : 
      57              : 
      58        99030 : MSTLLogicControl::TLSLogicVariants::~TLSLogicVariants() {
      59              :     std::map<std::string, MSTrafficLightLogic*>::const_iterator j;
      60       212457 :     for (const auto& var : myVariants) {
      61       113427 :         delete var.second;
      62              :     }
      63       102739 :     for (OnSwitchAction* osa : mySwitchActions) {
      64         3709 :         delete osa;
      65              :     }
      66        99030 : }
      67              : 
      68              : 
      69              : bool
      70        98660 : MSTLLogicControl::TLSLogicVariants::checkOriginalTLS() const {
      71              :     bool hadErrors = false;
      72       197408 :     for (std::map<std::string, MSTrafficLightLogic*>::const_iterator j = myVariants.begin(); j != myVariants.end(); ++j) {
      73        98748 :         const MSTrafficLightLogic::Phases& phases = (*j).second->getPhases();
      74        98748 :         int linkNo = (int)(*j).second->getLinks().size();
      75              :         bool hadProgramErrors = false;
      76       578384 :         for (MSTrafficLightLogic::Phases::const_iterator i = phases.begin(); i != phases.end(); ++i) {
      77       479636 :             if ((int)(*i)->getState().length() < linkNo) {
      78              :                 hadProgramErrors = true;
      79              :             }
      80              :         }
      81        98748 :         if (hadProgramErrors) {
      82            0 :             WRITE_ERRORF(TL("Mismatching phase size in tls '%', program '%'."), (*j).second->getID(), (*j).first);
      83              :             hadErrors = true;
      84              :         }
      85              :     }
      86        98660 :     return !hadErrors;
      87              : }
      88              : 
      89              : 
      90              : void
      91        98660 : MSTLLogicControl::TLSLogicVariants::saveInitialStates() {
      92        98660 :     myOriginalLinkStates = myCurrentProgram->collectLinkStates();
      93        98660 : }
      94              : 
      95              : 
      96              : void
      97         1363 : MSTLLogicControl::TLSLogicVariants::saveState(OutputDevice& out) {
      98         2738 :     for (const auto& item : myVariants) {
      99         1375 :         item.second->saveState(out);
     100              :     }
     101         1363 : }
     102              : 
     103              : 
     104              : bool
     105       113709 : MSTLLogicControl::TLSLogicVariants::addLogic(const std::string& programID,
     106              :         MSTrafficLightLogic* logic, bool netWasLoaded, bool isNewDefault) {
     107       113709 :     if (myVariants.find(programID) != myVariants.end()) {
     108            0 :         delete logic;
     109            0 :         return false;
     110              :     }
     111              :     // assert the links are set
     112       113709 :     if (netWasLoaded) {
     113              :         // this one has not yet its links set
     114        14323 :         if (myCurrentProgram == nullptr) {
     115              :             const std::string id = logic->getID();
     116            0 :             delete logic;
     117            0 :             throw ProcessError(TLF("No initial signal plan loaded for tls '%'.", id));
     118              :         }
     119        14323 :         logic->adaptLinkInformationFrom(*myCurrentProgram);
     120        14323 :         if (logic->getLinks().size() > logic->getPhase(0).getState().size()) {
     121              :             const std::string id = logic->getID();
     122            6 :             delete logic;
     123           12 :             throw ProcessError("Mismatching phase size in tls '" + id + "', program '" + programID + "'.");
     124              :         }
     125              :     }
     126              :     // add to the list of active
     127       113703 :     if (myVariants.size() == 0 || isNewDefault) {
     128       113703 :         if (myCurrentProgram != nullptr) {
     129        14405 :             myCurrentProgram->deactivateProgram();
     130              :         }
     131       113703 :         myCurrentProgram = logic;
     132       113703 :         myCurrentProgram->activateProgram();
     133       113703 :         if (myVariants.size() == 0) {
     134        99298 :             myDefaultProgram = logic;
     135              :         }
     136              :     }
     137              :     // add to the list of logic
     138       113703 :     myVariants[programID] = logic;
     139       113703 :     if (myVariants.size() == 1 || isNewDefault) {
     140       113703 :         logic->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
     141       113703 :         executeOnSwitchActions();
     142              :     }
     143              :     return true;
     144              : }
     145              : 
     146              : 
     147              : MSTrafficLightLogic*
     148        30592 : MSTLLogicControl::TLSLogicVariants::getLogic(const std::string& programID) const {
     149        30592 :     if (myVariants.find(programID) == myVariants.end()) {
     150              :         return nullptr;
     151              :     }
     152         2093 :     return myVariants.find(programID)->second;
     153              : }
     154              : 
     155              : 
     156              : MSTrafficLightLogic*
     157          352 : MSTLLogicControl::TLSLogicVariants::getLogicInstantiatingOff(MSTLLogicControl& tlc, const std::string& programID) {
     158          352 :     if (myVariants.find(programID) == myVariants.end()) {
     159           35 :         if (programID == "off") {
     160              :             // build an off-tll if this switch indicates it
     161           33 :             MSTrafficLightLogic* tlLogic = new MSOffTrafficLightLogic(tlc, myCurrentProgram->getID());
     162           66 :             if (!addLogic("off", tlLogic, true, true)) {
     163              :                 // inform the user if this fails
     164            0 :                 throw ProcessError(TLF("Could not build an off-state for tls '%'.", myCurrentProgram->getID()));
     165              :             }
     166              :         } else {
     167              :             // inform the user about a missing logic
     168            4 :             throw ProcessError("Can not switch tls '" + myCurrentProgram->getID() + "' to program '" + programID + "';\n The program is not known.");
     169              :         }
     170              :     }
     171          350 :     return getLogic(programID);
     172              : }
     173              : 
     174              : 
     175              : void
     176           38 : MSTLLogicControl::TLSLogicVariants::setStateInstantiatingOnline(MSTLLogicControl& tlc,
     177              :         const std::string& state) {
     178              :     // build only once...
     179           38 :     MSTrafficLightLogic* logic = getLogic(TRACI_PROGRAM);
     180           38 :     if (logic == nullptr) {
     181           28 :         MSPhaseDefinition* phase = new MSPhaseDefinition(DELTA_T, state);
     182              :         std::vector<MSPhaseDefinition*> phases;
     183           28 :         phases.push_back(phase);
     184           28 :         logic = new MSSimpleTrafficLightLogic(tlc, myCurrentProgram->getID(), TRACI_PROGRAM, 0, TrafficLightType::STATIC, phases, 0,
     185           28 :                                               MSNet::getInstance()->getCurrentTimeStep() + DELTA_T,
     186           84 :                                               Parameterised::Map());
     187           56 :         if (addLogic(TRACI_PROGRAM, logic, true, true)) {
     188           28 :             MSNet::getInstance()->createTLWrapper(logic);
     189              :         }
     190           28 :     } else {
     191           10 :         MSPhaseDefinition nphase(DELTA_T, state);
     192           10 :         *(dynamic_cast<MSSimpleTrafficLightLogic*>(logic)->getPhases()[0]) = nphase;
     193           10 :         switchTo(tlc, TRACI_PROGRAM);
     194           10 :     }
     195           38 : }
     196              : 
     197              : 
     198              : void
     199         3709 : MSTLLogicControl::TLSLogicVariants::addSwitchCommand(OnSwitchAction* c) {
     200         3709 :     mySwitchActions.push_back(c);
     201         3709 : }
     202              : 
     203              : 
     204              : std::vector<MSTrafficLightLogic*>
     205        35709 : MSTLLogicControl::TLSLogicVariants::getAllLogics() const {
     206              :     std::vector<MSTrafficLightLogic*> ret;
     207              :     std::map<std::string, MSTrafficLightLogic*>::const_iterator i;
     208        79205 :     for (i = myVariants.begin(); i != myVariants.end(); ++i) {
     209        43496 :         ret.push_back((*i).second);
     210              :     }
     211        35709 :     return ret;
     212            0 : }
     213              : 
     214              : 
     215              : bool
     216            0 : MSTLLogicControl::TLSLogicVariants::isActive(const MSTrafficLightLogic* tl) const {
     217            0 :     return tl == myCurrentProgram;
     218              : }
     219              : 
     220              : 
     221              : MSTrafficLightLogic*
     222      8882705 : MSTLLogicControl::TLSLogicVariants::getActive() const {
     223      8882705 :     return myCurrentProgram;
     224              : }
     225              : 
     226              : MSTrafficLightLogic*
     227        21266 : MSTLLogicControl::TLSLogicVariants::getDefault() const {
     228        21266 :     return myDefaultProgram;
     229              : }
     230              : 
     231              : 
     232              : void
     233          238 : MSTLLogicControl::TLSLogicVariants::switchTo(MSTLLogicControl& tlc, const std::string& programID) {
     234              :     // set the found wished sub-program as this tls' current one
     235          238 :     myCurrentProgram->deactivateProgram();
     236          238 :     myCurrentProgram = getLogicInstantiatingOff(tlc, programID);
     237          237 :     myCurrentProgram->activateProgram();
     238          237 :     myCurrentProgram->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
     239          237 :     executeOnSwitchActions();
     240          237 : }
     241              : 
     242              : 
     243              : void
     244      7320949 : MSTLLogicControl::TLSLogicVariants::executeOnSwitchActions() const {
     245      7838421 :     for (std::vector<OnSwitchAction*>::const_iterator i = mySwitchActions.begin(); i != mySwitchActions.end(); ++i) {
     246       517472 :         (*i)->execute();
     247              :     }
     248      7320949 : }
     249              : 
     250              : 
     251              : void
     252       797142 : MSTLLogicControl::TLSLogicVariants::addLink(MSLink* link, MSLane* lane, int pos) {
     253      1596148 :     for (std::map<std::string, MSTrafficLightLogic*>::iterator i = myVariants.begin(); i != myVariants.end(); ++i) {
     254       799006 :         (*i).second->addLink(link, lane, pos);
     255              :     }
     256       797142 : }
     257              : 
     258              : void
     259          810 : MSTLLogicControl::TLSLogicVariants::ignoreLinkIndex(int pos) {
     260         1620 :     for (std::map<std::string, MSTrafficLightLogic*>::iterator i = myVariants.begin(); i != myVariants.end(); ++i) {
     261          810 :         (*i).second->ignoreLinkIndex(pos);
     262              :     }
     263          810 : }
     264              : 
     265              : 
     266              : /* -------------------------------------------------------------------------
     267              :  * method definitions for the Switching Procedures
     268              :  * ----------------------------------------------------------------------- */
     269              : /* -------------------------------------------------------------------------
     270              :  * method definitions for WAUTSwitchProcedure
     271              :  * ----------------------------------------------------------------------- */
     272              : bool
     273          324 : MSTLLogicControl::WAUTSwitchProcedure::trySwitch(SUMOTime step) {
     274              :     // switch to the next programm if the GSP is reached
     275          324 :     if (isPosAtGSP(step, *myFrom)) {
     276              :         // adapt program's state
     277            4 :         if (mySwitchSynchron) {
     278            0 :             adaptLogic(step);
     279              :         } else {
     280            4 :             switchToPos(step, *myTo, getGSPTime(*myTo));
     281              :         }
     282              :         // switch to destination program
     283            4 :         return true;
     284              :     }
     285              :     // do not switch, yet
     286              :     return false;
     287              : }
     288              : 
     289              : 
     290              : SUMOTime
     291          328 : MSTLLogicControl::WAUTSwitchProcedure::getGSPTime(const MSTrafficLightLogic& logic) const {
     292          656 :     return string2time(logic.getParameter("GSP", "0"));
     293              : }
     294              : 
     295              : 
     296              : bool
     297          324 : MSTLLogicControl::WAUTSwitchProcedure::isPosAtGSP(SUMOTime currentTime, const MSTrafficLightLogic& logic) {
     298          324 :     const SUMOTime gspTime = getGSPTime(logic) % logic.getDefaultCycleTime();
     299          324 :     const SUMOTime programTime = logic.getOffsetFromIndex(logic.getCurrentPhaseIndex()) + logic.getSpentDuration(currentTime);
     300          324 :     return gspTime == programTime;
     301              : }
     302              : 
     303              : 
     304              : SUMOTime
     305            4 : MSTLLogicControl::WAUTSwitchProcedure::getDiffToStartOfPhase(MSTrafficLightLogic& logic, SUMOTime toTime) {
     306            4 :     int stepOfMyPos = logic.getIndexFromOffset(toTime);
     307            4 :     SUMOTime startOfPhase = logic.getOffsetFromIndex(stepOfMyPos);
     308              :     assert(toTime >= startOfPhase);
     309            4 :     return toTime - startOfPhase;
     310              : }
     311              : 
     312              : 
     313              : void
     314            4 : MSTLLogicControl::WAUTSwitchProcedure::switchToPos(SUMOTime simStep, MSTrafficLightLogic& logic, SUMOTime toTime) {
     315            4 :     int stepTo = logic.getIndexFromOffset(toTime);
     316            4 :     SUMOTime diff = getDiffToStartOfPhase(logic, toTime);
     317            4 :     const MSPhaseDefinition& phase = logic.getPhase(stepTo);
     318            4 :     SUMOTime leftDuration = phase.duration - diff;
     319            4 :     logic.changeStepAndDuration(myControl, simStep, stepTo, leftDuration);
     320            4 : }
     321              : 
     322              : 
     323              : 
     324              : /* -------------------------------------------------------------------------
     325              :  * method definitions for WAUTSwitchProcedure_JustSwitch
     326              :  * ----------------------------------------------------------------------- */
     327          109 : MSTLLogicControl::WAUTSwitchProcedure_JustSwitch::WAUTSwitchProcedure_JustSwitch(
     328              :     MSTLLogicControl& control, WAUT& waut,
     329              :     MSTrafficLightLogic* from, MSTrafficLightLogic* to, bool synchron)
     330          109 :     : MSTLLogicControl::WAUTSwitchProcedure(control, waut, from, to, synchron) {}
     331              : 
     332              : 
     333          218 : MSTLLogicControl::WAUTSwitchProcedure_JustSwitch::~WAUTSwitchProcedure_JustSwitch() {}
     334              : 
     335              : 
     336              : bool
     337          109 : MSTLLogicControl::WAUTSwitchProcedure_JustSwitch::trySwitch(SUMOTime) {
     338          109 :     return true;
     339              : }
     340              : 
     341              : 
     342              : 
     343              : /* -------------------------------------------------------------------------
     344              :  * method definitions for WAUTSwitchProcedure_GSP
     345              :  * ----------------------------------------------------------------------- */
     346            4 : MSTLLogicControl::WAUTSwitchProcedure_GSP::WAUTSwitchProcedure_GSP(
     347              :     MSTLLogicControl& control, WAUT& waut,
     348              :     MSTrafficLightLogic* from, MSTrafficLightLogic* to, bool synchron)
     349            4 :     : MSTLLogicControl::WAUTSwitchProcedure(control, waut, from, to, synchron) {}
     350              : 
     351              : 
     352            8 : MSTLLogicControl::WAUTSwitchProcedure_GSP::~WAUTSwitchProcedure_GSP() {}
     353              : 
     354              : 
     355              : void
     356            0 : MSTLLogicControl::WAUTSwitchProcedure_GSP::adaptLogic(SUMOTime step) {
     357            0 :     const SUMOTime gspTo = getGSPTime(*myTo) % myTo->getDefaultCycleTime();
     358            0 :     const SUMOTime currentPosTo = myTo->getOffsetFromIndex(myTo->getCurrentPhaseIndex()) + myTo->getSpentDuration(step);
     359            0 :     SUMOTime deltaToStretch = gspTo - currentPosTo;
     360            0 :     if (deltaToStretch < 0) {
     361            0 :         deltaToStretch += myTo->getDefaultCycleTime();
     362              :     }
     363            0 :     const int stepTo = myTo->getIndexFromOffset(gspTo);
     364            0 :     const SUMOTime newdur = myTo->getPhase(stepTo).duration - getDiffToStartOfPhase(*myTo, gspTo) + deltaToStretch;
     365            0 :     myTo->changeStepAndDuration(myControl, step, stepTo, newdur);
     366            0 : }
     367              : 
     368              : 
     369              : 
     370              : /* -------------------------------------------------------------------------
     371              :  * method definitions for WAUTSwitchProcedure_Stretch
     372              :  * ----------------------------------------------------------------------- */
     373            0 : MSTLLogicControl::WAUTSwitchProcedure_Stretch::WAUTSwitchProcedure_Stretch(
     374              :     MSTLLogicControl& control, WAUT& waut,
     375            0 :     MSTrafficLightLogic* from, MSTrafficLightLogic* to, bool synchron)
     376            0 :     : MSTLLogicControl::WAUTSwitchProcedure(control, waut, from, to, synchron) {
     377            0 :     int idx = 1;
     378            0 :     while (myTo->hasParameter("B" + toString(idx) + ".begin")) {
     379              :         StretchRange def;
     380            0 :         def.begin = string2time(myTo->getParameter("B" + toString(idx) + ".begin"));
     381            0 :         def.end = string2time(myTo->getParameter("B" + toString(idx) + ".end"));
     382            0 :         def.fac = StringUtils::toDouble(myTo->getParameter("B" + toString(idx) + ".factor"));
     383            0 :         myStretchRanges.emplace_back(def);
     384              :     }
     385              : 
     386            0 : }
     387              : 
     388              : 
     389            0 : MSTLLogicControl::WAUTSwitchProcedure_Stretch::~WAUTSwitchProcedure_Stretch() {}
     390              : 
     391              : 
     392              : void
     393            0 : MSTLLogicControl::WAUTSwitchProcedure_Stretch::adaptLogic(SUMOTime step) {
     394            0 :     SUMOTime gspTo = getGSPTime(*myTo);
     395            0 :     SUMOTime cycleTime = myTo->getDefaultCycleTime();
     396              :     // the position, where the logic has to be after synchronisation
     397            0 :     SUMOTime posAfterSyn = myTo->getPhaseIndexAtTime(step);
     398              :     // calculate the difference, that has to be equalized
     399              :     SUMOTime deltaToCut = 0;
     400            0 :     if (posAfterSyn < gspTo) {
     401            0 :         deltaToCut = posAfterSyn + cycleTime - gspTo;
     402              :     } else {
     403            0 :         deltaToCut =  posAfterSyn - gspTo;
     404              :     }
     405              :     // test, wheter cutting of the Signalplan is possible
     406              :     SUMOTime deltaPossible = 0;
     407            0 :     for (const StretchRange& def : myStretchRanges) {
     408              :         assert(def.end >= def.begin);
     409            0 :         deltaPossible += def.end - def.begin;
     410              :     }
     411            0 :     int stretchUmlaufAnz = (int) StringUtils::toDouble(myTo->getParameter("StretchUmlaufAnz", ""));
     412            0 :     deltaPossible = stretchUmlaufAnz * deltaPossible;
     413            0 :     if ((deltaPossible > deltaToCut) && (deltaToCut < (cycleTime / 2))) {
     414            0 :         cutLogic(step, gspTo, deltaToCut);
     415              :     } else {
     416            0 :         SUMOTime deltaToStretch = (cycleTime - deltaToCut) % cycleTime;
     417            0 :         stretchLogic(step, gspTo, deltaToStretch);
     418              :     }
     419            0 : }
     420              : 
     421              : 
     422              : void
     423            0 : MSTLLogicControl::WAUTSwitchProcedure_Stretch::cutLogic(SUMOTime step, SUMOTime startPos, SUMOTime allCutTime) {
     424            0 :     int actStep = myTo->getIndexFromOffset(startPos);
     425              :     // switches to startPos and cuts this phase, if there is a "Bereich"
     426              :     SUMOTime toCut = 0;
     427            0 :     for (const StretchRange& def : myStretchRanges) {
     428            0 :         int stepOfBegin = myTo->getIndexFromOffset(def.begin);
     429            0 :         if (stepOfBegin == actStep) {
     430            0 :             if (def.begin < startPos) {
     431            0 :                 toCut = def.end - startPos;
     432              :             } else {
     433            0 :                 toCut = def.end - def.begin;
     434              :             }
     435              :             toCut = MIN2(allCutTime, toCut);
     436            0 :             allCutTime = allCutTime - toCut;
     437              :         }
     438              :     }
     439            0 :     SUMOTime remainingDur = myTo->getPhase(actStep).duration - getDiffToStartOfPhase(*myTo, startPos);
     440            0 :     SUMOTime newDur = remainingDur - toCut;
     441            0 :     myTo->changeStepAndDuration(myControl, step, actStep, newDur);
     442              : 
     443              :     // changes the duration of all other phases
     444            0 :     int currStep = (actStep + 1) % (int)myTo->getPhases().size();
     445            0 :     while (allCutTime > 0) {
     446            0 :         for (int i = currStep; i < (int) myTo->getPhases().size(); i++) {
     447            0 :             SUMOTime beginOfPhase = myTo->getOffsetFromIndex(i);
     448            0 :             SUMOTime durOfPhase = myTo->getPhase(i).duration;
     449            0 :             SUMOTime endOfPhase = beginOfPhase + durOfPhase;
     450            0 :             for (const StretchRange& def : myStretchRanges) {
     451            0 :                 if ((beginOfPhase <= def.begin) && (endOfPhase >= def.end)) {
     452            0 :                     SUMOTime maxCutOfPhase = MIN2(def.end - def.begin, allCutTime);
     453            0 :                     allCutTime = allCutTime - maxCutOfPhase;
     454            0 :                     durOfPhase = durOfPhase - maxCutOfPhase;
     455              :                 }
     456              :             }
     457            0 :             myTo->addOverridingDuration(durOfPhase);
     458              :         }
     459              :         currStep = 0;
     460              :     }
     461            0 : }
     462              : 
     463              : void
     464            0 : MSTLLogicControl::WAUTSwitchProcedure_Stretch::stretchLogic(SUMOTime step, SUMOTime startPos, SUMOTime allStretchTime) {
     465            0 :     int currStep = myTo->getIndexFromOffset(startPos);
     466            0 :     SUMOTime durOfPhase = myTo->getPhase(currStep).duration;
     467              :     SUMOTime remainingStretchTime = allStretchTime;
     468              :     SUMOTime StretchTimeOfPhase = 0;
     469            0 :     int stretchUmlaufAnz = (int) StringUtils::toDouble(myTo->getParameter("StretchUmlaufAnz", ""));
     470              :     double facSum = 0;
     471            0 :     for (const StretchRange& def : myStretchRanges) {
     472            0 :         facSum += def.fac;
     473              :     }
     474            0 :     facSum *= stretchUmlaufAnz;
     475              : 
     476              :     //switch to startPos and stretch this phase, if there is a end of "bereich" between startpos and end of phase
     477            0 :     SUMOTime diffToStart = getDiffToStartOfPhase(*myTo, startPos);
     478            0 :     for (const StretchRange& def : myStretchRanges) {
     479            0 :         SUMOTime endOfPhase = (startPos + durOfPhase - diffToStart);
     480            0 :         if (def.end <= endOfPhase && def.end >= startPos) {
     481            0 :             double actualfac = def.fac / facSum;
     482            0 :             facSum = facSum - def.fac;
     483            0 :             StretchTimeOfPhase = TIME2STEPS(int(STEPS2TIME(remainingStretchTime) * actualfac + 0.5));
     484            0 :             remainingStretchTime = allStretchTime - StretchTimeOfPhase;
     485              :         }
     486              :     }
     487            0 :     if (facSum == 0) {
     488            0 :         WRITE_WARNINGF(TL("The computed factor sum in WAUT '%' at time '%' equals zero;\n assuming an error in WAUT definition."), myWAUT.id, toString(STEPS2TIME(step)));
     489            0 :         return;
     490              :     }
     491            0 :     durOfPhase = durOfPhase - diffToStart + StretchTimeOfPhase;
     492            0 :     myTo->changeStepAndDuration(myControl, step, currStep, durOfPhase);
     493              : 
     494            0 :     currStep = (currStep + 1) % (int)myTo->getPhases().size();
     495              :     // stretch all other phases, if there is a "bereich"
     496            0 :     while (remainingStretchTime > 0) {
     497            0 :         for (int i = currStep; i < (int)myTo->getPhases().size() && remainingStretchTime > 0; i++) {
     498            0 :             durOfPhase = myTo->getPhase(i).duration;
     499            0 :             SUMOTime beginOfPhase = myTo->getOffsetFromIndex(i);
     500            0 :             SUMOTime endOfPhase = beginOfPhase + durOfPhase;
     501            0 :             for (const StretchRange& def : myStretchRanges) {
     502            0 :                 if ((beginOfPhase <= def.end) && (endOfPhase >= def.end)) {
     503            0 :                     double actualfac = def.fac / facSum;
     504            0 :                     StretchTimeOfPhase = TIME2STEPS(int(STEPS2TIME(remainingStretchTime) * actualfac + 0.5));
     505            0 :                     facSum -= def.fac;
     506            0 :                     durOfPhase += StretchTimeOfPhase;
     507            0 :                     remainingStretchTime -= StretchTimeOfPhase;
     508              :                 }
     509              :             }
     510            0 :             myTo->addOverridingDuration(durOfPhase);
     511              :         }
     512              :         currStep = 0;
     513              :     }
     514              : }
     515              : 
     516              : 
     517              : /* -------------------------------------------------------------------------
     518              :  * method definitions for MSTLLogicControl
     519              :  * ----------------------------------------------------------------------- */
     520        42987 : MSTLLogicControl::MSTLLogicControl()
     521        42987 :     : myNetWasLoaded(false) {}
     522              : 
     523              : 
     524        40060 : MSTLLogicControl::~MSTLLogicControl() {
     525              :     // delete tls
     526       139090 :     for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
     527        99030 :         delete (*i).second;
     528              :     }
     529              :     // delete WAUTs
     530        40150 :     for (std::map<std::string, WAUT*>::const_iterator i = myWAUTs.begin(); i != myWAUTs.end(); ++i) {
     531           90 :         delete (*i).second;
     532              :     }
     533        40060 : }
     534              : 
     535              : 
     536              : void
     537            0 : MSTLLogicControl::setTrafficLightSignals(SUMOTime t) const {
     538            0 :     for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
     539            0 :         (*i).second->getActive()->setTrafficLightSignals(t);
     540              :     }
     541            0 : }
     542              : 
     543              : 
     544              : std::vector<MSTrafficLightLogic*>
     545        15631 : MSTLLogicControl::getAllLogics() const {
     546              :     std::vector<MSTrafficLightLogic*> ret;
     547              :     std::map<std::string, TLSLogicVariants*>::const_iterator i;
     548        51249 :     for (i = myLogics.begin(); i != myLogics.end(); ++i) {
     549        35618 :         std::vector<MSTrafficLightLogic*> s = (*i).second->getAllLogics();
     550              :         copy(s.begin(), s.end(), back_inserter(ret));
     551        35618 :     }
     552        15631 :     return ret;
     553            0 : }
     554              : 
     555              : MSTLLogicControl::TLSLogicVariants&
     556      8931448 : MSTLLogicControl::get(const std::string& id) const {
     557              :     std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
     558      8931448 :     if (i == myLogics.end()) {
     559           24 :         throw InvalidArgument("The tls '" + id + "' is not known.");
     560              :     }
     561      8931436 :     return *(*i).second;
     562              : }
     563              : 
     564              : 
     565              : MSTrafficLightLogic*
     566       225097 : MSTLLogicControl::get(const std::string& id, const std::string& programID) const {
     567              :     std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
     568       225097 :     if (i == myLogics.end()) {
     569              :         return nullptr;
     570              :     }
     571        30118 :     return (*i).second->getLogic(programID);
     572              : }
     573              : 
     574              : 
     575              : std::vector<std::string>
     576         2294 : MSTLLogicControl::getAllTLIds() const {
     577              :     std::vector<std::string> ret;
     578         8653 :     for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
     579         6359 :         ret.push_back((*i).first);
     580              :     }
     581         2294 :     return ret;
     582            0 : }
     583              : 
     584              : 
     585              : bool
     586       113527 : MSTLLogicControl::add(const std::string& id, const std::string& programID,
     587              :                       MSTrafficLightLogic* logic, bool newDefault) {
     588              :     std::map<std::string, TLSLogicVariants*>::iterator it = myLogics.find(id);
     589              :     TLSLogicVariants* tlmap;
     590       113527 :     if (it == myLogics.end()) {
     591        99298 :         tlmap = myLogics[id] = new TLSLogicVariants();
     592              :     } else {
     593        14229 :         tlmap = it->second;
     594              :     }
     595       113527 :     return tlmap->addLogic(programID, logic, myNetWasLoaded, newDefault);
     596              : }
     597              : 
     598              : 
     599              : bool
     600       124342 : MSTLLogicControl::knows(const std::string& id) const {
     601       124342 :     return myLogics.count(id) != 0;
     602              : }
     603              : 
     604              : 
     605              : bool
     606        42556 : MSTLLogicControl::closeNetworkReading() {
     607              :     bool hadErrors = false;
     608       141216 :     for (const auto& it : myLogics) {
     609        98660 :         hadErrors |= !it.second->checkOriginalTLS();
     610        98660 :         it.second->saveInitialStates();
     611              :     }
     612        42556 :     myNetWasLoaded = true;
     613        42556 :     return !hadErrors;
     614              : }
     615              : 
     616              : 
     617              : bool
     618            0 : MSTLLogicControl::isActive(const MSTrafficLightLogic* tl) const {
     619              :     std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(tl->getID());
     620            0 :     if (i == myLogics.end()) {
     621              :         return false;
     622              :     }
     623            0 :     return (*i).second->isActive(tl);
     624              : }
     625              : 
     626              : 
     627              : MSTrafficLightLogic*
     628        49335 : MSTLLogicControl::getActive(const std::string& id) const {
     629              :     std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
     630        49335 :     if (i == myLogics.end()) {
     631              :         return nullptr;
     632              :     }
     633        49335 :     return (*i).second->getActive();
     634              : }
     635              : 
     636              : 
     637              : void
     638          199 : MSTLLogicControl::switchTo(const std::string& id, const std::string& programID) {
     639              :     // try to get the tls program definitions
     640              :     std::map<std::string, TLSLogicVariants*>::iterator i = myLogics.find(id);
     641              :     // handle problems
     642          199 :     if (i == myLogics.end()) {
     643            0 :         throw ProcessError("Could not switch tls '" + id + "' to program '" + programID + "': No such tls exists.");
     644              :     }
     645          199 :     (*i).second->switchTo(*this, programID);
     646          199 : }
     647              : 
     648              : 
     649              : void
     650           90 : MSTLLogicControl::addWAUT(SUMOTime refTime, const std::string& id,
     651              :                           const std::string& startProg, SUMOTime period) {
     652              :     // check whether the waut was already defined
     653           90 :     if (myWAUTs.find(id) != myWAUTs.end()) {
     654              :         // report an error if so
     655            0 :         throw InvalidArgument("Waut '" + id + "' was already defined.");
     656              :     }
     657           90 :     WAUT* w = new WAUT;
     658           90 :     w->id = id;
     659           90 :     w->refTime = refTime;
     660           90 :     w->startProg = startProg;
     661           90 :     w->period = period;
     662           90 :     myWAUTs[id] = w;
     663           90 : }
     664              : 
     665              : 
     666              : void
     667          171 : MSTLLogicControl::addWAUTSwitch(const std::string& wautid,
     668              :                                 SUMOTime when, const std::string& to) {
     669              :     // try to get the waut
     670          171 :     if (myWAUTs.find(wautid) == myWAUTs.end()) {
     671              :         // report an error if the waut is not known
     672            0 :         throw InvalidArgument("Waut '" + wautid + "' was not yet defined.");
     673              :     }
     674              :     // build and save the waut switch definition
     675          171 :     WAUT* waut = myWAUTs[wautid];
     676              :     WAUTSwitch s;
     677              :     s.to = to;
     678          171 :     s.when = (waut->refTime + when);
     679          171 :     if (waut->period > 0) {
     680           41 :         s.when = s.when % waut->period;
     681              :     }
     682          171 :     myWAUTs[wautid]->switches.push_back(s);
     683          171 : }
     684              : 
     685              : 
     686              : void
     687           89 : MSTLLogicControl::addWAUTJunction(const std::string& wautid,
     688              :                                   const std::string& tls,
     689              :                                   const std::string& proc,
     690              :                                   bool synchron) {
     691              :     // try to get the waut
     692           89 :     if (myWAUTs.find(wautid) == myWAUTs.end()) {
     693              :         // report an error if the waut is not known
     694            4 :         throw InvalidArgument("Waut '" + wautid + "' was not yet defined.");
     695              :     }
     696              :     // try to get the tls to switch
     697           87 :     if (myLogics.find(tls) == myLogics.end()) {
     698              :         // report an error if the tls is not known
     699            2 :         throw InvalidArgument("TLS '" + tls + "' to switch in WAUT '" + wautid + "' was not yet defined.");
     700              :     }
     701              :     WAUTJunction j;
     702              :     j.junction = tls;
     703              :     j.procedure = proc;
     704           86 :     j.synchron = synchron;
     705           86 :     myWAUTs[wautid]->junctions.push_back(j);
     706              : 
     707           86 :     std::string initProg = myWAUTs[wautid]->startProg;
     708           86 :     std::vector<WAUTSwitch>::const_iterator first = myWAUTs[wautid]->switches.end();
     709              :     SUMOTime minExecTime = -1;
     710          255 :     for (std::vector<WAUTSwitch>::const_iterator i = myWAUTs[wautid]->switches.begin(); i != myWAUTs[wautid]->switches.end(); ++i) {
     711          169 :         if ((*i).when > MSNet::getInstance()->getCurrentTimeStep() && (minExecTime == -1 || (*i).when < minExecTime)) {
     712           62 :             minExecTime = (*i).when;
     713              :             first = i;
     714              :         }
     715          169 :         if (first != myWAUTs[wautid]->switches.begin()) {
     716          108 :             initProg = (*(first - 1)).to;
     717              :         }
     718              :     }
     719              :     // activate the first one
     720           86 :     switchTo(tls, initProg);
     721           86 : }
     722              : 
     723              : 
     724              : void
     725           88 : MSTLLogicControl::closeWAUT(const std::string& wautid) {
     726              :     // try to get the waut
     727           88 :     if (myWAUTs.find(wautid) == myWAUTs.end()) {
     728              :         // report an error if the waut is not known
     729            0 :         throw InvalidArgument("Waut '" + wautid + "' was not yet defined.");
     730              :     }
     731           88 :     WAUT* w = myWAUTs.find(wautid)->second;
     732           88 :     std::string initProg = myWAUTs[wautid]->startProg;
     733              :     // get the switch to be performed as first
     734              :     std::vector<WAUTSwitch>::const_iterator first = w->switches.end();
     735              :     SUMOTime minExecTime = -1;
     736          259 :     for (std::vector<WAUTSwitch>::const_iterator i = w->switches.begin(); i != w->switches.end(); ++i) {
     737          171 :         if ((*i).when > MSNet::getInstance()->getCurrentTimeStep() && (minExecTime == -1 || (*i).when < minExecTime)) {
     738           64 :             minExecTime = (*i).when;
     739              :             first = i;
     740              :         }
     741              :     }
     742              :     // activate the first one
     743           88 :     if (first != w->switches.end()) {
     744              :         std::vector<WAUTSwitch>::const_iterator mbegin = w->switches.begin();
     745          128 :         MSNet::getInstance()->getBeginOfTimestepEvents()->addEvent(
     746           64 :             new SwitchInitCommand(*this, wautid, (int)distance(mbegin, first)),
     747           64 :             (*first).when);
     748              :     }
     749              :     /*
     750              :     // set the current program to all junctions
     751              :     for(std::vector<WAUTJunction>::const_iterator i=w->junctions.begin(); i!=w->junctions.end(); ++i) {
     752              :         switchTo((*i).junction, initProg);
     753              :     }
     754              :     */
     755           88 : }
     756              : 
     757              : 
     758              : SUMOTime
     759          114 : MSTLLogicControl::initWautSwitch(MSTLLogicControl::SwitchInitCommand& cmd) {
     760              :     const std::string& wautid = cmd.getWAUTID();
     761              :     int& index = cmd.getIndex();
     762          114 :     WAUT* waut = myWAUTs[wautid];
     763          114 :     WAUTSwitch s = waut->switches[index];
     764          227 :     for (std::vector<WAUTJunction>::iterator i = myWAUTs[wautid]->junctions.begin(); i != myWAUTs[wautid]->junctions.end(); ++i) {
     765              :         // get the current program and the one to instantiate
     766          114 :         TLSLogicVariants* vars = myLogics.find((*i).junction)->second;
     767          114 :         MSTrafficLightLogic* from = vars->getActive();
     768          114 :         MSTrafficLightLogic* to = vars->getLogicInstantiatingOff(*this, s.to);
     769              :         WAUTSwitchProcedure* proc = nullptr;
     770          113 :         if ((*i).procedure == "GSP") {
     771            4 :             proc = new WAUTSwitchProcedure_GSP(*this, *myWAUTs[wautid], from, to, (*i).synchron);
     772          109 :         } else if ((*i).procedure == "Stretch") {
     773            0 :             proc = new WAUTSwitchProcedure_Stretch(*this, *myWAUTs[wautid], from, to, (*i).synchron);
     774              :         } else {
     775          109 :             proc = new WAUTSwitchProcedure_JustSwitch(*this, *myWAUTs[wautid], from, to, (*i).synchron);
     776              :         }
     777              : 
     778              :         WAUTSwitchProcess p;
     779              :         p.junction = (*i).junction;
     780          113 :         p.proc = proc;
     781          113 :         p.from = from;
     782          113 :         p.to = to;
     783              : 
     784          113 :         myCurrentlySwitched.push_back(p);
     785              :     }
     786          113 :     index++;
     787          113 :     if (index == (int)waut->switches.size()) {
     788           63 :         if (waut->period <= 0) {
     789              :             return 0;
     790              :         } else {
     791           24 :             index = 0; // start over
     792           70 :             for (WAUTSwitch& ws : waut->switches) {
     793           46 :                 ws.when += waut->period;
     794              :             }
     795              :         }
     796              :     }
     797           74 :     return myWAUTs[wautid]->switches[index].when - MSNet::getInstance()->getCurrentTimeStep();
     798              : }
     799              : 
     800              : 
     801              : void
     802     91772011 : MSTLLogicControl::check2Switch(SUMOTime step) {
     803     91772444 :     for (std::vector<WAUTSwitchProcess>::iterator i = myCurrentlySwitched.begin(); i != myCurrentlySwitched.end();) {
     804              :         const WAUTSwitchProcess& proc = *i;
     805          433 :         if (proc.proc->trySwitch(step)) {
     806          113 :             delete proc.proc;
     807              :             // do not switch away from TraCI control
     808          113 :             if (getActive(proc.to->getID())->getProgramID() != TRACI_PROGRAM) {
     809          113 :                 switchTo(proc.to->getID(), proc.to->getProgramID());
     810              :             }
     811          113 :             i = myCurrentlySwitched.erase(i);
     812              :         } else {
     813              :             ++i;
     814              :         }
     815              :     }
     816     91772011 : }
     817              : 
     818              : 
     819              : std::pair<SUMOTime, MSPhaseDefinition>
     820            0 : MSTLLogicControl::getPhaseDef(const std::string& tlid) const {
     821            0 :     MSTrafficLightLogic* tl = getActive(tlid);
     822            0 :     return std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), tl->getCurrentPhaseDef());
     823              : }
     824              : 
     825              : 
     826              : void
     827           91 : MSTLLogicControl::switchOffAll() {
     828          172 :     for (const auto& logic : myLogics) {
     829          162 :         logic.second->addLogic("off", new MSOffTrafficLightLogic(*this, logic.first), true, true);
     830              :     }
     831           91 : }
     832              : 
     833              : 
     834              : void
     835          425 : MSTLLogicControl::saveState(OutputDevice& out) {
     836          425 :     MSRailSignalConstraint::saveState(out); // always saves vehicle tracker states
     837         1788 :     for (const auto& logic : myLogics) {
     838         1363 :         logic.second->saveState(out);
     839              :     }
     840          425 :     MSDriveWay::saveState(out);
     841          425 : }
     842              : 
     843              : 
     844              : void
     845          177 : MSTLLogicControl::clearState(SUMOTime time, bool quickReload) {
     846          177 :     MSRailSignalConstraint::clearState();
     847          177 :     if (quickReload) {
     848            0 :         for (const auto& variants : myLogics) {
     849            0 :             for (auto& logic : variants.second->getAllLogics()) {
     850            0 :                 if (logic->getLogicType() == TrafficLightType::OFF
     851            0 :                         || logic->getLogicType() == TrafficLightType::RAIL_SIGNAL
     852            0 :                         || logic->getLogicType() == TrafficLightType::RAIL_CROSSING) {
     853            0 :                     continue;
     854              :                 }
     855              :                 int step = 0;
     856              :                 const SUMOTime cycleTime = logic->getDefaultCycleTime();
     857            0 :                 auto& phases = logic->getPhases();
     858            0 :                 SUMOTime offset = logic->getOffset();
     859            0 :                 if (offset >= 0) {
     860            0 :                     offset = (time + cycleTime - (offset % cycleTime)) % cycleTime;
     861              :                 } else {
     862            0 :                     offset = (time + ((-offset) % cycleTime)) % cycleTime;
     863              :                 }
     864              : 
     865            0 :                 while (offset >= phases[step]->duration) {
     866            0 :                     offset -= phases[step]->duration;
     867            0 :                     step++;
     868              :                 }
     869            0 :                 logic->loadState(*this, time, step, offset);
     870            0 :             }
     871              :         }
     872              :     }
     873          177 : }
     874              : 
     875              : 
     876              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1