SUMO - Simulation of Urban MObility
MSSOTLTrafficLightLogic.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2013-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 base abstract class for SOTL logics
18 /****************************************************************************/
19 
21 #include "../MSLane.h"
22 #include "../MSEdge.h"
23 #include "MSPushButton.h"
24 
25 #if 1
26 #define ANALYSIS_DBG(X) {X}
27 #else
28 #define ANALYSIS_DBG(X) DBG(X)
29 #endif
30 // ===========================================================================
31 // member method definitions
32 // ===========================================================================
34  MSTLLogicControl& tlcontrol,
35  const std::string& id,
36  const std::string& subid,
37  const Phases& phases,
38  int step,
39  SUMOTime delay,
40  const std::map<std::string, std::string>& parameters)
41  : MSPhasedTrafficLightLogic(tlcontrol, id, subid, phases, step, delay, parameters) {
42  this->mySensors = NULL;
43  this->myCountSensors = NULL;
44  sensorsSelfBuilt = true;
45  checkPhases();
46  setupCTS();
48 }
49 
51  MSTLLogicControl& tlcontrol,
52  const std::string& id,
53  const std::string& subid,
54  const Phases& phases,
55  int step,
56  SUMOTime delay,
57  const std::map<std::string, std::string>& parameters,
58  MSSOTLSensors* sensors)
59  : MSPhasedTrafficLightLogic(tlcontrol, id, subid, phases, step, delay, parameters) {
60  this->mySensors = sensors;
61  sensorsSelfBuilt = false;
62  checkPhases();
63  setupCTS();
65 }
66 
68  for (PhasePushButtons::iterator mapIt = m_pushButtons.begin(); mapIt != m_pushButtons.end(); ++mapIt)
69  for (std::vector<MSPushButton*>::iterator vIt = mapIt->second.begin(); vIt != mapIt->second.end(); ++vIt) {
70  delete *vIt;
71  }
72  m_pushButtons.clear();
73  for (int i = 0; i < (int)myPhases.size(); i++) {
74  delete myPhases[i];
75  }
76  if (sensorsSelfBuilt) {
77  delete mySensors;
78 // delete myCountSensors;
79  }
80 }
81 
83 
84 }
85 
86 void
88  for (int step = 0; step < (int)getPhases().size(); step++) {
89  if (getPhase(step).isUndefined()) {
90  MsgHandler::getErrorInstance()->inform("Step " + toString(step) + " of traffic light logic " + myID + " phases declaration has its type undeclared!");
91  }
92  }
93 }
94 
95 void
97  for (int phaseStep = 0; phaseStep < (int)getPhases().size(); phaseStep++) {
98  if (getPhase(phaseStep).isTarget()) {
99  targetPhasesCTS[phaseStep] = 0;
101  targetPhasesLastSelection[phaseStep] = 0;
102  }
103  }
104 }
105 
106 void
108  for (int step = 0; step < (int)getPhases().size(); step++) {
109  if (getPhase(step).isTarget()) {
110  setStep(step);
111  lastChain = step;
112  return;
113  }
114  }
115  MsgHandler::getErrorInstance()->inform("No phase of type target found for traffic light logic " + myID + " The logic could malfunction. Check phases declaration.");
116 }
117 
118 
119 void
121 
123 
125  decayThreshold = 1;
126  }
127  if (sensorsSelfBuilt) {
128  //Building SOTLSensors
129  switch (SENSORS_TYPE) {
130  case SENSORS_TYPE_E1:
131  assert(0); // Throw exception because TLS can only handle E2 sensors
132  case SENSORS_TYPE_E2:
133 
134  //Adding Sensors to the ingoing Lanes
135 
137 
138  DBG(
139  WRITE_MESSAGE("Listing lanes for TLS " + getID());
140 
141  for (int i = 0; i < lvv.size(); i++) {
142  LaneVector lv = lvv[i];
143 
144  for (int j = 0; j < lv.size(); j++) {
145  MSLane* lane = lv[j];
146  WRITE_MESSAGE(lane ->getID());
147  }
148  }
149  )
150 
153  mySensors->stepChanged(getCurrentPhaseIndex());
154  if (getParameter("USE_VEHICLE_TYPES_WEIGHTS", "0") == "1") {
155  ((MSSOTLE2Sensors*) mySensors)->setVehicleWeigths(getParameter("VEHICLE_TYPES_WEIGHTS", ""));
156  }
157 
158  //threshold speed param for tuning with irace
159  ((MSSOTLE2Sensors*)mySensors)->setSpeedThresholdParam(getSpeedThreshold());
160 
161  myCountSensors = new MSSOTLE2Sensors(myID + "Count", &(getPhases()));
164 
165  //Adding Sensors to the outgoing Lanes
166 
168 
169 
170  DBG(
171  WRITE_MESSAGE("Listing output lanes");
172  for (int i = 0; i < myLinks.size(); i++) {
173  LinkVector oneLink = getLinksAt(i);
174 
175  for (int j = 0; j < oneLink.size(); j++) {
176 
177  MSLane* lane = oneLink[j]->getLane();
178  WRITE_MESSAGE(lane ->getID());
179 
180  }
181  }
182  )
183 
184 
185  LaneVectorVector myLaneVector;
186 
187  LaneVector outLanes;
188  LinkVectorVector myoutLinks = getLinks();
189 
190  for (int i = 0; i < (int)myLinks.size(); i++) {
191  LinkVector oneLink = getLinksAt(i);
192  for (int j = 0; j < (int)oneLink.size(); j++) {
193  MSLane* lane = oneLink[j]->getLane();
194  outLanes.push_back(lane);
195  }
196  }
197 
198  if (outLanes.size() > 0) {
199  myLaneVector.push_back(outLanes);
200  }
201  if (myLaneVector.size() > 0) {
202  ((MSSOTLE2Sensors*)mySensors)->buildOutSensors(myLaneVector, nb, getOutputSensorsLength());
203  myCountSensors->buildCountOutSensors(myLaneVector, nb);
204  }
205 
206  }
207  }
208 }
209 
210 
211 void
213  std::map<int, SUMOTime>::iterator phaseIterator = targetPhasesCTS.find(phaseStep);
214  if (phaseIterator != targetPhasesCTS.end()) {
215  phaseIterator->second = 0;
217  }
218 }
219 
220 void
222  SUMOTime elapsedTimeSteps = 0;
224  //Iterate over the target phase map and update CTS value for every target phase except for the one belonging to the current steps chain
225  for (std::map<int, SUMOTime>::iterator mapIterator = targetPhasesCTS.begin();
226  mapIterator != targetPhasesCTS.end();
227  mapIterator++) {
228  int chain = mapIterator->first;
229  SUMOTime oldVal = mapIterator->second;
230  if (chain != lastChain) {
231  //Get the number of timesteps since the last check for that phase
232  elapsedTimeSteps = now - lastCheckForTargetPhase[chain];
233  //Update the last check time
234  lastCheckForTargetPhase[chain] = now;
235  //Increment the CTS
236  //SWITCH between 3 counting vehicles function
237  switch (getMode()) {
238  case (0):
239  mapIterator->second += elapsedTimeSteps
240  * countVehicles(getPhase(chain)); //SUMO
241  break;
242  case (1):
243  mapIterator->second += elapsedTimeSteps
244  * countVehicles(getPhase(chain)); //COMPLEX
245  break;
246  case (2):
247  mapIterator->second = countVehicles(getPhase(chain)); //QUEUE
248  break;
249  default:
250  WRITE_ERROR("Unrecognized traffic threshold calculation mode");
251  }
252  std::ostringstream oss;
253  oss << "MSSOTLTrafficLightLogic::updateCTS->TLC " << getID() << " chain " << chain << " oldVal " << oldVal << " newVal " << mapIterator->second;
254  WRITE_MESSAGE(oss.str());
255  }
258  }
259  }
260 }
261 
262 int
264 
265  if (!phase.isTarget()) {
266  return 0;
267  }
268 
269  int accumulator = 0;
270  //Iterate over the target lanes for the current target phase to get the number of approaching vehicles
272  for (MSPhaseDefinition::LaneIdVector::const_iterator laneIterator = targetLanes.begin(); laneIterator != targetLanes.end(); laneIterator++) {
273  //SWITCH between 3 counting vehicles function
274  switch (getMode()) {
275  case (0):
276  accumulator += mySensors->countVehicles((*laneIterator)); //SUMO
277  break;
278  case (1):
279  accumulator += ((MSSOTLE2Sensors*)mySensors)->estimateVehicles((*laneIterator)); //COMPLEX
280  break;
281  case (2):
282  accumulator = MAX2((int)((MSSOTLE2Sensors*)mySensors)->getEstimateQueueLength((*laneIterator)), accumulator); //QUEUE
283  break;
284  default:
285  WRITE_ERROR("Unrecognized traffic threshold calculation mode");
286  }
287  }
288  return accumulator;
289 }
290 
291 void
293  if (getCurrentPhaseDef().isGreenPhase()) {
295  }
296 // ANALYSIS_DBG(
297  DBG(
298  std::stringstream out;
299  out << decayThreshold;
300  WRITE_MESSAGE("\n" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + "\tMSSOTLTrafficLightLogic::updateDecayThreshold():: " + out.str());
301  )
302 }
303 bool
305 
306  DBG(
307  // WRITE_MESSAGE("\n" +time2string(MSNet::getInstance()->getCurrentTimeStep()) +"\tMSSOTLTrafficLightLogic::isThresholdPassed():: " + " tlsid=" + getID());
308 
309  std::ostringstream threshold_str;
310  // threshold_str << "tlsid=" << getID() << " targetPhaseCTS size=" << targetPhasesCTS.size();
311 // threshold_str << "\n";
312  WRITE_MESSAGE(threshold_str.str());
313  )
314  /*
315  * if a dynamic threshold based on the exponential decrease, if passed we force the phase change
316  */
317 // double random = ((double) RandHelper::rand(RAND_MAX) / (RAND_MAX));
318  double random = RandHelper::rand();
319 // ANALYSIS_DBG(
320  DBG(
322  std::ostringstream str;
323  str << time2string(MSNet::getInstance()->getCurrentTimeStep()) << "\tMSSOTLTrafficLightLogic::isThresholdPassed():: "
324  << " tlsid=" << getID() << " decayThreshold=" << decayThreshold << " random=" << random << ">" << (1 - decayThreshold)
325  << (random > (1 - decayThreshold) ? " true" : " false");
326 
327  WRITE_MESSAGE(str.str());
328  }
329  )
330  if (!isDecayThresholdActivated() || (isDecayThresholdActivated() && random > (1 - decayThreshold))) {
331  for (std::map<int, SUMOTime>::const_iterator iterator =
332  targetPhasesCTS.begin(); iterator != targetPhasesCTS.end();
333  iterator++) {
334  DBG(
335  SUMOTime step = MSNet::getInstance()->getCurrentTimeStep();
336  std::ostringstream threshold_str;
337  // threshold_str <<"\tTL " +getID()<<" time " +time2string(step)<< "(getThreshold()= " << getThreshold()
338  // << ", targetPhaseCTS= " << iterator->second << " )" << " phase="<<getPhase(iterator->first).getState();
339  threshold_str << getCurrentPhaseDef().getState() << ";" << time2string(step) << ";" << getThreshold()
340  << ";" << iterator->second << ";" << getPhase(iterator->first).getState() << ";"
341  << iterator->first << "!=" << lastChain;
342  WRITE_MESSAGE(threshold_str.str());
343  );
344  //Note that the current chain is not eligible to be directly targeted again, it would be unfair
345  if ((iterator->first != lastChain) && (getThreshold() <= iterator->second)) {
346  return true;
347  }
348  }
349  return false;
350  } else {
351  return true;
352  }
353 }
354 
355 
356 SUMOTime
358  MSPhaseDefinition currentPhase = getCurrentPhaseDef();
359 
361  SUMOTime elapsed = now - currentPhase.myLastSwitch;
362 
363  return elapsed;
364 }
365 
366 
367 int
369  SUMOTime maxCTS = 0;
370  int maxLastStep = getTargetPhaseMaxLastSelection();
371  bool usedMaxCTS = false;
372  std::vector<int> equalIndexes;
373  for (std::map<int, int>::const_iterator it = targetPhasesLastSelection.begin();
374  it != targetPhasesLastSelection.end(); ++it) {
375  if (it->first != lastChain) {
376  if (maxLastStep < it->second) {
377  maxLastStep = it->second;
378  equalIndexes.clear();
379  equalIndexes.push_back(it->first);
380  } else if (maxLastStep == it->second) {
381  equalIndexes.push_back(it->first);
382  }
383  }
384  }
385  if (equalIndexes.size() == 0) {
386  usedMaxCTS = true;
387  for (std::map<int, SUMOTime>::const_iterator iterator = targetPhasesCTS.begin();
388  iterator != targetPhasesCTS.end(); ++iterator) {
389  if (iterator->first != lastChain) {
390  if (maxCTS < iterator->second) {
391  maxCTS = iterator->second;
392  equalIndexes.clear();
393  equalIndexes.push_back(iterator->first);
394  } else if (maxCTS == iterator->second) {
395  equalIndexes.push_back(iterator->first);
396  }
397  }
398  }
399  }
400 
401  std::ostringstream oss;
402  oss << "MSSOTLTrafficLightLogic::getPhaseIndexWithMaxCTS-> TLC " << getID();
403  if (usedMaxCTS) {
404  oss << " maxCTS " << maxCTS;
405  } else {
406  oss << " forcing selection since not selected for " << maxLastStep;
407  }
408  if (equalIndexes.size() == 1) {
409  oss << " phase " << equalIndexes[0];
410  WRITE_MESSAGE(oss.str());
411  return equalIndexes[0];
412  } else {
413  const int index = RandHelper::getRandomFrom(equalIndexes);
414  oss << " phases [";
415  for (std::vector<int>::const_iterator it = equalIndexes.begin(); it != equalIndexes.end(); ++it) {
416  oss << *it << ", ";
417  }
418  oss << "]. Random select " << index;
419  WRITE_MESSAGE(oss.str());
420  return index;
421  }
422 }
423 
424 int
426  MSPhaseDefinition currentPhase = getCurrentPhaseDef();
427  //If the junction was in a commit step
428  //=> go to the target step that gives green to the set with the current highest CTS
429  // and return computeReturnTime()
430  if (currentPhase.isCommit()) {
431  // decide which chain to activate. Gotta work on this
432  return getPhaseIndexWithMaxCTS();
433  }
434  if (currentPhase.isTransient()) {
435  //If the junction was in a transient step
436  //=> go to the next step and return computeReturnTime()
437  return getCurrentPhaseIndex() + 1;
438  }
439 
440  if (currentPhase.isDecisional()) {
441 
442  if (canRelease()) {
443  return getCurrentPhaseIndex() + 1;
444  }
445  }
446 
447  return getCurrentPhaseIndex();
448 }
449 
450 SUMOTime
452  if (MSNet::getInstance()->getCurrentTimeStep() % 1000 == 0) {
453  WRITE_MESSAGE("MSSOTLTrafficLightLogic::trySwitch()")
454  // To check if decideNextPhase changes the step
455  int previousStep = getCurrentPhaseIndex() ;
456  SUMOTime elapsed = getCurrentPhaseElapsed();
457  // Update CTS according to sensors
458  updateCTS();
459 
460  // Invoking the function member, specialized for each SOTL logic
462  MSPhaseDefinition currentPhase = getCurrentPhaseDef();
463 
464  //At the end, check if new step started
465  if (getCurrentPhaseIndex() != previousStep) {
466  //Check if a new steps chain started
467  if (currentPhase.isTarget()) {
468  //Reset CTS for the ending steps chain
470  //Update lastTargetPhase
472  for (std::map<int, int>::iterator it = targetPhasesLastSelection.begin(); it != targetPhasesLastSelection.end(); ++ it) {
473  if (it->first == lastChain) {
474  if (it->second >= getTargetPhaseMaxLastSelection()) {
475  std::ostringstream oss;
476  oss << "Forced selection of the phase " << lastChain << " since its last selection was " << it->second << " changes ago";
477  WRITE_MESSAGE(oss.str())
478  }
479  it->second = 0;
480  } else if (it->first != previousStep) {
481  ++it->second;
482  }
483  }
485  decayThreshold = 1;
486  }
487  }
488  //Inform the sensors logic
490  //Store the time the new phase started
493  decayThreshold = 1;
494  }
495  ANALYSIS_DBG(
496  std::ostringstream oss;
497  oss << getID() << " from " << getPhase(previousStep).getState() << " to " << currentPhase.getState() << " after " << time2string(elapsed);
498  WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + "\tMSSOTLTrafficLightLogic::trySwitch " + oss.str());
499  )
500  }
501  }
502  return computeReturnTime();
503 }
504 
506  if (getParameter("USE_PUSH_BUTTON", "0") == "0") {
507  return false;
508  }
509  const MSPhaseDefinition currentPhase = getCurrentPhaseDef();
510  if (m_pushButtons.find(currentPhase.getState()) == m_pushButtons.end()) {
511  m_pushButtons[currentPhase.getState()] = MSPedestrianPushButton::loadPushButtons(&currentPhase);
512  }
513  return MSPushButton::anyActive(m_pushButtons[currentPhase.getState()]);
514 }
515 
const std::string & getState() const
Returns the state within this phase.
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:76
Builds detectors for microsim.
long long int SUMOTime
Definition: SUMOTime.h:36
void init(NLDetectorBuilder &nb)
Initialises the tls with sensors on incoming and outgoing lanes Sensors are built in the simulation a...
#define ANALYSIS_DBG(X)
const LaneVectorVector & getLaneVectors() const
Returns the list of lists of all lanes controlled by this tls.
static double rand(std::mt19937 *rng=0)
Returns a random real number in [0, 1)
Definition: RandHelper.h:61
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:67
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:68
const MSPhaseDefinition & getPhase(int givenstep) const
Returns the definition of the phase from the given position within the plan.
std::map< int, SUMOTime > lastCheckForTargetPhase
const std::string & getID() const
Returns the id.
Definition: Named.h:69
void buildCountOutSensors(MSTrafficLightLogic::LaneVectorVector controlledLanes, NLDetectorBuilder &nb)
const LinkVectorVector & getLinks() const
Returns the list of lists of all affected links.
const LinkVector & getLinksAt(int i) const
Returns the list of links that are controlled by the signals at the given position.
LaneVectorVector myLanes
The list of LaneVectors; each vector contains the incoming lanes that belong to the same link index...
A class that stores and controls tls and switching of their programs.
std::vector< LinkVector > LinkVectorVector
Definition of a list that holds lists of links that do have the same attribute.
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
SUMOTime myLastSwitch
Stores the timestep of the last on-switched of the phase.
Phases myPhases
The list of phases this logic uses.
virtual void init(NLDetectorBuilder &nb)
Initialises the tls with information about incoming lanes.
std::map< int, SUMOTime > targetPhasesCTS
void buildCountSensors(MSTrafficLightLogic::LaneVectorVector controlledLanes, NLDetectorBuilder &nb)
bool isTransient() const
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:256
#define DBG(X)
Definition: SwarmDebug.h:27
virtual int countVehicles(MSLane *lane)=0
std::vector< MSLink * > LinkVector
Definition of the list of links that are subjected to this tls.
bool isUndefined() const
std::vector< MSPhaseDefinition * > Phases
Definition of a list of phases, being the junction logic.
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:248
#define SENSORS_TYPE
LinkVectorVector myLinks
The list of LinkVectors; each vector contains the links that belong to the same link index...
MSSOTLTrafficLightLogic(MSTLLogicControl &tlcontrol, const std::string &id, const std::string &subid, const Phases &phases, int step, SUMOTime delay, const std::map< std::string, std::string > &parameters)
Constructor without sensors passed.
std::string myID
The name of the object.
Definition: Named.h:121
std::vector< MSLane * > LaneVector
Definition of the list of arrival lanes subjected to this tls.
std::vector< LaneVector > LaneVectorVector
Definition of a list that holds lists of lanes that do have the same attribute.
std::vector< std::string > LaneIdVector
const MSPhaseDefinition & getCurrentPhaseDef() const
Returns the definition of the current phase.
static const T & getRandomFrom(const std::vector< T > &v, std::mt19937 *rng=0)
Returns a random element from the given vector.
Definition: RandHelper.h:155
int getCurrentPhaseIndex() const
Returns the current index within the program.
void buildSensors(MSTrafficLightLogic::LaneVectorVector controlledLanes, NLDetectorBuilder &nb)
This function member has to be extended to properly build sensors for the input lanes Sensors has to ...
SUMOTime trySwitch()
Switches to the next phase.
const Phases & getPhases() const
Returns the phases of this tls program.
void inform(std::string msg, bool addType=true)
adds a new error to the list
Definition: MsgHandler.cpp:113
const std::string getParameter(const std::string &key, const std::string &defaultValue="") const
Returns the value for a given key.
static std::vector< MSPushButton * > loadPushButtons(const MSPhaseDefinition *)
Loads all the pushbuttons for all the controlled lanes of a stage.
virtual SUMOTime computeReturnTime()
#define SENSORS_TYPE_E2
virtual bool canRelease()=0
const LaneIdVector & getTargetLaneSet() const
virtual void stepChanged(int newStep)
A fixed traffic light logic.
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:243
static bool anyActive(const std::vector< MSPushButton *> &)
Checks if any pushbutton in the vector is active.
The definition of a single phase of a tls logic.
Representation of a lane in the micro simulation.
Definition: MSLane.h:71
#define SENSORS_TYPE_E1
void setStep(int step)
Forces a specific step.
bool isDecisional() const
std::map< int, int > targetPhasesLastSelection
int countVehicles(MSPhaseDefinition phase)