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"
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_ERROR("Mismatching phase size in tls '" + (*j).second->getID() + "', program '" + (*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  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 
142 MSTLLogicControl::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 
169 void
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,
180  std::map<std::string, std::string>());
181  addLogic(TRACI_PROGRAM, logic, true, true);
183  } else {
184  MSPhaseDefinition nphase(DELTA_T, state);
185  *(dynamic_cast<MSSimpleTrafficLightLogic*>(logic)->getPhases()[0]) = nphase;
186  switchTo(tlc, TRACI_PROGRAM);
187  }
188 }
189 
190 
191 void
193  mySwitchActions.push_back(c);
194 }
195 
196 
197 std::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 
208 bool
210  return tl == myCurrentProgram;
211 }
212 
213 
216  return myCurrentProgram;
217 }
218 
221  return myDefaultProgram;
222 }
223 
224 
225 void
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 
236 void
238  for (std::vector<OnSwitchAction*>::const_iterator i = mySwitchActions.begin(); i != mySwitchActions.end(); ++i) {
239  (*i)->execute();
240  }
241 }
242 
243 
244 void
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 
251 void
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  * ----------------------------------------------------------------------- */
265 bool
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 
283 SUMOTime
285  return string2time(logic.getParameter("GSP", "0"));
286 }
287 
288 
289 bool
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 
297 SUMOTime
299  int stepOfMyPos = logic.getIndexFromOffset(toTime);
300  SUMOTime startOfPhase = logic.getOffsetFromIndex(stepOfMyPos);
301  assert(toTime >= startOfPhase);
302  return toTime - startOfPhase;
303 }
304 
305 
306 void
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 
329 bool
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 
348 void
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 
385 void
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 
415 void
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 
456 void
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 
529 void
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 
537 std::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 
549 MSTLLogicControl::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 
559 MSTLLogicControl::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 
568 std::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 
578 bool
579 MSTLLogicControl::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 
590 bool
591 MSTLLogicControl::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 
600 bool
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 
612 bool
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 
623 MSTLLogicControl::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 
632 void
633 MSTLLogicControl::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 
644 void
645 MSTLLogicControl::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 
661 void
662 MSTLLogicControl::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 
681 void
682 MSTLLogicControl::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 
719 void
720 MSTLLogicControl::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 
753 SUMOTime
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 
796 void
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 
814 std::pair<SUMOTime, MSPhaseDefinition>
815 MSTLLogicControl::getPhaseDef(const std::string& tlid) const {
816  MSTrafficLightLogic* tl = getActive(tlid);
817  return std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), tl->getCurrentPhaseDef());
818 }
819 
820 
821 void
823  for (const auto& logic : myLogics) {
824  logic.second->addLogic("off", new MSOffTrafficLightLogic(*this, logic.first), true, true);
825  }
826 }
827 
828 
829 void
831  MSRailSignalConstraint::saveState(out); // always saves vehicle tracker states
832  for (const auto& logic : myLogics) {
833  logic.second->saveState(out);
834  }
835 }
836 
837 
838 void
841 }
842 
843 
844 /****************************************************************************/
#define TRACI_PROGRAM
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:288
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:280
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:53
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
long long int SUMOTime
Definition: SUMOTime.h:32
T MIN2(T a, T b)
Definition: StdDefs.h:74
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:82
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:174
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:318
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition: MSNet.h:469
virtual void createTLWrapper(MSTrafficLightLogic *)
creates a wrapper for the given logic (see GUINet)
Definition: MSNet.h:575
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.
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.
void clearState()
Clear all tls states before quick-loading state.
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
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.