Eclipse SUMO - Simulation of Urban MObility
MSTrafficLightLogic.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-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
17 // The parent class for traffic light logics
18 /****************************************************************************/
19 
20 
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #include <config.h>
25 
26 #include <cassert>
27 #include <string>
28 #include <iostream>
29 #include <map>
30 #include <microsim/MSLink.h>
31 #include <microsim/MSLane.h>
34 #include <microsim/MSNet.h>
35 #include <microsim/MSEdge.h>
36 #include <microsim/MSGlobals.h>
37 #include "MSTLLogicControl.h"
38 #include "MSTrafficLightLogic.h"
39 
40 
41 // ===========================================================================
42 // static value definitions
43 // ===========================================================================
45 
46 
47 // ===========================================================================
48 // member method definitions
49 // ===========================================================================
50 /* -------------------------------------------------------------------------
51  * member method definitions
52  * ----------------------------------------------------------------------- */
54  MSTrafficLightLogic* tlLogic, SUMOTime nextSwitch)
55  : myTLControl(tlcontrol), myTLLogic(tlLogic),
56  myAssumedNextSwitch(nextSwitch), myAmValid(true) {}
57 
58 
60 
61 
62 
65  // check whether this command has been descheduled
66  if (!myAmValid) {
67  return 0;
68  }
69  //
70  const bool isActive = myTLControl.isActive(myTLLogic);
71  int step1 = myTLLogic->getCurrentPhaseIndex();
72  SUMOTime next = myTLLogic->trySwitch();
73  int step2 = myTLLogic->getCurrentPhaseIndex();
74  if (step1 != step2) {
75  if (isActive) {
76  // execute any action connected to this tls
78  // set link priorities
80  // execute switch actions
82  }
83  }
84  myAssumedNextSwitch += next;
85  return next;
86 }
87 
88 
89 void
91  if (tlLogic == myTLLogic) {
92  myAmValid = false;
94  }
95 }
96 
97 
98 /* -------------------------------------------------------------------------
99  * member method definitions
100  * ----------------------------------------------------------------------- */
102  const std::string& programID, const TrafficLightType logicType, const SUMOTime delay,
103  const std::map<std::string, std::string>& parameters) :
104  Named(id), Parameterised(parameters),
105  myProgramID(programID),
106  myLogicType(logicType),
108  myDefaultCycleTime(0) {
109  mySwitchCommand = new SwitchCommand(tlcontrol, this, delay);
111 }
112 
113 
114 void
116  const Phases& phases = getPhases();
117  if (phases.size() > 0 && MSGlobals::gMesoTLSPenalty > 0) {
119  }
120  if (phases.size() > 1) {
121  bool haveWarnedAboutUnusedStates = false;
122  std::vector<bool> foundGreen(phases.front()->getState().size(), false);
123  for (int i = 0; i < (int)phases.size(); ++i) {
124  // warn about unused states
125  std::vector<int> nextPhases;
126  nextPhases.push_back((i + 1) % phases.size());
127  bool iNextDefault = true;
128  if (phases[i]->nextPhases.size() > 0) {
129  nextPhases = phases[i]->nextPhases;
130  iNextDefault = false;
131  }
132  for (int iNext : nextPhases) {
133  if (iNext < 0 || iNext >= (int)phases.size()) {
134  throw ProcessError("Invalid nextPhase " + toString(iNext) + " in tlLogic '" + getID()
135  + "', program '" + getProgramID() + "' with " + toString(phases.size()) + " phases");
136  }
137  const std::string optionalFrom = iNextDefault ? "" : " from phase " + toString(i);
138  const std::string& state1 = phases[i]->getState();
139  const std::string& state2 = phases[iNext]->getState();
140  assert(state1.size() == state2.size());
141  if (!haveWarnedAboutUnusedStates && state1.size() > myLanes.size() + myIgnoredIndices.size()) {
142  WRITE_WARNING("Unused states in tlLogic '" + getID()
143  + "', program '" + getProgramID() + "' in phase " + toString(i)
144  + " after tl-index " + toString((int)myLanes.size() - 1));
145  haveWarnedAboutUnusedStates = true;
146  }
147  // detect illegal states
148  const std::string::size_type illegal = state1.find_first_not_of(SUMOXMLDefinitions::ALLOWED_TLS_LINKSTATES);
149  if (std::string::npos != illegal) {
150  throw ProcessError("Illegal character '" + toString(state1[illegal]) + "' in tlLogic '" + getID()
151  + "', program '" + getProgramID() + "' in phase " + toString(i));
152  }
153  // warn about transitions from green to red without intermediate yellow
154  for (int j = 0; j < (int)MIN3(state1.size(), state2.size(), myLanes.size()); ++j) {
155  if ((LinkState)state2[j] == LINKSTATE_TL_RED
156  && ((LinkState)state1[j] == LINKSTATE_TL_GREEN_MAJOR
157  || (LinkState)state1[j] == LINKSTATE_TL_GREEN_MINOR)) {
158  for (LaneVector::const_iterator it = myLanes[j].begin(); it != myLanes[j].end(); ++it) {
159  if ((*it)->getPermissions() != SVC_PEDESTRIAN) {
160  WRITE_WARNING("Missing yellow phase in tlLogic '" + getID()
161  + "', program '" + getProgramID() + "' for tl-index " + toString(j)
162  + " when switching" + optionalFrom + " to phase " + toString(iNext));
163  return; // one warning per program is enough
164  }
165  }
166  }
167  }
168  // warn about links that never get the green light
169  for (int j = 0; j < (int)state1.size(); ++j) {
170  LinkState ls = (LinkState)state1[j];
172  foundGreen[j] = true;
173  }
174  }
175  }
176  }
177  for (int j = 0; j < (int)foundGreen.size(); ++j) {
178  if (!foundGreen[j]) {
179  WRITE_WARNING("Missing green phase in tlLogic '" + getID()
180  + "', program '" + getProgramID() + "' for tl-index " + toString(j));
181  break;
182  }
183  }
184  }
185 }
186 
187 
189  // no need to do something about mySwitchCommand here,
190  // it is handled by the event control
191 }
192 
193 
194 // ----------- Handling of controlled links
195 void
197  // !!! should be done within the loader (checking necessary)
198  myLinks.reserve(pos + 1);
199  while ((int)myLinks.size() <= pos) {
200  myLinks.push_back(LinkVector());
201  }
202  myLinks[pos].push_back(link);
203  //
204  myLanes.reserve(pos + 1);
205  while ((int)myLanes.size() <= pos) {
206  myLanes.push_back(LaneVector());
207  }
208  myLanes[pos].push_back(lane);
209  link->setTLState((LinkState) getCurrentPhaseDef().getState()[pos], MSNet::getInstance()->getCurrentTimeStep());
210 }
211 
212 
213 void
215  myLinks = logic.myLinks;
216  myLanes = logic.myLanes;
218 }
219 
220 
221 std::map<MSLink*, LinkState>
223  std::map<MSLink*, LinkState> ret;
224  for (LinkVectorVector::const_iterator i1 = myLinks.begin(); i1 != myLinks.end(); ++i1) {
225  const LinkVector& l = (*i1);
226  for (LinkVector::const_iterator i2 = l.begin(); i2 != l.end(); ++i2) {
227  ret[*i2] = (*i2)->getState();
228  }
229  }
230  return ret;
231 }
232 
233 
234 bool
236  // get the current traffic light signal combination
237  const std::string& state = getCurrentPhaseDef().getState();
238  // go through the links
239  for (int i = 0; i < (int)myLinks.size(); i++) {
240  const LinkVector& currGroup = myLinks[i];
241  LinkState ls = (LinkState) state[i];
242  for (LinkVector::const_iterator j = currGroup.begin(); j != currGroup.end(); j++) {
243  (*j)->setTLState(ls, t);
244  }
245  }
246  return true;
247 }
248 
249 
250 void
251 MSTrafficLightLogic::resetLinkStates(const std::map<MSLink*, LinkState>& vals) const {
252  for (LinkVectorVector::const_iterator i1 = myLinks.begin(); i1 != myLinks.end(); ++i1) {
253  const LinkVector& l = (*i1);
254  for (LinkVector::const_iterator i2 = l.begin(); i2 != l.end(); ++i2) {
255  assert(vals.find(*i2) != vals.end());
256  (*i2)->setTLState(vals.find(*i2)->second, MSNet::getInstance()->getCurrentTimeStep());
257  }
258  }
259 }
260 
261 
262 // ----------- Static Information Retrieval
263 int
264 MSTrafficLightLogic::getLinkIndex(const MSLink* const link) const {
265  int index = 0;
266  for (LinkVectorVector::const_iterator i1 = myLinks.begin(); i1 != myLinks.end(); ++i1, ++index) {
267  const LinkVector& l = (*i1);
268  for (LinkVector::const_iterator i2 = l.begin(); i2 != l.end(); ++i2) {
269  if ((*i2) == link) {
270  return index;
271  }
272  }
273  }
274  return -1;
275 }
276 
277 
278 
279 // ----------- Dynamic Information Retrieval
280 SUMOTime
282  return mySwitchCommand != nullptr ? mySwitchCommand->getNextSwitchTime() : -1;
283 }
284 
285 
286 SUMOTime
288  const SUMOTime nextSwitch = getNextSwitchTime();
289  if (nextSwitch == -1) {
290  return -1;
291  } else {
292  const SUMOTime remaining = nextSwitch - MSNet::getInstance()->getCurrentTimeStep();
293  return getCurrentPhaseDef().duration - remaining;
294  }
295 }
296 
297 
298 // ----------- Changing phases and phase durations
299 void
301  myOverridingTimes.push_back(duration);
302 }
303 
304 
305 void
308 }
309 
310 
312  // set mesoscopic time penalties
313  const Phases& phases = getPhases();
314  const int numLinks = (int)myLinks.size();
315  // warning already given if not all states are used
316  assert(numLinks <= (int)phases.front()->getState().size());
317  SUMOTime duration = 0;
318  std::vector<double> redDuration(numLinks, 0);
319  std::vector<double> totalRedDuration(numLinks, 0);
320  std::vector<double> penalty(numLinks, 0);
321  for (int i = 0; i < (int)phases.size(); ++i) {
322  const std::string& state = phases[i]->getState();
323  duration += phases[i]->duration;
324  // warn about transitions from green to red without intermediate yellow
325  for (int j = 0; j < numLinks; ++j) {
326  if ((LinkState)state[j] == LINKSTATE_TL_RED
327  || (LinkState)state[j] == LINKSTATE_TL_REDYELLOW) {
328  redDuration[j] += STEPS2TIME(phases[i]->duration);
329  totalRedDuration[j] += STEPS2TIME(phases[i]->duration);
330  } else if (redDuration[j] > 0) {
331  penalty[j] += 0.5 * (redDuration[j] * redDuration[j] + redDuration[j]);
332  redDuration[j] = 0;
333  }
334  }
335  }
337  for (int j = 0; j < numLinks; ++j) {
338  if (redDuration[j] > 0) {
339  penalty[j] += 0.5 * (redDuration[j] * redDuration[j] + redDuration[j]);
340  redDuration[j] = 0;
341  }
342  }
343  const double durationSeconds = STEPS2TIME(duration);
344  std::set<const MSJunction*> controlledJunctions;
345  for (int j = 0; j < numLinks; ++j) {
346  for (int k = 0; k < (int)myLinks[j].size(); ++k) {
347  myLinks[j][k]->setMesoTLSPenalty(TIME2STEPS(MSGlobals::gMesoTLSPenalty * penalty[j] / durationSeconds));
348  myLinks[j][k]->setGreenFraction(MAX2((durationSeconds - MSGlobals::gMesoTLSPenalty * totalRedDuration[j]) / durationSeconds, NUMERICAL_EPS)); // avoid zero capacity (warning issued before)
349  controlledJunctions.insert(myLinks[j][k]->getLane()->getEdge().getFromJunction()); // MSLink::myJunction is not yet initialized
350  //std::cout << " tls=" << getID() << " i=" << j << " link=" << myLinks[j][k]->getViaLaneOrLane()->getID() << " penalty=" << penalty[j] / durationSeconds << " durSecs=" << durationSeconds << " greenTime=" << " gF=" << myLinks[j][k]->getGreenFraction() << "\n";
351  }
352  }
353  // initialize empty-net travel times
354  // XXX refactor after merging sharps (links know their incoming edge)
355  for (std::set<const MSJunction*>::iterator it = controlledJunctions.begin(); it != controlledJunctions.end(); ++it) {
356  const ConstMSEdgeVector incoming = (*it)->getIncoming();
357  for (ConstMSEdgeVector::const_iterator it_e = incoming.begin(); it_e != incoming.end(); ++it_e) {
358  const_cast<MSEdge*>(*it_e)->recalcCache();
359  }
360  }
361 
362 }
363 
364 
365 void
367  myIgnoredIndices.insert(pos);
368 }
369 
370 
371 bool
373  return MSNet::getInstance()->isSelected(this);
374 }
375 
376 /****************************************************************************/
377 
SUMOTime myCurrentDurationIncrement
A value for enlarge the current duration.
The link has green light, may pass.
virtual const MSPhaseDefinition & getCurrentPhaseDef() const =0
Returns the definition of the current phase.
const std::string & getState() const
Returns the state within this phase.
Builds detectors for microsim.
void initMesoTLSPenalties()
initialize optional meso penalties
long long int SUMOTime
Definition: SUMOTime.h:35
Storage for all programs of a single tls.
MSTLLogicControl & myTLControl
The responsible traffic lights control.
static double gMesoTLSPenalty
Definition: MSGlobals.h:100
std::vector< SUMOTime > myOverridingTimes
A list of duration overrides.
SwitchCommand(MSTLLogicControl &tlcontrol, MSTrafficLightLogic *tlLogic, SUMOTime nextSwitch)
Constructor.
static const std::string ALLOWED_TLS_LINKSTATES
all allowed characters for phase state
SUMOTime myAssumedNextSwitch
Assumed switch time (may change in case of adaptive traffic lights)
The link has green light, has to brake.
void recalcCache()
Recalculates the cached values.
Definition: MSEdge.cpp:129
static const LaneVector myEmptyLaneVector
An empty lane vector.
bool isActive(const MSTrafficLightLogic *tl) const
Returns whether the given tls program is the currently active for his tls.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:168
T MAX2(T a, T b)
Definition: StdDefs.h:80
virtual int getCurrentPhaseIndex() const =0
Returns the current index within the program.
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:73
const std::string & getID() const
Returns the id.
Definition: Named.h:77
#define TIME2STEPS(x)
Definition: SUMOTime.h:59
SUMOTime getNextSwitchTime() const
Returns the assumed next switch time.
const TrafficLightType myLogicType
The type of the logic.
bool setTrafficLightSignals(SUMOTime t) const
Applies the current signal states to controlled links.
void resetLinkStates(const std::map< MSLink *, LinkState > &vals) const
Resets the states of controlled links.
int getLinkIndex(const MSLink *const link) const
Returns the index of the given link.
std::set< int > myIgnoredIndices
list of indices that are ignored in mesoscopic simulatino
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:239
LaneVectorVector myLanes
The list of LaneVectors; each vector contains the incoming lanes that belong to the same link index...
virtual ~MSTrafficLightLogic()
Destructor.
A class that stores and controls tls and switching of their programs.
A road/street connecting two junctions.
Definition: MSEdge.h:76
SUMOTime duration
The duration of the phase.
void deschedule(MSTrafficLightLogic *tlLogic)
Marks this swicth as invalid (if the phase duration has changed, f.e.)
Class realising the switch between the traffic light phases.
MSTrafficLightLogic(MSTLLogicControl &tlcontrol, const std::string &id, const std::string &programID, const TrafficLightType logicType, const SUMOTime delay, const std::map< std::string, std::string > &parameters)
Constructor.
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:48
SUMOTime myDefaultCycleTime
The cycle time (without changes)
const std::string & getProgramID() const
Returns this tl-logic&#39;s id.
MSTrafficLightLogic * myTLLogic
The logic to be executed on a switch.
virtual void init(NLDetectorBuilder &nb)
Initialises the tls with information about incoming lanes.
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition: MSNet.h:430
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
virtual void adaptLinkInformationFrom(const MSTrafficLightLogic &logic)
Applies information about controlled links and lanes from the given logic.
#define STEPS2TIME(x)
Definition: SUMOTime.h:57
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic, in MSLink and GNEInternalLane.
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:284
std::map< MSLink *, LinkState > collectLinkStates() const
Returns the (uncontrolled) states of the controlled links.
An upper class for objects with additional parameters.
Definition: Parameterised.h:43
void setCurrentDurationIncrement(SUMOTime delay)
Delays current phase by the given delay.
Base class for objects which have an id.
Definition: Named.h:57
virtual bool isSelected(const MSTrafficLightLogic *) const
return wheter the given logic (or rather it&#39;s wrapper) is selected in the GUI
Definition: MSNet.h:528
const std::string myProgramID
The id of the logic.
std::vector< MSLink * > LinkVector
Definition of the list of links that are subjected to this tls.
std::vector< MSPhaseDefinition * > Phases
Definition of a list of phases, being the junction logic.
bool isSelected() const
whether this logic is selected in the GUI
virtual const Phases & getPhases() const =0
Returns the phases of this tls program.
void addOverridingDuration(SUMOTime duration)
Changes the duration of the next phase.
LinkVectorVector myLinks
The list of LinkVectors; each vector contains the links that belong to the same link index...
std::vector< MSLane * > LaneVector
Definition of the list of arrival lanes subjected to this tls.
void ignoreLinkIndex(int pos)
ignore pedestrian crossing index in mesosim
SUMOTime getNextSwitchTime() const
Returns the assumed next switch time.
The link has red light (must brake)
virtual void addLink(MSLink *link, MSLane *lane, int pos)
Adds a link on building.
SwitchCommand * mySwitchCommand
The current switch command.
The parent class for traffic light logics.
T MIN3(T a, T b, T c)
Definition: StdDefs.h:87
#define NUMERICAL_EPS
Definition: config.h:145
TLSLogicVariants & get(const std::string &id) const
Returns the variants of a named tls.
SUMOTime getSpentDuration() const
Returns the duration spent in the current phase.
bool myAmValid
Information whether this switch command is still valid.
virtual SUMOTime trySwitch()=0
Switches to the next phase.
Representation of a lane in the micro simulation.
Definition: MSLane.h:83
The link has red light (must brake) but indicates upcoming green.
SUMOTime execute(SUMOTime currentTime)
Executes the regarded junction&#39;s "trySwitch"- method.
TrafficLightType