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-2020 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 (std::map<std::string, MSTrafficLightLogic*>::iterator j = myVariants.begin(); j != myVariants.end(); ++j) {
60  delete (*j).second;
61  }
62  for (std::vector<OnSwitchAction*>::iterator i = mySwitchActions.begin(); i != mySwitchActions.end(); ++i) {
63  delete *i;
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 bool
96 MSTLLogicControl::TLSLogicVariants::addLogic(const std::string& programID,
97  MSTrafficLightLogic* logic, bool netWasLoaded, bool isNewDefault) {
98  if (myVariants.find(programID) != myVariants.end()) {
99  return false;
100  }
101  // assert the links are set
102  if (netWasLoaded) {
103  // this one has not yet its links set
104  if (myCurrentProgram == nullptr) {
105  throw ProcessError("No initial signal plan loaded for tls '" + logic->getID() + "'.");
106  }
107  logic->adaptLinkInformationFrom(*myCurrentProgram);
108  if (logic->getLinks().size() > logic->getPhase(0).getState().size()) {
109  throw ProcessError("Mismatching phase size in tls '" + logic->getID() + "', program '" + programID + "'.");
110  }
111  }
112  // add to the list of active
113  if (myVariants.size() == 0 || isNewDefault) {
114  if (myCurrentProgram != nullptr) {
115  myCurrentProgram->deactivateProgram();
116  }
117  myCurrentProgram = logic;
118  myCurrentProgram->activateProgram();
119  if (myVariants.size() == 0) {
120  myDefaultProgram = logic;
121  }
122  }
123  // add to the list of logic
124  myVariants[programID] = logic;
125  if (myVariants.size() == 1 || isNewDefault) {
126  logic->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
127  executeOnSwitchActions();
128  }
129  return true;
130 }
131 
132 
134 MSTLLogicControl::TLSLogicVariants::getLogic(const std::string& programID) const {
135  if (myVariants.find(programID) == myVariants.end()) {
136  return nullptr;
137  }
138  return myVariants.find(programID)->second;
139 }
140 
141 
144  const std::string& programID) {
145  if (myVariants.find(programID) == myVariants.end()) {
146  if (programID == "off") {
147  // build an off-tll if this switch indicates it
148  if (!addLogic("off", new MSOffTrafficLightLogic(tlc, myCurrentProgram->getID()), true, true)) {
149  // inform the user if this fails
150  throw ProcessError("Could not build an off-state for tls '" + myCurrentProgram->getID() + "'.");
151  }
152  } else {
153  // inform the user about a missing logic
154  throw ProcessError("Can not switch tls '" + myCurrentProgram->getID() + "' to program '" + programID + "';\n The program is not known.");
155  }
156  }
157  return getLogic(programID);
158 }
159 
160 
161 void
163  const std::string& state) {
164  // build only once...
165  MSTrafficLightLogic* logic = getLogic(TRACI_PROGRAM);
166  if (logic == nullptr) {
167  MSPhaseDefinition* phase = new MSPhaseDefinition(DELTA_T, state, -1);
168  std::vector<MSPhaseDefinition*> phases;
169  phases.push_back(phase);
170  logic = new MSSimpleTrafficLightLogic(tlc, myCurrentProgram->getID(), TRACI_PROGRAM, TrafficLightType::STATIC, phases, 0,
172  std::map<std::string, std::string>());
173  addLogic(TRACI_PROGRAM, logic, true, true);
175  } else {
176  MSPhaseDefinition nphase(DELTA_T, state, -1);
177  *(dynamic_cast<MSSimpleTrafficLightLogic*>(logic)->getPhases()[0]) = nphase;
178  switchTo(tlc, TRACI_PROGRAM);
179  }
180 }
181 
182 
183 void
185  mySwitchActions.push_back(c);
186 }
187 
188 
189 std::vector<MSTrafficLightLogic*>
191  std::vector<MSTrafficLightLogic*> ret;
192  std::map<std::string, MSTrafficLightLogic*>::const_iterator i;
193  for (i = myVariants.begin(); i != myVariants.end(); ++i) {
194  ret.push_back((*i).second);
195  }
196  return ret;
197 }
198 
199 
200 bool
202  return tl == myCurrentProgram;
203 }
204 
205 
208  return myCurrentProgram;
209 }
210 
213  return myDefaultProgram;
214 }
215 
216 
217 void
219  // set the found wished sub-program as this tls' current one
220  myCurrentProgram->deactivateProgram();
221  myCurrentProgram = getLogicInstantiatingOff(tlc, programID);
222  myCurrentProgram->activateProgram();
223  myCurrentProgram->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
224  executeOnSwitchActions();
225 }
226 
227 
228 void
230  for (std::vector<OnSwitchAction*>::const_iterator i = mySwitchActions.begin(); i != mySwitchActions.end(); ++i) {
231  (*i)->execute();
232  }
233 }
234 
235 
236 void
238  for (std::map<std::string, MSTrafficLightLogic*>::iterator i = myVariants.begin(); i != myVariants.end(); ++i) {
239  (*i).second->addLink(link, lane, pos);
240  }
241 }
242 
243 void
245  for (std::map<std::string, MSTrafficLightLogic*>::iterator i = myVariants.begin(); i != myVariants.end(); ++i) {
246  (*i).second->ignoreLinkIndex(pos);
247  }
248 }
249 
250 
251 /* -------------------------------------------------------------------------
252  * method definitions for the Switching Procedures
253  * ----------------------------------------------------------------------- */
254 /* -------------------------------------------------------------------------
255  * method definitions for WAUTSwitchProcedure
256  * ----------------------------------------------------------------------- */
257 bool
259  // switch to the next programm if the GSP is reached
260  if (isPosAtGSP(step, *myFrom)) {
261  // adapt program's state
262  if (mySwitchSynchron) {
263  adaptLogic(step);
264  } else {
265  switchToPos(step, *myTo, getGSPTime(*myTo));
266  }
267  // switch to destination program
268  return true;
269  }
270  // do not switch, yet
271  return false;
272 }
273 
274 
275 SUMOTime
277  return string2time(logic.getParameter("GSP", "0"));
278 }
279 
280 
281 bool
283  const SUMOTime gspTime = getGSPTime(logic) % logic.getDefaultCycleTime();
284  const SUMOTime programTime = logic.getOffsetFromIndex(logic.getCurrentPhaseIndex()) + logic.getSpentDuration(currentTime);
285  return gspTime == programTime;
286 }
287 
288 
289 SUMOTime
291  int stepOfMyPos = logic.getIndexFromOffset(toTime);
292  SUMOTime startOfPhase = logic.getOffsetFromIndex(stepOfMyPos);
293  assert(toTime >= startOfPhase);
294  return toTime - startOfPhase;
295 }
296 
297 
298 void
300  int stepTo = logic.getIndexFromOffset(toTime);
301  SUMOTime diff = getDiffToStartOfPhase(logic, toTime);
302  const MSPhaseDefinition& phase = logic.getPhase(stepTo);
303  SUMOTime leftDuration = phase.duration - diff;
304  logic.changeStepAndDuration(myControl, simStep, stepTo, leftDuration);
305 }
306 
307 
308 
309 /* -------------------------------------------------------------------------
310  * method definitions for WAUTSwitchProcedure_JustSwitch
311  * ----------------------------------------------------------------------- */
313  MSTLLogicControl& control, WAUT& waut,
314  MSTrafficLightLogic* from, MSTrafficLightLogic* to, bool synchron)
315  : MSTLLogicControl::WAUTSwitchProcedure(control, waut, from, to, synchron) {}
316 
317 
319 
320 
321 bool
323  return true;
324 }
325 
326 
327 
328 /* -------------------------------------------------------------------------
329  * method definitions for WAUTSwitchProcedure_GSP
330  * ----------------------------------------------------------------------- */
332  MSTLLogicControl& control, WAUT& waut,
333  MSTrafficLightLogic* from, MSTrafficLightLogic* to, bool synchron)
334  : MSTLLogicControl::WAUTSwitchProcedure(control, waut, from, to, synchron) {}
335 
336 
338 
339 
340 void
342  const SUMOTime gspTo = getGSPTime(*myTo) % myTo->getDefaultCycleTime();
343  const SUMOTime currentPosTo = myTo->getOffsetFromIndex(myTo->getCurrentPhaseIndex()) + myTo->getSpentDuration(step);
344  SUMOTime deltaToStretch = gspTo - currentPosTo;
345  if (deltaToStretch < 0) {
346  deltaToStretch += myTo->getDefaultCycleTime();
347  }
348  const int stepTo = myTo->getIndexFromOffset(gspTo);
349  const SUMOTime newdur = myTo->getPhase(stepTo).duration - getDiffToStartOfPhase(*myTo, gspTo) + deltaToStretch;
350  myTo->changeStepAndDuration(myControl, step, stepTo, newdur);
351 }
352 
353 
354 
355 /* -------------------------------------------------------------------------
356  * method definitions for WAUTSwitchProcedure_Stretch
357  * ----------------------------------------------------------------------- */
359  MSTLLogicControl& control, WAUT& waut,
360  MSTrafficLightLogic* from, MSTrafficLightLogic* to, bool synchron)
361  : MSTLLogicControl::WAUTSwitchProcedure(control, waut, from, to, synchron) {
362  int idx = 1;
363  while (myTo->knowsParameter("B" + toString(idx) + ".begin")) {
364  StretchRange def;
365  def.begin = string2time(myTo->getParameter("B" + toString(idx) + ".begin"));
366  def.end = string2time(myTo->getParameter("B" + toString(idx) + ".end"));
367  def.fac = StringUtils::toDouble(myTo->getParameter("B" + toString(idx) + ".factor"));
368  myStretchRanges.emplace_back(def);
369  }
370 
371 }
372 
373 
375 
376 
377 void
379  SUMOTime gspTo = getGSPTime(*myTo);
380  SUMOTime cycleTime = myTo->getDefaultCycleTime();
381  // the position, where the logic has to be after synchronisation
382  SUMOTime posAfterSyn = myTo->getPhaseIndexAtTime(step);
383  // calculate the difference, that has to be equalized
384  SUMOTime deltaToCut = 0;
385  if (posAfterSyn < gspTo) {
386  deltaToCut = posAfterSyn + cycleTime - gspTo;
387  } else {
388  deltaToCut = posAfterSyn - gspTo;
389  }
390  // test, wheter cutting of the Signalplan is possible
391  SUMOTime deltaPossible = 0;
392  for (const StretchRange& def : myStretchRanges) {
393  assert(def.end >= def.begin);
394  deltaPossible += def.end - def.begin;
395  }
396  int stretchUmlaufAnz = (int) StringUtils::toDouble(myTo->getParameter("StretchUmlaufAnz", ""));
397  deltaPossible = stretchUmlaufAnz * deltaPossible;
398  if ((deltaPossible > deltaToCut) && (deltaToCut < (cycleTime / 2))) {
399  cutLogic(step, gspTo, deltaToCut);
400  } else {
401  SUMOTime deltaToStretch = (cycleTime - deltaToCut) % cycleTime;
402  stretchLogic(step, gspTo, deltaToStretch);
403  }
404 }
405 
406 
407 void
409  int actStep = myTo->getIndexFromOffset(startPos);
410  // switches to startPos and cuts this phase, if there is a "Bereich"
411  SUMOTime toCut = 0;
412  for (const StretchRange& def : myStretchRanges) {
413  int stepOfBegin = myTo->getIndexFromOffset(def.begin);
414  if (stepOfBegin == actStep) {
415  if (def.begin < startPos) {
416  toCut = def.end - startPos;
417  } else {
418  toCut = def.end - def.begin;
419  }
420  toCut = MIN2(allCutTime, toCut);
421  allCutTime = allCutTime - toCut;
422  }
423  }
424  SUMOTime remainingDur = myTo->getPhase(actStep).duration - getDiffToStartOfPhase(*myTo, startPos);
425  SUMOTime newDur = remainingDur - toCut;
426  myTo->changeStepAndDuration(myControl, step, actStep, newDur);
427 
428  // changes the duration of all other phases
429  int currStep = (actStep + 1) % (int)myTo->getPhases().size();
430  while (allCutTime > 0) {
431  for (int i = currStep; i < (int) myTo->getPhases().size(); i++) {
432  SUMOTime beginOfPhase = myTo->getOffsetFromIndex(i);
433  SUMOTime durOfPhase = myTo->getPhase(i).duration;
434  SUMOTime endOfPhase = beginOfPhase + durOfPhase;
435  for (const StretchRange& def : myStretchRanges) {
436  if ((beginOfPhase <= def.begin) && (endOfPhase >= def.end)) {
437  SUMOTime maxCutOfPhase = MIN2(def.end - def.begin, allCutTime);
438  allCutTime = allCutTime - maxCutOfPhase;
439  durOfPhase = durOfPhase - maxCutOfPhase;
440  }
441  }
442  myTo->addOverridingDuration(durOfPhase);
443  }
444  currStep = 0;
445  }
446 }
447 
448 void
450  int currStep = myTo->getIndexFromOffset(startPos);
451  SUMOTime durOfPhase = myTo->getPhase(currStep).duration;
452  SUMOTime remainingStretchTime = allStretchTime;
453  SUMOTime StretchTimeOfPhase = 0;
454  int stretchUmlaufAnz = (int) StringUtils::toDouble(myTo->getParameter("StretchUmlaufAnz", ""));
455  double facSum = 0;
456  for (const StretchRange& def : myStretchRanges) {
457  facSum += def.fac;
458  }
459  facSum *= stretchUmlaufAnz;
460 
461  //switch to startPos and stretch this phase, if there is a end of "bereich" between startpos and end of phase
462  SUMOTime diffToStart = getDiffToStartOfPhase(*myTo, startPos);
463  for (const StretchRange& def : myStretchRanges) {
464  SUMOTime endOfPhase = (startPos + durOfPhase - diffToStart);
465  if (def.end <= endOfPhase && def.end >= startPos) {
466  double actualfac = def.fac / facSum;
467  facSum = facSum - def.fac;
468  StretchTimeOfPhase = TIME2STEPS(int(STEPS2TIME(remainingStretchTime) * actualfac + 0.5));
469  remainingStretchTime = allStretchTime - StretchTimeOfPhase;
470  }
471  }
472  if (facSum == 0) {
473  WRITE_WARNING("The computed factor sum in WAUT '" + myWAUT.id + "' at time '" + toString(STEPS2TIME(step)) + "' equals zero;\n assuming an error in WAUT definition.");
474  return;
475  }
476  durOfPhase = durOfPhase - diffToStart + StretchTimeOfPhase;
477  myTo->changeStepAndDuration(myControl, step, currStep, durOfPhase);
478 
479  currStep = (currStep + 1) % (int)myTo->getPhases().size();
480  // stretch all other phases, if there is a "bereich"
481  while (remainingStretchTime > 0) {
482  for (int i = currStep; i < (int)myTo->getPhases().size() && remainingStretchTime > 0; i++) {
483  durOfPhase = myTo->getPhase(i).duration;
484  SUMOTime beginOfPhase = myTo->getOffsetFromIndex(i);
485  SUMOTime endOfPhase = beginOfPhase + durOfPhase;
486  for (const StretchRange& def : myStretchRanges) {
487  if ((beginOfPhase <= def.end) && (endOfPhase >= def.end)) {
488  double actualfac = def.fac / facSum;
489  StretchTimeOfPhase = TIME2STEPS(int(STEPS2TIME(remainingStretchTime) * actualfac + 0.5));
490  facSum -= def.fac;
491  durOfPhase += StretchTimeOfPhase;
492  remainingStretchTime -= StretchTimeOfPhase;
493  }
494  }
495  myTo->addOverridingDuration(durOfPhase);
496  }
497  currStep = 0;
498  }
499 }
500 
501 
502 /* -------------------------------------------------------------------------
503  * method definitions for MSTLLogicControl
504  * ----------------------------------------------------------------------- */
506  : myNetWasLoaded(false) {}
507 
508 
510  // delete tls
511  for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
512  delete (*i).second;
513  }
514  // delete WAUTs
515  for (std::map<std::string, WAUT*>::const_iterator i = myWAUTs.begin(); i != myWAUTs.end(); ++i) {
516  delete (*i).second;
517  }
518 }
519 
520 
521 void
523  for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
524  (*i).second->getActive()->setTrafficLightSignals(t);
525  }
526 }
527 
528 
529 std::vector<MSTrafficLightLogic*>
531  std::vector<MSTrafficLightLogic*> ret;
532  std::map<std::string, TLSLogicVariants*>::const_iterator i;
533  for (i = myLogics.begin(); i != myLogics.end(); ++i) {
534  std::vector<MSTrafficLightLogic*> s = (*i).second->getAllLogics();
535  copy(s.begin(), s.end(), back_inserter(ret));
536  }
537  return ret;
538 }
539 
541 MSTLLogicControl::get(const std::string& id) const {
542  std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
543  if (i == myLogics.end()) {
544  throw InvalidArgument("The tls '" + id + "' is not known.");
545  }
546  return *(*i).second;
547 }
548 
549 
551 MSTLLogicControl::get(const std::string& id, const std::string& programID) const {
552  std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
553  if (i == myLogics.end()) {
554  return nullptr;
555  }
556  return (*i).second->getLogic(programID);
557 }
558 
559 
560 std::vector<std::string>
562  std::vector<std::string> ret;
563  for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
564  ret.push_back((*i).first);
565  }
566  return ret;
567 }
568 
569 
570 bool
571 MSTLLogicControl::add(const std::string& id, const std::string& programID,
572  MSTrafficLightLogic* logic, bool newDefault) {
573  if (myLogics.find(id) == myLogics.end()) {
574  myLogics[id] = new TLSLogicVariants();
575  }
576  std::map<std::string, TLSLogicVariants*>::iterator i = myLogics.find(id);
577  TLSLogicVariants* tlmap = (*i).second;
578  return tlmap->addLogic(programID, logic, myNetWasLoaded, newDefault);
579 }
580 
581 
582 bool
583 MSTLLogicControl::knows(const std::string& id) const {
584  std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
585  if (i == myLogics.end()) {
586  return false;
587  }
588  return true;
589 }
590 
591 
592 bool
594  bool hadErrors = false;
595  for (std::map<std::string, TLSLogicVariants*>::iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
596  hadErrors |= !(*i).second->checkOriginalTLS();
597  (*i).second->saveInitialStates();
598  }
599  myNetWasLoaded = true;
600  return !hadErrors;
601 }
602 
603 
604 bool
606  std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(tl->getID());
607  if (i == myLogics.end()) {
608  return false;
609  }
610  return (*i).second->isActive(tl);
611 }
612 
613 
615 MSTLLogicControl::getActive(const std::string& id) const {
616  std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
617  if (i == myLogics.end()) {
618  return nullptr;
619  }
620  return (*i).second->getActive();
621 }
622 
623 
624 void
625 MSTLLogicControl::switchTo(const std::string& id, const std::string& programID) {
626  // try to get the tls program definitions
627  std::map<std::string, TLSLogicVariants*>::iterator i = myLogics.find(id);
628  // handle problems
629  if (i == myLogics.end()) {
630  throw ProcessError("Could not switch tls '" + id + "' to program '" + programID + "': No such tls exists.");
631  }
632  (*i).second->switchTo(*this, programID);
633 }
634 
635 
636 void
637 MSTLLogicControl::addWAUT(SUMOTime refTime, const std::string& id,
638  const std::string& startProg, SUMOTime period) {
639  // check whether the waut was already defined
640  if (myWAUTs.find(id) != myWAUTs.end()) {
641  // report an error if so
642  throw InvalidArgument("Waut '" + id + "' was already defined.");
643  }
644  WAUT* w = new WAUT;
645  w->id = id;
646  w->refTime = refTime;
647  w->startProg = startProg;
648  w->period = period;
649  myWAUTs[id] = w;
650 }
651 
652 
653 void
654 MSTLLogicControl::addWAUTSwitch(const std::string& wautid,
655  SUMOTime when, const std::string& to) {
656  // try to get the waut
657  if (myWAUTs.find(wautid) == myWAUTs.end()) {
658  // report an error if the waut is not known
659  throw InvalidArgument("Waut '" + wautid + "' was not yet defined.");
660  }
661  // build and save the waut switch definition
662  WAUT* waut = myWAUTs[wautid];
663  WAUTSwitch s;
664  s.to = to;
665  s.when = (waut->refTime + when);
666  if (waut->period > 0) {
667  s.when = s.when % waut->period;
668  }
669  myWAUTs[wautid]->switches.push_back(s);
670 }
671 
672 
673 void
674 MSTLLogicControl::addWAUTJunction(const std::string& wautid,
675  const std::string& tls,
676  const std::string& proc,
677  bool synchron) {
678  // try to get the waut
679  if (myWAUTs.find(wautid) == myWAUTs.end()) {
680  // report an error if the waut is not known
681  throw InvalidArgument("Waut '" + wautid + "' was not yet defined.");
682  }
683  // try to get the tls to switch
684  if (myLogics.find(tls) == myLogics.end()) {
685  // report an error if the tls is not known
686  throw InvalidArgument("TLS '" + tls + "' to switch in WAUT '" + wautid + "' was not yet defined.");
687  }
688  WAUTJunction j;
689  j.junction = tls;
690  j.procedure = proc;
691  j.synchron = synchron;
692  myWAUTs[wautid]->junctions.push_back(j);
693 
694  std::string initProg = myWAUTs[wautid]->startProg;
695  std::vector<WAUTSwitch>::const_iterator first = myWAUTs[wautid]->switches.end();
696  SUMOTime minExecTime = -1;
697  for (std::vector<WAUTSwitch>::const_iterator i = myWAUTs[wautid]->switches.begin(); i != myWAUTs[wautid]->switches.end(); ++i) {
698  if ((*i).when > MSNet::getInstance()->getCurrentTimeStep() && (minExecTime == -1 || (*i).when < minExecTime)) {
699  minExecTime = (*i).when;
700  first = i;
701  }
702  if (first != myWAUTs[wautid]->switches.begin()) {
703  initProg = (*(first - 1)).to;
704  }
705  }
706  // activate the first one
707  switchTo(tls, initProg);
708 }
709 
710 
711 void
712 MSTLLogicControl::closeWAUT(const std::string& wautid) {
713  // try to get the waut
714  if (myWAUTs.find(wautid) == myWAUTs.end()) {
715  // report an error if the waut is not known
716  throw InvalidArgument("Waut '" + wautid + "' was not yet defined.");
717  }
718  WAUT* w = myWAUTs.find(wautid)->second;
719  std::string initProg = myWAUTs[wautid]->startProg;
720  // get the switch to be performed as first
721  std::vector<WAUTSwitch>::const_iterator first = w->switches.end();
722  SUMOTime minExecTime = -1;
723  for (std::vector<WAUTSwitch>::const_iterator i = w->switches.begin(); i != w->switches.end(); ++i) {
724  if ((*i).when > MSNet::getInstance()->getCurrentTimeStep() && (minExecTime == -1 || (*i).when < minExecTime)) {
725  minExecTime = (*i).when;
726  first = i;
727  }
728  }
729  // activate the first one
730  if (first != w->switches.end()) {
731  std::vector<WAUTSwitch>::const_iterator mbegin = w->switches.begin();
733  new SwitchInitCommand(*this, wautid, (int)distance(mbegin, first)),
734  (*first).when);
735  }
736  /*
737  // set the current program to all junctions
738  for(std::vector<WAUTJunction>::const_iterator i=w->junctions.begin(); i!=w->junctions.end(); ++i) {
739  switchTo((*i).junction, initProg);
740  }
741  */
742 }
743 
744 
745 SUMOTime
747  const std::string& wautid = cmd.getWAUTID();
748  int& index = cmd.getIndex();
749  WAUT* waut = myWAUTs[wautid];
750  WAUTSwitch s = waut->switches[index];
751  for (std::vector<WAUTJunction>::iterator i = myWAUTs[wautid]->junctions.begin(); i != myWAUTs[wautid]->junctions.end(); ++i) {
752  // get the current program and the one to instantiate
753  TLSLogicVariants* vars = myLogics.find((*i).junction)->second;
754  MSTrafficLightLogic* from = vars->getActive();
755  MSTrafficLightLogic* to = vars->getLogicInstantiatingOff(*this, s.to);
756  WAUTSwitchProcedure* proc = nullptr;
757  if ((*i).procedure == "GSP") {
758  proc = new WAUTSwitchProcedure_GSP(*this, *myWAUTs[wautid], from, to, (*i).synchron);
759  } else if ((*i).procedure == "Stretch") {
760  proc = new WAUTSwitchProcedure_Stretch(*this, *myWAUTs[wautid], from, to, (*i).synchron);
761  } else {
762  proc = new WAUTSwitchProcedure_JustSwitch(*this, *myWAUTs[wautid], from, to, (*i).synchron);
763  }
764 
766  p.junction = (*i).junction;
767  p.proc = proc;
768  p.from = from;
769  p.to = to;
770 
771  myCurrentlySwitched.push_back(p);
772  }
773  index++;
774  if (index == (int)waut->switches.size()) {
775  if (waut->period <= 0) {
776  return 0;
777  } else {
778  index = 0; // start over
779  for (WAUTSwitch& ws : waut->switches) {
780  ws.when += waut->period;
781  }
782  }
783  }
784  return myWAUTs[wautid]->switches[index].when - MSNet::getInstance()->getCurrentTimeStep();
785 }
786 
787 
788 void
790  for (std::vector<WAUTSwitchProcess>::iterator i = myCurrentlySwitched.begin(); i != myCurrentlySwitched.end();) {
791  const WAUTSwitchProcess& proc = *i;
792  if (proc.proc->trySwitch(step)) {
793  delete proc.proc;
794  // do not switch away from TraCI control
795  if (getActive(proc.to->getID())->getProgramID() != TRACI_PROGRAM) {
796  switchTo(proc.to->getID(), proc.to->getProgramID());
797  }
798  i = myCurrentlySwitched.erase(i);
799  } else {
800  ++i;
801  }
802  }
803 }
804 
805 
806 std::pair<SUMOTime, MSPhaseDefinition>
807 MSTLLogicControl::getPhaseDef(const std::string& tlid) const {
808  MSTrafficLightLogic* tl = getActive(tlid);
809  return std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), tl->getCurrentPhaseDef());
810 }
811 
812 
813 void
815  for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
816  (*i).second->addLogic("off", new MSOffTrafficLightLogic(*this, (*i).first), true, true);
817  }
818 }
819 
820 void
823 }
824 
825 void
828 }
829 
830 /****************************************************************************/
#define TRACI_PROGRAM
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:284
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:276
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:31
T MIN2(T a, T b)
Definition: StdDefs.h:73
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:44
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:171
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:313
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition: MSNet.h:464
virtual void createTLWrapper(MSTrafficLightLogic *)
creates a wrapper for the given logic (see GUINet)
Definition: MSNet.h:570
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:73
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:60
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.