SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MSTLLogicControl.cpp
Go to the documentation of this file.
1 /****************************************************************************/
13 // A class that stores and controls tls and switching of their programs
14 /****************************************************************************/
15 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
16 // Copyright (C) 2001-2014 DLR (http://www.dlr.de/) and contributors
17 /****************************************************************************/
18 //
19 // This file is part of SUMO.
20 // SUMO is free software: you can redistribute it and/or modify
21 // it under the terms of the GNU General Public License as published by
22 // the Free Software Foundation, either version 3 of the License, or
23 // (at your option) any later version.
24 //
25 /****************************************************************************/
26 // ===========================================================================
27 // included modules
28 // ===========================================================================
29 #ifdef _MSC_VER
30 #include <windows_config.h>
31 #else
32 #include <config.h>
33 #endif
34 
35 #include <vector>
36 #include <algorithm>
37 #include <cassert>
38 #include <iterator>
39 #include "MSTrafficLightLogic.h"
41 #include "MSTLLogicControl.h"
42 #include "MSOffTrafficLightLogic.h"
44 #include <microsim/MSNet.h>
46 #include <utils/common/ToString.h>
48 
49 #ifdef CHECK_MEMORY_LEAKS
50 #include <foreign/nvwa/debug_new.h>
51 #endif // CHECK_MEMORY_LEAKS
52 
53 
54 // ===========================================================================
55 // method definitions
56 // ===========================================================================
57 /* -------------------------------------------------------------------------
58  * MSTLLogicControl::TLSLogicVariants - methods
59  * ----------------------------------------------------------------------- */
61  : myCurrentProgram(0) {
62 }
63 
64 
66  std::map<std::string, MSTrafficLightLogic*>::const_iterator j;
67  for (std::map<std::string, MSTrafficLightLogic*>::iterator j = myVariants.begin(); j != myVariants.end(); ++j) {
68  delete(*j).second;
69  }
70  for (std::vector<OnSwitchAction*>::iterator i = mySwitchActions.begin(); i != mySwitchActions.end(); ++i) {
71  delete *i;
72  }
73 }
74 
75 
76 bool
78  bool hadErrors = false;
79  for (std::map<std::string, MSTrafficLightLogic*>::const_iterator j = myVariants.begin(); j != myVariants.end(); ++j) {
80  const MSTrafficLightLogic::Phases& phases = (*j).second->getPhases();
81  unsigned int linkNo = (unsigned int)(*j).second->getLinks().size();
82  bool hadProgramErrors = false;
83  for (MSTrafficLightLogic::Phases::const_iterator i = phases.begin(); i != phases.end(); ++i) {
84  if ((*i)->getState().length() < linkNo) {
85  hadProgramErrors = true;
86  }
87  }
88  if (hadProgramErrors) {
89  WRITE_ERROR("Mismatching phase size in tls '" + (*j).second->getID() + "', program '" + (*j).first + "'.");
90  hadErrors = true;
91  }
92  }
93  return !hadErrors;
94 }
95 
96 
97 void
99  myOriginalLinkStates = myCurrentProgram->collectLinkStates();
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 == 0) {
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  myCurrentProgram = logic;
123  }
124  // add to the list of logic
125  myVariants[programID] = logic;
126  if (myVariants.size() == 1 || isNewDefault) {
127  logic->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
128  executeOnSwitchActions();
129  }
130  return true;
131 }
132 
133 
135 MSTLLogicControl::TLSLogicVariants::getLogic(const std::string& programID) const {
136  if (myVariants.find(programID) == myVariants.end()) {
137  return 0;
138  }
139  return myVariants.find(programID)->second;
140 }
141 
142 
145  const std::string& programID) {
146  if (myVariants.find(programID) == myVariants.end()) {
147  if (programID == "off") {
148  // build an off-tll if this switch indicates it
149  if (!addLogic("off", new MSOffTrafficLightLogic(tlc, myCurrentProgram->getID()), true, true)) {
150  // inform the user if this fails
151  throw ProcessError("Could not build an off-state for tls '" + myCurrentProgram->getID() + "'.");
152  }
153  } else {
154  // inform the user about a missing logic
155  throw ProcessError("Can not switch tls '" + myCurrentProgram->getID() + "' to program '" + programID + "';\n The program is not known.");
156  }
157  }
158  return getLogic(programID);
159 }
160 
161 
162 void
164  const std::string& state) {
165  // build only once...
166  MSTrafficLightLogic* logic = getLogic("online");
167  if (logic == 0) {
168  MSPhaseDefinition* phase = new MSPhaseDefinition(DELTA_T, state);
169  std::vector<MSPhaseDefinition*> phases;
170  phases.push_back(phase);
171  logic = new MSSimpleTrafficLightLogic(tlc, myCurrentProgram->getID(), "online", phases, 0,
173  std::map<std::string, std::string>());
174  addLogic("online", logic, true, true);
175  } else {
176  MSPhaseDefinition nphase(DELTA_T, state);
177  *(dynamic_cast<MSSimpleTrafficLightLogic*>(logic)->getPhases()[0]) = nphase;
178  switchTo(tlc, "online");
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 
211 
212 void
214  // set the found wished sub-program as this tls' current one
215  myCurrentProgram = getLogicInstantiatingOff(tlc, programID);
216  myCurrentProgram->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
217  executeOnSwitchActions();
218 }
219 
220 
221 void
223  for (std::vector<OnSwitchAction*>::const_iterator i = mySwitchActions.begin(); i != mySwitchActions.end(); ++i) {
224  (*i)->execute();
225  }
226 }
227 
228 
229 void
231  for (std::map<std::string, MSTrafficLightLogic*>::iterator i = myVariants.begin(); i != myVariants.end(); ++i) {
232  (*i).second->addLink(link, lane, pos);
233  }
234 }
235 
236 
237 
238 /* -------------------------------------------------------------------------
239  * method definitions for the Switching Procedures
240  * ----------------------------------------------------------------------- */
241 /* -------------------------------------------------------------------------
242  * method definitions for WAUTSwitchProcedure
243  * ----------------------------------------------------------------------- */
244 unsigned int
246  std::string val = logic.getParameter("GSP", "");
247  if (val.length() == 0) {
248  return 0;
249  }
250  return TplConvert::_2int(val.c_str());
251 }
252 
253 
254 bool
256  SUMOTime gspTime = TIME2STEPS(getGSPValue(logic)) % logic.getDefaultCycleTime();
257  SUMOTime programTime = logic.getOffsetFromIndex(logic.getCurrentPhaseIndex())
258  + (logic.getCurrentPhaseDef().duration - (logic.getNextSwitchTime() - currentTime));
259  return gspTime == programTime;
260 }
261 
262 
263 SUMOTime
265  unsigned int stepOfMyPos = logic.getIndexFromOffset(toTime);
266  SUMOTime startOfPhase = logic.getOffsetFromIndex(stepOfMyPos);
267  assert(toTime >= startOfPhase);
268  return toTime - startOfPhase;
269 }
270 
271 
272 void
274  unsigned int stepTo = logic.getIndexFromOffset(toTime);
275  SUMOTime diff = getDiffToStartOfPhase(logic, toTime);
276  const MSPhaseDefinition& phase = logic.getPhase(stepTo);
277  SUMOTime leftDuration = phase.duration - diff;
278  logic.changeStepAndDuration(myControl, simStep, stepTo, leftDuration);
279 }
280 
281 
282 
283 /* -------------------------------------------------------------------------
284  * method definitions for WAUTSwitchProcedure_JustSwitch
285  * ----------------------------------------------------------------------- */
287  MSTLLogicControl& control, WAUT& waut,
288  MSTrafficLightLogic* from, MSTrafficLightLogic* to, bool synchron)
289  : MSTLLogicControl::WAUTSwitchProcedure(control, waut, from, to, synchron) {}
290 
291 
293 
294 
295 bool
297  return true;
298 }
299 
300 
301 
302 /* -------------------------------------------------------------------------
303  * method definitions for WAUTSwitchProcedure_GSP
304  * ----------------------------------------------------------------------- */
306  MSTLLogicControl& control, WAUT& waut,
307  MSTrafficLightLogic* from, MSTrafficLightLogic* to, bool synchron)
308  : MSTLLogicControl::WAUTSwitchProcedure(control, waut, from, to, synchron) {}
309 
310 
312 
313 
314 bool
316  // switch to the next programm if the GSP is reached
317  if (isPosAtGSP(step, *myFrom)) {
318  // adapt program's state
319  if (mySwitchSynchron) {
320  adaptLogic(step);
321  } else {
322  switchToPos(step, *myTo, TIME2STEPS(getGSPValue(*myTo)));
323  }
324  // switch to destination program
325  return true;
326  }
327  // do not switch, yet
328  return false;
329 }
330 
331 
332 void
334  SUMOTime gspTo = TIME2STEPS(getGSPValue(*myTo));
335  unsigned int stepTo = myTo->getIndexFromOffset(gspTo);
336  SUMOTime cycleTimeTo = myTo->getDefaultCycleTime();
337  if (gspTo == cycleTimeTo) {
338  gspTo = 0;
339  }
340 
341  SUMOTime currentPosTo = myTo->getOffsetFromIndex(myTo->getCurrentPhaseIndex());
342  currentPosTo += (myTo->getCurrentPhaseDef().duration - (myTo->getNextSwitchTime() - step));
343  SUMOTime diff = getDiffToStartOfPhase(*myTo, gspTo);
344 
345  SUMOTime deltaToStretch = 0;
346  if (gspTo >= currentPosTo) {
347  deltaToStretch = (gspTo - currentPosTo);
348  } else {
349  deltaToStretch = (cycleTimeTo - currentPosTo + gspTo);
350  }
351  unsigned int newdur = (unsigned int) myTo->getPhase(stepTo).duration - diff + deltaToStretch;
352  myTo->changeStepAndDuration(myControl, step, stepTo, newdur);
353 }
354 
355 
356 
357 /* -------------------------------------------------------------------------
358  * method definitions for WAUTSwitchProcedure_Stretch
359  * ----------------------------------------------------------------------- */
361  MSTLLogicControl& control, WAUT& waut,
362  MSTrafficLightLogic* from, MSTrafficLightLogic* to, bool synchron)
363  : MSTLLogicControl::WAUTSwitchProcedure(control, waut, from, to, synchron) {}
364 
365 
367 
368 
369 bool
371  // switch to the next programm if the GSP is reached
372  if (isPosAtGSP(step, *myFrom)) {
373  // adapt program's state
374  if (mySwitchSynchron) {
375  adaptLogic(step);
376  } else {
377  switchToPos(step, *myTo, TIME2STEPS(getGSPValue(*myTo)));
378  }
379  // switch to destination program
380  return true;
381  }
382  // do not switch, yet
383  return false;
384 }
385 
386 
387 void
389  SUMOTime gspTo = TIME2STEPS(getGSPValue(*myTo));
390  SUMOTime cycleTime = myTo->getDefaultCycleTime();
391  // the position, where the logic has to be after synchronisation
392  SUMOTime posAfterSyn = myTo->getPhaseIndexAtTime(step);
393  // calculate the difference, that has to be equalized
394  SUMOTime deltaToCut = 0;
395  if (posAfterSyn < gspTo) {
396  deltaToCut = posAfterSyn + cycleTime - gspTo;
397  } else {
398  deltaToCut = posAfterSyn - gspTo;
399  }
400  // test, wheter cutting of the Signalplan is possible
401  SUMOTime deltaPossible = 0;
402  int areasNo = getStretchAreaNo(myTo);
403  for (int i = 0; i < areasNo; i++) {
404  StretchBereichDef def = getStretchBereichDef(myTo, i + 1);
405  assert(def.end >= def.begin);
406  deltaPossible += TIME2STEPS(def.end - def.begin);
407  }
408  int stretchUmlaufAnz = (int) TplConvert::_2SUMOReal(myTo->getParameter("StretchUmlaufAnz", "").c_str());
409  deltaPossible = stretchUmlaufAnz * deltaPossible;
410  if ((deltaPossible > deltaToCut) && (deltaToCut < (cycleTime / 2))) {
411  cutLogic(step, gspTo, deltaToCut);
412  } else {
413  SUMOTime deltaToStretch = (cycleTime - deltaToCut) % cycleTime;
414  stretchLogic(step, gspTo, deltaToStretch);
415  }
416 }
417 
418 
419 void
421  unsigned int actStep = myTo->getIndexFromOffset(startPos);
422  // switches to startPos and cuts this phase, if there is a "Bereich"
423  int areasNo = getStretchAreaNo(myTo);
424  SUMOTime toCut = 0;
425  for (int i = 0; i < areasNo; i++) {
426  StretchBereichDef def = getStretchBereichDef(myTo, i + 1);
427  SUMOTime begin = TIME2STEPS(def.begin);
428  unsigned int end = TIME2STEPS(def.end);
429  size_t stepOfBegin = myTo->getIndexFromOffset(begin);
430  if (stepOfBegin == actStep) {
431  if (begin < startPos) {
432  toCut = end - startPos;
433  } else {
434  toCut = end - begin;
435  }
436  toCut = MIN2(allCutTime, toCut);
437  allCutTime = allCutTime - toCut;
438  }
439  }
440  SUMOTime remainingDur = myTo->getPhase(actStep).duration - getDiffToStartOfPhase(*myTo, startPos);
441  SUMOTime newDur = remainingDur - toCut;
442  myTo->changeStepAndDuration(myControl, step, actStep, newDur);
443 
444  // changes the duration of all other phases
445  int currStep = (actStep + 1) % (int)myTo->getPhases().size();
446  while (allCutTime > 0) {
447  for (int i = currStep; i < (int) myTo->getPhases().size(); i++) {
448  SUMOTime beginOfPhase = myTo->getOffsetFromIndex(i);
449  SUMOTime durOfPhase = myTo->getPhase(i).duration;
450  SUMOTime endOfPhase = beginOfPhase + durOfPhase;
451  for (int i = 0; i < areasNo; i++) {
452  StretchBereichDef def = getStretchBereichDef(myTo, i + 1);
453  SUMOTime begin = TIME2STEPS(def.begin);
454  SUMOTime end = TIME2STEPS(def.end);
455  if ((beginOfPhase <= begin) && (endOfPhase >= end)) {
456  SUMOTime maxCutOfPhase = MIN2(end - begin, allCutTime);
457  allCutTime = allCutTime - maxCutOfPhase;
458  durOfPhase = durOfPhase - maxCutOfPhase;
459  }
460  }
461  myTo->addOverridingDuration(durOfPhase);
462  }
463  currStep = 0;
464  }
465 }
466 
467 void
469  unsigned int currStep = myTo->getIndexFromOffset(startPos);
470  SUMOTime durOfPhase = myTo->getPhase(currStep).duration;
471  SUMOTime remainingStretchTime = allStretchTime;
472  SUMOTime StretchTimeOfPhase = 0;
473  unsigned int stretchUmlaufAnz = (unsigned int) TplConvert::_2SUMOReal(myTo->getParameter("StretchUmlaufAnz", "").c_str());
474  SUMOReal facSum = 0;
475  int areasNo = getStretchAreaNo(myTo);
476  for (int x = 0; x < areasNo; x++) {
477  StretchBereichDef def = getStretchBereichDef(myTo, x + 1);
478  facSum += def.fac;
479  }
480  facSum *= stretchUmlaufAnz;
481 
482  //switch to startPos and stretch this phase, if there is a end of "bereich" between startpos and end of phase
483  SUMOTime diffToStart = getDiffToStartOfPhase(*myTo, startPos);
484  for (int x = 0; x < areasNo; x++) {
485  StretchBereichDef def = getStretchBereichDef(myTo, x + 1);
486  SUMOTime end = TIME2STEPS(def.end);
487  SUMOTime endOfPhase = (startPos + durOfPhase - diffToStart);
488  if (end <= endOfPhase && end >= startPos) {
489  SUMOReal fac = def.fac;
490  SUMOReal actualfac = fac / facSum;
491  facSum = facSum - fac;
492  StretchTimeOfPhase = TIME2STEPS(int(STEPS2TIME(remainingStretchTime) * actualfac + 0.5));
493  remainingStretchTime = allStretchTime - StretchTimeOfPhase;
494  }
495  }
496  if (facSum == 0) {
497  WRITE_WARNING("The computed factor sum in WAUT '" + myWAUT.id + "' at time '" + toString(STEPS2TIME(step)) + "' equals zero;\n assuming an error in WAUT definition.");
498  return;
499  }
500  durOfPhase = durOfPhase - diffToStart + StretchTimeOfPhase;
501  myTo->changeStepAndDuration(myControl, step, currStep, durOfPhase);
502 
503  currStep = (currStep + 1) % (int)myTo->getPhases().size();
504  // stretch all other phases, if there is a "bereich"
505  while (remainingStretchTime > 0) {
506  for (unsigned int i = currStep; i < myTo->getPhases().size() && remainingStretchTime > 0; i++) {
507  durOfPhase = myTo->getPhase(i).duration;
508  SUMOTime beginOfPhase = myTo->getOffsetFromIndex(i);
509  SUMOTime endOfPhase = beginOfPhase + durOfPhase;
510  for (int j = 0; j < areasNo && remainingStretchTime > 0; j++) {
511  StretchBereichDef def = getStretchBereichDef(myTo, j + 1);
512  SUMOTime end = TIME2STEPS(def.end);
513  SUMOReal fac = def.fac;
514  if ((beginOfPhase <= end) && (endOfPhase >= end)) {
515  SUMOReal actualfac = fac / facSum;
516  StretchTimeOfPhase = TIME2STEPS(int(STEPS2TIME(remainingStretchTime) * actualfac + 0.5));
517  facSum -= fac;
518  durOfPhase += StretchTimeOfPhase;
519  remainingStretchTime -= StretchTimeOfPhase;
520  }
521  }
522  myTo->addOverridingDuration(durOfPhase);
523  }
524  currStep = 0;
525  }
526 }
527 
528 int
530  int no = 0;
531  while (from->getParameter("B" + toString(no + 1) + ".begin", "") != "") {
532  no++;
533  }
534  return no;
535 }
536 
537 
540  StretchBereichDef def;
541  def.begin = TplConvert::_2SUMOReal(from->getParameter("B" + toString(index) + ".begin", "").c_str());
542  def.end = TplConvert::_2SUMOReal(from->getParameter("B" + toString(index) + ".end", "").c_str());
543  def.fac = TplConvert::_2SUMOReal(from->getParameter("B" + toString(index) + ".factor", "").c_str());
544  return def;
545 }
546 
547 
548 
549 /* -------------------------------------------------------------------------
550  * method definitions for MSTLLogicControl
551  * ----------------------------------------------------------------------- */
553  : myNetWasLoaded(false) {}
554 
555 
557  // delete tls
558  for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
559  delete(*i).second;
560  }
561  // delete WAUTs
562  for (std::map<std::string, WAUT*>::const_iterator i = myWAUTs.begin(); i != myWAUTs.end(); ++i) {
563  delete(*i).second;
564  }
565 }
566 
567 
568 void
570  for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
571  (*i).second->getActive()->setTrafficLightSignals(t);
572  }
573 }
574 
575 
576 std::vector<MSTrafficLightLogic*>
578  std::vector<MSTrafficLightLogic*> ret;
579  std::map<std::string, TLSLogicVariants*>::const_iterator i;
580  for (i = myLogics.begin(); i != myLogics.end(); ++i) {
581  std::vector<MSTrafficLightLogic*> s = (*i).second->getAllLogics();
582  copy(s.begin(), s.end(), back_inserter(ret));
583  }
584  return ret;
585 }
586 
588 MSTLLogicControl::get(const std::string& id) const {
589  std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
590  if (i == myLogics.end()) {
591  throw InvalidArgument("The tls '" + id + "' is not known.");
592  }
593  return *(*i).second;
594 }
595 
596 
598 MSTLLogicControl::get(const std::string& id, const std::string& programID) const {
599  std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
600  if (i == myLogics.end()) {
601  return 0;
602  }
603  return (*i).second->getLogic(programID);
604 }
605 
606 
607 std::vector<std::string>
609  std::vector<std::string> ret;
610  for (std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
611  ret.push_back((*i).first);
612  }
613  return ret;
614 }
615 
616 
617 bool
618 MSTLLogicControl::add(const std::string& id, const std::string& programID,
619  MSTrafficLightLogic* logic, bool newDefault) {
620  if (myLogics.find(id) == myLogics.end()) {
621  myLogics[id] = new TLSLogicVariants();
622  }
623  std::map<std::string, TLSLogicVariants*>::iterator i = myLogics.find(id);
624  TLSLogicVariants* tlmap = (*i).second;
625  return tlmap->addLogic(programID, logic, myNetWasLoaded, newDefault);
626 }
627 
628 
629 bool
630 MSTLLogicControl::knows(const std::string& id) const {
631  std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
632  if (i == myLogics.end()) {
633  return false;
634  }
635  return true;
636 }
637 
638 
639 bool
641  bool hadErrors = false;
642  for (std::map<std::string, TLSLogicVariants*>::iterator i = myLogics.begin(); i != myLogics.end(); ++i) {
643  hadErrors |= !(*i).second->checkOriginalTLS();
644  (*i).second->saveInitialStates();
645  }
646  myNetWasLoaded = true;
647  return !hadErrors;
648 }
649 
650 
651 bool
653  std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(tl->getID());
654  if (i == myLogics.end()) {
655  return false;
656  }
657  return (*i).second->isActive(tl);
658 }
659 
660 
662 MSTLLogicControl::getActive(const std::string& id) const {
663  std::map<std::string, TLSLogicVariants*>::const_iterator i = myLogics.find(id);
664  if (i == myLogics.end()) {
665  return 0;
666  }
667  return (*i).second->getActive();
668 }
669 
670 
671 void
672 MSTLLogicControl::switchTo(const std::string& id, const std::string& programID) {
673  // try to get the tls program definitions
674  std::map<std::string, TLSLogicVariants*>::iterator i = myLogics.find(id);
675  // handle problems
676  if (i == myLogics.end()) {
677  throw ProcessError("Could not switch tls '" + id + "' to program '" + programID + "': No such tls exists.");
678  }
679  (*i).second->switchTo(*this, programID);
680 }
681 
682 
683 void
684 MSTLLogicControl::addWAUT(SUMOTime refTime, const std::string& id,
685  const std::string& startProg) {
686  // check whether the waut was already defined
687  if (myWAUTs.find(id) != myWAUTs.end()) {
688  // report an error if so
689  throw InvalidArgument("Waut '" + id + "' was already defined.");
690  }
691  WAUT* w = new WAUT;
692  w->id = id;
693  w->refTime = refTime;
694  w->startProg = startProg;
695  myWAUTs[id] = w;
696 }
697 
698 
699 void
700 MSTLLogicControl::addWAUTSwitch(const std::string& wautid,
701  SUMOTime when, const std::string& to) {
702  // try to get the waut
703  if (myWAUTs.find(wautid) == myWAUTs.end()) {
704  // report an error if the waut is not known
705  throw InvalidArgument("Waut '" + wautid + "' was not yet defined.");
706  }
707  // build and save the waut switch definition
708  WAUTSwitch s;
709  s.to = to;
710  s.when = (myWAUTs[wautid]->refTime + when) % 86400000;
711  myWAUTs[wautid]->switches.push_back(s);
712 }
713 
714 
715 void
716 MSTLLogicControl::addWAUTJunction(const std::string& wautid,
717  const std::string& tls,
718  const std::string& proc,
719  bool synchron) {
720  // try to get the waut
721  if (myWAUTs.find(wautid) == myWAUTs.end()) {
722  // report an error if the waut is not known
723  throw InvalidArgument("Waut '" + wautid + "' was not yet defined.");
724  }
725  // try to get the tls to switch
726  if (myLogics.find(tls) == myLogics.end()) {
727  // report an error if the tls is not known
728  throw InvalidArgument("TLS '" + tls + "' to switch in WAUT '" + wautid + "' was not yet defined.");
729  }
730  WAUTJunction j;
731  j.junction = tls;
732  j.procedure = proc;
733  j.synchron = synchron;
734  myWAUTs[wautid]->junctions.push_back(j);
735 
736  std::string initProg = myWAUTs[wautid]->startProg;
737  std::vector<WAUTSwitch>::const_iterator first = myWAUTs[wautid]->switches.end();
738  SUMOTime minExecTime = -1;
739  for (std::vector<WAUTSwitch>::const_iterator i = myWAUTs[wautid]->switches.begin(); i != myWAUTs[wautid]->switches.end(); ++i) {
740  if ((*i).when > MSNet::getInstance()->getCurrentTimeStep() && (minExecTime == -1 || (*i).when < minExecTime)) {
741  minExecTime = (*i).when;
742  first = i;
743  }
744  if (first != myWAUTs[wautid]->switches.begin()) {
745  initProg = (*(first - 1)).to;
746  }
747  }
748  // activate the first one
749  switchTo(tls, initProg);
750 }
751 
752 
753 void
754 MSTLLogicControl::closeWAUT(const std::string& wautid) {
755  // try to get the waut
756  if (myWAUTs.find(wautid) == myWAUTs.end()) {
757  // report an error if the waut is not known
758  throw InvalidArgument("Waut '" + wautid + "' was not yet defined.");
759  }
760  WAUT* w = myWAUTs.find(wautid)->second;
761  std::string initProg = myWAUTs[wautid]->startProg;
762  // get the switch to be performed as first
763  std::vector<WAUTSwitch>::const_iterator first = w->switches.end();
764  SUMOTime minExecTime = -1;
765  for (std::vector<WAUTSwitch>::const_iterator i = w->switches.begin(); i != w->switches.end(); ++i) {
766  if ((*i).when > MSNet::getInstance()->getCurrentTimeStep() && (minExecTime == -1 || (*i).when < minExecTime)) {
767  minExecTime = (*i).when;
768  first = i;
769  }
770  }
771  // activate the first one
772  if (first != w->switches.end()) {
773  std::vector<WAUTSwitch>::const_iterator mbegin = w->switches.begin();
775  new SwitchInitCommand(*this, wautid, (unsigned int)distance(mbegin, first)),
776  (*first).when, MSEventControl::NO_CHANGE);
777  }
778  /*
779  // set the current program to all junctions
780  for(std::vector<WAUTJunction>::const_iterator i=w->junctions.begin(); i!=w->junctions.end(); ++i) {
781  switchTo((*i).junction, initProg);
782  }
783  */
784 }
785 
786 
787 SUMOTime
789  const std::string& wautid = cmd.getWAUTID();
790  unsigned int& index = cmd.getIndex();
791  WAUTSwitch s = myWAUTs[wautid]->switches[index];
792  for (std::vector<WAUTJunction>::iterator i = myWAUTs[wautid]->junctions.begin(); i != myWAUTs[wautid]->junctions.end(); ++i) {
793  // get the current program and the one to instantiate
794  TLSLogicVariants* vars = myLogics.find((*i).junction)->second;
795  MSTrafficLightLogic* from = vars->getActive();
796  MSTrafficLightLogic* to = vars->getLogicInstantiatingOff(*this, s.to);
797  WAUTSwitchProcedure* proc = 0;
798  if ((*i).procedure == "GSP") {
799  proc = new WAUTSwitchProcedure_GSP(*this, *myWAUTs[wautid], from, to, (*i).synchron);
800  } else if ((*i).procedure == "Stretch") {
801  proc = new WAUTSwitchProcedure_Stretch(*this, *myWAUTs[wautid], from, to, (*i).synchron);
802  } else {
803  proc = new WAUTSwitchProcedure_JustSwitch(*this, *myWAUTs[wautid], from, to, (*i).synchron);
804  }
805 
807  p.junction = (*i).junction;
808  p.proc = proc;
809  p.from = from;
810  p.to = to;
811 
812  myCurrentlySwitched.push_back(p);
813  }
814  index++;
815  if (index == static_cast<unsigned int>(myWAUTs[wautid]->switches.size())) {
816  return 0;
817  }
818  return myWAUTs[wautid]->switches[index].when - MSNet::getInstance()->getCurrentTimeStep();
819 }
820 
821 
822 void
824  for (std::vector<WAUTSwitchProcess>::iterator i = myCurrentlySwitched.begin(); i != myCurrentlySwitched.end();) {
825  const WAUTSwitchProcess& proc = *i;
826  if (proc.proc->trySwitch(step)) {
827  delete proc.proc;
828  switchTo((*i).to->getID(), (*i).to->getProgramID());
829  i = myCurrentlySwitched.erase(i);
830  } else {
831  ++i;
832  }
833  }
834 }
835 
836 
837 std::pair<SUMOTime, MSPhaseDefinition>
838 MSTLLogicControl::getPhaseDef(const std::string& tlid) const {
839  MSTrafficLightLogic* tl = getActive(tlid);
840  return std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), tl->getCurrentPhaseDef());
841 }
842 
843 
844 
845 /****************************************************************************/
846