SUMO - Simulation of Urban MObility
MSTLLogicControl.cpp
Go to the documentation of this file.
00001 /****************************************************************************/
00013 // A class that stores and controls tls and switching of their programs
00014 /****************************************************************************/
00015 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00016 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
00017 /****************************************************************************/
00018 //
00019 //   This file is part of SUMO.
00020 //   SUMO is free software: you can redistribute it and/or modify
00021 //   it under the terms of the GNU General Public License as published by
00022 //   the Free Software Foundation, either version 3 of the License, or
00023 //   (at your option) any later version.
00024 //
00025 /****************************************************************************/
00026 // ===========================================================================
00027 // included modules
00028 // ===========================================================================
00029 #ifdef _MSC_VER
00030 #include <windows_config.h>
00031 #else
00032 #include <config.h>
00033 #endif
00034 
00035 #include <vector>
00036 #include <algorithm>
00037 #include <cassert>
00038 #include <iterator>
00039 #include "MSTrafficLightLogic.h"
00040 #include "MSSimpleTrafficLightLogic.h"
00041 #include "MSTLLogicControl.h"
00042 #include "MSOffTrafficLightLogic.h"
00043 #include <microsim/MSEventControl.h>
00044 #include <microsim/MSNet.h>
00045 #include <utils/common/TplConvert.h>
00046 #include <utils/common/ToString.h>
00047 #include <utils/common/MsgHandler.h>
00048 
00049 #ifdef CHECK_MEMORY_LEAKS
00050 #include <foreign/nvwa/debug_new.h>
00051 #endif // CHECK_MEMORY_LEAKS
00052 
00053 
00054 // ===========================================================================
00055 // method definitions
00056 // ===========================================================================
00057 /* -------------------------------------------------------------------------
00058  * MSTLLogicControl::TLSLogicVariants - methods
00059  * ----------------------------------------------------------------------- */
00060 MSTLLogicControl::TLSLogicVariants::TLSLogicVariants()
00061     : myCurrentProgram(0) {
00062 }
00063 
00064 
00065 MSTLLogicControl::TLSLogicVariants::~TLSLogicVariants() {
00066     std::map<std::string, MSTrafficLightLogic*>::const_iterator j;
00067     for (std::map<std::string, MSTrafficLightLogic*>::iterator j = myVariants.begin(); j != myVariants.end(); ++j) {
00068         delete(*j).second;
00069     }
00070     for (std::vector<OnSwitchAction*>::iterator i = mySwitchActions.begin(); i != mySwitchActions.end(); ++i) {
00071         delete *i;
00072     }
00073 }
00074 
00075 
00076 bool
00077 MSTLLogicControl::TLSLogicVariants::checkOriginalTLS() const {
00078     bool hadErrors = false;
00079     for (std::map<std::string, MSTrafficLightLogic*>::const_iterator j = myVariants.begin(); j != myVariants.end(); ++j) {
00080         const MSTrafficLightLogic::Phases& phases = (*j).second->getPhases();
00081         unsigned int linkNo = (unsigned int)(*j).second->getLinks().size();
00082         bool hadProgramErrors = false;
00083         for (MSTrafficLightLogic::Phases::const_iterator i = phases.begin(); i != phases.end(); ++i) {
00084             if ((*i)->getState().length() < linkNo) {
00085                 hadProgramErrors = true;
00086             }
00087         }
00088         if (hadProgramErrors) {
00089             WRITE_ERROR("Mismatching phase size in tls '" + (*j).second->getID() + "', program '" + (*j).first + "'.");
00090             hadErrors = true;
00091         }
00092     }
00093     return !hadErrors;
00094 }
00095 
00096 
00097 void
00098 MSTLLogicControl::TLSLogicVariants::saveInitialStates() {
00099     myOriginalLinkStates = myCurrentProgram->collectLinkStates();
00100 }
00101 
00102 
00103 bool
00104 MSTLLogicControl::TLSLogicVariants::addLogic(const std::string& programID,
00105         MSTrafficLightLogic* logic, bool netWasLoaded, bool isNewDefault) {
00106     if (myVariants.find(programID) != myVariants.end()) {
00107         return false;
00108     }
00109     // assert the links are set
00110     if (netWasLoaded) {
00111         // this one has not yet its links set
00112         if (myCurrentProgram == 0) {
00113             throw ProcessError("No initial signal plan loaded for tls '" + logic->getID() + "'.");
00114         }
00115         logic->adaptLinkInformationFrom(*myCurrentProgram);
00116         if (logic->getLinks().size() > logic->getPhase(0).getState().size()) {
00117             throw ProcessError("Mismatching phase size in tls '" + logic->getID() + "', program '" + programID + "'.");
00118         }
00119     }
00120     // add to the list of active
00121     if (myVariants.size() == 0 || isNewDefault) {
00122         myCurrentProgram = logic;
00123     }
00124     // add to the list of logic
00125     myVariants[programID] = logic;
00126     if (myVariants.size() == 1 || isNewDefault) {
00127         logic->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
00128         executeOnSwitchActions();
00129     }
00130     return true;
00131 }
00132 
00133 
00134 MSTrafficLightLogic*
00135 MSTLLogicControl::TLSLogicVariants::getLogic(const std::string& programID) const {
00136     if (myVariants.find(programID) == myVariants.end()) {
00137         return 0;
00138     }
00139     return myVariants.find(programID)->second;
00140 }
00141 
00142 
00143 MSTrafficLightLogic*
00144 MSTLLogicControl::TLSLogicVariants::getLogicInstantiatingOff(MSTLLogicControl& tlc,
00145         const std::string& programID) {
00146     if (myVariants.find(programID) == myVariants.end()) {
00147         if (programID == "off") {
00148             // build an off-tll if this switch indicates it
00149             if (!addLogic("off", new MSOffTrafficLightLogic(tlc, myCurrentProgram->getID()), true, true)) {
00150                 // inform the user if this fails
00151                 throw ProcessError("Could not build an off-state for tls '" + myCurrentProgram->getID() + "'.");
00152             }
00153         } else {
00154             // inform the user about a missing logic
00155             throw ProcessError("Can not switch tls '" + myCurrentProgram->getID() + "' to program '" + programID + "';\n The program is not known.");
00156         }
00157     }
00158     return getLogic(programID);
00159 }
00160 
00161 
00162 void
00163 MSTLLogicControl::TLSLogicVariants::addSwitchCommand(OnSwitchAction* c) {
00164     mySwitchActions.push_back(c);
00165 }
00166 
00167 
00168 std::vector<MSTrafficLightLogic*>
00169 MSTLLogicControl::TLSLogicVariants::getAllLogics() const {
00170     std::vector<MSTrafficLightLogic*> ret;
00171     std::map<std::string, MSTrafficLightLogic*>::const_iterator i;
00172     for (i = myVariants.begin(); i != myVariants.end(); ++i) {
00173         ret.push_back((*i).second);
00174     }
00175     return ret;
00176 }
00177 
00178 
00179 bool
00180 MSTLLogicControl::TLSLogicVariants::isActive(const MSTrafficLightLogic* tl) const {
00181     return tl == myCurrentProgram;
00182 }
00183 
00184 
00185 MSTrafficLightLogic*
00186 MSTLLogicControl::TLSLogicVariants::getActive() const {
00187     return myCurrentProgram;
00188 }
00189 
00190 
00191 void
00192 MSTLLogicControl::TLSLogicVariants::switchTo(MSTLLogicControl& tlc, const std::string& programID) {
00193     // set the found wished sub-program as this tls' current one
00194     myCurrentProgram = getLogicInstantiatingOff(tlc, programID);
00195 }
00196 
00197 
00198 void
00199 MSTLLogicControl::TLSLogicVariants::executeOnSwitchActions() const {
00200     for (std::vector<OnSwitchAction*>::const_iterator i = mySwitchActions.begin(); i != mySwitchActions.end(); ++i) {
00201         (*i)->execute();
00202     }
00203 }
00204 
00205 
00206 void
00207 MSTLLogicControl::TLSLogicVariants::addLink(MSLink* link, MSLane* lane, unsigned int pos) {
00208     for (std::map<std::string, MSTrafficLightLogic*>::iterator i = myVariants.begin(); i != myVariants.end(); ++i) {
00209         (*i).second->addLink(link, lane, pos);
00210     }
00211 }
00212 
00213 
00214 
00215 /* -------------------------------------------------------------------------
00216  * method definitions for the Switching Procedures
00217  * ----------------------------------------------------------------------- */
00218 /* -------------------------------------------------------------------------
00219  * method definitions for WAUTSwitchProcedure
00220  * ----------------------------------------------------------------------- */
00221 unsigned int
00222 MSTLLogicControl::WAUTSwitchProcedure::getGSPValue(const MSTrafficLightLogic& logic) const {
00223     std::string val = logic.getParameterValue("GSP");
00224     if (val.length() == 0) {
00225         return 0;
00226     }
00227     return TplConvert<char>::_2int(val.c_str());
00228 }
00229 
00230 
00231 bool
00232 MSTLLogicControl::WAUTSwitchProcedure::isPosAtGSP(SUMOTime currentTime, const MSTrafficLightLogic& logic) {
00233     SUMOTime gspTime = TIME2STEPS(getGSPValue(logic)) % logic.getDefaultCycleTime();
00234     SUMOTime programTime = logic.getOffsetFromIndex(logic.getCurrentPhaseIndex())
00235                            + (logic.getCurrentPhaseDef().duration - (logic.getNextSwitchTime() - currentTime));
00236     return gspTime == programTime;
00237 }
00238 
00239 
00240 SUMOTime
00241 MSTLLogicControl::WAUTSwitchProcedure::getDiffToStartOfPhase(MSTrafficLightLogic& logic, SUMOTime toTime) {
00242     unsigned int stepOfMyPos = logic.getIndexFromOffset(toTime);
00243     SUMOTime startOfPhase = logic.getOffsetFromIndex(stepOfMyPos);
00244     assert(toTime >= startOfPhase);
00245     return toTime - startOfPhase;
00246 }
00247 
00248 
00249 void
00250 MSTLLogicControl::WAUTSwitchProcedure::switchToPos(SUMOTime simStep, MSTrafficLightLogic& logic, SUMOTime toTime) {
00251     unsigned int stepTo = logic.getIndexFromOffset(toTime);
00252     SUMOTime diff = getDiffToStartOfPhase(logic, toTime);
00253     const MSPhaseDefinition& phase = logic.getPhase(stepTo);
00254     SUMOTime leftDuration = phase.duration - diff;
00255     logic.changeStepAndDuration(myControl, simStep, stepTo, leftDuration);
00256 }
00257 
00258 
00259 
00260 /* -------------------------------------------------------------------------
00261  * method definitions for WAUTSwitchProcedure_JustSwitch
00262  * ----------------------------------------------------------------------- */
00263 MSTLLogicControl::WAUTSwitchProcedure_JustSwitch::WAUTSwitchProcedure_JustSwitch(
00264     MSTLLogicControl& control, WAUT& waut,
00265     MSTrafficLightLogic* from, MSTrafficLightLogic* to, bool synchron)
00266     : MSTLLogicControl::WAUTSwitchProcedure(control, waut, from, to, synchron) {}
00267 
00268 
00269 MSTLLogicControl::WAUTSwitchProcedure_JustSwitch::~WAUTSwitchProcedure_JustSwitch() {}
00270 
00271 
00272 bool
00273 MSTLLogicControl::WAUTSwitchProcedure_JustSwitch::trySwitch(SUMOTime) {
00274     return true;
00275 }
00276 
00277 
00278 
00279 /* -------------------------------------------------------------------------
00280  * method definitions for WAUTSwitchProcedure_GSP
00281  * ----------------------------------------------------------------------- */
00282 MSTLLogicControl::WAUTSwitchProcedure_GSP::WAUTSwitchProcedure_GSP(
00283     MSTLLogicControl& control, WAUT& waut,
00284     MSTrafficLightLogic* from, MSTrafficLightLogic* to, bool synchron)
00285     : MSTLLogicControl::WAUTSwitchProcedure(control, waut, from, to, synchron) {}
00286 
00287 
00288 MSTLLogicControl::WAUTSwitchProcedure_GSP::~WAUTSwitchProcedure_GSP() {}
00289 
00290 
00291 bool
00292 MSTLLogicControl::WAUTSwitchProcedure_GSP::trySwitch(SUMOTime step) {
00293     // switch to the next programm if the GSP is reached
00294     if (isPosAtGSP(step, *myFrom)) {
00295         // adapt program's state
00296         if (mySwitchSynchron) {
00297             adaptLogic(step);
00298         } else {
00299             switchToPos(step, *myTo, TIME2STEPS(getGSPValue(*myTo)));
00300         }
00301         // switch to destination program
00302         return true;
00303     }
00304     // do not switch, yet
00305     return false;
00306 }
00307 
00308 
00309 void
00310 MSTLLogicControl::WAUTSwitchProcedure_GSP::adaptLogic(SUMOTime step) {
00311     SUMOTime gspTo = TIME2STEPS(getGSPValue(*myTo));
00312     unsigned int stepTo = myTo->getIndexFromOffset(gspTo);
00313     SUMOTime cycleTimeTo = myTo->getDefaultCycleTime();
00314     if (gspTo == cycleTimeTo) {
00315         gspTo = 0;
00316     }
00317 
00318     SUMOTime currentPosTo = myTo->getOffsetFromIndex(myTo->getCurrentPhaseIndex());
00319     currentPosTo += (myTo->getCurrentPhaseDef().duration - (myTo->getNextSwitchTime() - step));
00320     SUMOTime diff = getDiffToStartOfPhase(*myTo, gspTo);
00321 
00322     SUMOTime deltaToStretch = 0;
00323     if (gspTo >= currentPosTo) {
00324         deltaToStretch = (gspTo - currentPosTo);
00325     } else {
00326         deltaToStretch = (cycleTimeTo - currentPosTo + gspTo);
00327     }
00328     unsigned int newdur = (unsigned int) myTo->getPhase(stepTo).duration - diff + deltaToStretch;
00329     myTo->changeStepAndDuration(myControl, step, stepTo, newdur);
00330 }
00331 
00332 
00333 
00334 /* -------------------------------------------------------------------------
00335  * method definitions for WAUTSwitchProcedure_Stretch
00336  * ----------------------------------------------------------------------- */
00337 MSTLLogicControl::WAUTSwitchProcedure_Stretch::WAUTSwitchProcedure_Stretch(
00338     MSTLLogicControl& control, WAUT& waut,
00339     MSTrafficLightLogic* from, MSTrafficLightLogic* to, bool synchron)
00340     : MSTLLogicControl::WAUTSwitchProcedure(control, waut, from, to, synchron) {}
00341 
00342 
00343 MSTLLogicControl::WAUTSwitchProcedure_Stretch::~WAUTSwitchProcedure_Stretch() {}
00344 
00345 
00346 bool
00347 MSTLLogicControl::WAUTSwitchProcedure_Stretch::trySwitch(SUMOTime step) {
00348     // switch to the next programm if the GSP is reached
00349     if (isPosAtGSP(step, *myFrom)) {
00350         // adapt program's state
00351         if (mySwitchSynchron) {
00352             adaptLogic(step);
00353         } else {
00354             switchToPos(step, *myTo, TIME2STEPS(getGSPValue(*myTo)));
00355         }
00356         // switch to destination program
00357         return true;
00358     }
00359     // do not switch, yet
00360     return false;
00361 }
00362 
00363 
00364 void
00365 MSTLLogicControl::WAUTSwitchProcedure_Stretch::adaptLogic(SUMOTime step) {
00366     SUMOTime gspTo = TIME2STEPS(getGSPValue(*myTo));
00367     SUMOTime cycleTime = myTo->getDefaultCycleTime();
00368     // the position, where the logic has to be after synchronisation
00369     SUMOTime posAfterSyn = myTo->getPhaseIndexAtTime(step);
00370     // calculate the difference, that has to be equalized
00371     SUMOTime deltaToCut = 0;
00372     if (posAfterSyn < gspTo) {
00373         deltaToCut = posAfterSyn + cycleTime - gspTo;
00374     } else {
00375         deltaToCut =  posAfterSyn - gspTo;
00376     }
00377     // test, wheter cutting of the Signalplan is possible
00378     SUMOTime deltaPossible = 0;
00379     int areasNo = getStretchAreaNo(myTo);
00380     for (int i = 0; i < areasNo; i++) {
00381         StretchBereichDef def = getStretchBereichDef(myTo, i + 1);
00382         assert(def.end >= def.begin) ;
00383         deltaPossible += TIME2STEPS(def.end - def.begin);
00384     }
00385     int stretchUmlaufAnz = (int) TplConvert<char>::_2SUMOReal(myTo->getParameterValue("StretchUmlaufAnz").c_str());
00386     deltaPossible = stretchUmlaufAnz * deltaPossible;
00387     if ((deltaPossible > deltaToCut) && (deltaToCut < (cycleTime / 2))) {
00388         cutLogic(step, gspTo, deltaToCut);
00389     } else {
00390         SUMOTime deltaToStretch = (cycleTime - deltaToCut) % cycleTime;
00391         stretchLogic(step, gspTo, deltaToStretch);
00392     }
00393 }
00394 
00395 
00396 void
00397 MSTLLogicControl::WAUTSwitchProcedure_Stretch::cutLogic(SUMOTime step, SUMOTime startPos, SUMOTime allCutTime) {
00398     unsigned int actStep = myTo->getIndexFromOffset(startPos);
00399     // switches to startPos and cuts this phase, if there is a "Bereich"
00400     int areasNo = getStretchAreaNo(myTo);
00401     SUMOTime toCut = 0;
00402     for (int i = 0; i < areasNo; i++) {
00403         StretchBereichDef def = getStretchBereichDef(myTo, i + 1);
00404         SUMOTime begin = TIME2STEPS(def.begin);
00405         unsigned int end = TIME2STEPS(def.end);
00406         size_t stepOfBegin = myTo->getIndexFromOffset(begin);
00407         if (stepOfBegin == actStep) {
00408             if (begin < startPos) {
00409                 toCut = end - startPos;
00410             } else {
00411                 toCut = end - begin;
00412             }
00413             toCut = MIN2(allCutTime, toCut);
00414             allCutTime = allCutTime - toCut;
00415         }
00416     }
00417     SUMOTime remainingDur = myTo->getPhase(actStep).duration - getDiffToStartOfPhase(*myTo, startPos);
00418     SUMOTime newDur = remainingDur - toCut;
00419     myTo->changeStepAndDuration(myControl, step, actStep, newDur);
00420 
00421     // changes the duration of all other phases
00422     int currStep = (actStep + 1) % (int)myTo->getPhases().size();
00423     while (allCutTime > 0) {
00424         for (int i = currStep; i < (int) myTo->getPhases().size(); i++) {
00425             SUMOTime beginOfPhase = myTo->getOffsetFromIndex(i);
00426             SUMOTime durOfPhase = myTo->getPhase(i).duration;
00427             SUMOTime endOfPhase = beginOfPhase + durOfPhase;
00428             for (int i = 0; i < areasNo; i++) {
00429                 StretchBereichDef def = getStretchBereichDef(myTo, i + 1);
00430                 SUMOTime begin = TIME2STEPS(def.begin);
00431                 SUMOTime end = TIME2STEPS(def.end);
00432                 if ((beginOfPhase <= begin) && (endOfPhase >= end)) {
00433                     SUMOTime maxCutOfPhase = MIN2(end - begin, allCutTime);
00434                     allCutTime = allCutTime - maxCutOfPhase;
00435                     durOfPhase = durOfPhase - maxCutOfPhase;
00436                 }
00437             }
00438             myTo->addOverridingDuration(durOfPhase);
00439         }
00440         currStep = 0;
00441     }
00442 }
00443 
00444 void
00445 MSTLLogicControl::WAUTSwitchProcedure_Stretch::stretchLogic(SUMOTime step, SUMOTime startPos, SUMOTime allStretchTime) {
00446     unsigned int currStep = myTo->getIndexFromOffset(startPos);
00447     SUMOTime durOfPhase = myTo->getPhase(currStep).duration;
00448     SUMOTime remainingStretchTime = allStretchTime;
00449     SUMOTime StretchTimeOfPhase = 0;
00450     unsigned int stretchUmlaufAnz = (unsigned int) TplConvert<char>::_2SUMOReal(myTo->getParameterValue("StretchUmlaufAnz").c_str());
00451     SUMOReal facSum = 0;
00452     int areasNo = getStretchAreaNo(myTo);
00453     for (int x = 0; x < areasNo; x++) {
00454         StretchBereichDef def = getStretchBereichDef(myTo, x + 1);
00455         facSum += def.fac;
00456     }
00457     facSum *= stretchUmlaufAnz;
00458 
00459     //switch to startPos and stretch this phase, if there is a end of "bereich" between startpos and end of phase
00460     SUMOTime diffToStart = getDiffToStartOfPhase(*myTo, startPos);
00461     for (int x = 0; x < areasNo; x++) {
00462         StretchBereichDef def = getStretchBereichDef(myTo, x + 1);
00463         SUMOTime end = TIME2STEPS(def.end);
00464         SUMOTime endOfPhase = (startPos + durOfPhase - diffToStart);
00465         if (end <= endOfPhase && end >= startPos) {
00466             SUMOReal fac = def.fac;
00467             SUMOReal actualfac = fac / facSum;
00468             facSum = facSum - fac;
00469             StretchTimeOfPhase = TIME2STEPS(STEPS2TIME(remainingStretchTime) * actualfac + 0.5);
00470             remainingStretchTime = allStretchTime - StretchTimeOfPhase;
00471         }
00472     }
00473     durOfPhase = durOfPhase - diffToStart + StretchTimeOfPhase;
00474     myTo->changeStepAndDuration(myControl, step, currStep, durOfPhase);
00475 
00476     currStep = (currStep + 1) % (int)myTo->getPhases().size();
00477     // stretch all other phases, if there is a "bereich"
00478     while (remainingStretchTime > 0) {
00479         for (unsigned int i = currStep; i < myTo->getPhases().size() && remainingStretchTime > 0; i++) {
00480             durOfPhase = myTo->getPhase(i).duration;
00481             SUMOTime beginOfPhase = myTo->getOffsetFromIndex(i);
00482             SUMOTime endOfPhase = beginOfPhase + durOfPhase;
00483             for (int j = 0; j < areasNo && remainingStretchTime > 0; j++) {
00484                 StretchBereichDef def = getStretchBereichDef(myTo, j + 1);
00485                 SUMOTime end = TIME2STEPS(def.end);
00486                 SUMOReal fac = def.fac;
00487                 if ((beginOfPhase <= end) && (endOfPhase >= end)) {
00488                     SUMOReal actualfac = fac / facSum;
00489                     StretchTimeOfPhase = TIME2STEPS(STEPS2TIME(remainingStretchTime) * actualfac + 0.5);
00490                     facSum -= fac;
00491                     durOfPhase += StretchTimeOfPhase;
00492                     remainingStretchTime -= StretchTimeOfPhase;
00493                 }
00494             }
00495             myTo->addOverridingDuration(durOfPhase);
00496         }
00497         currStep = 0;
00498     }
00499 }
00500 
00501 int
00502 MSTLLogicControl::WAUTSwitchProcedure_Stretch::getStretchAreaNo(MSTrafficLightLogic* from) const {
00503     int no = 0;
00504     while (from->getParameterValue("B" + toString(no + 1) + ".begin") != "") {
00505         no++;
00506     }
00507     return no;
00508 }
00509 
00510 
00511 MSTLLogicControl::WAUTSwitchProcedure_Stretch::StretchBereichDef
00512 MSTLLogicControl::WAUTSwitchProcedure_Stretch::getStretchBereichDef(MSTrafficLightLogic* from, int index) const {
00513     StretchBereichDef def;
00514     def.begin = TplConvert<char>::_2SUMOReal(from->getParameterValue("B" + toString(index) + ".begin").c_str());
00515     def.end = TplConvert<char>::_2SUMOReal(from->getParameterValue("B" + toString(index) + ".end").c_str());
00516     def.fac = TplConvert<char>::_2SUMOReal(from->getParameterValue("B" + toString(index) + ".factor").c_str());
00517     return def;
00518 }
00519 
00520 
00521 
00522 /* -------------------------------------------------------------------------
00523  * method definitions for MSTLLogicControl
00524  * ----------------------------------------------------------------------- */
00525 MSTLLogicControl::MSTLLogicControl()
00526     : myNetWasLoaded(false) {}
00527 
00528 
00529 MSTLLogicControl::~MSTLLogicControl() {
00530     // delete tls
00531     for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
00532         delete(*i).second;
00533     }
00534     // delete WAUTs
00535     for (std::map<std::string, WAUT*>::const_iterator i = myWAUTs.begin(); i != myWAUTs.end(); ++i) {
00536         delete(*i).second;
00537     }
00538 }
00539 
00540 
00541 void
00542 MSTLLogicControl::setTrafficLightSignals(SUMOTime t) const {
00543     for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
00544         (*i).second->getActive()->setTrafficLightSignals(t);
00545     }
00546 }
00547 
00548 
00549 std::vector<MSTrafficLightLogic*>
00550 MSTLLogicControl::getAllLogics() const {
00551     std::vector<MSTrafficLightLogic*> ret;
00552     std::map<std::string, TLSLogicVariants*>::const_iterator i;
00553     for (i = myLogics.begin(); i != myLogics.end(); ++i) {
00554         std::vector<MSTrafficLightLogic*> s = (*i).second->getAllLogics();
00555         copy(s.begin(), s.end(), back_inserter(ret));
00556     }
00557     return ret;
00558 }
00559 
00560 MSTLLogicControl::TLSLogicVariants&
00561 MSTLLogicControl::get(const std::string& id) const {
00562     std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
00563     if (i == myLogics.end()) {
00564         throw InvalidArgument("The tls '" + id + "' is not known.");
00565     }
00566     return *(*i).second;
00567 }
00568 
00569 
00570 MSTrafficLightLogic*
00571 MSTLLogicControl::get(const std::string& id, const std::string& programID) const {
00572     std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
00573     if (i == myLogics.end()) {
00574         return 0;
00575     }
00576     return (*i).second->getLogic(programID);
00577 }
00578 
00579 
00580 std::vector<std::string>
00581 MSTLLogicControl::getAllTLIds() const {
00582     std::vector<std::string> ret;
00583     for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
00584         ret.push_back((*i).first);
00585     }
00586     return ret;
00587 }
00588 
00589 
00590 bool
00591 MSTLLogicControl::add(const std::string& id, const std::string& programID,
00592                       MSTrafficLightLogic* logic, bool newDefault) {
00593     if (myLogics.find(id) == myLogics.end()) {
00594         myLogics[id] = new TLSLogicVariants();
00595     }
00596     std::map<std::string, TLSLogicVariants*>::iterator i = myLogics.find(id);
00597     TLSLogicVariants* tlmap = (*i).second;
00598     return tlmap->addLogic(programID, logic, myNetWasLoaded, newDefault);
00599 }
00600 
00601 
00602 bool
00603 MSTLLogicControl::knows(const std::string& id) const {
00604     std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
00605     if (i == myLogics.end()) {
00606         return false;
00607     }
00608     return true;
00609 }
00610 
00611 
00612 bool
00613 MSTLLogicControl::closeNetworkReading() {
00614     bool hadErrors = false;
00615     for (std::map<std::string, TLSLogicVariants*>::iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
00616         hadErrors |= !(*i).second->checkOriginalTLS();
00617         (*i).second->saveInitialStates();
00618     }
00619     myNetWasLoaded = true;
00620     return !hadErrors;
00621 }
00622 
00623 
00624 bool
00625 MSTLLogicControl::isActive(const MSTrafficLightLogic* tl) const {
00626     std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(tl->getID());
00627     if (i == myLogics.end()) {
00628         return false;
00629     }
00630     return (*i).second->isActive(tl);
00631 }
00632 
00633 
00634 MSTrafficLightLogic*
00635 MSTLLogicControl::getActive(const std::string& id) const {
00636     std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
00637     if (i == myLogics.end()) {
00638         return 0;
00639     }
00640     return (*i).second->getActive();
00641 }
00642 
00643 
00644 void
00645 MSTLLogicControl::switchTo(const std::string& id, const std::string& programID) {
00646     // try to get the tls program definitions
00647     std::map<std::string, TLSLogicVariants*>::iterator i = myLogics.find(id);
00648     // handle problems
00649     if (i == myLogics.end()) {
00650         throw ProcessError("Could not switch tls '" + id + "' to program '" + programID + "': No such tls exists.");
00651     }
00652     (*i).second->switchTo(*this, programID);
00653 }
00654 
00655 
00656 void
00657 MSTLLogicControl::addWAUT(SUMOTime refTime, const std::string& id,
00658                           const std::string& startProg) {
00659     // check whether the waut was already defined
00660     if (myWAUTs.find(id) != myWAUTs.end()) {
00661         // report an error if so
00662         throw InvalidArgument("Waut '" + id + "' was already defined.");
00663     }
00664     WAUT* w = new WAUT;
00665     w->id = id;
00666     w->refTime = refTime;
00667     w->startProg = startProg;
00668     myWAUTs[id] = w;
00669 }
00670 
00671 
00672 void
00673 MSTLLogicControl::addWAUTSwitch(const std::string& wautid,
00674                                 SUMOTime when, const std::string& to) {
00675     // try to get the waut
00676     if (myWAUTs.find(wautid) == myWAUTs.end()) {
00677         // report an error if the waut is not known
00678         throw InvalidArgument("Waut '" + wautid + "' was not yet defined.");
00679     }
00680     // build and save the waut switch definition
00681     WAUTSwitch s;
00682     s.to = to;
00683     s.when = (myWAUTs[wautid]->refTime + when) % 86400000;
00684     myWAUTs[wautid]->switches.push_back(s);
00685 }
00686 
00687 
00688 void
00689 MSTLLogicControl::addWAUTJunction(const std::string& wautid,
00690                                   const std::string& tls,
00691                                   const std::string& proc,
00692                                   bool synchron) {
00693     // try to get the waut
00694     if (myWAUTs.find(wautid) == myWAUTs.end()) {
00695         // report an error if the waut is not known
00696         throw InvalidArgument("Waut '" + wautid + "' was not yet defined.");
00697     }
00698     // try to get the tls to switch
00699     if (myLogics.find(tls) == myLogics.end()) {
00700         // report an error if the tls is not known
00701         throw InvalidArgument("TLS '" + tls + "' to switch in WAUT '" + wautid + "' was not yet defined.");
00702     }
00703     WAUTJunction j;
00704     j.junction = tls;
00705     j.procedure = proc;
00706     j.synchron = synchron;
00707     myWAUTs[wautid]->junctions.push_back(j);
00708 
00709     std::string initProg = myWAUTs[wautid]->startProg;
00710     std::vector<WAUTSwitch>::const_iterator first = myWAUTs[wautid]->switches.end();
00711     SUMOTime minExecTime = -1;
00712     for (std::vector<WAUTSwitch>::const_iterator i = myWAUTs[wautid]->switches.begin(); i != myWAUTs[wautid]->switches.end(); ++i) {
00713         if ((*i).when > MSNet::getInstance()->getCurrentTimeStep() && (minExecTime == -1 || (*i).when < minExecTime)) {
00714             minExecTime = (*i).when;
00715             first = i;
00716         }
00717         if (first != myWAUTs[wautid]->switches.begin()) {
00718             initProg = (*(first - 1)).to;
00719         }
00720     }
00721     // activate the first one
00722     switchTo(tls, initProg);
00723 }
00724 
00725 
00726 void
00727 MSTLLogicControl::closeWAUT(const std::string& wautid) {
00728     // try to get the waut
00729     if (myWAUTs.find(wautid) == myWAUTs.end()) {
00730         // report an error if the waut is not known
00731         throw InvalidArgument("Waut '" + wautid + "' was not yet defined.");
00732     }
00733     WAUT* w = myWAUTs.find(wautid)->second;
00734     std::string initProg = myWAUTs[wautid]->startProg;
00735     // get the switch to be performed as first
00736     std::vector<WAUTSwitch>::const_iterator first = w->switches.end();
00737     SUMOTime minExecTime = -1;
00738     for (std::vector<WAUTSwitch>::const_iterator i = w->switches.begin(); i != w->switches.end(); ++i) {
00739         if ((*i).when > MSNet::getInstance()->getCurrentTimeStep() && (minExecTime == -1 || (*i).when < minExecTime)) {
00740             minExecTime = (*i).when;
00741             first = i;
00742         }
00743     }
00744     // activate the first one
00745     if (first != w->switches.end()) {
00746         std::vector<WAUTSwitch>::const_iterator mbegin = w->switches.begin();
00747         MSNet::getInstance()->getBeginOfTimestepEvents().addEvent(
00748             new SwitchInitCommand(*this, wautid, (unsigned int)distance(mbegin, first)),
00749             (*first).when, MSEventControl::NO_CHANGE);
00750     }
00751     /*
00752     // set the current program to all junctions
00753     for(std::vector<WAUTJunction>::const_iterator i=w->junctions.begin(); i!=w->junctions.end(); ++i) {
00754         switchTo((*i).junction, initProg);
00755     }
00756     */
00757 }
00758 
00759 
00760 SUMOTime
00761 MSTLLogicControl::initWautSwitch(MSTLLogicControl::SwitchInitCommand& cmd) {
00762     const std::string& wautid = cmd.getWAUTID();
00763     unsigned int& index = cmd.getIndex();
00764     WAUTSwitch s = myWAUTs[wautid]->switches[index];
00765     for (std::vector<WAUTJunction>::iterator i = myWAUTs[wautid]->junctions.begin(); i != myWAUTs[wautid]->junctions.end(); ++i) {
00766         // get the current program and the one to instantiate
00767         TLSLogicVariants* vars = myLogics.find((*i).junction)->second;
00768         MSTrafficLightLogic* from = vars->getActive();
00769         MSTrafficLightLogic* to = vars->getLogicInstantiatingOff(*this, s.to);
00770         WAUTSwitchProcedure* proc = 0;
00771         if ((*i).procedure == "GSP") {
00772             proc = new WAUTSwitchProcedure_GSP(*this, *myWAUTs[wautid], from, to, (*i).synchron);
00773         } else if ((*i).procedure == "Stretch") {
00774             proc = new WAUTSwitchProcedure_Stretch(*this, *myWAUTs[wautid], from, to, (*i).synchron);
00775         } else {
00776             proc = new WAUTSwitchProcedure_JustSwitch(*this, *myWAUTs[wautid], from, to, (*i).synchron);
00777         }
00778 
00779         WAUTSwitchProcess p;
00780         p.junction = (*i).junction;
00781         p.proc = proc;
00782         p.from = from;
00783         p.to = to;
00784 
00785         myCurrentlySwitched.push_back(p);
00786     }
00787     index++;
00788     if (index == (int) myWAUTs[wautid]->switches.size()) {
00789         return 0;
00790     }
00791     return myWAUTs[wautid]->switches[index].when - MSNet::getInstance()->getCurrentTimeStep();
00792 }
00793 
00794 
00795 void
00796 MSTLLogicControl::check2Switch(SUMOTime step) {
00797     for (std::vector<WAUTSwitchProcess>::iterator i = myCurrentlySwitched.begin(); i != myCurrentlySwitched.end();) {
00798         const WAUTSwitchProcess& proc = *i;
00799         if (proc.proc->trySwitch(step)) {
00800             delete proc.proc;
00801             switchTo((*i).to->getID(), (*i).to->getProgramID());
00802             i = myCurrentlySwitched.erase(i);
00803         } else {
00804             ++i;
00805         }
00806     }
00807 }
00808 
00809 
00810 std::pair<SUMOTime, MSPhaseDefinition>
00811 MSTLLogicControl::getPhaseDef(const std::string& tlid) const {
00812     MSTrafficLightLogic* tl = getActive(tlid);
00813     return std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), tl->getCurrentPhaseDef());
00814 }
00815 
00816 
00817 
00818 /****************************************************************************/
00819 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines