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-2024 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
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("Mismatching phase size in tls '" + id + "', program '" + 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("Can not switch tls '" + myCurrentProgram->getID() + "' to program '" + programID + "';\n The program is not known.");
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) {
181 MSPhaseDefinition* phase = new MSPhaseDefinition(DELTA_T, state);
182 std::vector<MSPhaseDefinition*> phases;
183 phases.push_back(phase);
184 logic = new MSSimpleTrafficLightLogic(tlc, myCurrentProgram->getID(), TRACI_PROGRAM, 0, TrafficLightType::STATIC, phases, 0,
187 if (addLogic(TRACI_PROGRAM, logic, true, true)) {
189 }
190 } else {
191 MSPhaseDefinition nphase(DELTA_T, state);
192 *(dynamic_cast<MSSimpleTrafficLightLogic*>(logic)->getPhases()[0]) = nphase;
194 }
195}
196
197
198void
200 mySwitchActions.push_back(c);
201}
202
203
204std::vector<MSTrafficLightLogic*>
206 std::vector<MSTrafficLightLogic*> ret;
207 std::map<std::string, MSTrafficLightLogic*>::const_iterator i;
208 for (i = myVariants.begin(); i != myVariants.end(); ++i) {
209 ret.push_back((*i).second);
210 }
211 return ret;
212}
213
214
215bool
217 return tl == myCurrentProgram;
218}
219
220
223 return myCurrentProgram;
224}
225
228 return myDefaultProgram;
229}
230
231
232void
234 // set the found wished sub-program as this tls' current one
235 myCurrentProgram->deactivateProgram();
236 myCurrentProgram = getLogicInstantiatingOff(tlc, programID);
237 myCurrentProgram->activateProgram();
238 myCurrentProgram->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
239 executeOnSwitchActions();
240}
241
242
243void
245 for (std::vector<OnSwitchAction*>::const_iterator i = mySwitchActions.begin(); i != mySwitchActions.end(); ++i) {
246 (*i)->execute();
247 }
248}
249
250
251void
253 for (std::map<std::string, MSTrafficLightLogic*>::iterator i = myVariants.begin(); i != myVariants.end(); ++i) {
254 (*i).second->addLink(link, lane, pos);
255 }
256}
257
258void
260 for (std::map<std::string, MSTrafficLightLogic*>::iterator i = myVariants.begin(); i != myVariants.end(); ++i) {
261 (*i).second->ignoreLinkIndex(pos);
262 }
263}
264
265
266/* -------------------------------------------------------------------------
267 * method definitions for the Switching Procedures
268 * ----------------------------------------------------------------------- */
269/* -------------------------------------------------------------------------
270 * method definitions for WAUTSwitchProcedure
271 * ----------------------------------------------------------------------- */
272bool
274 // switch to the next programm if the GSP is reached
275 if (isPosAtGSP(step, *myFrom)) {
276 // adapt program's state
277 if (mySwitchSynchron) {
278 adaptLogic(step);
279 } else {
280 switchToPos(step, *myTo, getGSPTime(*myTo));
281 }
282 // switch to destination program
283 return true;
284 }
285 // do not switch, yet
286 return false;
287}
288
289
294
295
296bool
298 const SUMOTime gspTime = getGSPTime(logic) % logic.getDefaultCycleTime();
299 const SUMOTime programTime = logic.getOffsetFromIndex(logic.getCurrentPhaseIndex()) + logic.getSpentDuration(currentTime);
300 return gspTime == programTime;
301}
302
303
306 int stepOfMyPos = logic.getIndexFromOffset(toTime);
307 SUMOTime startOfPhase = logic.getOffsetFromIndex(stepOfMyPos);
308 assert(toTime >= startOfPhase);
309 return toTime - startOfPhase;
310}
311
312
313void
315 int stepTo = logic.getIndexFromOffset(toTime);
316 SUMOTime diff = getDiffToStartOfPhase(logic, toTime);
317 const MSPhaseDefinition& phase = logic.getPhase(stepTo);
318 SUMOTime leftDuration = phase.duration - diff;
319 logic.changeStepAndDuration(myControl, simStep, stepTo, leftDuration);
320}
321
322
323
324/* -------------------------------------------------------------------------
325 * method definitions for WAUTSwitchProcedure_JustSwitch
326 * ----------------------------------------------------------------------- */
331
332
334
335
336bool
340
341
342
343/* -------------------------------------------------------------------------
344 * method definitions for WAUTSwitchProcedure_GSP
345 * ----------------------------------------------------------------------- */
350
351
353
354
355void
357 const SUMOTime gspTo = getGSPTime(*myTo) % myTo->getDefaultCycleTime();
358 const SUMOTime currentPosTo = myTo->getOffsetFromIndex(myTo->getCurrentPhaseIndex()) + myTo->getSpentDuration(step);
359 SUMOTime deltaToStretch = gspTo - currentPosTo;
360 if (deltaToStretch < 0) {
361 deltaToStretch += myTo->getDefaultCycleTime();
362 }
363 const int stepTo = myTo->getIndexFromOffset(gspTo);
364 const SUMOTime newdur = myTo->getPhase(stepTo).duration - getDiffToStartOfPhase(*myTo, gspTo) + deltaToStretch;
365 myTo->changeStepAndDuration(myControl, step, stepTo, newdur);
366}
367
368
369
370/* -------------------------------------------------------------------------
371 * method definitions for WAUTSwitchProcedure_Stretch
372 * ----------------------------------------------------------------------- */
374 MSTLLogicControl& control, WAUT& waut,
375 MSTrafficLightLogic* from, MSTrafficLightLogic* to, bool synchron)
376 : MSTLLogicControl::WAUTSwitchProcedure(control, waut, from, to, synchron) {
377 int idx = 1;
378 while (myTo->hasParameter("B" + toString(idx) + ".begin")) {
379 StretchRange def;
380 def.begin = string2time(myTo->getParameter("B" + toString(idx) + ".begin"));
381 def.end = string2time(myTo->getParameter("B" + toString(idx) + ".end"));
382 def.fac = StringUtils::toDouble(myTo->getParameter("B" + toString(idx) + ".factor"));
383 myStretchRanges.emplace_back(def);
384 }
385
386}
387
388
390
391
392void
394 SUMOTime gspTo = getGSPTime(*myTo);
395 SUMOTime cycleTime = myTo->getDefaultCycleTime();
396 // the position, where the logic has to be after synchronisation
397 SUMOTime posAfterSyn = myTo->getPhaseIndexAtTime(step);
398 // calculate the difference, that has to be equalized
399 SUMOTime deltaToCut = 0;
400 if (posAfterSyn < gspTo) {
401 deltaToCut = posAfterSyn + cycleTime - gspTo;
402 } else {
403 deltaToCut = posAfterSyn - gspTo;
404 }
405 // test, wheter cutting of the Signalplan is possible
406 SUMOTime deltaPossible = 0;
407 for (const StretchRange& def : myStretchRanges) {
408 assert(def.end >= def.begin);
409 deltaPossible += def.end - def.begin;
410 }
411 int stretchUmlaufAnz = (int) StringUtils::toDouble(myTo->getParameter("StretchUmlaufAnz", ""));
412 deltaPossible = stretchUmlaufAnz * deltaPossible;
413 if ((deltaPossible > deltaToCut) && (deltaToCut < (cycleTime / 2))) {
414 cutLogic(step, gspTo, deltaToCut);
415 } else {
416 SUMOTime deltaToStretch = (cycleTime - deltaToCut) % cycleTime;
417 stretchLogic(step, gspTo, deltaToStretch);
418 }
419}
420
421
422void
424 int actStep = myTo->getIndexFromOffset(startPos);
425 // switches to startPos and cuts this phase, if there is a "Bereich"
426 SUMOTime toCut = 0;
427 for (const StretchRange& def : myStretchRanges) {
428 int stepOfBegin = myTo->getIndexFromOffset(def.begin);
429 if (stepOfBegin == actStep) {
430 if (def.begin < startPos) {
431 toCut = def.end - startPos;
432 } else {
433 toCut = def.end - def.begin;
434 }
435 toCut = MIN2(allCutTime, toCut);
436 allCutTime = allCutTime - toCut;
437 }
438 }
439 SUMOTime remainingDur = myTo->getPhase(actStep).duration - getDiffToStartOfPhase(*myTo, startPos);
440 SUMOTime newDur = remainingDur - toCut;
441 myTo->changeStepAndDuration(myControl, step, actStep, newDur);
442
443 // changes the duration of all other phases
444 int currStep = (actStep + 1) % (int)myTo->getPhases().size();
445 while (allCutTime > 0) {
446 for (int i = currStep; i < (int) myTo->getPhases().size(); i++) {
447 SUMOTime beginOfPhase = myTo->getOffsetFromIndex(i);
448 SUMOTime durOfPhase = myTo->getPhase(i).duration;
449 SUMOTime endOfPhase = beginOfPhase + durOfPhase;
450 for (const StretchRange& def : myStretchRanges) {
451 if ((beginOfPhase <= def.begin) && (endOfPhase >= def.end)) {
452 SUMOTime maxCutOfPhase = MIN2(def.end - def.begin, allCutTime);
453 allCutTime = allCutTime - maxCutOfPhase;
454 durOfPhase = durOfPhase - maxCutOfPhase;
455 }
456 }
457 myTo->addOverridingDuration(durOfPhase);
458 }
459 currStep = 0;
460 }
461}
462
463void
465 int currStep = myTo->getIndexFromOffset(startPos);
466 SUMOTime durOfPhase = myTo->getPhase(currStep).duration;
467 SUMOTime remainingStretchTime = allStretchTime;
468 SUMOTime StretchTimeOfPhase = 0;
469 int stretchUmlaufAnz = (int) StringUtils::toDouble(myTo->getParameter("StretchUmlaufAnz", ""));
470 double facSum = 0;
471 for (const StretchRange& def : myStretchRanges) {
472 facSum += def.fac;
473 }
474 facSum *= stretchUmlaufAnz;
475
476 //switch to startPos and stretch this phase, if there is a end of "bereich" between startpos and end of phase
477 SUMOTime diffToStart = getDiffToStartOfPhase(*myTo, startPos);
478 for (const StretchRange& def : myStretchRanges) {
479 SUMOTime endOfPhase = (startPos + durOfPhase - diffToStart);
480 if (def.end <= endOfPhase && def.end >= startPos) {
481 double actualfac = def.fac / facSum;
482 facSum = facSum - def.fac;
483 StretchTimeOfPhase = TIME2STEPS(int(STEPS2TIME(remainingStretchTime) * actualfac + 0.5));
484 remainingStretchTime = allStretchTime - StretchTimeOfPhase;
485 }
486 }
487 if (facSum == 0) {
488 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)));
489 return;
490 }
491 durOfPhase = durOfPhase - diffToStart + StretchTimeOfPhase;
492 myTo->changeStepAndDuration(myControl, step, currStep, durOfPhase);
493
494 currStep = (currStep + 1) % (int)myTo->getPhases().size();
495 // stretch all other phases, if there is a "bereich"
496 while (remainingStretchTime > 0) {
497 for (int i = currStep; i < (int)myTo->getPhases().size() && remainingStretchTime > 0; i++) {
498 durOfPhase = myTo->getPhase(i).duration;
499 SUMOTime beginOfPhase = myTo->getOffsetFromIndex(i);
500 SUMOTime endOfPhase = beginOfPhase + durOfPhase;
501 for (const StretchRange& def : myStretchRanges) {
502 if ((beginOfPhase <= def.end) && (endOfPhase >= def.end)) {
503 double actualfac = def.fac / facSum;
504 StretchTimeOfPhase = TIME2STEPS(int(STEPS2TIME(remainingStretchTime) * actualfac + 0.5));
505 facSum -= def.fac;
506 durOfPhase += StretchTimeOfPhase;
507 remainingStretchTime -= StretchTimeOfPhase;
508 }
509 }
510 myTo->addOverridingDuration(durOfPhase);
511 }
512 currStep = 0;
513 }
514}
515
516
517/* -------------------------------------------------------------------------
518 * method definitions for MSTLLogicControl
519 * ----------------------------------------------------------------------- */
522
523
525 // delete tls
526 for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
527 delete (*i).second;
528 }
529 // delete WAUTs
530 for (std::map<std::string, WAUT*>::const_iterator i = myWAUTs.begin(); i != myWAUTs.end(); ++i) {
531 delete (*i).second;
532 }
533}
534
535
536void
538 for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
539 (*i).second->getActive()->setTrafficLightSignals(t);
540 }
541}
542
543
544std::vector<MSTrafficLightLogic*>
546 std::vector<MSTrafficLightLogic*> ret;
547 std::map<std::string, TLSLogicVariants*>::const_iterator i;
548 for (i = myLogics.begin(); i != myLogics.end(); ++i) {
549 std::vector<MSTrafficLightLogic*> s = (*i).second->getAllLogics();
550 copy(s.begin(), s.end(), back_inserter(ret));
551 }
552 return ret;
553}
554
556MSTLLogicControl::get(const std::string& id) const {
557 std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
558 if (i == myLogics.end()) {
559 throw InvalidArgument("The tls '" + id + "' is not known.");
560 }
561 return *(*i).second;
562}
563
564
566MSTLLogicControl::get(const std::string& id, const std::string& programID) const {
567 std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
568 if (i == myLogics.end()) {
569 return nullptr;
570 }
571 return (*i).second->getLogic(programID);
572}
573
574
575std::vector<std::string>
577 std::vector<std::string> ret;
578 for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
579 ret.push_back((*i).first);
580 }
581 return ret;
582}
583
584
585bool
586MSTLLogicControl::add(const std::string& id, const std::string& programID,
587 MSTrafficLightLogic* logic, bool newDefault) {
588 std::map<std::string, TLSLogicVariants*>::iterator it = myLogics.find(id);
589 TLSLogicVariants* tlmap;
590 if (it == myLogics.end()) {
591 tlmap = myLogics[id] = new TLSLogicVariants();
592 } else {
593 tlmap = it->second;
594 }
595 return tlmap->addLogic(programID, logic, myNetWasLoaded, newDefault);
596}
597
598
599bool
600MSTLLogicControl::knows(const std::string& id) const {
601 return myLogics.count(id) != 0;
602}
603
604
605bool
607 bool hadErrors = false;
608 for (const auto& it : myLogics) {
609 hadErrors |= !it.second->checkOriginalTLS();
610 it.second->saveInitialStates();
611 }
612 myNetWasLoaded = true;
613 return !hadErrors;
614}
615
616
617bool
619 std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(tl->getID());
620 if (i == myLogics.end()) {
621 return false;
622 }
623 return (*i).second->isActive(tl);
624}
625
626
628MSTLLogicControl::getActive(const std::string& id) const {
629 std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
630 if (i == myLogics.end()) {
631 return nullptr;
632 }
633 return (*i).second->getActive();
634}
635
636
637void
638MSTLLogicControl::switchTo(const std::string& id, const std::string& programID) {
639 // try to get the tls program definitions
640 std::map<std::string, TLSLogicVariants*>::iterator i = myLogics.find(id);
641 // handle problems
642 if (i == myLogics.end()) {
643 throw ProcessError("Could not switch tls '" + id + "' to program '" + programID + "': No such tls exists.");
644 }
645 (*i).second->switchTo(*this, programID);
646}
647
648
649void
650MSTLLogicControl::addWAUT(SUMOTime refTime, const std::string& id,
651 const std::string& startProg, SUMOTime period) {
652 // check whether the waut was already defined
653 if (myWAUTs.find(id) != myWAUTs.end()) {
654 // report an error if so
655 throw InvalidArgument("Waut '" + id + "' was already defined.");
656 }
657 WAUT* w = new WAUT;
658 w->id = id;
659 w->refTime = refTime;
660 w->startProg = startProg;
661 w->period = period;
662 myWAUTs[id] = w;
663}
664
665
666void
667MSTLLogicControl::addWAUTSwitch(const std::string& wautid,
668 SUMOTime when, const std::string& to) {
669 // try to get the waut
670 if (myWAUTs.find(wautid) == myWAUTs.end()) {
671 // report an error if the waut is not known
672 throw InvalidArgument("Waut '" + wautid + "' was not yet defined.");
673 }
674 // build and save the waut switch definition
675 WAUT* waut = myWAUTs[wautid];
676 WAUTSwitch s;
677 s.to = to;
678 s.when = (waut->refTime + when);
679 if (waut->period > 0) {
680 s.when = s.when % waut->period;
681 }
682 myWAUTs[wautid]->switches.push_back(s);
683}
684
685
686void
687MSTLLogicControl::addWAUTJunction(const std::string& wautid,
688 const std::string& tls,
689 const std::string& proc,
690 bool synchron) {
691 // try to get the waut
692 if (myWAUTs.find(wautid) == myWAUTs.end()) {
693 // report an error if the waut is not known
694 throw InvalidArgument("Waut '" + wautid + "' was not yet defined.");
695 }
696 // try to get the tls to switch
697 if (myLogics.find(tls) == myLogics.end()) {
698 // report an error if the tls is not known
699 throw InvalidArgument("TLS '" + tls + "' to switch in WAUT '" + wautid + "' was not yet defined.");
700 }
701 WAUTJunction j;
702 j.junction = tls;
703 j.procedure = proc;
704 j.synchron = synchron;
705 myWAUTs[wautid]->junctions.push_back(j);
706
707 std::string initProg = myWAUTs[wautid]->startProg;
708 std::vector<WAUTSwitch>::const_iterator first = myWAUTs[wautid]->switches.end();
709 SUMOTime minExecTime = -1;
710 for (std::vector<WAUTSwitch>::const_iterator i = myWAUTs[wautid]->switches.begin(); i != myWAUTs[wautid]->switches.end(); ++i) {
711 if ((*i).when > MSNet::getInstance()->getCurrentTimeStep() && (minExecTime == -1 || (*i).when < minExecTime)) {
712 minExecTime = (*i).when;
713 first = i;
714 }
715 if (first != myWAUTs[wautid]->switches.begin()) {
716 initProg = (*(first - 1)).to;
717 }
718 }
719 // activate the first one
720 switchTo(tls, initProg);
721}
722
723
724void
725MSTLLogicControl::closeWAUT(const std::string& wautid) {
726 // try to get the waut
727 if (myWAUTs.find(wautid) == myWAUTs.end()) {
728 // report an error if the waut is not known
729 throw InvalidArgument("Waut '" + wautid + "' was not yet defined.");
730 }
731 WAUT* w = myWAUTs.find(wautid)->second;
732 std::string initProg = myWAUTs[wautid]->startProg;
733 // get the switch to be performed as first
734 std::vector<WAUTSwitch>::const_iterator first = w->switches.end();
735 SUMOTime minExecTime = -1;
736 for (std::vector<WAUTSwitch>::const_iterator i = w->switches.begin(); i != w->switches.end(); ++i) {
737 if ((*i).when > MSNet::getInstance()->getCurrentTimeStep() && (minExecTime == -1 || (*i).when < minExecTime)) {
738 minExecTime = (*i).when;
739 first = i;
740 }
741 }
742 // activate the first one
743 if (first != w->switches.end()) {
744 std::vector<WAUTSwitch>::const_iterator mbegin = w->switches.begin();
746 new SwitchInitCommand(*this, wautid, (int)distance(mbegin, first)),
747 (*first).when);
748 }
749 /*
750 // set the current program to all junctions
751 for(std::vector<WAUTJunction>::const_iterator i=w->junctions.begin(); i!=w->junctions.end(); ++i) {
752 switchTo((*i).junction, initProg);
753 }
754 */
755}
756
757
760 const std::string& wautid = cmd.getWAUTID();
761 int& index = cmd.getIndex();
762 WAUT* waut = myWAUTs[wautid];
763 WAUTSwitch s = waut->switches[index];
764 for (std::vector<WAUTJunction>::iterator i = myWAUTs[wautid]->junctions.begin(); i != myWAUTs[wautid]->junctions.end(); ++i) {
765 // get the current program and the one to instantiate
766 TLSLogicVariants* vars = myLogics.find((*i).junction)->second;
767 MSTrafficLightLogic* from = vars->getActive();
768 MSTrafficLightLogic* to = vars->getLogicInstantiatingOff(*this, s.to);
769 WAUTSwitchProcedure* proc = nullptr;
770 if ((*i).procedure == "GSP") {
771 proc = new WAUTSwitchProcedure_GSP(*this, *myWAUTs[wautid], from, to, (*i).synchron);
772 } else if ((*i).procedure == "Stretch") {
773 proc = new WAUTSwitchProcedure_Stretch(*this, *myWAUTs[wautid], from, to, (*i).synchron);
774 } else {
775 proc = new WAUTSwitchProcedure_JustSwitch(*this, *myWAUTs[wautid], from, to, (*i).synchron);
776 }
777
779 p.junction = (*i).junction;
780 p.proc = proc;
781 p.from = from;
782 p.to = to;
783
784 myCurrentlySwitched.push_back(p);
785 }
786 index++;
787 if (index == (int)waut->switches.size()) {
788 if (waut->period <= 0) {
789 return 0;
790 } else {
791 index = 0; // start over
792 for (WAUTSwitch& ws : waut->switches) {
793 ws.when += waut->period;
794 }
795 }
796 }
797 return myWAUTs[wautid]->switches[index].when - MSNet::getInstance()->getCurrentTimeStep();
798}
799
800
801void
803 for (std::vector<WAUTSwitchProcess>::iterator i = myCurrentlySwitched.begin(); i != myCurrentlySwitched.end();) {
804 const WAUTSwitchProcess& proc = *i;
805 if (proc.proc->trySwitch(step)) {
806 delete proc.proc;
807 // do not switch away from TraCI control
808 if (getActive(proc.to->getID())->getProgramID() != TRACI_PROGRAM) {
809 switchTo(proc.to->getID(), proc.to->getProgramID());
810 }
811 i = myCurrentlySwitched.erase(i);
812 } else {
813 ++i;
814 }
815 }
816}
817
818
819std::pair<SUMOTime, MSPhaseDefinition>
820MSTLLogicControl::getPhaseDef(const std::string& tlid) const {
821 MSTrafficLightLogic* tl = getActive(tlid);
822 return std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), tl->getCurrentPhaseDef());
823}
824
825
826void
828 for (const auto& logic : myLogics) {
829 logic.second->addLogic("off", new MSOffTrafficLightLogic(*this, logic.first), true, true);
830 }
831}
832
833
834void
836 MSRailSignalConstraint::saveState(out); // always saves vehicle tracker states
837 for (const auto& logic : myLogics) {
838 logic.second->saveState(out);
839 }
841}
842
843
844void
845MSTLLogicControl::clearState(SUMOTime time, bool quickReload) {
847 if (quickReload) {
848 for (const auto& variants : myLogics) {
849 for (auto& logic : variants.second->getAllLogics()) {
850 if (logic->getLogicType() == TrafficLightType::OFF
851 || logic->getLogicType() == TrafficLightType::RAIL_SIGNAL
852 || logic->getLogicType() == TrafficLightType::RAIL_CROSSING) {
853 continue;
854 }
855 int step = 0;
856 const SUMOTime cycleTime = logic->getDefaultCycleTime();
857 auto& phases = logic->getPhases();
858 SUMOTime offset = logic->getOffset();
859 if (offset >= 0) {
860 offset = (time + cycleTime - (offset % cycleTime)) % cycleTime;
861 } else {
862 offset = (time + ((-offset) % cycleTime)) % cycleTime;
863 }
864
865 while (offset >= phases[step]->duration) {
866 offset -= phases[step]->duration;
867 step++;
868 }
869 logic->loadState(*this, time, step, offset);
870 }
871 }
872 }
873}
874
875
876/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define TRACI_PROGRAM
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:296
#define WRITE_ERRORF(...)
Definition MsgHandler.h:305
#define TL(string)
Definition MsgHandler.h:315
#define TLF(string,...)
Definition MsgHandler.h:317
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:55
#define TIME2STEPS(x)
Definition SUMOTime.h:57
T MIN2(T a, T b)
Definition StdDefs.h:76
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:185
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:583
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.
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.