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 // setting tl as active and updating signal states happens on the calling side (MSTrafficLightLogic::loadState)
251 if (myCurrentProgram != tl) {
252 myCurrentProgram->deactivateProgram();
253 myCurrentProgram = tl;
254 }
255}
256
257
258void
260 for (std::vector<OnSwitchAction*>::const_iterator i = mySwitchActions.begin(); i != mySwitchActions.end(); ++i) {
261 (*i)->execute();
262 }
263}
264
265
266void
268 for (std::map<std::string, MSTrafficLightLogic*>::iterator i = myVariants.begin(); i != myVariants.end(); ++i) {
269 (*i).second->addLink(link, lane, pos);
270 }
271}
272
273void
275 for (std::map<std::string, MSTrafficLightLogic*>::iterator i = myVariants.begin(); i != myVariants.end(); ++i) {
276 (*i).second->ignoreLinkIndex(pos);
277 }
278}
279
280
281/* -------------------------------------------------------------------------
282 * method definitions for the Switching Procedures
283 * ----------------------------------------------------------------------- */
284/* -------------------------------------------------------------------------
285 * method definitions for WAUTSwitchProcedure
286 * ----------------------------------------------------------------------- */
287bool
289 // switch to the next programm if the GSP is reached
290 if (isPosAtGSP(step, *myFrom)) {
291 // adapt program's state
292 if (mySwitchSynchron) {
293 adaptLogic(step);
294 } else {
295 switchToPos(step, *myTo, getGSPTime(*myTo));
296 }
297 // switch to destination program
298 return true;
299 }
300 // do not switch, yet
301 return false;
302}
303
304
309
310
311bool
313 const SUMOTime gspTime = getGSPTime(logic) % logic.getDefaultCycleTime();
314 const SUMOTime programTime = logic.getOffsetFromIndex(logic.getCurrentPhaseIndex()) + logic.getSpentDuration(currentTime);
315 return gspTime == programTime;
316}
317
318
321 int stepOfMyPos = logic.getIndexFromOffset(toTime);
322 SUMOTime startOfPhase = logic.getOffsetFromIndex(stepOfMyPos);
323 assert(toTime >= startOfPhase);
324 return toTime - startOfPhase;
325}
326
327
328void
330 int stepTo = logic.getIndexFromOffset(toTime);
331 SUMOTime diff = getDiffToStartOfPhase(logic, toTime);
332 const MSPhaseDefinition& phase = logic.getPhase(stepTo);
333 SUMOTime leftDuration = phase.duration - diff;
334 logic.changeStepAndDuration(myControl, simStep, stepTo, leftDuration);
335}
336
337
338
339/* -------------------------------------------------------------------------
340 * method definitions for WAUTSwitchProcedure_JustSwitch
341 * ----------------------------------------------------------------------- */
346
347
349
350
351bool
355
356
357
358/* -------------------------------------------------------------------------
359 * method definitions for WAUTSwitchProcedure_GSP
360 * ----------------------------------------------------------------------- */
365
366
368
369
370void
372 const SUMOTime gspTo = getGSPTime(*myTo) % myTo->getDefaultCycleTime();
373 const SUMOTime currentPosTo = myTo->getOffsetFromIndex(myTo->getCurrentPhaseIndex()) + myTo->getSpentDuration(step);
374 SUMOTime deltaToStretch = gspTo - currentPosTo;
375 if (deltaToStretch < 0) {
376 deltaToStretch += myTo->getDefaultCycleTime();
377 }
378 const int stepTo = myTo->getIndexFromOffset(gspTo);
379 const SUMOTime newdur = myTo->getPhase(stepTo).duration - getDiffToStartOfPhase(*myTo, gspTo) + deltaToStretch;
380 myTo->changeStepAndDuration(myControl, step, stepTo, newdur);
381}
382
383
384
385/* -------------------------------------------------------------------------
386 * method definitions for WAUTSwitchProcedure_Stretch
387 * ----------------------------------------------------------------------- */
389 MSTLLogicControl& control, WAUT& waut,
390 MSTrafficLightLogic* from, MSTrafficLightLogic* to, bool synchron)
391 : MSTLLogicControl::WAUTSwitchProcedure(control, waut, from, to, synchron) {
392 int idx = 1;
393 while (myTo->hasParameter("B" + toString(idx) + ".begin")) {
394 StretchRange def;
395 def.begin = string2time(myTo->getParameter("B" + toString(idx) + ".begin"));
396 def.end = string2time(myTo->getParameter("B" + toString(idx) + ".end"));
397 def.fac = StringUtils::toDouble(myTo->getParameter("B" + toString(idx) + ".factor"));
398 myStretchRanges.emplace_back(def);
399 }
400
401}
402
403
405
406
407void
409 SUMOTime gspTo = getGSPTime(*myTo);
410 SUMOTime cycleTime = myTo->getDefaultCycleTime();
411 // the position, where the logic has to be after synchronisation
412 SUMOTime posAfterSyn = myTo->getPhaseIndexAtTime(step);
413 // calculate the difference, that has to be equalized
414 SUMOTime deltaToCut = 0;
415 if (posAfterSyn < gspTo) {
416 deltaToCut = posAfterSyn + cycleTime - gspTo;
417 } else {
418 deltaToCut = posAfterSyn - gspTo;
419 }
420 // test, wheter cutting of the Signalplan is possible
421 SUMOTime deltaPossible = 0;
422 for (const StretchRange& def : myStretchRanges) {
423 assert(def.end >= def.begin);
424 deltaPossible += def.end - def.begin;
425 }
426 int stretchUmlaufAnz = (int) StringUtils::toDouble(myTo->getParameter("StretchUmlaufAnz", ""));
427 deltaPossible = stretchUmlaufAnz * deltaPossible;
428 if ((deltaPossible > deltaToCut) && (deltaToCut < (cycleTime / 2))) {
429 cutLogic(step, gspTo, deltaToCut);
430 } else {
431 SUMOTime deltaToStretch = (cycleTime - deltaToCut) % cycleTime;
432 stretchLogic(step, gspTo, deltaToStretch);
433 }
434}
435
436
437void
439 int actStep = myTo->getIndexFromOffset(startPos);
440 // switches to startPos and cuts this phase, if there is a "Bereich"
441 SUMOTime toCut = 0;
442 for (const StretchRange& def : myStretchRanges) {
443 int stepOfBegin = myTo->getIndexFromOffset(def.begin);
444 if (stepOfBegin == actStep) {
445 if (def.begin < startPos) {
446 toCut = def.end - startPos;
447 } else {
448 toCut = def.end - def.begin;
449 }
450 toCut = MIN2(allCutTime, toCut);
451 allCutTime = allCutTime - toCut;
452 }
453 }
454 SUMOTime remainingDur = myTo->getPhase(actStep).duration - getDiffToStartOfPhase(*myTo, startPos);
455 SUMOTime newDur = remainingDur - toCut;
456 myTo->changeStepAndDuration(myControl, step, actStep, newDur);
457
458 // changes the duration of all other phases
459 int currStep = (actStep + 1) % (int)myTo->getPhases().size();
460 while (allCutTime > 0) {
461 for (int i = currStep; i < (int) myTo->getPhases().size(); i++) {
462 SUMOTime beginOfPhase = myTo->getOffsetFromIndex(i);
463 SUMOTime durOfPhase = myTo->getPhase(i).duration;
464 SUMOTime endOfPhase = beginOfPhase + durOfPhase;
465 for (const StretchRange& def : myStretchRanges) {
466 if ((beginOfPhase <= def.begin) && (endOfPhase >= def.end)) {
467 SUMOTime maxCutOfPhase = MIN2(def.end - def.begin, allCutTime);
468 allCutTime = allCutTime - maxCutOfPhase;
469 durOfPhase = durOfPhase - maxCutOfPhase;
470 }
471 }
472 myTo->addOverridingDuration(durOfPhase);
473 }
474 currStep = 0;
475 }
476}
477
478void
480 int currStep = myTo->getIndexFromOffset(startPos);
481 SUMOTime durOfPhase = myTo->getPhase(currStep).duration;
482 SUMOTime remainingStretchTime = allStretchTime;
483 SUMOTime StretchTimeOfPhase = 0;
484 int stretchUmlaufAnz = (int) StringUtils::toDouble(myTo->getParameter("StretchUmlaufAnz", ""));
485 double facSum = 0;
486 for (const StretchRange& def : myStretchRanges) {
487 facSum += def.fac;
488 }
489 facSum *= stretchUmlaufAnz;
490
491 //switch to startPos and stretch this phase, if there is a end of "bereich" between startpos and end of phase
492 SUMOTime diffToStart = getDiffToStartOfPhase(*myTo, startPos);
493 for (const StretchRange& def : myStretchRanges) {
494 SUMOTime endOfPhase = (startPos + durOfPhase - diffToStart);
495 if (def.end <= endOfPhase && def.end >= startPos) {
496 double actualfac = def.fac / facSum;
497 facSum = facSum - def.fac;
498 StretchTimeOfPhase = TIME2STEPS(int(STEPS2TIME(remainingStretchTime) * actualfac + 0.5));
499 remainingStretchTime = allStretchTime - StretchTimeOfPhase;
500 }
501 }
502 if (facSum == 0) {
503 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)));
504 return;
505 }
506 durOfPhase = durOfPhase - diffToStart + StretchTimeOfPhase;
507 myTo->changeStepAndDuration(myControl, step, currStep, durOfPhase);
508
509 currStep = (currStep + 1) % (int)myTo->getPhases().size();
510 // stretch all other phases, if there is a "bereich"
511 while (remainingStretchTime > 0) {
512 for (int i = currStep; i < (int)myTo->getPhases().size() && remainingStretchTime > 0; i++) {
513 durOfPhase = myTo->getPhase(i).duration;
514 SUMOTime beginOfPhase = myTo->getOffsetFromIndex(i);
515 SUMOTime endOfPhase = beginOfPhase + durOfPhase;
516 for (const StretchRange& def : myStretchRanges) {
517 if ((beginOfPhase <= def.end) && (endOfPhase >= def.end)) {
518 double actualfac = def.fac / facSum;
519 StretchTimeOfPhase = TIME2STEPS(int(STEPS2TIME(remainingStretchTime) * actualfac + 0.5));
520 facSum -= def.fac;
521 durOfPhase += StretchTimeOfPhase;
522 remainingStretchTime -= StretchTimeOfPhase;
523 }
524 }
525 myTo->addOverridingDuration(durOfPhase);
526 }
527 currStep = 0;
528 }
529}
530
531
532/* -------------------------------------------------------------------------
533 * method definitions for MSTLLogicControl
534 * ----------------------------------------------------------------------- */
537
538
540 // delete tls
541 for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
542 delete (*i).second;
543 }
544 // delete WAUTs
545 for (std::map<std::string, WAUT*>::const_iterator i = myWAUTs.begin(); i != myWAUTs.end(); ++i) {
546 delete (*i).second;
547 }
548}
549
550
551void
553 for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
554 (*i).second->getActive()->setTrafficLightSignals(t);
555 }
556}
557
558
559std::vector<MSTrafficLightLogic*>
561 std::vector<MSTrafficLightLogic*> ret;
562 std::map<std::string, TLSLogicVariants*>::const_iterator i;
563 for (i = myLogics.begin(); i != myLogics.end(); ++i) {
564 std::vector<MSTrafficLightLogic*> s = (*i).second->getAllLogics();
565 copy(s.begin(), s.end(), back_inserter(ret));
566 }
567 return ret;
568}
569
571MSTLLogicControl::get(const std::string& id) const {
572 std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
573 if (i == myLogics.end()) {
574 throw InvalidArgument("The tls '" + id + "' is not known.");
575 }
576 return *(*i).second;
577}
578
579
581MSTLLogicControl::get(const std::string& id, const std::string& programID) const {
582 std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
583 if (i == myLogics.end()) {
584 return nullptr;
585 }
586 return (*i).second->getLogic(programID);
587}
588
589
590std::vector<std::string>
592 std::vector<std::string> ret;
593 for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
594 ret.push_back((*i).first);
595 }
596 return ret;
597}
598
599
600bool
601MSTLLogicControl::add(const std::string& id, const std::string& programID,
602 MSTrafficLightLogic* logic, bool newDefault) {
603 std::map<std::string, TLSLogicVariants*>::iterator it = myLogics.find(id);
604 TLSLogicVariants* tlmap;
605 if (it == myLogics.end()) {
606 tlmap = myLogics[id] = new TLSLogicVariants();
607 } else {
608 tlmap = it->second;
609 }
610 return tlmap->addLogic(programID, logic, myNetWasLoaded, newDefault);
611}
612
613
614bool
615MSTLLogicControl::knows(const std::string& id) const {
616 return myLogics.count(id) != 0;
617}
618
619
620bool
622 bool hadErrors = false;
623 for (const auto& it : myLogics) {
624 hadErrors |= !it.second->checkOriginalTLS();
625 it.second->saveInitialStates();
626 }
627 myNetWasLoaded = true;
628 return !hadErrors;
629}
630
631
632bool
634 std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(tl->getID());
635 if (i == myLogics.end()) {
636 return false;
637 }
638 return (*i).second->isActive(tl);
639}
640
641
643MSTLLogicControl::getActive(const std::string& id) const {
644 std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
645 if (i == myLogics.end()) {
646 return nullptr;
647 }
648 return (*i).second->getActive();
649}
650
651
652void
653MSTLLogicControl::switchTo(const std::string& id, const std::string& programID) {
654 // try to get the tls program definitions
655 std::map<std::string, TLSLogicVariants*>::iterator i = myLogics.find(id);
656 // handle problems
657 if (i == myLogics.end()) {
658 throw ProcessError(TLF("Could not switch tls '%' to program '%': No such tls exists.", id, programID));
659 }
660 (*i).second->switchTo(*this, programID);
661}
662
663
664void
665MSTLLogicControl::addWAUT(SUMOTime refTime, const std::string& id,
666 const std::string& startProg, SUMOTime period) {
667 // check whether the waut was already defined
668 if (myWAUTs.find(id) != myWAUTs.end()) {
669 // report an error if so
670 throw InvalidArgument(TLF("Waut '%' was already defined.", id));
671 }
672 WAUT* w = new WAUT;
673 w->id = id;
674 w->refTime = refTime;
675 w->startProg = startProg;
676 w->period = period;
677 myWAUTs[id] = w;
678}
679
680
681void
682MSTLLogicControl::addWAUTSwitch(const std::string& wautid,
683 SUMOTime when, const std::string& to) {
684 // try to get the waut
685 if (myWAUTs.find(wautid) == myWAUTs.end()) {
686 // report an error if the waut is not known
687 throw InvalidArgument(TLF("Waut '%' was not yet defined.", wautid));
688 }
689 // build and save the waut switch definition
690 WAUT* waut = myWAUTs[wautid];
691 WAUTSwitch s;
692 s.to = to;
693 s.when = (waut->refTime + when);
694 if (waut->period > 0) {
695 s.when = s.when % waut->period;
696 }
697 myWAUTs[wautid]->switches.push_back(s);
698}
699
700
701void
702MSTLLogicControl::addWAUTJunction(const std::string& wautid,
703 const std::string& tls,
704 const std::string& proc,
705 bool synchron) {
706 // try to get the waut
707 if (myWAUTs.find(wautid) == myWAUTs.end()) {
708 // report an error if the waut is not known
709 throw InvalidArgument(TLF("Waut '%' was not yet defined.", wautid));
710 }
711 // try to get the tls to switch
712 if (myLogics.find(tls) == myLogics.end()) {
713 // report an error if the tls is not known
714 throw InvalidArgument(TLF("TLS '%' to switch in WAUT '%' was not yet defined.", tls, wautid));
715 }
716 WAUTJunction j;
717 j.junction = tls;
718 j.procedure = proc;
719 j.synchron = synchron;
720 myWAUTs[wautid]->junctions.push_back(j);
721
722 std::string initProg = myWAUTs[wautid]->startProg;
723 std::vector<WAUTSwitch>::const_iterator first = myWAUTs[wautid]->switches.end();
724 SUMOTime minExecTime = -1;
725 for (std::vector<WAUTSwitch>::const_iterator i = myWAUTs[wautid]->switches.begin(); i != myWAUTs[wautid]->switches.end(); ++i) {
726 if ((*i).when > MSNet::getInstance()->getCurrentTimeStep() && (minExecTime == -1 || (*i).when < minExecTime)) {
727 minExecTime = (*i).when;
728 first = i;
729 }
730 if (first != myWAUTs[wautid]->switches.begin()) {
731 initProg = (*(first - 1)).to;
732 }
733 }
734 // activate the first one
735 switchTo(tls, initProg);
736}
737
738
739void
740MSTLLogicControl::closeWAUT(const std::string& wautid) {
741 // try to get the waut
742 if (myWAUTs.find(wautid) == myWAUTs.end()) {
743 // report an error if the waut is not known
744 throw InvalidArgument(TLF("Waut '%' was not yet defined.", wautid));
745 }
746 WAUT* w = myWAUTs.find(wautid)->second;
747 std::string initProg = myWAUTs[wautid]->startProg;
748 // get the switch to be performed as first
749 SUMOTime minExecTime = SUMOTime_MAX;
750 int firstIndex = -1;
751 int i = 0;
752 for (const WAUTSwitch& s : w->switches) {
753 if (s.when >= SIMSTEP && s.when < minExecTime) {
754 minExecTime = s.when;
755 firstIndex = i;
756 }
757 i++;
758 }
759 // activate the first one
760 if (firstIndex >= 0) {
762 new SwitchInitCommand(*this, wautid, firstIndex), MAX2(SIMSTEP, minExecTime));
763 }
764 /*
765 // set the current program to all junctions
766 for(std::vector<WAUTJunction>::const_iterator i=w->junctions.begin(); i!=w->junctions.end(); ++i) {
767 switchTo((*i).junction, initProg);
768 }
769 */
770}
771
772
775 const std::string& wautid = cmd.getWAUTID();
776 int& index = cmd.getIndex();
777 WAUT* waut = myWAUTs[wautid];
778 WAUTSwitch s = waut->switches[index];
779 for (std::vector<WAUTJunction>::iterator i = myWAUTs[wautid]->junctions.begin(); i != myWAUTs[wautid]->junctions.end(); ++i) {
780 // get the current program and the one to instantiate
781 TLSLogicVariants* vars = myLogics.find((*i).junction)->second;
782 MSTrafficLightLogic* from = vars->getActive();
783 MSTrafficLightLogic* to = vars->getLogicInstantiatingOff(*this, s.to);
784 WAUTSwitchProcedure* proc = nullptr;
785 if ((*i).procedure == "GSP") {
786 proc = new WAUTSwitchProcedure_GSP(*this, *myWAUTs[wautid], from, to, (*i).synchron);
787 } else if ((*i).procedure == "Stretch") {
788 proc = new WAUTSwitchProcedure_Stretch(*this, *myWAUTs[wautid], from, to, (*i).synchron);
789 } else {
790 proc = new WAUTSwitchProcedure_JustSwitch(*this, *myWAUTs[wautid], from, to, (*i).synchron);
791 }
792
794 p.junction = (*i).junction;
795 p.proc = proc;
796 p.from = from;
797 p.to = to;
798
799 myCurrentlySwitched.push_back(p);
800 }
801 index++;
802 if (index == (int)waut->switches.size()) {
803 if (waut->period <= 0) {
804 return 0;
805 } else {
806 index = 0; // start over
807 for (WAUTSwitch& ws : waut->switches) {
808 ws.when += waut->period;
809 }
810 }
811 }
812 return myWAUTs[wautid]->switches[index].when - MSNet::getInstance()->getCurrentTimeStep();
813}
814
815
816void
818 for (std::vector<WAUTSwitchProcess>::iterator i = myCurrentlySwitched.begin(); i != myCurrentlySwitched.end();) {
819 const WAUTSwitchProcess& proc = *i;
820 if (proc.proc->trySwitch(step)) {
821 delete proc.proc;
822 // do not switch away from TraCI control
823 if (getActive(proc.to->getID())->getProgramID() != TRACI_PROGRAM) {
824 switchTo(proc.to->getID(), proc.to->getProgramID());
825 }
826 i = myCurrentlySwitched.erase(i);
827 } else {
828 ++i;
829 }
830 }
831}
832
833
834std::pair<SUMOTime, MSPhaseDefinition>
835MSTLLogicControl::getPhaseDef(const std::string& tlid) const {
836 MSTrafficLightLogic* tl = getActive(tlid);
837 return std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), tl->getCurrentPhaseDef());
838}
839
840
841void
843 for (const auto& logic : myLogics) {
844 if (logic.second->getActive()->getLogicType() == TrafficLightType::RAIL_SIGNAL) {
845 // there is no sensible fall-back behavior when switching of rail
846 // signals so they should ignore tls.all-off
847 continue;
848 }
849 logic.second->addLogic("off", new MSOffTrafficLightLogic(*this, logic.first), true, true);
850 }
851}
852
853
854void
856 MSRailSignalConstraint::saveState(out); // always saves vehicle tracker states
857 for (const auto& logic : myLogics) {
858 logic.second->saveState(out);
859 }
861}
862
863
864void
865MSTLLogicControl::clearState(SUMOTime time, bool quickReload) {
867 if (quickReload) {
868 for (const auto& variants : myLogics) {
869 for (auto& logic : variants.second->getAllLogics()) {
870 if (logic->getLogicType() == TrafficLightType::OFF
871 || logic->getLogicType() == TrafficLightType::RAIL_SIGNAL
872 || logic->getLogicType() == TrafficLightType::RAIL_CROSSING) {
873 continue;
874 }
875 int step = 0;
876 const SUMOTime cycleTime = logic->getDefaultCycleTime();
877 auto& phases = logic->getPhases();
878 SUMOTime offset = logic->getOffset();
879 if (offset >= 0) {
880 offset = (time + cycleTime - (offset % cycleTime)) % cycleTime;
881 } else {
882 offset = (time + ((-offset) % cycleTime)) % cycleTime;
883 }
884
885 while (offset >= phases[step]->duration) {
886 offset -= phases[step]->duration;
887 step++;
888 }
889 logic->loadState(*this, time, step, offset, logic->isActive());
890 }
891 }
892 }
893}
894
895
896/****************************************************************************/
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.
void switchToLoaded(MSTrafficLightLogic *tl)
set current program upon loading saved state
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.
virtual void addLink(MSLink *link, MSLane *lane, int pos)
Adds a link on building.
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.