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