SUMO - Simulation of Urban MObility
MSSOTLTrafficLightLogic.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // The base abstract class for SOTL logics
10 /****************************************************************************/
11 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
12 // Copyright 2001-2013 DLR (http://www.dlr.de/) and contributors
13 /****************************************************************************/
14 //
15 // This file is part of SUMO.
16 // SUMO is free software: you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation, either version 3 of the License, or
19 // (at your option) any later version.
20 //
21 /****************************************************************************/
22 
24 #include "../MSLane.h"
25 #include "../MSEdge.h"
26 #include "MSPushButton.h"
27 
28 #ifdef CHECK_MEMORY_LEAKS
29 #include <foreign/nvwa/debug_new.h>
30 #endif // CHECK_MEMORY_LEAKS
31 
32 #if 1
33 #define ANALYSIS_DBG(X) {X}
34 #else
35 #define ANALYSIS_DBG(X) DBG(X)
36 #endif
37 // ===========================================================================
38 // member method definitions
39 // ===========================================================================
41  MSTLLogicControl& tlcontrol,
42  const std::string& id,
43  const std::string& subid,
44  const Phases& phases,
45  int step,
46  SUMOTime delay,
47  const std::map<std::string, std::string>& parameters)
48  : MSPhasedTrafficLightLogic(tlcontrol, id, subid, phases, step, delay, parameters) {
49  this->mySensors = NULL;
50  this->myCountSensors = NULL;
51  sensorsSelfBuilt = true;
52  checkPhases();
53  setupCTS();
55 }
56 
58  MSTLLogicControl& tlcontrol,
59  const std::string& id,
60  const std::string& subid,
61  const Phases& phases,
62  int step,
63  SUMOTime delay,
64  const std::map<std::string, std::string>& parameters,
65  MSSOTLSensors* sensors)
66  : MSPhasedTrafficLightLogic(tlcontrol, id, subid, phases, step, delay, parameters) {
67  this->mySensors = sensors;
68  sensorsSelfBuilt = false;
69  checkPhases();
70  setupCTS();
72 }
73 
75  for (PhasePushButtons::iterator mapIt = m_pushButtons.begin(); mapIt != m_pushButtons.end(); ++mapIt)
76  for (std::vector<MSPushButton*>::iterator vIt = mapIt->second.begin(); vIt != mapIt->second.end(); ++vIt) {
77  delete *vIt;
78  }
79  m_pushButtons.clear();
80  for (int i = 0; i < (int)myPhases.size(); i++) {
81  delete myPhases[i];
82  }
83  if (sensorsSelfBuilt) {
84  delete mySensors;
85 // delete myCountSensors;
86  }
87 }
88 
90 
91 }
92 
93 void
95  for (int step = 0; step < (int)getPhases().size(); step++) {
96  if (getPhase(step).isUndefined()) {
97  MsgHandler::getErrorInstance()->inform("Step " + toString(step) + " of traffic light logic " + myID + " phases declaration has its type undeclared!");
98  }
99  }
100 }
101 
102 void
104  for (int phaseStep = 0; phaseStep < (int)getPhases().size(); phaseStep++) {
105  if (getPhase(phaseStep).isTarget()) {
106  targetPhasesCTS[phaseStep] = 0;
108  targetPhasesLastSelection[phaseStep] = 0;
109  }
110  }
111 }
112 
113 void
115  for (int step = 0; step < (int)getPhases().size(); step++) {
116  if (getPhase(step).isTarget()) {
117  setStep(step);
118  lastChain = step;
119  return;
120  }
121  }
122  MsgHandler::getErrorInstance()->inform("No phase of type target found for traffic light logic " + myID + " The logic could malfunction. Check phases declaration.");
123 }
124 
125 
126 void
128 
130 
132  decayThreshold = 1;
133  }
134  if (sensorsSelfBuilt) {
135  //Building SOTLSensors
136  switch (SENSORS_TYPE) {
137  case SENSORS_TYPE_E1:
138  assert(0); // Throw exception because TLS can only handle E2 sensors
139  case SENSORS_TYPE_E2:
140 
141  //Adding Sensors to the ingoing Lanes
142 
144 
145  DBG(
146  WRITE_MESSAGE("Listing lanes for TLS " + getID());
147 
148  for (int i = 0; i < lvv.size(); i++) {
149  LaneVector lv = lvv[i];
150 
151  for (int j = 0; j < lv.size(); j++) {
152  MSLane* lane = lv[j];
153  WRITE_MESSAGE(lane ->getID());
154  }
155  }
156  )
157 
160  mySensors->stepChanged(getCurrentPhaseIndex());
161  if (getParameter("USE_VEHICLE_TYPES_WEIGHTS", "0") == "1") {
162  ((MSSOTLE2Sensors*) mySensors)->setVehicleWeigths(getParameter("VEHICLE_TYPES_WEIGHTS", ""));
163  }
164 
165  //threshold speed param for tuning with irace
166  ((MSSOTLE2Sensors*)mySensors)->setSpeedThresholdParam(getSpeedThreshold());
167 
168  myCountSensors = new MSSOTLE2Sensors(myID + "Count", &(getPhases()));
171 
172  //Adding Sensors to the outgoing Lanes
173 
175 
176 
177  DBG(
178  WRITE_MESSAGE("Listing output lanes");
179  for (int i = 0; i < myLinks.size(); i++) {
180  LinkVector oneLink = getLinksAt(i);
181 
182  for (int j = 0; j < oneLink.size(); j++) {
183 
184  MSLane* lane = oneLink[j]->getLane();
185  WRITE_MESSAGE(lane ->getID());
186 
187  }
188  }
189  )
190 
191 
192  LaneVectorVector myLaneVector;
193 
194  LaneVector outLanes;
195  LinkVectorVector myoutLinks = getLinks();
196 
197  for (int i = 0; i < (int)myLinks.size(); i++) {
198  LinkVector oneLink = getLinksAt(i);
199  for (int j = 0; j < (int)oneLink.size(); j++) {
200  MSLane* lane = oneLink[j]->getLane();
201  outLanes.push_back(lane);
202  }
203  }
204 
205  if (outLanes.size() > 0) {
206  myLaneVector.push_back(outLanes);
207  }
208  if (myLaneVector.size() > 0) {
209  ((MSSOTLE2Sensors*)mySensors)->buildOutSensors(myLaneVector, nb, getOutputSensorsLength());
210  myCountSensors->buildCountOutSensors(myLaneVector, nb);
211  }
212 
213  }
214  }
215 }
216 
217 
218 void
220  std::map<int, SUMOTime>::iterator phaseIterator = targetPhasesCTS.find(phaseStep);
221  if (phaseIterator != targetPhasesCTS.end()) {
222  phaseIterator->second = 0;
224  }
225 }
226 
227 void
229  SUMOTime elapsedTimeSteps = 0;
231  //Iterate over the target phase map and update CTS value for every target phase except for the one belonging to the current steps chain
232  for (std::map<int, SUMOTime>::iterator mapIterator = targetPhasesCTS.begin();
233  mapIterator != targetPhasesCTS.end();
234  mapIterator++) {
235  int chain = mapIterator->first;
236  SUMOTime oldVal = mapIterator->second;
237  if (chain != lastChain) {
238  //Get the number of timesteps since the last check for that phase
239  elapsedTimeSteps = now - lastCheckForTargetPhase[chain];
240  //Update the last check time
241  lastCheckForTargetPhase[chain] = now;
242  //Increment the CTS
243  //SWITCH between 3 counting vehicles function
244  switch (getMode()) {
245  case (0):
246  mapIterator->second += elapsedTimeSteps
247  * countVehicles(getPhase(chain)); //SUMO
248  break;
249  case (1):
250  mapIterator->second += elapsedTimeSteps
251  * countVehicles(getPhase(chain)); //COMPLEX
252  break;
253  case (2):
254  mapIterator->second = countVehicles(getPhase(chain)); //QUEUE
255  break;
256  default:
257  WRITE_ERROR("Unrecognized traffic threshold calculation mode");
258  }
259  std::ostringstream oss;
260  oss << "MSSOTLTrafficLightLogic::updateCTS->TLC " << getID() << " chain " << chain << " oldVal " << oldVal << " newVal " << mapIterator->second;
261  WRITE_MESSAGE(oss.str());
262  }
265  }
266  }
267 }
268 
269 int
271 
272  if (!phase.isTarget()) {
273  return 0;
274  }
275 
276  int accumulator = 0;
277  //Iterate over the target lanes for the current target phase to get the number of approaching vehicles
279  for (MSPhaseDefinition::LaneIdVector::const_iterator laneIterator = targetLanes.begin(); laneIterator != targetLanes.end(); laneIterator++) {
280  //SWITCH between 3 counting vehicles function
281  switch (getMode()) {
282  case (0):
283  accumulator += mySensors->countVehicles((*laneIterator)); //SUMO
284  break;
285  case (1):
286  accumulator += ((MSSOTLE2Sensors*)mySensors)->estimateVehicles((*laneIterator)); //COMPLEX
287  break;
288  case (2):
289  accumulator = MAX2((int)((MSSOTLE2Sensors*)mySensors)->getEstimateQueueLength((*laneIterator)), accumulator); //QUEUE
290  break;
291  default:
292  WRITE_ERROR("Unrecognized traffic threshold calculation mode");
293  }
294  }
295  return accumulator;
296 }
297 
298 void
300  if (getCurrentPhaseDef().isGreenPhase()) {
302  }
303 // ANALYSIS_DBG(
304  DBG(
305  std::stringstream out;
306  out << decayThreshold;
307  WRITE_MESSAGE("\n" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + "\tMSSOTLTrafficLightLogic::updateDecayThreshold():: " + out.str());
308  )
309 }
310 bool
312 
313  DBG(
314  // WRITE_MESSAGE("\n" +time2string(MSNet::getInstance()->getCurrentTimeStep()) +"\tMSSOTLTrafficLightLogic::isThresholdPassed():: " + " tlsid=" + getID());
315 
316  std::ostringstream threshold_str;
317  // threshold_str << "tlsid=" << getID() << " targetPhaseCTS size=" << targetPhasesCTS.size();
318 // threshold_str << "\n";
319  WRITE_MESSAGE(threshold_str.str());
320  )
321  /*
322  * if a dynamic threshold based on the exponential decrease, if passed we force the phase change
323  */
324 // SUMOReal random = ((SUMOReal) RandHelper::rand(RAND_MAX) / (RAND_MAX));
325  SUMOReal random = RandHelper::rand();
326 // ANALYSIS_DBG(
327  DBG(
329  std::ostringstream str;
330  str << time2string(MSNet::getInstance()->getCurrentTimeStep()) << "\tMSSOTLTrafficLightLogic::isThresholdPassed():: "
331  << " tlsid=" << getID() << " decayThreshold=" << decayThreshold << " random=" << random << ">" << (1 - decayThreshold)
332  << (random > (1 - decayThreshold) ? " true" : " false");
333 
334  WRITE_MESSAGE(str.str());
335  }
336  )
337  if (!isDecayThresholdActivated() || (isDecayThresholdActivated() && random > (1 - decayThreshold))) {
338  for (std::map<int, SUMOTime>::const_iterator iterator =
339  targetPhasesCTS.begin(); iterator != targetPhasesCTS.end();
340  iterator++) {
341  DBG(
342  SUMOTime step = MSNet::getInstance()->getCurrentTimeStep();
343  std::ostringstream threshold_str;
344  // threshold_str <<"\tTL " +getID()<<" time " +time2string(step)<< "(getThreshold()= " << getThreshold()
345  // << ", targetPhaseCTS= " << iterator->second << " )" << " phase="<<getPhase(iterator->first).getState();
346  threshold_str << getCurrentPhaseDef().getState() << ";" << time2string(step) << ";" << getThreshold()
347  << ";" << iterator->second << ";" << getPhase(iterator->first).getState() << ";"
348  << iterator->first << "!=" << lastChain;
349  WRITE_MESSAGE(threshold_str.str());
350  );
351  //Note that the current chain is not eligible to be directly targeted again, it would be unfair
352  if ((iterator->first != lastChain) && (getThreshold() <= iterator->second)) {
353  return true;
354  }
355  }
356  return false;
357  } else {
358  return true;
359  }
360 }
361 
362 
363 SUMOTime
365  MSPhaseDefinition currentPhase = getCurrentPhaseDef();
366 
368  SUMOTime elapsed = now - currentPhase.myLastSwitch;
369 
370  return elapsed;
371 }
372 
373 
374 int
376  SUMOTime maxCTS = 0;
377  int maxLastStep = getTargetPhaseMaxLastSelection();
378  bool usedMaxCTS = false;
379  std::vector<int> equalIndexes;
380  for (std::map<int, int>::const_iterator it = targetPhasesLastSelection.begin();
381  it != targetPhasesLastSelection.end(); ++it) {
382  if (it->first != lastChain) {
383  if (maxLastStep < it->second) {
384  maxLastStep = it->second;
385  equalIndexes.clear();
386  equalIndexes.push_back(it->first);
387  } else if (maxLastStep == it->second) {
388  equalIndexes.push_back(it->first);
389  }
390  }
391  }
392  if (equalIndexes.size() == 0) {
393  usedMaxCTS = true;
394  for (std::map<int, SUMOTime>::const_iterator iterator = targetPhasesCTS.begin();
395  iterator != targetPhasesCTS.end(); ++iterator) {
396  if (iterator->first != lastChain) {
397  if (maxCTS < iterator->second) {
398  maxCTS = iterator->second;
399  equalIndexes.clear();
400  equalIndexes.push_back(iterator->first);
401  } else if (maxCTS == iterator->second) {
402  equalIndexes.push_back(iterator->first);
403  }
404  }
405  }
406  }
407 
408  std::ostringstream oss;
409  oss << "MSSOTLTrafficLightLogic::getPhaseIndexWithMaxCTS-> TLC " << getID();
410  if (usedMaxCTS) {
411  oss << " maxCTS " << maxCTS;
412  } else {
413  oss << " forcing selection since not selected for " << maxLastStep;
414  }
415  if (equalIndexes.size() == 1) {
416  oss << " phase " << equalIndexes[0];
417  WRITE_MESSAGE(oss.str());
418  return equalIndexes[0];
419  } else {
420  const int index = RandHelper::getRandomFrom(equalIndexes);
421  oss << " phases [";
422  for (std::vector<int>::const_iterator it = equalIndexes.begin(); it != equalIndexes.end(); ++it) {
423  oss << *it << ", ";
424  }
425  oss << "]. Random select " << index;
426  WRITE_MESSAGE(oss.str());
427  return index;
428  }
429 }
430 
431 int
433  MSPhaseDefinition currentPhase = getCurrentPhaseDef();
434  //If the junction was in a commit step
435  //=> go to the target step that gives green to the set with the current highest CTS
436  // and return computeReturnTime()
437  if (currentPhase.isCommit()) {
438  // decide which chain to activate. Gotta work on this
439  return getPhaseIndexWithMaxCTS();
440  }
441  if (currentPhase.isTransient()) {
442  //If the junction was in a transient step
443  //=> go to the next step and return computeReturnTime()
444  return getCurrentPhaseIndex() + 1;
445  }
446 
447  if (currentPhase.isDecisional()) {
448 
449  if (canRelease()) {
450  return getCurrentPhaseIndex() + 1;
451  }
452  }
453 
454  return getCurrentPhaseIndex();
455 }
456 
457 SUMOTime
459  if (MSNet::getInstance()->getCurrentTimeStep() % 1000 == 0) {
460  WRITE_MESSAGE("MSSOTLTrafficLightLogic::trySwitch()")
461  // To check if decideNextPhase changes the step
462  int previousStep = getCurrentPhaseIndex() ;
463  SUMOTime elapsed = getCurrentPhaseElapsed();
464  // Update CTS according to sensors
465  updateCTS();
466 
467  // Invoking the function member, specialized for each SOTL logic
469  MSPhaseDefinition currentPhase = getCurrentPhaseDef();
470 
471  //At the end, check if new step started
472  if (getCurrentPhaseIndex() != previousStep) {
473  //Check if a new steps chain started
474  if (currentPhase.isTarget()) {
475  //Reset CTS for the ending steps chain
477  //Update lastTargetPhase
479  for (std::map<int, int>::iterator it = targetPhasesLastSelection.begin(); it != targetPhasesLastSelection.end(); ++ it) {
480  if (it->first == lastChain) {
481  if (it->second >= getTargetPhaseMaxLastSelection()) {
482  std::ostringstream oss;
483  oss << "Forced selection of the phase " << lastChain << " since its last selection was " << it->second << " changes ago";
484  WRITE_MESSAGE(oss.str())
485  }
486  it->second = 0;
487  } else if (it->first != previousStep) {
488  ++it->second;
489  }
490  }
492  decayThreshold = 1;
493  }
494  }
495  //Inform the sensors logic
497  //Store the time the new phase started
500  decayThreshold = 1;
501  }
502  ANALYSIS_DBG(
503  std::ostringstream oss;
504  oss << getID() << " from " << getPhase(previousStep).getState() << " to " << currentPhase.getState() << " after " << time2string(elapsed);
505  WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + "\tMSSOTLTrafficLightLogic::trySwitch " + oss.str());
506  )
507  }
508  }
509  return computeReturnTime();
510 }
511 
513  if (getParameter("USE_PUSH_BUTTON", "0") == "0") {
514  return false;
515  }
516  const MSPhaseDefinition currentPhase = getCurrentPhaseDef();
517  if (m_pushButtons.find(currentPhase.getState()) == m_pushButtons.end()) {
518  m_pushButtons[currentPhase.getState()] = MSPedestrianPushButton::loadPushButtons(&currentPhase);
519  }
520  return MSPushButton::anyActive(m_pushButtons[currentPhase.getState()]);
521 }
522 
static const T & getRandomFrom(const std::vector< T > &v)
Returns a random element from the given vector.
Definition: RandHelper.h:114
const std::string & getState() const
Returns the state within this phase.
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:80
Builds detectors for microsim.
long long int SUMOTime
Definition: SUMOTime.h:43
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 SUMOReal rand()
Returns a random real number in [0, 1)
Definition: RandHelper.h:62
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:59
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:159
T MAX2(T a, T b)
Definition: StdDefs.h:75
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:66
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.
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:254
#define DBG(X)
Definition: SwarmDebug.h:30
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
virtual int countVehicles(MSLane *lane)=0
std::vector< MSLink * > LinkVector
Definition of the list of links that participate in this tl-light.
bool isUndefined() const
std::vector< MSPhaseDefinition * > Phases
Definition of a list of phases, being the junction logic.
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:206
const std::string & getParameter(const std::string &key, const std::string &defaultValue) const
Returns the value for a given key.
#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:136
std::vector< MSLane * > LaneVector
Definition of the list of links that participate in this tl-light.
std::vector< LaneVector > LaneVectorVector
Definition of a list that holds lists of links that do have the same attribute.
std::vector< std::string > LaneIdVector
const MSPhaseDefinition & getCurrentPhaseDef() const
Returns the definition of the current phase.
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:89
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
#define SUMOReal
Definition: config.h:213
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:201
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:79
#define SENSORS_TYPE_E1
void setStep(int step)
Forces a specific step.
bool isDecisional() const
std::map< int, int > targetPhasesLastSelection
int countVehicles(MSPhaseDefinition phase)