SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 
131  if (isDecayThresholdActivated()) {
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 
143  LaneVectorVector lvv = getLaneVectors();
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 
158  mySensors = new MSSOTLE2Sensors(myID, &(getPhases()));
159  ((MSSOTLE2Sensors*)mySensors)->buildSensors(myLanes, nb, getInputSensorsLength());
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()));
169  myCountSensors->buildCountSensors(myLanes, nb);
170  myCountSensors->stepChanged(getCurrentPhaseIndex());
171 
172  //Adding Sensors to the outgoing Lanes
173 
174  LinkVectorVector myLinks = getLinks();
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
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
const std::string & getState() const
Returns the state within this phase.
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)
bool isTarget() const
bool isCommit() const
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 bool anyActive(const std::vector< MSPushButton * > &)
Checks if any pushbutton in the vector is active.
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
std::map< int, SUMOTime > lastCheckForTargetPhase
const std::string & getParameter(const std::string &key, const std::string &defaultValue) const
Returns the value for a given key.
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:254
A class that stores and controls tls and switching of their programs.
const std::string & getID() const
Returns the id.
Definition: Named.h:66
std::vector< LinkVector > LinkVectorVector
Definition of a list that holds lists of links that do have the same attribute.
int getCurrentPhaseIndex() const
Returns the current index within the program.
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
const MSPhaseDefinition & getPhase(int givenstep) const
Returns the definition of the phase from the given position within the plan.
#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.
std::vector< MSPhaseDefinition * > Phases
Definition of a list of phases, being the junction logic.
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:206
#define SENSORS_TYPE
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.
const LaneIdVector & getTargetLaneSet() const
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
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.
void inform(std::string msg, bool addType=true)
adds a new error to the list
Definition: MsgHandler.cpp:89
const Phases & getPhases() const
Returns the phases of this tls program.
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:214
virtual bool canRelease()=0
virtual void stepChanged(int newStep)
bool isTransient() const
A fixed traffic light logic.
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:201
The definition of a single phase of a tls logic.
Representation of a lane in the micro simulation.
Definition: MSLane.h:79
const MSPhaseDefinition & getCurrentPhaseDef() const
Returns the definition of the current phase.
bool isDecisional() const
#define SENSORS_TYPE_E1
void setStep(int step)
Forces a specific step.
std::map< int, int > targetPhasesLastSelection
bool isUndefined() const
int countVehicles(MSPhaseDefinition phase)