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