Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-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 MSTrafficLightLogic.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Sept 2002
19 : ///
20 : // The parent class for traffic light logics
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <cassert>
25 : #include <string>
26 : #include <iostream>
27 : #include <map>
28 : #include <microsim/MSLink.h>
29 : #include <microsim/MSLane.h>
30 : #include <microsim/MSEventControl.h>
31 : #include <microsim/MSJunctionLogic.h>
32 : #include <microsim/MSNet.h>
33 : #include <microsim/MSEdge.h>
34 : #include <microsim/MSGlobals.h>
35 : #include <mesosim/MESegment.h>
36 : #include "MSTLLogicControl.h"
37 : #include "MSTrafficLightLogic.h"
38 :
39 :
40 : // ===========================================================================
41 : // static value definitions
42 : // ===========================================================================
43 : const MSTrafficLightLogic::LaneVector MSTrafficLightLogic::myEmptyLaneVector;
44 :
45 :
46 : // ===========================================================================
47 : // member method definitions
48 : // ===========================================================================
49 : /* -------------------------------------------------------------------------
50 : * member method definitions
51 : * ----------------------------------------------------------------------- */
52 116926 : MSTrafficLightLogic::SwitchCommand::SwitchCommand(MSTLLogicControl& tlcontrol,
53 116926 : MSTrafficLightLogic* tlLogic, SUMOTime nextSwitch) :
54 116926 : myTLControl(tlcontrol), myTLLogic(tlLogic),
55 116926 : myAssumedNextSwitch(nextSwitch), myAmValid(true) {
56 : // higher than default command priority of 0
57 116926 : priority = 1;
58 116926 : }
59 :
60 :
61 232454 : MSTrafficLightLogic::SwitchCommand::~SwitchCommand() {}
62 :
63 :
64 :
65 : SUMOTime
66 9528619 : MSTrafficLightLogic::SwitchCommand::execute(SUMOTime t) {
67 : // check whether this command has been descheduled
68 9528619 : if (!myAmValid) {
69 : return 0;
70 : }
71 9522379 : int step1 = myTLLogic->getCurrentPhaseIndex();
72 9522379 : SUMOTime next = myTLLogic->trySwitch();
73 9522694 : while (next == 0) {
74 : // skip phase and switch again
75 315 : next = myTLLogic->trySwitch();
76 : }
77 9522379 : int step2 = myTLLogic->getCurrentPhaseIndex();
78 9522379 : if (step1 != step2) {
79 7861461 : if (myTLLogic->isActive()) {
80 : // execute any action connected to this tls
81 7205991 : const MSTLLogicControl::TLSLogicVariants& vars = myTLControl.get(myTLLogic->getID());
82 : // set link priorities
83 7205991 : myTLLogic->setTrafficLightSignals(t);
84 : // execute switch actions
85 7205991 : vars.executeOnSwitchActions();
86 : }
87 : }
88 9522379 : myAssumedNextSwitch += next;
89 9522379 : return next;
90 : }
91 :
92 :
93 : void
94 6702 : MSTrafficLightLogic::SwitchCommand::deschedule(MSTrafficLightLogic* tlLogic) {
95 6702 : if (tlLogic == myTLLogic) {
96 6702 : myAmValid = false;
97 6702 : myAssumedNextSwitch = -1;
98 : }
99 6702 : }
100 :
101 :
102 : SUMOTime
103 1003 : MSTrafficLightLogic::SwitchCommand::shiftTime(SUMOTime currentTime, SUMOTime execTime, SUMOTime newTime) {
104 : if (myTLLogic->getDefaultCycleTime() == DELTA_T) {
105 : // MSRailSignal
106 : return newTime;
107 : } else {
108 : UNUSED_PARAMETER(currentTime);
109 : UNUSED_PARAMETER(execTime);
110 : // XXX changeStepAndDuration (computed as in NLJunctionControlBuilder::closeTrafficLightLogic
111 : return newTime;
112 : }
113 : }
114 :
115 : /* -------------------------------------------------------------------------
116 : * member method definitions
117 : * ----------------------------------------------------------------------- */
118 113709 : MSTrafficLightLogic::MSTrafficLightLogic(MSTLLogicControl& tlcontrol, const std::string& id,
119 : const std::string& programID, const SUMOTime offset, const TrafficLightType logicType, const SUMOTime delay,
120 113709 : const Parameterised::Map& parameters) :
121 : Named(id), Parameterised(parameters),
122 113709 : myProgramID(programID),
123 113709 : myOffset(offset),
124 113709 : myLogicType(logicType),
125 113709 : myCurrentDurationIncrement(-1),
126 113709 : myDefaultCycleTime(0),
127 113709 : myAmActive(true) {
128 113709 : mySwitchCommand = new SwitchCommand(tlcontrol, this, delay);
129 113709 : MSNet::getInstance()->getBeginOfTimestepEvents()->addEvent(mySwitchCommand, delay);
130 113709 : }
131 :
132 :
133 : void
134 102130 : MSTrafficLightLogic::init(NLDetectorBuilder&) {
135 102130 : const Phases& phases = getPhases();
136 102130 : if (phases.size() > 0 && (MSGlobals::gUseMesoSim || MSGlobals::gTLSPenalty > 0)) {
137 17221 : initMesoTLSPenalties();
138 : }
139 102130 : if (phases.size() > 1) {
140 : bool haveWarnedAboutUnusedStates = false;
141 85008 : std::vector<bool> foundGreen(phases.front()->getState().size(), false);
142 537032 : for (int i = 0; i < (int)phases.size(); ++i) {
143 : // warn about unused states
144 : std::vector<int> nextPhases;
145 452027 : nextPhases.push_back((i + 1) % phases.size());
146 : bool iNextDefault = true;
147 452027 : if (phases[i]->nextPhases.size() > 0) {
148 292 : nextPhases = phases[i]->nextPhases;
149 : iNextDefault = false;
150 : }
151 904184 : for (int iNext : nextPhases) {
152 452160 : if (iNext < 0 || iNext >= (int)phases.size()) {
153 1 : throw ProcessError("Invalid nextPhase " + toString(iNext) + " in tlLogic '" + getID()
154 3 : + "', program '" + getProgramID() + "' with " + toString(phases.size()) + " phases");
155 : }
156 452583 : const std::string optionalFrom = iNextDefault ? "" : " from phase " + toString(i);
157 452159 : const std::string& state1 = phases[i]->getState();
158 452159 : const std::string& state2 = phases[iNext]->getState();
159 452159 : if (state1.size() != state2.size()) {
160 1 : throw ProcessError("Mismatching phase state length in tlLogic '" + getID()
161 4 : + "', program '" + getProgramID() + "' in phases " + toString(i) + " and " + toString(iNext));
162 : }
163 452158 : if (!haveWarnedAboutUnusedStates && state1.size() > myLanes.size() + myIgnoredIndices.size()) {
164 222 : WRITE_WARNINGF(TL("Unused states in tlLogic '%', program '%' in phase % after tl-index %"),
165 : getID(), getProgramID(), i, (int)myLanes.size() - 1);
166 : haveWarnedAboutUnusedStates = true;
167 : }
168 : // detect illegal states
169 : const std::string::size_type illegal = state1.find_first_not_of(SUMOXMLDefinitions::ALLOWED_TLS_LINKSTATES);
170 452158 : if (std::string::npos != illegal) {
171 1 : throw ProcessError("Illegal character '" + toString(state1[illegal]) + "' in tlLogic '" + getID()
172 3 : + "', program '" + getProgramID() + "' in phase " + toString(i));
173 : }
174 : // warn about transitions from green to red without intermediate yellow
175 : bool haveWarned = false;
176 5480227 : for (int j = 0; j < (int)MIN3(state1.size(), state2.size(), myLanes.size()) && !haveWarned; ++j) {
177 5028070 : if ((LinkState)state2[j] == LINKSTATE_TL_RED
178 5028070 : && ((LinkState)state1[j] == LINKSTATE_TL_GREEN_MAJOR
179 2683085 : || (LinkState)state1[j] == LINKSTATE_TL_GREEN_MINOR)) {
180 25820 : for (LaneVector::const_iterator it = myLanes[j].begin(); it != myLanes[j].end(); ++it) {
181 13486 : if ((*it)->getPermissions() != SVC_PEDESTRIAN) {
182 1208 : if (getLogicType() != TrafficLightType::NEMA) {
183 1217 : WRITE_WARNINGF(TL("Missing yellow phase in tlLogic '%', program '%' for tl-index % when switching% to phase %."),
184 : getID(), getProgramID(), j, optionalFrom, iNext);
185 : // one warning per program is enough
186 : haveWarned = true;
187 : }
188 : break;
189 : }
190 : }
191 : }
192 : }
193 : // warn about links that never get the green light
194 5496101 : for (int j = 0; j < (int)state1.size(); ++j) {
195 5043944 : LinkState ls = (LinkState)state1[j];
196 5043944 : if (ls == LINKSTATE_TL_GREEN_MAJOR || ls == LINKSTATE_TL_GREEN_MINOR || ls == LINKSTATE_TL_OFF_BLINKING || ls == LINKSTATE_TL_OFF_NOSIGNAL || ls == LINKSTATE_STOP) {
197 : foundGreen[j] = true;
198 : }
199 : }
200 : }
201 452027 : }
202 1894256 : for (int j = 0; j < (int)foundGreen.size(); ++j) {
203 862217 : if (!foundGreen[j]) {
204 285 : WRITE_WARNINGF(TL("Missing green phase in tlLogic '%', program '%' for tl-index %."), getID(), getProgramID(), j);
205 94 : break;
206 : }
207 : }
208 : }
209 : // check incompatible junction logic
210 : // this can happen if the network was built with a very different signal
211 : // plan from the one currently being used.
212 : // Connections that never had a common green phase during network building may
213 : // have a symmetric response relation to avoid certain kinds of jam but this
214 : // can lead to deadlock if a different program gives minor green to both
215 : // connections at the same time
216 : // Note: mutual conflict between 'g' and 'G' is expected for traffic_light_right_on_red
217 :
218 102127 : const bool mustCheck = MSNet::getInstance()->hasInternalLinks();
219 : // The checks only runs for definitions from additional file and this is sufficient.
220 : // The distinction is implicit because original logics are loaded earlier and at that time hasInternalLinks is always false
221 : // Also, when the network has no internal links, mutual conflicts are not built by netconvert
222 : //std::cout << "init tlLogic=" << getID() << " prog=" << getProgramID() << " links=" << myLinks.size() << " internal=" << MSNet::getInstance()->hasInternalLinks() << "\n";
223 102127 : if (mustCheck && phases.size() > 0) {
224 : // see NBNode::tlsConflict
225 : std::set<const MSJunction*> controlledJunctions;
226 33374 : const int numLinks = (int)myLinks.size();
227 257823 : for (int j = 0; j < numLinks; ++j) {
228 447929 : for (int k = 0; k < (int)myLinks[j].size(); ++k) {
229 223480 : MSLink* link = myLinks[j][k];
230 : assert(link->getJunction() != nullptr);
231 223480 : controlledJunctions.insert(link->getJunction());
232 : }
233 : }
234 33374 : const std::string minor = "gos";
235 67302 : for (const MSJunction* junction : controlledJunctions) {
236 33928 : const MSJunctionLogic* logic = junction->getLogic();
237 33928 : if (logic != nullptr) {
238 : // find symmetrical response
239 : const int logicSize = logic->getLogicSize();
240 : bool foundProblem = false;
241 : std::vector<int> tlIndex;
242 258344 : for (int u = 0; u < logicSize && !foundProblem; u++) {
243 224424 : const MSLogicJunction::LinkBits& response = logic->getResponseFor(u);
244 3306080 : for (int v = 0; v < logicSize && !foundProblem; v++) {
245 3081656 : if (response.test(v)) {
246 601582 : if (logic->getResponseFor(v).test(u)) {
247 : // get tls link index for links u and v
248 133204 : if (tlIndex.size() == 0) {
249 : // init tlindex for all links once
250 4570 : tlIndex.resize(logicSize, -1);
251 96655 : for (int j = 0; j < numLinks; ++j) {
252 184291 : for (int k = 0; k < (int)myLinks[j].size(); ++k) {
253 92206 : MSLink* link = myLinks[j][k];
254 92206 : if (link->getJunction() == junction) {
255 91484 : tlIndex[link->getIndex()] = link->getTLIndex();
256 : }
257 : }
258 : }
259 : }
260 133204 : const int tlu = tlIndex[u];
261 133204 : const int tlv = tlIndex[v];
262 133204 : if (tlu >= 0 && tlv >= 0) {
263 : int phaseIndex = 0;
264 1197779 : for (MSPhaseDefinition* p : phases) {
265 1064584 : if (minor.find(p->getState()[tlu]) != std::string::npos
266 1064584 : && minor.find(p->getState()[tlv]) != std::string::npos) {
267 27 : WRITE_WARNING(TLF("Program '%' at tlLogic '%' is incompatible with logic at junction '%' (mutual conflict between link indices %,% tl indices %,% phase %).\n"
268 : " To avoid deadlock/collisions, either: rebuild the signal plan with a newer version of netconvert/netedit\n"
269 : " or rebuild the network with option '--tls.ignore-internal-junction-jam' or include the program when building.",
270 : getProgramID(), getID(), junction->getID(), u, v, tlu, tlv, phaseIndex));
271 : // only one warning per program
272 : foundProblem = true;
273 9 : break;
274 : }
275 1064575 : phaseIndex++;
276 : }
277 : }
278 : }
279 : }
280 : }
281 : }
282 33920 : }
283 : }
284 : }
285 102127 : myNumLinks = (int)myLinks.size();
286 102127 : }
287 :
288 :
289 226866 : MSTrafficLightLogic::~MSTrafficLightLogic() {
290 : // no need to do something about mySwitchCommand here,
291 : // it is handled by the event control
292 226866 : }
293 :
294 :
295 : // ----------- Handling of controlled links
296 : void
297 798732 : MSTrafficLightLogic::addLink(MSLink* link, MSLane* lane, int pos) {
298 : // !!! should be done within the loader (checking necessary)
299 798732 : myLinks.reserve(pos + 1);
300 1598621 : while ((int)myLinks.size() <= pos) {
301 799889 : myLinks.push_back(LinkVector());
302 : }
303 798732 : myLinks[pos].push_back(link);
304 : //
305 798732 : myLanes.reserve(pos + 1);
306 1598621 : while ((int)myLanes.size() <= pos) {
307 799889 : myLanes.push_back(LaneVector());
308 : }
309 798732 : myLanes[pos].push_back(lane);
310 798732 : link->setTLState((LinkState) getCurrentPhaseDef().getState()[pos], MSNet::getInstance()->getCurrentTimeStep());
311 798732 : }
312 :
313 :
314 : void
315 14323 : MSTrafficLightLogic::adaptLinkInformationFrom(const MSTrafficLightLogic& logic) {
316 14323 : myLinks = logic.myLinks;
317 14323 : myLanes = logic.myLanes;
318 : myIgnoredIndices = logic.myIgnoredIndices;
319 14323 : }
320 :
321 :
322 : std::map<MSLink*, LinkState>
323 98660 : MSTrafficLightLogic::collectLinkStates() const {
324 : std::map<MSLink*, LinkState> ret;
325 890905 : for (LinkVectorVector::const_iterator i1 = myLinks.begin(); i1 != myLinks.end(); ++i1) {
326 : const LinkVector& l = (*i1);
327 1583333 : for (LinkVector::const_iterator i2 = l.begin(); i2 != l.end(); ++i2) {
328 791088 : ret[*i2] = (*i2)->getState();
329 : }
330 : }
331 98660 : return ret;
332 : }
333 :
334 :
335 : bool
336 23650084 : MSTrafficLightLogic::setTrafficLightSignals(SUMOTime t) const {
337 : // get the current traffic light signal combination
338 23650084 : const std::string& state = getCurrentPhaseDef().getState();
339 : // go through the links
340 136202142 : for (int i = 0; i < (int)myLinks.size(); i++) {
341 112552058 : const LinkVector& currGroup = myLinks[i];
342 112552058 : LinkState ls = (LinkState) state[i];
343 225094739 : for (LinkVector::const_iterator j = currGroup.begin(); j != currGroup.end(); j++) {
344 112542681 : (*j)->setTLState(ls, t);
345 : }
346 : }
347 23650084 : return true;
348 : }
349 :
350 :
351 : void
352 0 : MSTrafficLightLogic::resetLinkStates(const std::map<MSLink*, LinkState>& vals) const {
353 0 : for (LinkVectorVector::const_iterator i1 = myLinks.begin(); i1 != myLinks.end(); ++i1) {
354 : const LinkVector& l = (*i1);
355 0 : for (LinkVector::const_iterator i2 = l.begin(); i2 != l.end(); ++i2) {
356 : assert(vals.find(*i2) != vals.end());
357 0 : (*i2)->setTLState(vals.find(*i2)->second, MSNet::getInstance()->getCurrentTimeStep());
358 : }
359 : }
360 0 : }
361 :
362 :
363 : // ----------- Static Information Retrieval
364 : int
365 0 : MSTrafficLightLogic::getLinkIndex(const MSLink* const link) const {
366 : int index = 0;
367 0 : for (LinkVectorVector::const_iterator i1 = myLinks.begin(); i1 != myLinks.end(); ++i1, ++index) {
368 : const LinkVector& l = (*i1);
369 0 : for (LinkVector::const_iterator i2 = l.begin(); i2 != l.end(); ++i2) {
370 0 : if ((*i2) == link) {
371 : return index;
372 : }
373 : }
374 : }
375 : return -1;
376 : }
377 :
378 :
379 :
380 : // ----------- Dynamic Information Retrieval
381 : SUMOTime
382 111496 : MSTrafficLightLogic::getNextSwitchTime() const {
383 111496 : return mySwitchCommand != nullptr ? mySwitchCommand->getNextSwitchTime() : -1;
384 : }
385 :
386 :
387 : SUMOTime
388 2584 : MSTrafficLightLogic::getSpentDuration(SUMOTime simStep) const {
389 2584 : if (simStep == -1) {
390 2260 : simStep = SIMSTEP;
391 : }
392 2584 : return simStep - getCurrentPhaseDef().myLastSwitch;
393 : }
394 :
395 :
396 : // ----------- Changing phases and phase durations
397 : void
398 0 : MSTrafficLightLogic::addOverridingDuration(SUMOTime duration) {
399 0 : myOverridingTimes.push_back(duration);
400 0 : }
401 :
402 :
403 : void
404 0 : MSTrafficLightLogic::setCurrentDurationIncrement(SUMOTime delay) {
405 0 : myCurrentDurationIncrement = delay;
406 0 : }
407 :
408 :
409 17225 : void MSTrafficLightLogic::initMesoTLSPenalties() {
410 : // set mesoscopic time penalties
411 17225 : const Phases& phases = getPhases();
412 17225 : const int numLinks = (int)myLinks.size();
413 : // warning already given if not all states are used
414 : assert(numLinks <= (int)phases.front()->getState().size());
415 : SUMOTime duration = 0;
416 17225 : std::vector<double> firstRedDuration(numLinks, 0);
417 17225 : std::vector<double> redDuration(numLinks, 0);
418 17225 : std::vector<double> totalRedDuration(numLinks, 0);
419 17225 : std::vector<double> penalty(numLinks, 0);
420 107899 : for (int i = 0; i < (int)phases.size(); ++i) {
421 90674 : const std::string& state = phases[i]->getState();
422 90674 : duration += phases[i]->duration;
423 : // warn about transitions from green to red without intermediate yellow
424 1101956 : for (int j = 0; j < numLinks; ++j) {
425 1011282 : double& red = redDuration[j];
426 1011282 : if ((LinkState)state[j] == LINKSTATE_TL_RED
427 1011282 : || (LinkState)state[j] == LINKSTATE_TL_REDYELLOW) {
428 523264 : red += STEPS2TIME(phases[i]->duration);
429 523264 : totalRedDuration[j] += STEPS2TIME(phases[i]->duration);
430 488018 : } else if (red > 0) {
431 62623 : if (firstRedDuration[j] == 0) {
432 : // store for handling wrap-around
433 62583 : firstRedDuration[j] = red;
434 : } else {
435 : // vehicle may arive in any second or the red duration
436 : // compute the sum over [0,red]
437 40 : penalty[j] += 0.5 * (red * red + red);
438 : }
439 62623 : red = 0;
440 : }
441 : }
442 : }
443 : // final phase and wrap-around to first phase
444 197826 : for (int j = 0; j < numLinks; ++j) {
445 180601 : double red = redDuration[j] + firstRedDuration[j];
446 180601 : if (red) {
447 130909 : penalty[j] += 0.5 * (red * red + red);
448 : }
449 : }
450 17225 : double tlsPenalty = MSGlobals::gTLSPenalty;
451 17225 : const double durationSeconds = STEPS2TIME(duration);
452 : std::set<const MSJunction*> controlledJunctions;
453 197826 : for (int j = 0; j < numLinks; ++j) {
454 361158 : for (int k = 0; k < (int)myLinks[j].size(); ++k) {
455 180557 : MSLink* link = myLinks[j][k];
456 : MSEdge& edge = link->getLaneBefore()->getEdge();
457 180557 : if (MSGlobals::gUseMesoSim) {
458 180397 : const MESegment::MesoEdgeType& edgeType = MSNet::getInstance()->getMesoType(edge.getEdgeType());
459 180397 : tlsPenalty = edgeType.tlsPenalty;
460 180397 : double greenFraction = (durationSeconds - totalRedDuration[j]) / durationSeconds;
461 180397 : if (edgeType.tlsFlowPenalty == 0) {
462 : greenFraction = 1;
463 : } else {
464 120 : greenFraction = MAX2(MIN2(greenFraction / edgeType.tlsFlowPenalty, 1.0), 0.01);
465 : }
466 : if (greenFraction == 0.01) {
467 48 : WRITE_WARNINGF(TL("Green fraction is only 1% for link % in tlLogic '%', program '%'."), "%", j, getID(), getProgramID());
468 : }
469 : link->setGreenFraction(greenFraction);
470 : }
471 180557 : link->setMesoTLSPenalty(TIME2STEPS(tlsPenalty * penalty[j] / durationSeconds));
472 180557 : controlledJunctions.insert(link->getLane()->getEdge().getFromJunction()); // MSLink::myJunction is not yet initialized
473 : //std::cout << " tls=" << getID() << " i=" << j << " link=" << link->getDescription() << " p=" << penalty[j] << " fr=" << firstRedDuration[j] << " r=" << redDuration[j] << " tr=" << totalRedDuration[j] << " durSecs=" << durationSeconds << " tlsPen=" << STEPS2TIME(link->getMesoTLSPenalty()) << " gF=" << myLinks[j][k]->getGreenFraction() << "\n";
474 : }
475 : }
476 : // initialize empty-net travel times
477 : // XXX refactor after merging sharps (links know their incoming edge)
478 34474 : for (std::set<const MSJunction*>::iterator it = controlledJunctions.begin(); it != controlledJunctions.end(); ++it) {
479 17249 : const ConstMSEdgeVector incoming = (*it)->getIncoming();
480 97343 : for (ConstMSEdgeVector::const_iterator it_e = incoming.begin(); it_e != incoming.end(); ++it_e) {
481 80094 : const_cast<MSEdge*>(*it_e)->recalcCache();
482 : }
483 17249 : }
484 :
485 17225 : }
486 :
487 :
488 : void
489 810 : MSTrafficLightLogic::ignoreLinkIndex(int pos) {
490 : myIgnoredIndices.insert(pos);
491 810 : }
492 :
493 : SUMOTime
494 160886 : MSTrafficLightLogic::getTimeInCycle() const {
495 160886 : return mapTimeInCycle(SIMSTEP);
496 : }
497 :
498 :
499 : SUMOTime
500 0 : MSTrafficLightLogic::mapTimeInCycle(SUMOTime t) const {
501 0 : return (t - myOffset) % myDefaultCycleTime;
502 : }
503 :
504 :
505 : bool
506 0 : MSTrafficLightLogic::isSelected() const {
507 0 : return MSNet::getInstance()->isSelected(this);
508 : }
509 :
510 :
511 : void
512 113940 : MSTrafficLightLogic::activateProgram() {
513 113940 : myAmActive = true;
514 : // updated the traffic light logic stored in the link
515 309017 : for (const LinkVector& currGroup : myLinks) {
516 390222 : for (MSLink* link : currGroup) {
517 195145 : link->setTLLogic(this);
518 : }
519 : }
520 113940 : }
521 :
522 :
523 : void
524 14643 : MSTrafficLightLogic::deactivateProgram() {
525 14643 : myAmActive = false;
526 14643 : }
527 :
528 : bool
529 24610 : MSTrafficLightLogic::getsMajorGreen(int linkIndex) const {
530 24610 : if (linkIndex >= 0 && linkIndex < getNumLinks()) {
531 35859 : for (const MSPhaseDefinition* p : getPhases()) {
532 : const std::string& s = p->getState();
533 : assert(linkIndex < (int)s.size());
534 34336 : if (s[linkIndex] == LINKSTATE_TL_GREEN_MAJOR) {
535 : return true;
536 : }
537 : }
538 : }
539 : return false;
540 :
541 : }
542 :
543 :
544 : SUMOTime
545 1828 : MSTrafficLightLogic::getMinDur(int step) const {
546 1828 : const MSPhaseDefinition& p = step < 0 ? getCurrentPhaseDef() : getPhase(step);
547 1828 : return p.minDuration;
548 : }
549 :
550 : SUMOTime
551 2447 : MSTrafficLightLogic::getMaxDur(int step) const {
552 2447 : const MSPhaseDefinition& p = step < 0 ? getCurrentPhaseDef() : getPhase(step);
553 2447 : return p.maxDuration;
554 : }
555 :
556 : SUMOTime
557 221794 : MSTrafficLightLogic::getEarliestEnd(int step) const {
558 221794 : const MSPhaseDefinition& p = step < 0 ? getCurrentPhaseDef() : getPhase(step);
559 221794 : return p.earliestEnd;
560 : }
561 :
562 : SUMOTime
563 304574 : MSTrafficLightLogic::getLatestEnd(int step) const {
564 304574 : const MSPhaseDefinition& p = step < 0 ? getCurrentPhaseDef() : getPhase(step);
565 304574 : return p.latestEnd;
566 : }
567 :
568 :
569 : void
570 1426 : MSTrafficLightLogic::loadState(MSTLLogicControl& tlcontrol, SUMOTime t, int step, SUMOTime spentDuration) {
571 1426 : const SUMOTime remaining = getPhase(step).duration - spentDuration;
572 1426 : changeStepAndDuration(tlcontrol, t, step, remaining);
573 1426 : setTrafficLightSignals(t - spentDuration);
574 1426 : }
575 :
576 :
577 : SUMOTime
578 110096 : MSTrafficLightLogic::computeCycleTime(const Phases& phases) {
579 : SUMOTime result = 0;
580 624820 : for (const MSPhaseDefinition* p : phases) {
581 514724 : result += p->duration;
582 : }
583 110096 : return result;
584 : }
585 :
586 :
587 :
588 : /****************************************************************************/
|