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 NBTrafficLightLogic.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Sept 2002
19 : ///
20 : // A SUMO-compliant built logic for a traffic light
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <vector>
25 : #include <bitset>
26 : #include <utility>
27 : #include <string>
28 : #include <sstream>
29 : #include <cassert>
30 : #include "NBEdge.h"
31 : #include "NBEdgeCont.h"
32 : #include "NBTrafficLightLogic.h"
33 : #include "NBTrafficLightDefinition.h"
34 : #include <utils/options/OptionsCont.h>
35 : #include <utils/options/Option.h>
36 : #include <utils/common/ToString.h>
37 : #include <utils/common/MsgHandler.h>
38 : #include <utils/common/StringTokenizer.h>
39 : #include <utils/iodevices/OutputDevice.h>
40 :
41 :
42 : // ===========================================================================
43 : // static members
44 : // ===========================================================================
45 :
46 : // ===========================================================================
47 : // member method definitions
48 : // ===========================================================================
49 3421 : NBTrafficLightLogic::NBTrafficLightLogic(const std::string& id,
50 : const std::string& subid, int noLinks,
51 3421 : SUMOTime offset, TrafficLightType type) :
52 3421 : Named(id), myNumLinks(noLinks), mySubID(subid),
53 3421 : myOffset(offset),
54 6842 : myType(type) {}
55 :
56 :
57 622 : NBTrafficLightLogic::NBTrafficLightLogic(const NBTrafficLightLogic* logic) :
58 : Named(logic->getID()),
59 622 : myNumLinks(logic->myNumLinks),
60 622 : mySubID(logic->getProgramID()),
61 622 : myOffset(logic->getOffset()),
62 622 : myPhases(logic->myPhases.begin(), logic->myPhases.end()),
63 622 : myType(logic->getType()) {
64 622 : updateParameters(logic->getParametersMap());
65 622 : }
66 :
67 :
68 8100 : NBTrafficLightLogic::~NBTrafficLightLogic() {}
69 :
70 :
71 : void
72 6895 : NBTrafficLightLogic::addStep(const SUMOTime duration, const std::string& state, const std::vector<int>& next, const std::string& name, const int index) {
73 6895 : addStep(duration, state,
74 : NBTrafficLightDefinition::UNSPECIFIED_DURATION,
75 : NBTrafficLightDefinition::UNSPECIFIED_DURATION,
76 : NBTrafficLightDefinition::UNSPECIFIED_DURATION,
77 : NBTrafficLightDefinition::UNSPECIFIED_DURATION,
78 : NBTrafficLightDefinition::UNSPECIFIED_DURATION,
79 : NBTrafficLightDefinition::UNSPECIFIED_DURATION,
80 : NBTrafficLightDefinition::UNSPECIFIED_DURATION,
81 : name, next, index);
82 6895 : }
83 :
84 :
85 : void
86 17115 : NBTrafficLightLogic::addStep(const SUMOTime duration, const std::string& state, const SUMOTime minDur, const SUMOTime maxDur, const SUMOTime earliestEnd,
87 : const SUMOTime latestEnd, const SUMOTime vehExt, const SUMOTime yellow, const SUMOTime red,
88 : const std::string& name,
89 : const std::vector<int>& next,
90 : int index) {
91 : // check state size
92 17115 : if (myNumLinks == 0) {
93 : // initialize
94 580 : myNumLinks = (int)state.size();
95 16535 : } else if ((int)state.size() != myNumLinks) {
96 0 : throw ProcessError("When adding phase to tlLogic '" + getID() + "': state length of " + toString(state.size()) +
97 0 : " does not match declared number of links " + toString(myNumLinks));
98 : }
99 : // check state contents
100 : const std::string::size_type illegal = state.find_first_not_of(SUMOXMLDefinitions::ALLOWED_TLS_LINKSTATES);
101 17115 : if (std::string::npos != illegal) {
102 2 : throw ProcessError(TLF("When adding phase: illegal character '%' in state", toString(state[illegal])));
103 : }
104 : // interpret index
105 17114 : if (index < 0 || index >= (int)myPhases.size()) {
106 : // insert at the end
107 17114 : index = (int)myPhases.size();
108 : }
109 34228 : myPhases.insert(myPhases.begin() + index, PhaseDefinition(duration, state, minDur, maxDur, earliestEnd, latestEnd, vehExt, yellow, red, next, name));
110 17114 : }
111 :
112 :
113 : void
114 0 : NBTrafficLightLogic::deletePhase(int index) {
115 0 : if (index >= (int)myPhases.size()) {
116 0 : throw InvalidArgument("Index " + toString(index) + " out of range for logic with "
117 0 : + toString(myPhases.size()) + " phases.");
118 : }
119 0 : myPhases.erase(myPhases.begin() + index);
120 0 : }
121 :
122 :
123 : void
124 0 : NBTrafficLightLogic::swapPhase(int indexPhaseA, int indexPhaseB) {
125 0 : if (indexPhaseA >= (int)myPhases.size()) {
126 0 : throw InvalidArgument("Index " + toString(indexPhaseA) + " out of range for logic with "
127 0 : + toString(myPhases.size()) + " phases.");
128 : }
129 0 : if (indexPhaseB >= (int)myPhases.size()) {
130 0 : throw InvalidArgument("Index " + toString(indexPhaseB) + " out of range for logic with "
131 0 : + toString(myPhases.size()) + " phases.");
132 : }
133 : // declare auxiliar PhaseDefinition and swap
134 0 : const auto auxPhase = myPhases.at(indexPhaseA);
135 0 : myPhases.at(indexPhaseA) = myPhases.at(indexPhaseB);
136 0 : myPhases.at(indexPhaseB) = auxPhase;
137 0 : }
138 :
139 :
140 : void
141 0 : NBTrafficLightLogic::swapfirstPhase() {
142 0 : const auto firstPhase = myPhases.front();
143 0 : myPhases.erase(myPhases.begin());
144 0 : myPhases.push_back(firstPhase);
145 0 : }
146 :
147 :
148 : void
149 0 : NBTrafficLightLogic::swaplastPhase() {
150 0 : const auto lastPhase = myPhases.back();
151 : myPhases.pop_back();
152 0 : myPhases.insert(myPhases.begin(), lastPhase);
153 0 : }
154 :
155 : void
156 11 : NBTrafficLightLogic::setStateLength(int numLinks, LinkState fill) {
157 11 : if (myNumLinks > numLinks) {
158 0 : for (PhaseDefinition& p : myPhases) {
159 0 : p.state = p.state.substr(0, numLinks);
160 : }
161 : } else {
162 11 : std::string add(numLinks - myNumLinks, (char)fill);
163 107 : for (PhaseDefinition& p : myPhases) {
164 192 : p.state = p.state + add;
165 : }
166 : }
167 11 : myNumLinks = numLinks;
168 11 : }
169 :
170 :
171 : void
172 29 : NBTrafficLightLogic::deleteStateIndex(int index) {
173 : assert(index >= 0);
174 : assert(index < myNumLinks);
175 227 : for (PhaseDefinition& p : myPhases) {
176 198 : p.state.erase(index, 1);
177 : }
178 29 : myNumLinks--;
179 29 : }
180 :
181 :
182 : void
183 42 : NBTrafficLightLogic::resetPhases() {
184 42 : myNumLinks = 0;
185 : myPhases.clear();
186 42 : }
187 :
188 :
189 : SUMOTime
190 8344 : NBTrafficLightLogic::getDuration() const {
191 : SUMOTime duration = 0;
192 48542 : for (PhaseDefinitionVector::const_iterator i = myPhases.begin(); i != myPhases.end(); ++i) {
193 40198 : duration += (*i).duration;
194 : }
195 8344 : return duration;
196 : }
197 :
198 :
199 : void
200 4070 : NBTrafficLightLogic::closeBuilding(bool checkVarDurations) {
201 20951 : for (int i = 0; i < (int)myPhases.size() - 1;) {
202 16881 : if (myPhases[i].state != myPhases[i + 1].state || myPhases[i].next.size() > 0 || myPhases[i + 1].next.size() > 0 || myPhases[i].name != myPhases[i + 1].name) {
203 : ++i;
204 15934 : continue;
205 : }
206 947 : myPhases[i].duration += myPhases[i + 1].duration;
207 947 : if (myPhases[i + 1].minDur != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
208 168 : if (myPhases[i].minDur != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
209 156 : myPhases[i].minDur += myPhases[i + 1].minDur;
210 : } else {
211 12 : myPhases[i].minDur = myPhases[i + 1].minDur;
212 : }
213 : }
214 947 : if (myPhases[i + 1].maxDur != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
215 12 : if (myPhases[i].maxDur != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
216 12 : myPhases[i].maxDur += myPhases[i + 1].maxDur;
217 : } else {
218 0 : myPhases[i].maxDur = myPhases[i + 1].maxDur;
219 : }
220 : }
221 947 : myPhases.erase(myPhases.begin() + i + 1);
222 : }
223 : // check if actuated lights are defined correctly
224 4070 : if (checkVarDurations) {
225 3448 : if (myType != TrafficLightType::STATIC) {
226 : bool found = false;
227 566 : for (auto p : myPhases) {
228 563 : if (p.minDur != NBTrafficLightDefinition::UNSPECIFIED_DURATION
229 18 : || p.maxDur != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
230 : found = true;
231 : break;
232 : }
233 563 : }
234 : if (!found) {
235 9 : WRITE_WARNINGF(TL("Non-static traffic light '%' does not define variable phase length."), getID());
236 : }
237 : }
238 : }
239 4070 : }
240 :
241 :
242 : void
243 2650 : NBTrafficLightLogic::setPhaseState(int phaseIndex, int tlIndex, LinkState linkState) {
244 : assert(phaseIndex < (int)myPhases.size());
245 2650 : std::string& phaseState = myPhases[phaseIndex].state;
246 : assert(tlIndex < (int)phaseState.size());
247 2650 : phaseState[tlIndex] = (char)linkState;
248 2650 : }
249 :
250 :
251 : void
252 7974 : NBTrafficLightLogic::setPhaseDuration(int phaseIndex, SUMOTime duration) {
253 : assert(phaseIndex < (int)myPhases.size());
254 7974 : myPhases[phaseIndex].duration = duration;
255 7974 : }
256 :
257 :
258 : void
259 4 : NBTrafficLightLogic::setPhaseMinDuration(int phaseIndex, SUMOTime duration) {
260 : assert(phaseIndex < (int)myPhases.size());
261 4 : myPhases[phaseIndex].minDur = duration;
262 4 : }
263 :
264 :
265 : void
266 10 : NBTrafficLightLogic::setPhaseMaxDuration(int phaseIndex, SUMOTime duration) {
267 : assert(phaseIndex < (int)myPhases.size());
268 10 : myPhases[phaseIndex].maxDur = duration;
269 10 : }
270 :
271 :
272 : void
273 0 : NBTrafficLightLogic::setPhaseEarliestEnd(int phaseIndex, SUMOTime duration) {
274 : assert(phaseIndex < (int)myPhases.size());
275 0 : myPhases[phaseIndex].earliestEnd = duration;
276 0 : }
277 :
278 :
279 : void
280 0 : NBTrafficLightLogic::setPhaseLatestEnd(int phaseIndex, SUMOTime duration) {
281 : assert(phaseIndex < (int)myPhases.size());
282 0 : myPhases[phaseIndex].latestEnd = duration;
283 0 : }
284 :
285 :
286 : void
287 0 : NBTrafficLightLogic::setPhaseVehExt(int phaseIndex, SUMOTime duration) {
288 : assert(phaseIndex < (int)myPhases.size());
289 0 : myPhases[phaseIndex].vehExt = duration;
290 0 : }
291 :
292 :
293 : void
294 0 : NBTrafficLightLogic::setPhaseYellow(int phaseIndex, SUMOTime duration) {
295 : assert(phaseIndex < (int)myPhases.size());
296 0 : myPhases[phaseIndex].yellow = duration;
297 0 : }
298 :
299 :
300 : void
301 0 : NBTrafficLightLogic::setPhaseRed(int phaseIndex, SUMOTime duration) {
302 : assert(phaseIndex < (int)myPhases.size());
303 0 : myPhases[phaseIndex].red = duration;
304 0 : }
305 :
306 :
307 : void
308 19 : NBTrafficLightLogic::setPhaseNext(int phaseIndex, const std::vector<int>& next) {
309 : assert(phaseIndex < (int)myPhases.size());
310 19 : myPhases[phaseIndex].next = next;
311 19 : }
312 :
313 :
314 : void
315 0 : NBTrafficLightLogic::setPhaseName(int phaseIndex, const std::string& name) {
316 : assert(phaseIndex < (int)myPhases.size());
317 0 : myPhases[phaseIndex].name = name;
318 0 : }
319 :
320 :
321 : void
322 0 : NBTrafficLightLogic::overrideState(int phaseIndex, const char c) {
323 : assert(phaseIndex < (int)myPhases.size());
324 0 : for (int i = 0; i < (int)myPhases[phaseIndex].state.size(); i++) {
325 0 : myPhases[phaseIndex].state[i] = c;
326 : }
327 0 : }
328 :
329 : /****************************************************************************/
|