LCOV - code coverage report
Current view: top level - src/microsim/traffic_lights - MSTLLogicControl.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 259 396 65.4 %
Date: 2024-05-19 15:37:39 Functions: 49 60 81.7 %

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

Generated by: LCOV version 1.14