Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2013-2024 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file MSSOTLTrafficLightLogic.cpp
15 : /// @author Gianfilippo Slager
16 : /// @author Anna Chiara Bellini
17 : /// @author Federico Caselli
18 : /// @date Apr 2013
19 : ///
20 : // The base abstract class for SOTL logics
21 : /****************************************************************************/
22 :
23 : #include <microsim/MSLane.h>
24 : #include <microsim/MSEdge.h>
25 : #include "MSPushButton.h"
26 : #include "MSSOTLTrafficLightLogic.h"
27 : //#define SWARM_DEBUG
28 : //#define ANALYSIS_DEBUG
29 :
30 : // ===========================================================================
31 : // member method definitions
32 : // ===========================================================================
33 96 : MSSOTLTrafficLightLogic::MSSOTLTrafficLightLogic(
34 : MSTLLogicControl& tlcontrol,
35 : const std::string& id,
36 : const std::string& programID,
37 : const TrafficLightType logicType,
38 : const Phases& phases,
39 : int step,
40 : SUMOTime delay,
41 96 : const Parameterised::Map& parameters) :
42 96 : MSSimpleTrafficLightLogic(tlcontrol, id, programID, 0, logicType, phases, step, delay, parameters) {
43 96 : this->mySensors = nullptr;
44 96 : this->myCountSensors = nullptr;
45 96 : sensorsSelfBuilt = true;
46 96 : checkPhases();
47 96 : setupCTS();
48 96 : setToATargetPhase();
49 96 : }
50 :
51 0 : MSSOTLTrafficLightLogic::MSSOTLTrafficLightLogic(
52 : MSTLLogicControl& tlcontrol,
53 : const std::string& id,
54 : const std::string& programID,
55 : const TrafficLightType logicType,
56 : const Phases& phases,
57 : int step,
58 : SUMOTime delay,
59 : const Parameterised::Map& parameters,
60 0 : MSSOTLSensors* sensors) :
61 0 : MSSimpleTrafficLightLogic(tlcontrol, id, programID, 0, logicType, phases, step, delay, parameters) {
62 0 : this->mySensors = sensors;
63 0 : sensorsSelfBuilt = false;
64 0 : checkPhases();
65 0 : setupCTS();
66 0 : setToATargetPhase();
67 0 : }
68 :
69 96 : MSSOTLTrafficLightLogic::~MSSOTLTrafficLightLogic() {
70 96 : for (PhasePushButtons::iterator mapIt = m_pushButtons.begin(); mapIt != m_pushButtons.end(); ++mapIt)
71 0 : for (std::vector<MSPushButton*>::iterator vIt = mapIt->second.begin(); vIt != mapIt->second.end(); ++vIt) {
72 0 : delete *vIt;
73 : }
74 : m_pushButtons.clear();
75 96 : if (sensorsSelfBuilt) {
76 96 : delete mySensors;
77 : // delete myCountSensors;
78 : }
79 96 : }
80 :
81 0 : void MSSOTLTrafficLightLogic::logStatus() {
82 :
83 0 : }
84 :
85 : void
86 96 : MSSOTLTrafficLightLogic::checkPhases() {
87 672 : for (int step = 0; step < (int)getPhases().size(); step++) {
88 576 : if (getPhase(step).isUndefined()) {
89 0 : MsgHandler::getErrorInstance()->inform("Step " + toString(step) + " of traffic light logic " + myID + " phases declaration has its type undeclared!");
90 : }
91 : }
92 96 : }
93 :
94 : void
95 96 : MSSOTLTrafficLightLogic::setupCTS() {
96 672 : for (int phaseStep = 0; phaseStep < (int)getPhases().size(); phaseStep++) {
97 576 : if (getPhase(phaseStep).isTarget()) {
98 192 : targetPhasesCTS[phaseStep] = 0;
99 192 : lastCheckForTargetPhase[phaseStep] = MSNet::getInstance()->getCurrentTimeStep();
100 192 : targetPhasesLastSelection[phaseStep] = 0;
101 : }
102 : }
103 96 : }
104 :
105 : void
106 96 : MSSOTLTrafficLightLogic::setToATargetPhase() {
107 96 : for (int step = 0; step < (int)getPhases().size(); step++) {
108 96 : if (getPhase(step).isTarget()) {
109 96 : setStep(step);
110 96 : lastChain = step;
111 96 : return;
112 : }
113 : }
114 0 : MsgHandler::getErrorInstance()->inform("No phase of type target found for traffic light logic " + myID + " The logic could malfunction. Check phases declaration.");
115 : }
116 :
117 :
118 : void
119 96 : MSSOTLTrafficLightLogic::init(NLDetectorBuilder& nb) {
120 :
121 96 : MSTrafficLightLogic::init(nb);
122 :
123 96 : if (isDecayThresholdActivated()) {
124 0 : decayThreshold = 1;
125 : }
126 96 : if (sensorsSelfBuilt) {
127 : //Building SOTLSensors
128 : switch (SENSORS_TYPE) {
129 96 : case SENSORS_TYPE_E1:
130 : assert(0); // Throw exception because TLS can only handle E2 sensors
131 : case SENSORS_TYPE_E2:
132 :
133 : //Adding Sensors to the ingoing Lanes
134 :
135 192 : LaneVectorVector lvv = getLaneVectors();
136 :
137 : #ifdef SWARM_DEBUG
138 : WRITE_MESSAGE("Listing lanes for TLS " + getID());
139 :
140 : for (int i = 0; i < lvv.size(); i++) {
141 : LaneVector lv = lvv[i];
142 :
143 : for (int j = 0; j < lv.size(); j++) {
144 : MSLane* lane = lv[j];
145 : WRITE_MESSAGE(lane ->getID());
146 : }
147 : }
148 : #endif
149 :
150 192 : mySensors = new MSSOTLE2Sensors(myID, &(getPhases()));
151 96 : ((MSSOTLE2Sensors*)mySensors)->buildSensors(myLanes, nb, getInputSensorsLength());
152 96 : mySensors->stepChanged(getCurrentPhaseIndex());
153 192 : if (getParameter("USE_VEHICLE_TYPES_WEIGHTS", "0") == "1") {
154 0 : ((MSSOTLE2Sensors*) mySensors)->setVehicleWeigths(getParameter("VEHICLE_TYPES_WEIGHTS", ""));
155 : }
156 :
157 : //threshold speed param for tuning with irace
158 96 : ((MSSOTLE2Sensors*)mySensors)->setSpeedThresholdParam(getSpeedThreshold());
159 :
160 96 : myCountSensors = new MSSOTLE2Sensors(myID + "Count", &(getPhases()));
161 96 : myCountSensors->buildCountSensors(myLanes, nb);
162 96 : myCountSensors->stepChanged(getCurrentPhaseIndex());
163 :
164 : //Adding Sensors to the outgoing Lanes
165 :
166 192 : LinkVectorVector links = getLinks();
167 :
168 : #ifdef SWARM_DEBUG
169 : WRITE_MESSAGE(TL("Listing output lanes"));
170 : for (int i = 0; i < links.size(); i++) {
171 : LinkVector oneLink = getLinksAt(i);
172 : for (int j = 0; j < oneLink.size(); j++) {
173 : MSLane* lane = oneLink[j]->getLane();
174 : WRITE_MESSAGE(lane ->getID());
175 : }
176 : }
177 : #endif
178 :
179 96 : LaneVectorVector myLaneVector;
180 96 : LaneVector outLanes;
181 192 : LinkVectorVector myoutLinks = getLinks();
182 :
183 480 : for (int i = 0; i < (int)links.size(); i++) {
184 384 : LinkVector oneLink = getLinksAt(i);
185 768 : for (int j = 0; j < (int)oneLink.size(); j++) {
186 384 : MSLane* lane = oneLink[j]->getLane();
187 384 : outLanes.push_back(lane);
188 : }
189 384 : }
190 :
191 96 : if (outLanes.size() > 0) {
192 96 : myLaneVector.push_back(outLanes);
193 : }
194 96 : if (myLaneVector.size() > 0) {
195 96 : ((MSSOTLE2Sensors*)mySensors)->buildOutSensors(myLaneVector, nb, getOutputSensorsLength());
196 96 : myCountSensors->buildCountOutSensors(myLaneVector, nb);
197 : }
198 :
199 : }
200 : }
201 96 : }
202 :
203 :
204 : void
205 3513 : MSSOTLTrafficLightLogic::resetCTS(int phaseStep) {
206 : std::map<int, SUMOTime>::iterator phaseIterator = targetPhasesCTS.find(phaseStep);
207 3513 : if (phaseIterator != targetPhasesCTS.end()) {
208 3513 : phaseIterator->second = 0;
209 3513 : lastCheckForTargetPhase[phaseStep] = MSNet::getInstance()->getCurrentTimeStep();
210 : }
211 3513 : }
212 :
213 : void
214 99148 : MSSOTLTrafficLightLogic::updateCTS() {
215 : SUMOTime elapsedTimeSteps = 0;
216 99148 : SUMOTime now = MSNet::getInstance()->getCurrentTimeStep();
217 : //Iterate over the target phase map and update CTS value for every target phase except for the one belonging to the current steps chain
218 99148 : for (std::map<int, SUMOTime>::iterator mapIterator = targetPhasesCTS.begin();
219 297444 : mapIterator != targetPhasesCTS.end();
220 : mapIterator++) {
221 198296 : int chain = mapIterator->first;
222 198296 : SUMOTime oldVal = mapIterator->second;
223 198296 : if (chain != lastChain) {
224 : //Get the number of timesteps since the last check for that phase
225 99148 : elapsedTimeSteps = now - lastCheckForTargetPhase[chain];
226 : //Update the last check time
227 99148 : lastCheckForTargetPhase[chain] = now;
228 : //Increment the CTS
229 : //SWITCH between 3 counting vehicles function
230 99148 : switch (getMode()) {
231 99148 : case (0):
232 99148 : mapIterator->second += elapsedTimeSteps
233 99148 : * countVehicles(getPhase(chain)); //SUMO
234 99148 : break;
235 0 : case (1):
236 0 : mapIterator->second += elapsedTimeSteps
237 0 : * countVehicles(getPhase(chain)); //COMPLEX
238 0 : break;
239 0 : case (2):
240 0 : mapIterator->second = countVehicles(getPhase(chain)); //QUEUE
241 0 : break;
242 0 : default:
243 0 : WRITE_ERROR(TL("Unrecognized traffic threshold calculation mode"));
244 : }
245 99148 : std::ostringstream oss;
246 198296 : oss << "MSSOTLTrafficLightLogic::updateCTS->TLC " << getID() << " chain " << chain << " oldVal " << oldVal << " newVal " << mapIterator->second;
247 198296 : WRITE_MESSAGE(oss.str());
248 : }
249 198296 : if (isDecayThresholdActivated()) {
250 0 : updateDecayThreshold();
251 : }
252 : }
253 99148 : }
254 :
255 : int
256 181974 : MSSOTLTrafficLightLogic::countVehicles(MSPhaseDefinition phase) {
257 :
258 181974 : if (!phase.isTarget()) {
259 : return 0;
260 : }
261 :
262 : int accumulator = 0;
263 : //Iterate over the target lanes for the current target phase to get the number of approaching vehicles
264 527028 : for (const std::string& lane : phase.getTargetLaneSet()) {
265 : //SWITCH between 3 counting vehicles function
266 351352 : switch (getMode()) {
267 351352 : case (0):
268 702704 : accumulator += mySensors->countVehicles(lane); //SUMO
269 351352 : break;
270 0 : case (1):
271 0 : accumulator += ((MSSOTLE2Sensors*)mySensors)->estimateVehicles(lane); //COMPLEX
272 0 : break;
273 0 : case (2):
274 0 : accumulator = MAX2((int)((MSSOTLE2Sensors*)mySensors)->getEstimateQueueLength(lane), accumulator); //QUEUE
275 0 : break;
276 0 : default:
277 0 : WRITE_ERROR(TL("Unrecognized traffic threshold calculation mode"));
278 : }
279 : }
280 : return accumulator;
281 : }
282 :
283 : void
284 0 : MSSOTLTrafficLightLogic::updateDecayThreshold() {
285 0 : if (getCurrentPhaseDef().isGreenPhase()) {
286 0 : decayThreshold = decayThreshold * exp(getDecayConstant());
287 : }
288 : #ifdef SWARM_DEBUG
289 : std::stringstream out;
290 : out << decayThreshold;
291 : WRITE_MESSAGE("\n" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + "\tMSSOTLTrafficLightLogic::updateDecayThreshold():: " + out.str());
292 : #endif
293 0 : }
294 : bool
295 82826 : MSSOTLTrafficLightLogic::isThresholdPassed() {
296 : #ifdef SWARM_DEBUG
297 : // WRITE_MESSAGEF(TL("\n% tlsid=% // WRITE_MESSAGEF(TL("\n% tlsid=" + getID()), ime2string(MSNet::getInstance()->getCurrentTimeStep()) +"\tMSSOTLTrafficLightLogic::isThresholdPassed():: ", getID()), ime2string(MSNet::getInstance()->getCurrentTimeStep()) +"\tMSSOTLTrafficLightLogic::isThresholdPassed():: ");
298 :
299 : std::ostringstream threshold_str;
300 : // threshold_str << "tlsid=" << getID() << " targetPhaseCTS size=" << targetPhasesCTS.size();
301 : // threshold_str << "\n";
302 : WRITE_MESSAGE(threshold_str.str());
303 : #endif
304 : /*
305 : * if a dynamic threshold based on the exponential decrease, if passed we force the phase change
306 : */
307 : // double random = ((double) RandHelper::rand(RAND_MAX) / (RAND_MAX));
308 82826 : double random = RandHelper::rand();
309 : // ANALYSIS_DBG(
310 : #ifdef SWARM_DEBUG
311 : if (isDecayThresholdActivated()) {
312 : std::ostringstream str;
313 : str << time2string(MSNet::getInstance()->getCurrentTimeStep()) << "\tMSSOTLTrafficLightLogic::isThresholdPassed():: "
314 : << " tlsid=" << getID() << " decayThreshold=" << decayThreshold << " random=" << random << ">" << (1 - decayThreshold)
315 : << (random > (1 - decayThreshold) ? " true" : " false");
316 :
317 : WRITE_MESSAGE(str.str());
318 : }
319 : #endif
320 82826 : if (!isDecayThresholdActivated() || (isDecayThresholdActivated() && random > (1 - decayThreshold))) {
321 82826 : for (std::map<int, SUMOTime>::const_iterator iterator =
322 178743 : targetPhasesCTS.begin(); iterator != targetPhasesCTS.end();
323 : iterator++) {
324 : #ifdef SWARM_DEBUG
325 : SUMOTime step = MSNet::getInstance()->getCurrentTimeStep();
326 : std::ostringstream threshold_str;
327 : // threshold_str <<"\tTL " +getID()<<" time=" +time2string(step)<< "(getThreshold()= " << getThreshold()
328 : // << ", targetPhaseCTS= " << iterator->second << " )" << " phase="<<getPhase(iterator->first).getState();
329 : threshold_str << getCurrentPhaseDef().getState() << ";" << time2string(step) << ";" << getThreshold()
330 : << ";" << iterator->second << ";" << getPhase(iterator->first).getState() << ";"
331 : << iterator->first << "!=" << lastChain;
332 : WRITE_MESSAGE(threshold_str.str());
333 : #endif
334 : //Note that the current chain is not eligible to be directly targeted again, it would be unfair
335 142284 : if ((iterator->first != lastChain) && (getThreshold() <= iterator->second)) {
336 : return true;
337 : }
338 : }
339 : return false;
340 : } else {
341 : return true;
342 : }
343 : }
344 :
345 :
346 : SUMOTime
347 113024 : MSSOTLTrafficLightLogic::getCurrentPhaseElapsed() {
348 113024 : MSPhaseDefinition currentPhase = getCurrentPhaseDef();
349 :
350 113024 : SUMOTime now = MSNet::getInstance()->getCurrentTimeStep();
351 113024 : SUMOTime elapsed = now - currentPhase.myLastSwitch;
352 :
353 113024 : return elapsed;
354 113024 : }
355 :
356 :
357 : int
358 83190 : MSSOTLTrafficLightLogic::getPhaseIndexWithMaxCTS() {
359 : SUMOTime maxCTS = 0;
360 : int maxLastStep = getTargetPhaseMaxLastSelection();
361 : bool usedMaxCTS = false;
362 : std::vector<int> equalIndexes;
363 83190 : for (std::map<int, int>::const_iterator it = targetPhasesLastSelection.begin();
364 249570 : it != targetPhasesLastSelection.end(); ++it) {
365 166380 : if (it->first != lastChain) {
366 83190 : if (maxLastStep < it->second) {
367 : maxLastStep = it->second;
368 : equalIndexes.clear();
369 0 : equalIndexes.push_back(it->first);
370 83190 : } else if (maxLastStep == it->second) {
371 70793 : equalIndexes.push_back(it->first);
372 : }
373 : }
374 : }
375 83190 : if (equalIndexes.size() == 0) {
376 : usedMaxCTS = true;
377 12397 : for (std::map<int, SUMOTime>::const_iterator iterator = targetPhasesCTS.begin();
378 37191 : iterator != targetPhasesCTS.end(); ++iterator) {
379 24794 : if (iterator->first != lastChain) {
380 12397 : if (maxCTS < iterator->second) {
381 : maxCTS = iterator->second;
382 : equalIndexes.clear();
383 144 : equalIndexes.push_back(iterator->first);
384 12253 : } else if (maxCTS == iterator->second) {
385 12253 : equalIndexes.push_back(iterator->first);
386 : }
387 : }
388 : }
389 : }
390 :
391 83190 : std::ostringstream oss;
392 : oss << "MSSOTLTrafficLightLogic::getPhaseIndexWithMaxCTS-> TLC " << getID();
393 83190 : if (usedMaxCTS) {
394 : oss << " maxCTS " << maxCTS;
395 : } else {
396 70793 : oss << " forcing selection since not selected for " << maxLastStep;
397 : }
398 83190 : if (equalIndexes.size() == 1) {
399 83190 : oss << " phase " << equalIndexes[0];
400 166380 : WRITE_MESSAGE(oss.str());
401 83190 : return equalIndexes[0];
402 : } else {
403 0 : const int index = RandHelper::getRandomFrom(equalIndexes);
404 0 : oss << " phases [";
405 0 : for (std::vector<int>::const_iterator it = equalIndexes.begin(); it != equalIndexes.end(); ++it) {
406 0 : oss << *it << ", ";
407 : }
408 0 : oss << "]. Random select " << index;
409 0 : WRITE_MESSAGE(oss.str());
410 0 : return index;
411 : }
412 83190 : }
413 :
414 : int
415 15404 : MSSOTLTrafficLightLogic::decideNextPhase() {
416 15404 : MSPhaseDefinition currentPhase = getCurrentPhaseDef();
417 : //If the junction was in a commit step
418 : //=> go to the target step that gives green to the set with the current highest CTS
419 : // and return computeReturnTime()
420 15404 : if (currentPhase.isCommit()) {
421 : // decide which chain to activate. Gotta work on this
422 364 : return getPhaseIndexWithMaxCTS();
423 : }
424 15040 : if (currentPhase.isTransient()) {
425 : //If the junction was in a transient step
426 : //=> go to the next step and return computeReturnTime()
427 365 : return getCurrentPhaseIndex() + 1;
428 : }
429 :
430 : if (currentPhase.isDecisional()) {
431 :
432 14675 : if (canRelease()) {
433 369 : return getCurrentPhaseIndex() + 1;
434 : }
435 : }
436 :
437 14306 : return getCurrentPhaseIndex();
438 15404 : }
439 :
440 : SUMOTime
441 99148 : MSSOTLTrafficLightLogic::trySwitch() {
442 99148 : if (MSNet::getInstance()->getCurrentTimeStep() % 1000 == 0) {
443 99148 : WRITE_MESSAGE("MSSOTLTrafficLightLogic::trySwitch()");
444 : // To check if decideNextPhase changes the step
445 99148 : int previousStep = getCurrentPhaseIndex() ;
446 : #ifdef ANALYSIS_DEBUG
447 : SUMOTime elapsed = getCurrentPhaseElapsed();
448 : #endif
449 : // Update CTS according to sensors
450 99148 : updateCTS();
451 :
452 : // Invoking the function member, specialized for each SOTL logic
453 99148 : setStep(decideNextPhase());
454 99148 : MSPhaseDefinition currentPhase = getCurrentPhaseDef();
455 :
456 : //At the end, check if new step started
457 99148 : if (getCurrentPhaseIndex() != previousStep) {
458 : //Check if a new steps chain started
459 10545 : if (currentPhase.isTarget()) {
460 : //Reset CTS for the ending steps chain
461 3513 : resetCTS(lastChain);
462 : //Update lastTargetPhase
463 3513 : lastChain = getCurrentPhaseIndex();
464 10539 : for (std::map<int, int>::iterator it = targetPhasesLastSelection.begin(); it != targetPhasesLastSelection.end(); ++ it) {
465 7026 : if (it->first == lastChain) {
466 3513 : if (it->second >= getTargetPhaseMaxLastSelection()) {
467 3435 : std::ostringstream oss;
468 6870 : oss << "Forced selection of the phase " << lastChain << " since its last selection was " << it->second << " changes ago";
469 3435 : WRITE_MESSAGE(oss.str())
470 3435 : }
471 3513 : it->second = 0;
472 3513 : } else if (it->first != previousStep) {
473 3513 : ++it->second;
474 : }
475 : }
476 3513 : if (isDecayThresholdActivated()) {
477 0 : decayThreshold = 1;
478 : }
479 : }
480 : //Inform the sensors logic
481 10545 : mySensors->stepChanged(getCurrentPhaseIndex());
482 : //Store the time the new phase started
483 10545 : currentPhase.myLastSwitch = MSNet::getInstance()->getCurrentTimeStep();
484 10545 : if (isDecayThresholdActivated()) {
485 0 : decayThreshold = 1;
486 : }
487 : #ifdef ANALYSIS_DEBUG
488 : std::ostringstream oss;
489 : oss << getID() << " from " << getPhase(previousStep).getState() << " to " << currentPhase.getState() << " after " << time2string(elapsed);
490 : WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + "\tMSSOTLTrafficLightLogic::trySwitch " + oss.str());
491 : #endif
492 : }
493 99148 : }
494 99148 : return computeReturnTime();
495 : }
496 :
497 82826 : bool MSSOTLTrafficLightLogic::isPushButtonPressed() {
498 165652 : if (getParameter("USE_PUSH_BUTTON", "0") == "0") {
499 : return false;
500 : }
501 0 : const MSPhaseDefinition currentPhase = getCurrentPhaseDef();
502 0 : if (m_pushButtons.find(currentPhase.getState()) == m_pushButtons.end()) {
503 0 : m_pushButtons[currentPhase.getState()] = MSPedestrianPushButton::loadPushButtons(¤tPhase);
504 : }
505 0 : return MSPushButton::anyActive(m_pushButtons[currentPhase.getState()]);
506 0 : }
507 :
508 :
509 99244 : void MSSOTLTrafficLightLogic::setStep(int step) {
510 99244 : step = step % myPhases.size();
511 99244 : if (myStep != step) {
512 10545 : myStep = step;
513 10545 : myPhases[myStep]->myLastSwitch = MSNet::getInstance()->getCurrentTimeStep();
514 : }
515 99244 : }
|