Eclipse SUMO - Simulation of Urban MObility
MSSimpleTrafficLightLogic.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
22 // A fixed traffic light logic
23 /****************************************************************************/
24 #include <config.h>
25 
26 #include <cassert>
27 #include <utility>
28 #include <vector>
29 #include <bitset>
30 #include <sstream>
33 #include <microsim/MSNet.h>
35 #include "MSTLLogicControl.h"
36 #include "MSTrafficLightLogic.h"
38 
39 //#define DEBUG_COORDINATION
40 #define DEBUG_COND (getID()=="C")
41 
42 
43 // ===========================================================================
44 // member method definitions
45 // ===========================================================================
47  const std::string& id, const std::string& programID, const SUMOTime offset, const TrafficLightType logicType, const Phases& phases,
48  int step, SUMOTime delay,
49  const Parameterised::Map& parameters) :
50  MSTrafficLightLogic(tlcontrol, id, programID, offset, logicType, delay, parameters),
51  myPhases(phases),
52  myStep(step) {
54  if (myStep < (int)myPhases.size()) {
55  myPhases[myStep]->myLastSwitch = SIMSTEP;
56  }
57  // the following initializations are only used by 'actuated' and 'delay_based' but do not affect 'static'
60  }
62  if (myPhases.size() > 0) {
63  SUMOTime earliest = SIMSTEP + getEarliest(-1);
64  if (earliest > getNextSwitchTime()) {
66  mySwitchCommand = new SwitchCommand(tlcontrol, this, earliest);
68  }
69  }
70 }
71 
72 
74  deletePhases();
75 }
76 
77 
78 // ------------ Switching and setting current rows
81  // check whether the current duration shall be increased
85  return delay;
86  }
87 
88  // increment the index
89  if (myPhases[myStep]->nextPhases.size() > 0 && myPhases[myStep]->nextPhases.front() >= 0) {
90  myStep = myPhases[myStep]->nextPhases.front();
91  } else {
92  myStep++;
93  }
94  // if the last phase was reached ...
95  if (myStep >= (int)myPhases.size()) {
96  // ... set the index to the first phase
97  myStep = 0;
98  }
99  assert((int)myPhases.size() > myStep);
100  //stores the time the phase started
102  // check whether the next duration was overridden
103  if (myOverridingTimes.size() > 0) {
104  SUMOTime nextDuration = myOverridingTimes[0];
105  myOverridingTimes.erase(myOverridingTimes.begin());
106  return nextDuration;
107  }
108  // return offset to the next switch
109  return myPhases[myStep]->duration;
110 }
111 
112 
113 // ------------ Static Information Retrieval
114 int
116  return (int) myPhases.size();
117 }
118 
119 
122  return myPhases;
123 }
124 
125 
128  return myPhases;
129 }
130 
131 
132 const MSPhaseDefinition&
134  assert((int)myPhases.size() > givenStep);
135  return *myPhases[givenStep];
136 }
137 
138 
139 // ------------ Dynamic Information Retrieval
140 int
142  return myStep;
143 }
144 
145 
146 const MSPhaseDefinition&
148  return *myPhases[myStep];
149 }
150 
151 
152 // ------------ Conversion between time and phase
153 SUMOTime
155  SUMOTime position = 0;
156  if (myStep > 0) {
157  for (int i = 0; i < myStep; i++) {
158  position = position + getPhase(i).duration;
159  }
160  }
161  position = position + simStep - getPhase(myStep).myLastSwitch;
162  position = position % myDefaultCycleTime;
163  assert(position <= myDefaultCycleTime);
164  return position;
165 }
166 
167 
168 SUMOTime
170  assert(index < (int)myPhases.size());
171  if (index == 0) {
172  return 0;
173  }
174  SUMOTime pos = 0;
175  for (int i = 0; i < index; i++) {
176  pos += getPhase(i).duration;
177  }
178  return pos;
179 }
180 
181 
182 int
184  offset = offset % myDefaultCycleTime;
185  if (offset == myDefaultCycleTime) {
186  return 0;
187  }
188  SUMOTime testPos = 0;
189  for (int i = 0; i < (int)myPhases.size(); i++) {
190  testPos = testPos + getPhase(i).duration;
191  if (testPos > offset) {
192  return i;
193  }
194  if (testPos == offset) {
195  assert((int)myPhases.size() > (i + 1));
196  return (i + 1);
197  }
198  }
199  return 0;
200 }
201 
202 
203 SUMOTime
205  return (myCoordinated
206  ? (t - myOffset) % myDefaultCycleTime
207  : (t - myPhases[0]->myLastSwitch) % myDefaultCycleTime);
208 }
209 
210 
211 
212 
213 SUMOTime
215  SUMOTime earliest = getEarliestEnd();
216  if (earliest == MSPhaseDefinition::UNSPECIFIED_DURATION) {
217  return 0;
218  } else {
219  if (prevStart >= SIMSTEP - getTimeInCycle() && prevStart < getCurrentPhaseDef().myLastEnd) {
220  // phase was started and ended once already in the current cycle
221  // it should not end a second time in the same cycle
222  earliest += myDefaultCycleTime;
223 #ifdef DEBUG_COORDINATION
224  if (DEBUG_COND) {
225  std::cout << SIMTIME << " tl=" << getID() << " getEarliest phase=" << myStep
226  << " prevStart= " << STEPS2TIME(prevStart)
227  << " prevEnd= " << STEPS2TIME(getCurrentPhaseDef().myLastEnd)
228  << " cycleStart=" << STEPS2TIME(SIMSTEP - getTimeInCycle()) << " started Twice - move into next cycle\n";
229  }
230 #endif
231  } else {
232  SUMOTime latest = getLatestEnd();
234  const SUMOTime minRemaining = getMinDur() - (SIMSTEP - getCurrentPhaseDef().myLastSwitch);
235  const SUMOTime minEnd = getTimeInCycle() + minRemaining;
236  if (latest > earliest && latest < minEnd) {
237  // cannot terminate phase between earliest and latest -> move end into next cycle
238  earliest += myDefaultCycleTime;
239  } else if (latest < earliest && latest >= minEnd) {
240  // can ignore earliest since it counts from the previous cycle
241  earliest -= myDefaultCycleTime;
242  }
243 #ifdef DEBUG_COORDINATION
244  if (DEBUG_COND) {
245  std::cout << SIMTIME << " tl=" << getID() << " getEarliest phase=" << myStep << " latest=" << STEPS2TIME(latest) << " minEnd="
246  << STEPS2TIME(minEnd) << " earliest=" << STEPS2TIME(earliest) << "\n";
247  }
248 #endif
249  }
250  }
251  const SUMOTime maxRemaining = getMaxDur() - (SIMSTEP - getCurrentPhaseDef().myLastSwitch);
252  return MIN2(earliest - getTimeInCycle(), maxRemaining);
253  }
254 }
255 
256 
257 SUMOTime
259  const SUMOTime latest = getLatestEnd();
261  return SUMOTime_MAX; // no restriction
262  } else {
263  if (latest < getEarliestEnd()) {
264  const SUMOTime running = SIMSTEP - getCurrentPhaseDef().myLastSwitch;
265  if (running < getTimeInCycle()) {
266  // phase was started in the current cycle so the restriction does not apply yet
267  return SUMOTime_MAX;
268  }
269  }
270 #ifdef DEBUG_COORDINATION
271  if (DEBUG_COND) {
272  std::cout << SIMTIME << " tl=" << getID() << " getLatest phase=" << myStep << " latest=" << STEPS2TIME(latest)
273  << " cycTime=" << STEPS2TIME(getTimeInCycle()) << " res=" << STEPS2TIME(latest - getTimeInCycle()) << "\n";
274  }
275 #endif
276  if (latest == myDefaultCycleTime && getTimeInCycle() == 0) {
277  // special case: end on cylce time wrap-around
278  return 0;
279  }
280  return MAX2(SUMOTime(0), latest - getTimeInCycle());
281  }
282 }
283 
284 
285 
286 // ------------ Changing phases and phase durations
287 void
289  SUMOTime simStep, int step, SUMOTime stepDuration) {
291  mySwitchCommand = new SwitchCommand(tlcontrol, this, stepDuration + simStep);
292  if (step >= 0 && step != myStep) {
293  myStep = step;
295  setTrafficLightSignals(simStep);
296  tlcontrol.get(getID()).executeOnSwitchActions();
297  }
299  mySwitchCommand, stepDuration + simStep);
300 }
301 
302 
303 void
305  assert(step < (int)phases.size());
306  deletePhases();
307  myPhases = phases;
308  myStep = step;
310 }
311 
312 
313 void
315  for (int i = 0; i < (int)myPhases.size(); i++) {
316  delete myPhases[i];
317  }
318 }
319 
320 void
323  out.writeAttr(SUMO_ATTR_ID, getID());
327  out.closeTag();
328 }
329 
330 const std::string
331 MSSimpleTrafficLightLogic::getParameter(const std::string& key, const std::string defaultValue) const {
332  if (key == "cycleTime") {
334  } else if (key == "offset") {
335  return toString(STEPS2TIME(myOffset));
336  } else if (key == "coordinated") {
337  return toString(myCoordinated);
338  } else if (key == "cycleSecond") {
340  } else if (key == "typeName") {
341  return toString(this->getLogicType());
342  }
343  return Parameterised::getParameter(key, defaultValue);
344 }
345 
346 void
347 MSSimpleTrafficLightLogic::setParameter(const std::string& key, const std::string& value) {
348  if (key == "cycleTime") {
350  Parameterised::setParameter(key, value);
351  } else if (key == "cycleSecond" || key == "typeName") {
352  throw InvalidArgument(key + " cannot be changed dynamically for traffic light '" + getID() + "'");
353  } else if (key == "offset") {
354  myOffset = string2time(value);
355  } else if (key == "coordinated") {
357  Parameterised::setParameter(key, value);
358  } else {
359  Parameterised::setParameter(key, value);
360  }
361 }
362 
363 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#define DEBUG_COND
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition: SUMOTime.cpp:46
#define STEPS2TIME(x)
Definition: SUMOTime.h:55
#define SIMSTEP
Definition: SUMOTime.h:61
#define SUMOTime_MAX
Definition: SUMOTime.h:34
#define SIMTIME
Definition: SUMOTime.h:62
#define TIME2STEPS(x)
Definition: SUMOTime.h:57
TrafficLightType
@ SUMO_TAG_TLLOGIC
a traffic light logic
@ SUMO_ATTR_PHASE
@ SUMO_ATTR_ID
@ SUMO_ATTR_PROGRAMID
@ SUMO_ATTR_DURATION
@ SUMO_ATTR_CYCLETIME
T MIN2(T a, T b)
Definition: StdDefs.h:76
T MAX2(T a, T b)
Definition: StdDefs.h:82
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.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:182
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition: MSNet.h:471
The definition of a single phase of a tls logic.
static const SUMOTime UNSPECIFIED_DURATION
SUMOTime myLastSwitch
Stores the timestep of the last on-switched of the phase.
SUMOTime duration
The duration of the phase.
SUMOTime getLatest() const
the maximum duration for keeping the current phase when considering 'latestEnd'
int getIndexFromOffset(SUMOTime offset) const override
Returns the step (the phasenumber) of a given position of the cycle.
virtual void changeStepAndDuration(MSTLLogicControl &tlcontrol, SUMOTime simStep, int step, SUMOTime stepDuration) override
Changes the current phase and her duration.
Phases myPhases
The list of phases this logic uses.
virtual void saveState(OutputDevice &out) const override
Saves the current tls states into the given stream.
const MSPhaseDefinition & getPhase(int givenstep) const override
Returns the definition of the phase from the given position within the plan.
SUMOTime getPhaseIndexAtTime(SUMOTime simStep) const override
Returns the index of the logic at the given simulation step.
SUMOTime getOffsetFromIndex(int index) const override
Returns the position (start of a phase during a cycle) from of a given step.
int getPhaseNumber() const override
Returns the number of phases.
SUMOTime getEarliest(SUMOTime prevStart) const
the minimum duration for keeping the current phase when considering 'earliestEnd'
void setPhases(const Phases &phases, int index)
Replaces the phases and set the phase index.
MSSimpleTrafficLightLogic(MSTLLogicControl &tlcontrol, const std::string &id, const std::string &programID, const SUMOTime offset, const TrafficLightType logicType, const Phases &phases, int step, SUMOTime delay, const Parameterised::Map &parameters)
Constructor.
virtual SUMOTime mapTimeInCycle(SUMOTime t) const override
map the given time into the current cycle
bool myCoordinated
whether coordination parameters earliestEnd, latestEnd are
int getCurrentPhaseIndex() const override
Returns the current index within the program.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const override
gets a parameter
void deletePhases()
frees memory responsibilities
const Phases & getPhases() const override
Returns the phases of this tls program.
virtual void setParameter(const std::string &key, const std::string &value) override
Sets a parameter and updates internal constants.
virtual SUMOTime trySwitch() override
Switches to the next phase.
const MSPhaseDefinition & getCurrentPhaseDef() const override
Returns the definition of the current phase.
A class that stores and controls tls and switching of their programs.
TLSLogicVariants & get(const std::string &id) const
Returns the variants of a named tls.
Class realising the switch between the traffic light phases.
void deschedule(MSTrafficLightLogic *tlLogic)
Marks this swicth as invalid (if the phase duration has changed, f.e.)
The parent class for traffic light logics.
SUMOTime myOffset
the offset parameter of the current program
SUMOTime computeCycleTime(const Phases &phases)
virtual SUMOTime getLatestEnd(int step=-1) const
std::vector< SUMOTime > myOverridingTimes
A list of duration overrides.
virtual SUMOTime getMinDur(int step=-1) const
SUMOTime myDefaultCycleTime
The cycle time (without changes)
SUMOTime getTimeInCycle() const
return time within the current cycle
TrafficLightType getLogicType() const
Returns the type of the logic.
virtual SUMOTime getEarliestEnd(int step=-1) const
SwitchCommand * mySwitchCommand
The current switch command.
SUMOTime myCurrentDurationIncrement
A value for enlarge the current duration.
virtual SUMOTime getMaxDur(int step=-1) const
SUMOTime getNextSwitchTime() const
Returns the assumed next switch time.
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
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
bool hasParameter(const std::string &key) const
Returns whether the parameter is set.
std::map< std::string, std::string > Map
parameters map
Definition: Parameterised.h:45
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
virtual void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static bool toBool(const std::string &sData)
converts a string into the bool value described by it by calling the char-type converter