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, SUMOTime delay, const std::map<std::string, std::string>& parameters) :
103  Named(id), Parameterised(parameters),
104  myProgramID(programID),
106  myDefaultCycleTime(0) {
107  mySwitchCommand = new SwitchCommand(tlcontrol, this, delay);
109 }
110 
111 
112 void
114  const Phases& phases = getPhases();
115  if (phases.size() > 0 && MSGlobals::gMesoTLSPenalty > 0) {
117  }
118  if (phases.size() > 1) {
119  bool haveWarnedAboutUnusedStates = false;
120  std::vector<bool> foundGreen(phases.front()->getState().size(), false);
121  for (int i = 0; i < (int)phases.size(); ++i) {
122  // warn about unused stats
123  const int iNext = (i + 1) % phases.size();
124  const std::string& state1 = phases[i]->getState();
125  const std::string& state2 = phases[iNext]->getState();
126  assert(state1.size() == state2.size());
127  if (!haveWarnedAboutUnusedStates && state1.size() > myLanes.size()) {
128  WRITE_WARNING("Unused states in tlLogic '" + getID()
129  + "', program '" + getProgramID() + "' in phase " + toString(i)
130  + " after tl-index " + toString((int)myLanes.size() - 1));
131  haveWarnedAboutUnusedStates = true;
132  }
133  // warn about transitions from green to red without intermediate yellow
134  for (int j = 0; j < (int)MIN3(state1.size(), state2.size(), myLanes.size()); ++j) {
135  if ((LinkState)state2[j] == LINKSTATE_TL_RED
136  && ((LinkState)state1[j] == LINKSTATE_TL_GREEN_MAJOR
137  || (LinkState)state1[j] == LINKSTATE_TL_GREEN_MINOR)) {
138  for (LaneVector::const_iterator it = myLanes[j].begin(); it != myLanes[j].end(); ++it) {
139  if ((*it)->getPermissions() != SVC_PEDESTRIAN) {
140  WRITE_WARNING("Missing yellow phase in tlLogic '" + getID()
141  + "', program '" + getProgramID() + "' for tl-index " + toString(j)
142  + " when switching to phase " + toString(iNext));
143  return; // one warning per program is enough
144  }
145  }
146  }
147  }
148  // warn about links that never get the green light
149  for (int j = 0; j < (int)state1.size(); ++j) {
150  LinkState ls = (LinkState)state1[j];
152  foundGreen[j] = true;
153  }
154  }
155  }
156  for (int j = 0; j < (int)foundGreen.size(); ++j) {
157  if (!foundGreen[j]) {
158  WRITE_WARNING("Missing green phase in tlLogic '" + getID()
159  + "', program '" + getProgramID() + "' for tl-index " + toString(j));
160  break;
161  }
162  }
163  }
164 }
165 
166 
168  // no need to do something about mySwitchCommand here,
169  // it is handled by the event control
170 }
171 
172 
173 // ----------- Handling of controlled links
174 void
176  // !!! should be done within the loader (checking necessary)
177  myLinks.reserve(pos + 1);
178  while ((int)myLinks.size() <= pos) {
179  myLinks.push_back(LinkVector());
180  }
181  myLinks[pos].push_back(link);
182  //
183  myLanes.reserve(pos + 1);
184  while ((int)myLanes.size() <= pos) {
185  myLanes.push_back(LaneVector());
186  }
187  myLanes[pos].push_back(lane);
188  link->setTLState((LinkState) getCurrentPhaseDef().getState()[pos], MSNet::getInstance()->getCurrentTimeStep());
189 }
190 
191 
192 void
194  myLinks = logic.myLinks;
195  myLanes = logic.myLanes;
196 }
197 
198 
199 std::map<MSLink*, LinkState>
201  std::map<MSLink*, LinkState> ret;
202  for (LinkVectorVector::const_iterator i1 = myLinks.begin(); i1 != myLinks.end(); ++i1) {
203  const LinkVector& l = (*i1);
204  for (LinkVector::const_iterator i2 = l.begin(); i2 != l.end(); ++i2) {
205  ret[*i2] = (*i2)->getState();
206  }
207  }
208  return ret;
209 }
210 
211 
212 bool
214  // get the current traffic light signal combination
215  const std::string& state = getCurrentPhaseDef().getState();
216  // go through the links
217  for (int i = 0; i < (int)myLinks.size(); i++) {
218  const LinkVector& currGroup = myLinks[i];
219  LinkState ls = (LinkState) state[i];
220  for (LinkVector::const_iterator j = currGroup.begin(); j != currGroup.end(); j++) {
221  (*j)->setTLState(ls, t);
222  }
223  }
224  return true;
225 }
226 
227 
228 void
229 MSTrafficLightLogic::resetLinkStates(const std::map<MSLink*, LinkState>& vals) const {
230  for (LinkVectorVector::const_iterator i1 = myLinks.begin(); i1 != myLinks.end(); ++i1) {
231  const LinkVector& l = (*i1);
232  for (LinkVector::const_iterator i2 = l.begin(); i2 != l.end(); ++i2) {
233  assert(vals.find(*i2) != vals.end());
234  (*i2)->setTLState(vals.find(*i2)->second, MSNet::getInstance()->getCurrentTimeStep());
235  }
236  }
237 }
238 
239 
240 // ----------- Static Information Retrieval
241 int
242 MSTrafficLightLogic::getLinkIndex(const MSLink* const link) const {
243  int index = 0;
244  for (LinkVectorVector::const_iterator i1 = myLinks.begin(); i1 != myLinks.end(); ++i1, ++index) {
245  const LinkVector& l = (*i1);
246  for (LinkVector::const_iterator i2 = l.begin(); i2 != l.end(); ++i2) {
247  if ((*i2) == link) {
248  return index;
249  }
250  }
251  }
252  return -1;
253 }
254 
255 
256 
257 // ----------- Dynamic Information Retrieval
258 SUMOTime
260  return mySwitchCommand != 0 ? mySwitchCommand->getNextSwitchTime() : -1;
261 }
262 
263 
264 SUMOTime
266  const SUMOTime nextSwitch = getNextSwitchTime();
267  if (nextSwitch == -1) {
268  return -1;
269  } else {
270  const SUMOTime remaining = nextSwitch - MSNet::getInstance()->getCurrentTimeStep();
271  return getCurrentPhaseDef().duration - remaining;
272  }
273 }
274 
275 
276 // ----------- Changing phases and phase durations
277 void
279  myOverridingTimes.push_back(duration);
280 }
281 
282 
283 void
286 }
287 
288 
290  // set mesoscopic time penalties
291  const Phases& phases = getPhases();
292  const int numLinks = (int)myLinks.size();
293  // warning already given if not all states are used
294  assert(numLinks <= (int)phases.front()->getState().size());
295  SUMOTime duration = 0;
296  std::vector<double> redDuration(numLinks, 0);
297  std::vector<double> totalRedDuration(numLinks, 0);
298  std::vector<double> penalty(numLinks, 0);
299  for (int i = 0; i < (int)phases.size(); ++i) {
300  const std::string& state = phases[i]->getState();
301  duration += phases[i]->duration;
302  // warn about transitions from green to red without intermediate yellow
303  for (int j = 0; j < numLinks; ++j) {
304  if ((LinkState)state[j] == LINKSTATE_TL_RED
305  || (LinkState)state[j] == LINKSTATE_TL_REDYELLOW) {
306  redDuration[j] += STEPS2TIME(phases[i]->duration);
307  totalRedDuration[j] += STEPS2TIME(phases[i]->duration);
308  } else if (redDuration[j] > 0) {
309  penalty[j] += 0.5 * (redDuration[j] * redDuration[j] + redDuration[j]);
310  redDuration[j] = 0;
311  }
312  }
313  }
315  for (int j = 0; j < numLinks; ++j) {
316  if (redDuration[j] > 0) {
317  penalty[j] += 0.5 * (redDuration[j] * redDuration[j] + redDuration[j]);
318  redDuration[j] = 0;
319  }
320  }
321  const double durationSeconds = STEPS2TIME(duration);
322  std::set<const MSJunction*> controlledJunctions;
323  for (int j = 0; j < numLinks; ++j) {
324  for (int k = 0; k < (int)myLinks[j].size(); ++k) {
325  myLinks[j][k]->setMesoTLSPenalty(TIME2STEPS(MSGlobals::gMesoTLSPenalty * penalty[j] / durationSeconds));
326  myLinks[j][k]->setGreenFraction(MAX2((durationSeconds - MSGlobals::gMesoTLSPenalty * totalRedDuration[j]) / durationSeconds, NUMERICAL_EPS)); // avoid zero capacity (warning issued before)
327  controlledJunctions.insert(myLinks[j][k]->getLane()->getEdge().getFromJunction()); // MSLink::myJunction is not yet initialized
328  //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";
329  }
330  }
331  // initialize empty-net travel times
332  // XXX refactor after merging sharps (links know their incoming edge)
333  for (std::set<const MSJunction*>::iterator it = controlledJunctions.begin(); it != controlledJunctions.end(); ++it) {
334  const ConstMSEdgeVector incoming = (*it)->getIncoming();
335  for (ConstMSEdgeVector::const_iterator it_e = incoming.begin(); it_e != incoming.end(); ++it_e) {
336  const_cast<MSEdge*>(*it_e)->recalcCache();
337  }
338  }
339 
340 }
341 
342 /****************************************************************************/
343 
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.
std::string myProgramID
The id of the logic.
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:122
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:160
T MAX2(T a, T b)
Definition: StdDefs.h:76
virtual int getCurrentPhaseIndex() const =0
Returns the current index within the program.
MSTrafficLightLogic(MSTLLogicControl &tlcontrol, const std::string &id, const std::string &programID, SUMOTime delay, const std::map< std::string, std::string > &parameters)
Constructor.
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:72
const std::string & getID() const
Returns the id.
Definition: Named.h:69
#define TIME2STEPS(x)
Definition: SUMOTime.h:60
SUMOTime getNextSwitchTime() const
Returns the assumed next switch time.
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.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:242
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.
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:402
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:256
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:49
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.
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:71
The link has red light (must brake) but indicates upcoming green.
SUMOTime execute(SUMOTime currentTime)
Executes the regarded junction&#39;s "trySwitch"- method.