Eclipse SUMO - Simulation of Urban MObility
MSTLLogicControl.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3// Copyright (C) 2001-2023 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/****************************************************************************/
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"
34#include "MSTLLogicControl.h"
38#include <microsim/MSNet.h>
42
43#define TRACI_PROGRAM "online"
44
45// ===========================================================================
46// method definitions
47// ===========================================================================
48/* -------------------------------------------------------------------------
49 * MSTLLogicControl::TLSLogicVariants - methods
50 * ----------------------------------------------------------------------- */
52 myCurrentProgram(nullptr),
53 myDefaultProgram(nullptr) {
54}
55
56
58 std::map<std::string, MSTrafficLightLogic*>::const_iterator j;
59 for (const auto& var : myVariants) {
60 delete var.second;
61 }
62 for (OnSwitchAction* osa : mySwitchActions) {
63 delete osa;
64 }
65}
66
67
68bool
70 bool hadErrors = false;
71 for (std::map<std::string, MSTrafficLightLogic*>::const_iterator j = myVariants.begin(); j != myVariants.end(); ++j) {
72 const MSTrafficLightLogic::Phases& phases = (*j).second->getPhases();
73 int linkNo = (int)(*j).second->getLinks().size();
74 bool hadProgramErrors = false;
75 for (MSTrafficLightLogic::Phases::const_iterator i = phases.begin(); i != phases.end(); ++i) {
76 if ((int)(*i)->getState().length() < linkNo) {
77 hadProgramErrors = true;
78 }
79 }
80 if (hadProgramErrors) {
81 WRITE_ERRORF(TL("Mismatching phase size in tls '%', program '%'."), (*j).second->getID(), (*j).first);
82 hadErrors = true;
83 }
84 }
85 return !hadErrors;
86}
87
88
89void
91 myOriginalLinkStates = myCurrentProgram->collectLinkStates();
92}
93
94
95void
97 for (const auto& item : myVariants) {
98 item.second->saveState(out);
99 }
100}
101
102
103bool
105 MSTrafficLightLogic* logic, bool netWasLoaded, bool isNewDefault) {
106 if (myVariants.find(programID) != myVariants.end()) {
107 delete logic;
108 return false;
109 }
110 // assert the links are set
111 if (netWasLoaded) {
112 // this one has not yet its links set
113 if (myCurrentProgram == nullptr) {
114 const std::string id = logic->getID();
115 delete logic;
116 throw ProcessError(TLF("No initial signal plan loaded for tls '%'.", id));
117 }
118 logic->adaptLinkInformationFrom(*myCurrentProgram);
119 if (logic->getLinks().size() > logic->getPhase(0).getState().size()) {
120 const std::string id = logic->getID();
121 delete logic;
122 throw ProcessError("Mismatching phase size in tls '" + id + "', program '" + programID + "'.");
123 }
124 }
125 // add to the list of active
126 if (myVariants.size() == 0 || isNewDefault) {
127 if (myCurrentProgram != nullptr) {
128 myCurrentProgram->deactivateProgram();
129 }
130 myCurrentProgram = logic;
131 myCurrentProgram->activateProgram();
132 if (myVariants.size() == 0) {
133 myDefaultProgram = logic;
134 }
135 }
136 // add to the list of logic
137 myVariants[programID] = logic;
138 if (myVariants.size() == 1 || isNewDefault) {
139 logic->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
140 executeOnSwitchActions();
141 }
142 return true;
143}
144
145
147MSTLLogicControl::TLSLogicVariants::getLogic(const std::string& programID) const {
148 if (myVariants.find(programID) == myVariants.end()) {
149 return nullptr;
150 }
151 return myVariants.find(programID)->second;
152}
153
154
157 if (myVariants.find(programID) == myVariants.end()) {
158 if (programID == "off") {
159 // build an off-tll if this switch indicates it
160 MSTrafficLightLogic* tlLogic = new MSOffTrafficLightLogic(tlc, myCurrentProgram->getID());
161 if (!addLogic("off", tlLogic, true, true)) {
162 // inform the user if this fails
163 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 throw ProcessError("Can not switch tls '" + myCurrentProgram->getID() + "' to program '" + programID + "';\n The program is not known.");
168 }
169 }
170 return getLogic(programID);
171}
172
173
174void
176 const std::string& state) {
177 // build only once...
178 MSTrafficLightLogic* logic = getLogic(TRACI_PROGRAM);
179 if (logic == nullptr) {
180 MSPhaseDefinition* phase = new MSPhaseDefinition(DELTA_T, state);
181 std::vector<MSPhaseDefinition*> phases;
182 phases.push_back(phase);
183 logic = new MSSimpleTrafficLightLogic(tlc, myCurrentProgram->getID(), TRACI_PROGRAM, 0, TrafficLightType::STATIC, phases, 0,
186 if (addLogic(TRACI_PROGRAM, logic, true, true)) {
188 }
189 } else {
190 MSPhaseDefinition nphase(DELTA_T, state);
191 *(dynamic_cast<MSSimpleTrafficLightLogic*>(logic)->getPhases()[0]) = nphase;
193 }
194}
195
196
197void
199 mySwitchActions.push_back(c);
200}
201
202
203std::vector<MSTrafficLightLogic*>
205 std::vector<MSTrafficLightLogic*> ret;
206 std::map<std::string, MSTrafficLightLogic*>::const_iterator i;
207 for (i = myVariants.begin(); i != myVariants.end(); ++i) {
208 ret.push_back((*i).second);
209 }
210 return ret;
211}
212
213
214bool
216 return tl == myCurrentProgram;
217}
218
219
222 return myCurrentProgram;
223}
224
227 return myDefaultProgram;
228}
229
230
231void
233 // set the found wished sub-program as this tls' current one
234 myCurrentProgram->deactivateProgram();
235 myCurrentProgram = getLogicInstantiatingOff(tlc, programID);
236 myCurrentProgram->activateProgram();
237 myCurrentProgram->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
238 executeOnSwitchActions();
239}
240
241
242void
244 for (std::vector<OnSwitchAction*>::const_iterator i = mySwitchActions.begin(); i != mySwitchActions.end(); ++i) {
245 (*i)->execute();
246 }
247}
248
249
250void
252 for (std::map<std::string, MSTrafficLightLogic*>::iterator i = myVariants.begin(); i != myVariants.end(); ++i) {
253 (*i).second->addLink(link, lane, pos);
254 }
255}
256
257void
259 for (std::map<std::string, MSTrafficLightLogic*>::iterator i = myVariants.begin(); i != myVariants.end(); ++i) {
260 (*i).second->ignoreLinkIndex(pos);
261 }
262}
263
264
265/* -------------------------------------------------------------------------
266 * method definitions for the Switching Procedures
267 * ----------------------------------------------------------------------- */
268/* -------------------------------------------------------------------------
269 * method definitions for WAUTSwitchProcedure
270 * ----------------------------------------------------------------------- */
271bool
273 // switch to the next programm if the GSP is reached
274 if (isPosAtGSP(step, *myFrom)) {
275 // adapt program's state
276 if (mySwitchSynchron) {
277 adaptLogic(step);
278 } else {
279 switchToPos(step, *myTo, getGSPTime(*myTo));
280 }
281 // switch to destination program
282 return true;
283 }
284 // do not switch, yet
285 return false;
286}
287
288
291 return string2time(logic.getParameter("GSP", "0"));
292}
293
294
295bool
297 const SUMOTime gspTime = getGSPTime(logic) % logic.getDefaultCycleTime();
298 const SUMOTime programTime = logic.getOffsetFromIndex(logic.getCurrentPhaseIndex()) + logic.getSpentDuration(currentTime);
299 return gspTime == programTime;
300}
301
302
305 int stepOfMyPos = logic.getIndexFromOffset(toTime);
306 SUMOTime startOfPhase = logic.getOffsetFromIndex(stepOfMyPos);
307 assert(toTime >= startOfPhase);
308 return toTime - startOfPhase;
309}
310
311
312void
314 int stepTo = logic.getIndexFromOffset(toTime);
315 SUMOTime diff = getDiffToStartOfPhase(logic, toTime);
316 const MSPhaseDefinition& phase = logic.getPhase(stepTo);
317 SUMOTime leftDuration = phase.duration - diff;
318 logic.changeStepAndDuration(myControl, simStep, stepTo, leftDuration);
319}
320
321
322
323/* -------------------------------------------------------------------------
324 * method definitions for WAUTSwitchProcedure_JustSwitch
325 * ----------------------------------------------------------------------- */
327 MSTLLogicControl& control, WAUT& waut,
328 MSTrafficLightLogic* from, MSTrafficLightLogic* to, bool synchron)
329 : MSTLLogicControl::WAUTSwitchProcedure(control, waut, from, to, synchron) {}
330
331
333
334
335bool
337 return true;
338}
339
340
341
342/* -------------------------------------------------------------------------
343 * method definitions for WAUTSwitchProcedure_GSP
344 * ----------------------------------------------------------------------- */
346 MSTLLogicControl& control, WAUT& waut,
347 MSTrafficLightLogic* from, MSTrafficLightLogic* to, bool synchron)
348 : MSTLLogicControl::WAUTSwitchProcedure(control, waut, from, to, synchron) {}
349
350
352
353
354void
356 const SUMOTime gspTo = getGSPTime(*myTo) % myTo->getDefaultCycleTime();
357 const SUMOTime currentPosTo = myTo->getOffsetFromIndex(myTo->getCurrentPhaseIndex()) + myTo->getSpentDuration(step);
358 SUMOTime deltaToStretch = gspTo - currentPosTo;
359 if (deltaToStretch < 0) {
360 deltaToStretch += myTo->getDefaultCycleTime();
361 }
362 const int stepTo = myTo->getIndexFromOffset(gspTo);
363 const SUMOTime newdur = myTo->getPhase(stepTo).duration - getDiffToStartOfPhase(*myTo, gspTo) + deltaToStretch;
364 myTo->changeStepAndDuration(myControl, step, stepTo, newdur);
365}
366
367
368
369/* -------------------------------------------------------------------------
370 * method definitions for WAUTSwitchProcedure_Stretch
371 * ----------------------------------------------------------------------- */
373 MSTLLogicControl& control, WAUT& waut,
374 MSTrafficLightLogic* from, MSTrafficLightLogic* to, bool synchron)
375 : MSTLLogicControl::WAUTSwitchProcedure(control, waut, from, to, synchron) {
376 int idx = 1;
377 while (myTo->knowsParameter("B" + toString(idx) + ".begin")) {
378 StretchRange def;
379 def.begin = string2time(myTo->getParameter("B" + toString(idx) + ".begin"));
380 def.end = string2time(myTo->getParameter("B" + toString(idx) + ".end"));
381 def.fac = StringUtils::toDouble(myTo->getParameter("B" + toString(idx) + ".factor"));
382 myStretchRanges.emplace_back(def);
383 }
384
385}
386
387
389
390
391void
393 SUMOTime gspTo = getGSPTime(*myTo);
394 SUMOTime cycleTime = myTo->getDefaultCycleTime();
395 // the position, where the logic has to be after synchronisation
396 SUMOTime posAfterSyn = myTo->getPhaseIndexAtTime(step);
397 // calculate the difference, that has to be equalized
398 SUMOTime deltaToCut = 0;
399 if (posAfterSyn < gspTo) {
400 deltaToCut = posAfterSyn + cycleTime - gspTo;
401 } else {
402 deltaToCut = posAfterSyn - gspTo;
403 }
404 // test, wheter cutting of the Signalplan is possible
405 SUMOTime deltaPossible = 0;
406 for (const StretchRange& def : myStretchRanges) {
407 assert(def.end >= def.begin);
408 deltaPossible += def.end - def.begin;
409 }
410 int stretchUmlaufAnz = (int) StringUtils::toDouble(myTo->getParameter("StretchUmlaufAnz", ""));
411 deltaPossible = stretchUmlaufAnz * deltaPossible;
412 if ((deltaPossible > deltaToCut) && (deltaToCut < (cycleTime / 2))) {
413 cutLogic(step, gspTo, deltaToCut);
414 } else {
415 SUMOTime deltaToStretch = (cycleTime - deltaToCut) % cycleTime;
416 stretchLogic(step, gspTo, deltaToStretch);
417 }
418}
419
420
421void
423 int actStep = myTo->getIndexFromOffset(startPos);
424 // switches to startPos and cuts this phase, if there is a "Bereich"
425 SUMOTime toCut = 0;
426 for (const StretchRange& def : myStretchRanges) {
427 int stepOfBegin = myTo->getIndexFromOffset(def.begin);
428 if (stepOfBegin == actStep) {
429 if (def.begin < startPos) {
430 toCut = def.end - startPos;
431 } else {
432 toCut = def.end - def.begin;
433 }
434 toCut = MIN2(allCutTime, toCut);
435 allCutTime = allCutTime - toCut;
436 }
437 }
438 SUMOTime remainingDur = myTo->getPhase(actStep).duration - getDiffToStartOfPhase(*myTo, startPos);
439 SUMOTime newDur = remainingDur - toCut;
440 myTo->changeStepAndDuration(myControl, step, actStep, newDur);
441
442 // changes the duration of all other phases
443 int currStep = (actStep + 1) % (int)myTo->getPhases().size();
444 while (allCutTime > 0) {
445 for (int i = currStep; i < (int) myTo->getPhases().size(); i++) {
446 SUMOTime beginOfPhase = myTo->getOffsetFromIndex(i);
447 SUMOTime durOfPhase = myTo->getPhase(i).duration;
448 SUMOTime endOfPhase = beginOfPhase + durOfPhase;
449 for (const StretchRange& def : myStretchRanges) {
450 if ((beginOfPhase <= def.begin) && (endOfPhase >= def.end)) {
451 SUMOTime maxCutOfPhase = MIN2(def.end - def.begin, allCutTime);
452 allCutTime = allCutTime - maxCutOfPhase;
453 durOfPhase = durOfPhase - maxCutOfPhase;
454 }
455 }
456 myTo->addOverridingDuration(durOfPhase);
457 }
458 currStep = 0;
459 }
460}
461
462void
464 int currStep = myTo->getIndexFromOffset(startPos);
465 SUMOTime durOfPhase = myTo->getPhase(currStep).duration;
466 SUMOTime remainingStretchTime = allStretchTime;
467 SUMOTime StretchTimeOfPhase = 0;
468 int stretchUmlaufAnz = (int) StringUtils::toDouble(myTo->getParameter("StretchUmlaufAnz", ""));
469 double facSum = 0;
470 for (const StretchRange& def : myStretchRanges) {
471 facSum += def.fac;
472 }
473 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 SUMOTime diffToStart = getDiffToStartOfPhase(*myTo, startPos);
477 for (const StretchRange& def : myStretchRanges) {
478 SUMOTime endOfPhase = (startPos + durOfPhase - diffToStart);
479 if (def.end <= endOfPhase && def.end >= startPos) {
480 double actualfac = def.fac / facSum;
481 facSum = facSum - def.fac;
482 StretchTimeOfPhase = TIME2STEPS(int(STEPS2TIME(remainingStretchTime) * actualfac + 0.5));
483 remainingStretchTime = allStretchTime - StretchTimeOfPhase;
484 }
485 }
486 if (facSum == 0) {
487 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 return;
489 }
490 durOfPhase = durOfPhase - diffToStart + StretchTimeOfPhase;
491 myTo->changeStepAndDuration(myControl, step, currStep, durOfPhase);
492
493 currStep = (currStep + 1) % (int)myTo->getPhases().size();
494 // stretch all other phases, if there is a "bereich"
495 while (remainingStretchTime > 0) {
496 for (int i = currStep; i < (int)myTo->getPhases().size() && remainingStretchTime > 0; i++) {
497 durOfPhase = myTo->getPhase(i).duration;
498 SUMOTime beginOfPhase = myTo->getOffsetFromIndex(i);
499 SUMOTime endOfPhase = beginOfPhase + durOfPhase;
500 for (const StretchRange& def : myStretchRanges) {
501 if ((beginOfPhase <= def.end) && (endOfPhase >= def.end)) {
502 double actualfac = def.fac / facSum;
503 StretchTimeOfPhase = TIME2STEPS(int(STEPS2TIME(remainingStretchTime) * actualfac + 0.5));
504 facSum -= def.fac;
505 durOfPhase += StretchTimeOfPhase;
506 remainingStretchTime -= StretchTimeOfPhase;
507 }
508 }
509 myTo->addOverridingDuration(durOfPhase);
510 }
511 currStep = 0;
512 }
513}
514
515
516/* -------------------------------------------------------------------------
517 * method definitions for MSTLLogicControl
518 * ----------------------------------------------------------------------- */
520 : myNetWasLoaded(false) {}
521
522
524 // delete tls
525 for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
526 delete (*i).second;
527 }
528 // delete WAUTs
529 for (std::map<std::string, WAUT*>::const_iterator i = myWAUTs.begin(); i != myWAUTs.end(); ++i) {
530 delete (*i).second;
531 }
532}
533
534
535void
537 for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
538 (*i).second->getActive()->setTrafficLightSignals(t);
539 }
540}
541
542
543std::vector<MSTrafficLightLogic*>
545 std::vector<MSTrafficLightLogic*> ret;
546 std::map<std::string, TLSLogicVariants*>::const_iterator i;
547 for (i = myLogics.begin(); i != myLogics.end(); ++i) {
548 std::vector<MSTrafficLightLogic*> s = (*i).second->getAllLogics();
549 copy(s.begin(), s.end(), back_inserter(ret));
550 }
551 return ret;
552}
553
555MSTLLogicControl::get(const std::string& id) const {
556 std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
557 if (i == myLogics.end()) {
558 throw InvalidArgument("The tls '" + id + "' is not known.");
559 }
560 return *(*i).second;
561}
562
563
565MSTLLogicControl::get(const std::string& id, const std::string& programID) const {
566 std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
567 if (i == myLogics.end()) {
568 return nullptr;
569 }
570 return (*i).second->getLogic(programID);
571}
572
573
574std::vector<std::string>
576 std::vector<std::string> ret;
577 for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
578 ret.push_back((*i).first);
579 }
580 return ret;
581}
582
583
584bool
585MSTLLogicControl::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 if (it == myLogics.end()) {
590 tlmap = myLogics[id] = new TLSLogicVariants();
591 } else {
592 tlmap = it->second;
593 }
594 return tlmap->addLogic(programID, logic, myNetWasLoaded, newDefault);
595}
596
597
598bool
599MSTLLogicControl::knows(const std::string& id) const {
600 return myLogics.count(id) != 0;
601}
602
603
604bool
606 bool hadErrors = false;
607 for (const auto& it : myLogics) {
608 hadErrors |= !it.second->checkOriginalTLS();
609 it.second->saveInitialStates();
610 }
611 myNetWasLoaded = true;
612 return !hadErrors;
613}
614
615
616bool
618 std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(tl->getID());
619 if (i == myLogics.end()) {
620 return false;
621 }
622 return (*i).second->isActive(tl);
623}
624
625
627MSTLLogicControl::getActive(const std::string& id) const {
628 std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
629 if (i == myLogics.end()) {
630 return nullptr;
631 }
632 return (*i).second->getActive();
633}
634
635
636void
637MSTLLogicControl::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 if (i == myLogics.end()) {
642 throw ProcessError("Could not switch tls '" + id + "' to program '" + programID + "': No such tls exists.");
643 }
644 (*i).second->switchTo(*this, programID);
645}
646
647
648void
649MSTLLogicControl::addWAUT(SUMOTime refTime, const std::string& id,
650 const std::string& startProg, SUMOTime period) {
651 // check whether the waut was already defined
652 if (myWAUTs.find(id) != myWAUTs.end()) {
653 // report an error if so
654 throw InvalidArgument("Waut '" + id + "' was already defined.");
655 }
656 WAUT* w = new WAUT;
657 w->id = id;
658 w->refTime = refTime;
659 w->startProg = startProg;
660 w->period = period;
661 myWAUTs[id] = w;
662}
663
664
665void
666MSTLLogicControl::addWAUTSwitch(const std::string& wautid,
667 SUMOTime when, const std::string& to) {
668 // try to get the waut
669 if (myWAUTs.find(wautid) == myWAUTs.end()) {
670 // report an error if the waut is not known
671 throw InvalidArgument("Waut '" + wautid + "' was not yet defined.");
672 }
673 // build and save the waut switch definition
674 WAUT* waut = myWAUTs[wautid];
675 WAUTSwitch s;
676 s.to = to;
677 s.when = (waut->refTime + when);
678 if (waut->period > 0) {
679 s.when = s.when % waut->period;
680 }
681 myWAUTs[wautid]->switches.push_back(s);
682}
683
684
685void
686MSTLLogicControl::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 if (myWAUTs.find(wautid) == myWAUTs.end()) {
692 // report an error if the waut is not known
693 throw InvalidArgument("Waut '" + wautid + "' was not yet defined.");
694 }
695 // try to get the tls to switch
696 if (myLogics.find(tls) == myLogics.end()) {
697 // report an error if the tls is not known
698 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 j.synchron = synchron;
704 myWAUTs[wautid]->junctions.push_back(j);
705
706 std::string initProg = myWAUTs[wautid]->startProg;
707 std::vector<WAUTSwitch>::const_iterator first = myWAUTs[wautid]->switches.end();
708 SUMOTime minExecTime = -1;
709 for (std::vector<WAUTSwitch>::const_iterator i = myWAUTs[wautid]->switches.begin(); i != myWAUTs[wautid]->switches.end(); ++i) {
710 if ((*i).when > MSNet::getInstance()->getCurrentTimeStep() && (minExecTime == -1 || (*i).when < minExecTime)) {
711 minExecTime = (*i).when;
712 first = i;
713 }
714 if (first != myWAUTs[wautid]->switches.begin()) {
715 initProg = (*(first - 1)).to;
716 }
717 }
718 // activate the first one
719 switchTo(tls, initProg);
720}
721
722
723void
724MSTLLogicControl::closeWAUT(const std::string& wautid) {
725 // try to get the waut
726 if (myWAUTs.find(wautid) == myWAUTs.end()) {
727 // report an error if the waut is not known
728 throw InvalidArgument("Waut '" + wautid + "' was not yet defined.");
729 }
730 WAUT* w = myWAUTs.find(wautid)->second;
731 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 for (std::vector<WAUTSwitch>::const_iterator i = w->switches.begin(); i != w->switches.end(); ++i) {
736 if ((*i).when > MSNet::getInstance()->getCurrentTimeStep() && (minExecTime == -1 || (*i).when < minExecTime)) {
737 minExecTime = (*i).when;
738 first = i;
739 }
740 }
741 // activate the first one
742 if (first != w->switches.end()) {
743 std::vector<WAUTSwitch>::const_iterator mbegin = w->switches.begin();
745 new SwitchInitCommand(*this, wautid, (int)distance(mbegin, first)),
746 (*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}
755
756
759 const std::string& wautid = cmd.getWAUTID();
760 int& index = cmd.getIndex();
761 WAUT* waut = myWAUTs[wautid];
762 WAUTSwitch s = waut->switches[index];
763 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 TLSLogicVariants* vars = myLogics.find((*i).junction)->second;
766 MSTrafficLightLogic* from = vars->getActive();
767 MSTrafficLightLogic* to = vars->getLogicInstantiatingOff(*this, s.to);
768 WAUTSwitchProcedure* proc = nullptr;
769 if ((*i).procedure == "GSP") {
770 proc = new WAUTSwitchProcedure_GSP(*this, *myWAUTs[wautid], from, to, (*i).synchron);
771 } else if ((*i).procedure == "Stretch") {
772 proc = new WAUTSwitchProcedure_Stretch(*this, *myWAUTs[wautid], from, to, (*i).synchron);
773 } else {
774 proc = new WAUTSwitchProcedure_JustSwitch(*this, *myWAUTs[wautid], from, to, (*i).synchron);
775 }
776
778 p.junction = (*i).junction;
779 p.proc = proc;
780 p.from = from;
781 p.to = to;
782
783 myCurrentlySwitched.push_back(p);
784 }
785 index++;
786 if (index == (int)waut->switches.size()) {
787 if (waut->period <= 0) {
788 return 0;
789 } else {
790 index = 0; // start over
791 for (WAUTSwitch& ws : waut->switches) {
792 ws.when += waut->period;
793 }
794 }
795 }
796 return myWAUTs[wautid]->switches[index].when - MSNet::getInstance()->getCurrentTimeStep();
797}
798
799
800void
802 for (std::vector<WAUTSwitchProcess>::iterator i = myCurrentlySwitched.begin(); i != myCurrentlySwitched.end();) {
803 const WAUTSwitchProcess& proc = *i;
804 if (proc.proc->trySwitch(step)) {
805 delete proc.proc;
806 // do not switch away from TraCI control
807 if (getActive(proc.to->getID())->getProgramID() != TRACI_PROGRAM) {
808 switchTo(proc.to->getID(), proc.to->getProgramID());
809 }
810 i = myCurrentlySwitched.erase(i);
811 } else {
812 ++i;
813 }
814 }
815}
816
817
818std::pair<SUMOTime, MSPhaseDefinition>
819MSTLLogicControl::getPhaseDef(const std::string& tlid) const {
820 MSTrafficLightLogic* tl = getActive(tlid);
821 return std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), tl->getCurrentPhaseDef());
822}
823
824
825void
827 for (const auto& logic : myLogics) {
828 logic.second->addLogic("off", new MSOffTrafficLightLogic(*this, logic.first), true, true);
829 }
830}
831
832
833void
835 MSRailSignalConstraint::saveState(out); // always saves vehicle tracker states
836 for (const auto& logic : myLogics) {
837 logic.second->saveState(out);
838 }
839}
840
841
842void
843MSTLLogicControl::clearState(SUMOTime time, bool quickReload) {
845 if (quickReload) {
846 for (const auto& variants : myLogics) {
847 for (auto& logic : variants.second->getAllLogics()) {
848 if (logic->getLogicType() == TrafficLightType::OFF
849 || logic->getLogicType() == TrafficLightType::RAIL_SIGNAL
850 || logic->getLogicType() == TrafficLightType::RAIL_CROSSING) {
851 continue;
852 }
853 int step = 0;
854 const SUMOTime cycleTime = logic->getDefaultCycleTime();
855 auto& phases = logic->getPhases();
856 SUMOTime offset = logic->getOffset();
857 if (offset >= 0) {
858 offset = (time + cycleTime - (offset % cycleTime)) % cycleTime;
859 } else {
860 offset = (time + ((-offset) % cycleTime)) % cycleTime;
861 }
862
863 while (offset >= phases[step]->duration) {
864 offset -= phases[step]->duration;
865 step++;
866 }
867 logic->loadState(*this, time, step, offset);
868 }
869 }
870 }
871}
872
873
874/****************************************************************************/
long long int SUMOTime
Definition: GUI.h:36
#define TRACI_PROGRAM
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:268
#define WRITE_ERRORF(...)
Definition: MsgHandler.h:277
#define TL(string)
Definition: MsgHandler.h:284
#define TLF(string,...)
Definition: MsgHandler.h:285
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition: SUMOTime.cpp:45
#define STEPS2TIME(x)
Definition: SUMOTime.h:54
#define TIME2STEPS(x)
Definition: SUMOTime.h:56
T MIN2(T a, T b)
Definition: StdDefs.h:76
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:183
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition: MSNet.h:471
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
virtual void createTLWrapper(MSTrafficLightLogic *)
creates a wrapper for the given logic (see GUINet)
Definition: MSNet.h:577
A traffic lights logic which represents a tls in an off-mode.
The definition of a single phase of a tls logic.
const std::string & getState() const
Returns the state within this phase.
SUMOTime duration
The duration of the phase.
static void saveState(OutputDevice &out)
Saves the current constraint states into the given stream.
static void clearState()
Clear all constraint states before quick-loading state.
A fixed traffic light logic.
Base class for things to execute if a tls switches to a new phase.
This event-class is used to initialise a WAUT switch at a certain time.
const std::string & getWAUTID() const
Returns the WAUT-id.
int & getIndex()
Returns a reference to the index.
Storage for all programs of a single tls.
void addLink(MSLink *link, MSLane *lane, int pos)
void switchTo(MSTLLogicControl &tlc, const std::string &programID)
void addSwitchCommand(OnSwitchAction *c)
void setStateInstantiatingOnline(MSTLLogicControl &tlc, const std::string &state)
bool checkOriginalTLS() const
Verifies traffic lights loaded from the network.
std::vector< MSTrafficLightLogic * > getAllLogics() const
MSTrafficLightLogic * getLogic(const std::string &programID) const
bool addLogic(const std::string &programID, MSTrafficLightLogic *logic, bool netWasLoaded, bool isNewDefault=true)
Adds a logic (program). In case of an error the logic gets deleted.
MSTrafficLightLogic * getActive() const
MSTrafficLightLogic * getDefault() const
return the default program (that last used program except TRACI_PROGRAM)
MSTrafficLightLogic * getLogicInstantiatingOff(MSTLLogicControl &tlc, const std::string &programID)
bool isActive(const MSTrafficLightLogic *tl) const
This class switches using the GSP algorithm.
WAUTSwitchProcedure_GSP(MSTLLogicControl &control, WAUT &waut, MSTrafficLightLogic *from, MSTrafficLightLogic *to, bool synchron)
Constructor.
void adaptLogic(SUMOTime step)
Stretches the destination program's phase to which the tls was switched.
This class simply switches to the next program.
bool trySwitch(SUMOTime step)
Determines whether a switch is possible.
WAUTSwitchProcedure_JustSwitch(MSTLLogicControl &control, WAUT &waut, MSTrafficLightLogic *from, MSTrafficLightLogic *to, bool synchron)
Constructor.
This class switches using the Stretch algorithm.
void adaptLogic(SUMOTime step)
Determines the destination program's changes and applies them.
std::vector< StretchRange > myStretchRanges
the given Stretch-areas for the "to" program, this is 0-based indexed, while the input is 1-based
WAUTSwitchProcedure_Stretch(MSTLLogicControl &control, WAUT &waut, MSTrafficLightLogic *from, MSTrafficLightLogic *to, bool synchron)
Constructor.
void cutLogic(SUMOTime step, SUMOTime startPos, SUMOTime allCutTime)
Cuts the logic to synchronize.
void stretchLogic(SUMOTime step, SUMOTime startPos, SUMOTime allStretchTime)
Stretches the logic to synchronize.
This is the abstract base class for switching from one tls program to another.
virtual bool trySwitch(SUMOTime step)
Determines whether a switch is possible.
MSTrafficLightLogic * myTo
The program to switch the tls to.
bool isPosAtGSP(SUMOTime currentTime, const MSTrafficLightLogic &logic)
Checks, whether the position of a signal programm is at the GSP ("Good Switching Point")
SUMOTime getGSPTime(const MSTrafficLightLogic &logic) const
Returns the GSP-value.
SUMOTime getDiffToStartOfPhase(MSTrafficLightLogic &logic, SUMOTime toTime)
Returns the difference between a given time and the start of the phase.
void switchToPos(SUMOTime simStep, MSTrafficLightLogic &logic, SUMOTime toTime)
switches the given logic directly to the given position
A class that stores and controls tls and switching of their programs.
void addWAUTJunction(const std::string &wautid, const std::string &tls, const std::string &proc, bool synchron)
Adds a tls to the list of tls to be switched by the named WAUT.
void clearState(SUMOTime time, bool quickReload=false)
Clear all tls states before quick-loading state.
std::vector< MSTrafficLightLogic * > getAllLogics() const
Returns a vector which contains all logics.
std::vector< WAUTSwitchProcess > myCurrentlySwitched
A list of currently running switching procedures.
std::pair< SUMOTime, MSPhaseDefinition > getPhaseDef(const std::string &tlid) const
return the complete phase definition for a named traffic lights logic
std::map< std::string, TLSLogicVariants * > myLogics
A map from ids to the corresponding variants.
void addWAUT(SUMOTime refTime, const std::string &id, const std::string &startProg, SUMOTime period)
Adds a WAUT definition.
std::vector< std::string > getAllTLIds() const
void switchTo(const std::string &id, const std::string &programID)
Switches the named (id) tls to the named (programID) program.
MSTrafficLightLogic * getActive(const std::string &id) const
Returns the active program of a named tls.
bool closeNetworkReading()
Lets MSTLLogicControl know that the network has been loaded.
void setTrafficLightSignals(SUMOTime t) const
Lets all running (current) tls programs apply their current signal states to links they control.
bool knows(const std::string &id) const
Returns the information whether the named tls is stored.
void saveState(OutputDevice &out)
Saves the current tls states into the given stream.
bool myNetWasLoaded
Information whether the net was completely loaded.
void switchOffAll()
switch all logic variants to 'off'
void addWAUTSwitch(const std::string &wautid, SUMOTime when, const std::string &to)
Adds a WAUT switch step to a previously built WAUT.
TLSLogicVariants & get(const std::string &id) const
Returns the variants of a named tls.
MSTLLogicControl()
Constructor.
SUMOTime initWautSwitch(SwitchInitCommand &cmd)
Initialises switching a WAUT.
~MSTLLogicControl()
Destructor.
void check2Switch(SUMOTime step)
Checks whether any WAUT is trying to switch a tls into another program.
std::map< std::string, WAUT * > myWAUTs
A map of ids to corresponding WAUTs.
bool isActive(const MSTrafficLightLogic *tl) const
Returns whether the given tls program is the currently active for his tls.
bool add(const std::string &id, const std::string &programID, MSTrafficLightLogic *logic, bool newDefault=true)
Adds a tls program to the container.
void closeWAUT(const std::string &wautid)
Closes loading of a WAUT.
The parent class for traffic light logics.
const LinkVectorVector & getLinks() const
Returns the list of lists of all affected links.
virtual void adaptLinkInformationFrom(const MSTrafficLightLogic &logic)
Applies information about controlled links and lanes from the given logic.
virtual const MSPhaseDefinition & getCurrentPhaseDef() const =0
Returns the definition of the current phase.
virtual int getCurrentPhaseIndex() const =0
Returns the current index within the program.
virtual SUMOTime getOffsetFromIndex(int index) const =0
Returns the position (start of a phase during a cycle) from of a given step.
virtual void changeStepAndDuration(MSTLLogicControl &tlcontrol, SUMOTime simStep, int step, SUMOTime stepDuration)=0
Changes the current phase and her duration.
virtual const MSPhaseDefinition & getPhase(int givenstep) const =0
Returns the definition of the phase from the given position within the plan.
const std::string & getProgramID() const
Returns this tl-logic's id.
virtual int getIndexFromOffset(SUMOTime offset) const =0
Returns the step (the phasenumber) of a given position of the cycle.
SUMOTime getDefaultCycleTime() const
Returns the cycle time (in ms)
virtual void activateProgram()
called when switching programs
SUMOTime getSpentDuration(SUMOTime simStep=-1) const
Returns the duration spent in the current phase.
bool setTrafficLightSignals(SUMOTime t) const
Applies the current signal states to controlled links.
std::vector< MSPhaseDefinition * > Phases
Definition of a list of phases, being the junction logic.
const std::string & getID() const
Returns the id.
Definition: Named.h:74
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
std::map< std::string, std::string > Map
parameters map
Definition: Parameterised.h:45
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
bool knowsParameter(const std::string &key) const
Returns whether the parameter is known.
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
A WAUT definition.
std::string startProg
The name of the start program.
std::vector< WAUTSwitch > switches
The list of switches to be done by the WAUT.
SUMOTime period
The period with which to repeat switches.
std::string id
The id of the WAUT.
SUMOTime refTime
The reference time (offset to the switch times)
Storage for a junction assigned to a WAUT.
std::string procedure
The procedure to switch the junction with.
bool synchron
Information whether this junction shall be switched synchron.
std::string junction
The junction name.
Storage for a WAUTs switch point.
SUMOTime when
The time the WAUT shall switch the TLS.
std::string to
The program name the WAUT shall switch the TLS to.
double fac
The weight factor of a stretch/cut area.
An initialised switch process.
MSTrafficLightLogic * to
The program to switch the tls to.
std::string junction
The id of the junction to switch.
MSTrafficLightLogic * from
The current program of the tls.
WAUTSwitchProcedure * proc
The used procedure.