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