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-2018 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  const int iNext = phases[i]->nextPhase < 0 ? (i + 1) % phases.size() : phases[i]->nextPhase;
126  if (iNext < 0 || iNext >= (int)phases.size()) {
127  throw ProcessError("Invalid nextPhase " + toString(iNext) + " in tlLogic '" + getID()
128  + "', program '" + getProgramID() + "' with " + toString(phases.size()) + " phases");
129  }
130  const std::string optionalFrom = phases[i]->nextPhase < 0 ? "" : " from phase " + toString(i);
131  const std::string& state1 = phases[i]->getState();
132  const std::string& state2 = phases[iNext]->getState();
133  assert(state1.size() == state2.size());
134  if (!haveWarnedAboutUnusedStates && state1.size() > myLanes.size() + myIgnoredIndices.size()) {
135  WRITE_WARNING("Unused states in tlLogic '" + getID()
136  + "', program '" + getProgramID() + "' in phase " + toString(i)
137  + " after tl-index " + toString((int)myLanes.size() - 1));
138  haveWarnedAboutUnusedStates = true;
139  }
140  // detect illegal states
141  const std::string::size_type illegal = state1.find_first_not_of(SUMOXMLDefinitions::ALLOWED_TLS_LINKSTATES);
142  if (std::string::npos != illegal) {
143  throw ProcessError("Illegal character '" + toString(state1[illegal]) + "' in tlLogic '" + getID()
144  + "', program '" + getProgramID() + "' in phase " + toString(i));
145  }
146  // warn about transitions from green to red without intermediate yellow
147  for (int j = 0; j < (int)MIN3(state1.size(), state2.size(), myLanes.size()); ++j) {
148  if ((LinkState)state2[j] == LINKSTATE_TL_RED
149  && ((LinkState)state1[j] == LINKSTATE_TL_GREEN_MAJOR
150  || (LinkState)state1[j] == LINKSTATE_TL_GREEN_MINOR)) {
151  for (LaneVector::const_iterator it = myLanes[j].begin(); it != myLanes[j].end(); ++it) {
152  if ((*it)->getPermissions() != SVC_PEDESTRIAN) {
153  WRITE_WARNING("Missing yellow phase in tlLogic '" + getID()
154  + "', program '" + getProgramID() + "' for tl-index " + toString(j)
155  + " when switching" + optionalFrom + " to phase " + toString(iNext));
156  return; // one warning per program is enough
157  }
158  }
159  }
160  }
161  // warn about links that never get the green light
162  for (int j = 0; j < (int)state1.size(); ++j) {
163  LinkState ls = (LinkState)state1[j];
165  foundGreen[j] = true;
166  }
167  }
168  }
169  for (int j = 0; j < (int)foundGreen.size(); ++j) {
170  if (!foundGreen[j]) {
171  WRITE_WARNING("Missing green phase in tlLogic '" + getID()
172  + "', program '" + getProgramID() + "' for tl-index " + toString(j));
173  break;
174  }
175  }
176  }
177 }
178 
179 
181  // no need to do something about mySwitchCommand here,
182  // it is handled by the event control
183 }
184 
185 
186 // ----------- Handling of controlled links
187 void
189  // !!! should be done within the loader (checking necessary)
190  myLinks.reserve(pos + 1);
191  while ((int)myLinks.size() <= pos) {
192  myLinks.push_back(LinkVector());
193  }
194  myLinks[pos].push_back(link);
195  //
196  myLanes.reserve(pos + 1);
197  while ((int)myLanes.size() <= pos) {
198  myLanes.push_back(LaneVector());
199  }
200  myLanes[pos].push_back(lane);
201  link->setTLState((LinkState) getCurrentPhaseDef().getState()[pos], MSNet::getInstance()->getCurrentTimeStep());
202 }
203 
204 
205 void
207  myLinks = logic.myLinks;
208  myLanes = logic.myLanes;
210 }
211 
212 
213 std::map<MSLink*, LinkState>
215  std::map<MSLink*, LinkState> ret;
216  for (LinkVectorVector::const_iterator i1 = myLinks.begin(); i1 != myLinks.end(); ++i1) {
217  const LinkVector& l = (*i1);
218  for (LinkVector::const_iterator i2 = l.begin(); i2 != l.end(); ++i2) {
219  ret[*i2] = (*i2)->getState();
220  }
221  }
222  return ret;
223 }
224 
225 
226 bool
228  // get the current traffic light signal combination
229  const std::string& state = getCurrentPhaseDef().getState();
230  // go through the links
231  for (int i = 0; i < (int)myLinks.size(); i++) {
232  const LinkVector& currGroup = myLinks[i];
233  LinkState ls = (LinkState) state[i];
234  for (LinkVector::const_iterator j = currGroup.begin(); j != currGroup.end(); j++) {
235  (*j)->setTLState(ls, t);
236  }
237  }
238  return true;
239 }
240 
241 
242 void
243 MSTrafficLightLogic::resetLinkStates(const std::map<MSLink*, LinkState>& vals) const {
244  for (LinkVectorVector::const_iterator i1 = myLinks.begin(); i1 != myLinks.end(); ++i1) {
245  const LinkVector& l = (*i1);
246  for (LinkVector::const_iterator i2 = l.begin(); i2 != l.end(); ++i2) {
247  assert(vals.find(*i2) != vals.end());
248  (*i2)->setTLState(vals.find(*i2)->second, MSNet::getInstance()->getCurrentTimeStep());
249  }
250  }
251 }
252 
253 
254 // ----------- Static Information Retrieval
255 int
256 MSTrafficLightLogic::getLinkIndex(const MSLink* const link) const {
257  int index = 0;
258  for (LinkVectorVector::const_iterator i1 = myLinks.begin(); i1 != myLinks.end(); ++i1, ++index) {
259  const LinkVector& l = (*i1);
260  for (LinkVector::const_iterator i2 = l.begin(); i2 != l.end(); ++i2) {
261  if ((*i2) == link) {
262  return index;
263  }
264  }
265  }
266  return -1;
267 }
268 
269 
270 
271 // ----------- Dynamic Information Retrieval
272 SUMOTime
274  return mySwitchCommand != nullptr ? mySwitchCommand->getNextSwitchTime() : -1;
275 }
276 
277 
278 SUMOTime
280  const SUMOTime nextSwitch = getNextSwitchTime();
281  if (nextSwitch == -1) {
282  return -1;
283  } else {
284  const SUMOTime remaining = nextSwitch - MSNet::getInstance()->getCurrentTimeStep();
285  return getCurrentPhaseDef().duration - remaining;
286  }
287 }
288 
289 
290 // ----------- Changing phases and phase durations
291 void
293  myOverridingTimes.push_back(duration);
294 }
295 
296 
297 void
300 }
301 
302 
304  // set mesoscopic time penalties
305  const Phases& phases = getPhases();
306  const int numLinks = (int)myLinks.size();
307  // warning already given if not all states are used
308  assert(numLinks <= (int)phases.front()->getState().size());
309  SUMOTime duration = 0;
310  std::vector<double> redDuration(numLinks, 0);
311  std::vector<double> totalRedDuration(numLinks, 0);
312  std::vector<double> penalty(numLinks, 0);
313  for (int i = 0; i < (int)phases.size(); ++i) {
314  const std::string& state = phases[i]->getState();
315  duration += phases[i]->duration;
316  // warn about transitions from green to red without intermediate yellow
317  for (int j = 0; j < numLinks; ++j) {
318  if ((LinkState)state[j] == LINKSTATE_TL_RED
319  || (LinkState)state[j] == LINKSTATE_TL_REDYELLOW) {
320  redDuration[j] += STEPS2TIME(phases[i]->duration);
321  totalRedDuration[j] += STEPS2TIME(phases[i]->duration);
322  } else if (redDuration[j] > 0) {
323  penalty[j] += 0.5 * (redDuration[j] * redDuration[j] + redDuration[j]);
324  redDuration[j] = 0;
325  }
326  }
327  }
329  for (int j = 0; j < numLinks; ++j) {
330  if (redDuration[j] > 0) {
331  penalty[j] += 0.5 * (redDuration[j] * redDuration[j] + redDuration[j]);
332  redDuration[j] = 0;
333  }
334  }
335  const double durationSeconds = STEPS2TIME(duration);
336  std::set<const MSJunction*> controlledJunctions;
337  for (int j = 0; j < numLinks; ++j) {
338  for (int k = 0; k < (int)myLinks[j].size(); ++k) {
339  myLinks[j][k]->setMesoTLSPenalty(TIME2STEPS(MSGlobals::gMesoTLSPenalty * penalty[j] / durationSeconds));
340  myLinks[j][k]->setGreenFraction(MAX2((durationSeconds - MSGlobals::gMesoTLSPenalty * totalRedDuration[j]) / durationSeconds, NUMERICAL_EPS)); // avoid zero capacity (warning issued before)
341  controlledJunctions.insert(myLinks[j][k]->getLane()->getEdge().getFromJunction()); // MSLink::myJunction is not yet initialized
342  //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";
343  }
344  }
345  // initialize empty-net travel times
346  // XXX refactor after merging sharps (links know their incoming edge)
347  for (std::set<const MSJunction*>::iterator it = controlledJunctions.begin(); it != controlledJunctions.end(); ++it) {
348  const ConstMSEdgeVector incoming = (*it)->getIncoming();
349  for (ConstMSEdgeVector::const_iterator it_e = incoming.begin(); it_e != incoming.end(); ++it_e) {
350  const_cast<MSEdge*>(*it_e)->recalcCache();
351  }
352  }
353 
354 }
355 
356 
357 void
359  myIgnoredIndices.insert(pos);
360 }
361 
362 /****************************************************************************/
363 
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:36
is a pedestrian
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:126
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:165
T MAX2(T a, T b)
Definition: StdDefs.h:76
virtual int getCurrentPhaseIndex() const =0
Returns the current index within the program.
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:72
const std::string & getID() const
Returns the id.
Definition: Named.h:78
#define TIME2STEPS(x)
Definition: SUMOTime.h:60
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:241
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:75
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:49
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:409
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:58
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:263
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:44
void setCurrentDurationIncrement(SUMOTime delay)
Delays current phase by the given delay.
Base class for objects which have an id.
Definition: Named.h:58
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.
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:83
#define NUMERICAL_EPS
Definition: config.h:148
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:78
The link has red light (must brake) but indicates upcoming green.
SUMOTime execute(SUMOTime currentTime)
Executes the regarded junction&#39;s "trySwitch"- method.
TrafficLightType