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 4418 : NBTrafficLightLogic::NBTrafficLightLogic(const std::string& id,
50 : const std::string& subid, int noLinks,
51 4418 : SUMOTime offset, TrafficLightType type) :
52 4418 : Named(id), myNumLinks(noLinks), mySubID(subid),
53 4418 : myOffset(offset),
54 8836 : myType(type) {}
55 :
56 :
57 974 : NBTrafficLightLogic::NBTrafficLightLogic(const NBTrafficLightLogic* logic) :
58 : Named(logic->getID()),
59 974 : myNumLinks(logic->myNumLinks),
60 974 : mySubID(logic->getProgramID()),
61 974 : myOffset(logic->getOffset()),
62 974 : myPhases(logic->myPhases.begin(), logic->myPhases.end()),
63 974 : myType(logic->getType())
64 : {
65 974 : updateParameters(logic->getParametersMap());
66 974 : }
67 :
68 :
69 16202 : NBTrafficLightLogic::~NBTrafficLightLogic() {}
70 :
71 :
72 : void
73 8559 : NBTrafficLightLogic::addStep(const SUMOTime duration, const std::string& state, const std::vector<int>& next, const std::string& name, const int index) {
74 8559 : addStep(duration, state,
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 : NBTrafficLightDefinition::UNSPECIFIED_DURATION,
82 : name, next, index);
83 8559 : }
84 :
85 :
86 : void
87 22020 : NBTrafficLightLogic::addStep(const SUMOTime duration, const std::string& state, const SUMOTime minDur, const SUMOTime maxDur, const SUMOTime earliestEnd,
88 : const SUMOTime latestEnd, const SUMOTime vehExt, const SUMOTime yellow, const SUMOTime red,
89 : const std::string& name,
90 : const std::vector<int>& next,
91 : int index) {
92 : // check state size
93 22020 : if (myNumLinks == 0) {
94 : // initialize
95 911 : myNumLinks = (int)state.size();
96 21109 : } else if ((int)state.size() != myNumLinks) {
97 0 : throw ProcessError("When adding phase to tlLogic '" + getID() + "': state length of " + toString(state.size()) +
98 0 : " does not match declared number of links " + toString(myNumLinks));
99 : }
100 : // check state contents
101 : const std::string::size_type illegal = state.find_first_not_of(SUMOXMLDefinitions::ALLOWED_TLS_LINKSTATES);
102 22020 : if (std::string::npos != illegal) {
103 3 : throw ProcessError(TLF("When adding phase: illegal character '%' in state", toString(state[illegal])));
104 : }
105 : // interpret index
106 22019 : if (index < 0 || index >= (int)myPhases.size()) {
107 : // insert at the end
108 22019 : index = (int)myPhases.size();
109 : }
110 44038 : myPhases.insert(myPhases.begin() + index, PhaseDefinition(duration, state, minDur, maxDur, earliestEnd, latestEnd, vehExt, yellow, red, next, name));
111 22019 : }
112 :
113 :
114 : void
115 0 : NBTrafficLightLogic::deletePhase(int index) {
116 0 : if (index >= (int)myPhases.size()) {
117 0 : throw InvalidArgument("Index " + toString(index) + " out of range for logic with "
118 0 : + toString(myPhases.size()) + " phases.");
119 : }
120 0 : myPhases.erase(myPhases.begin() + index);
121 0 : }
122 :
123 :
124 : void
125 0 : NBTrafficLightLogic::swapPhase(int indexPhaseA, int indexPhaseB) {
126 0 : if (indexPhaseA >= (int)myPhases.size()) {
127 0 : throw InvalidArgument("Index " + toString(indexPhaseA) + " out of range for logic with "
128 0 : + toString(myPhases.size()) + " phases.");
129 : }
130 0 : if (indexPhaseB >= (int)myPhases.size()) {
131 0 : throw InvalidArgument("Index " + toString(indexPhaseB) + " out of range for logic with "
132 0 : + toString(myPhases.size()) + " phases.");
133 : }
134 : // declare auxiliar PhaseDefinition and swap
135 0 : const auto auxPhase = myPhases.at(indexPhaseA);
136 0 : myPhases.at(indexPhaseA) = myPhases.at(indexPhaseB);
137 0 : myPhases.at(indexPhaseB) = auxPhase;
138 0 : }
139 :
140 :
141 : void
142 0 : NBTrafficLightLogic::swapfirstPhase() {
143 0 : const auto firstPhase = myPhases.front();
144 0 : myPhases.erase(myPhases.begin());
145 0 : myPhases.push_back(firstPhase);
146 0 : }
147 :
148 :
149 : void
150 0 : NBTrafficLightLogic::swaplastPhase() {
151 0 : const auto lastPhase = myPhases.back();
152 0 : myPhases.pop_back();
153 0 : myPhases.insert(myPhases.begin(), lastPhase);
154 0 : }
155 :
156 : void
157 11 : NBTrafficLightLogic::setStateLength(int numLinks, LinkState fill) {
158 11 : if (myNumLinks > numLinks) {
159 0 : for (PhaseDefinition& p : myPhases) {
160 0 : p.state = p.state.substr(0, numLinks);
161 : }
162 : } else {
163 11 : std::string add(numLinks - myNumLinks, (char)fill);
164 107 : for (PhaseDefinition& p : myPhases) {
165 192 : p.state = p.state + add;
166 : }
167 : }
168 11 : myNumLinks = numLinks;
169 11 : }
170 :
171 :
172 : void
173 29 : NBTrafficLightLogic::deleteStateIndex(int index) {
174 : assert(index >= 0);
175 : assert(index < myNumLinks);
176 227 : for (PhaseDefinition& p : myPhases) {
177 198 : p.state.erase(index, 1);
178 : }
179 29 : myNumLinks--;
180 29 : }
181 :
182 :
183 : void
184 41 : NBTrafficLightLogic::resetPhases() {
185 41 : myNumLinks = 0;
186 : myPhases.clear();
187 41 : }
188 :
189 :
190 : SUMOTime
191 10523 : NBTrafficLightLogic::getDuration() const {
192 : SUMOTime duration = 0;
193 61911 : for (PhaseDefinitionVector::const_iterator i = myPhases.begin(); i != myPhases.end(); ++i) {
194 51388 : duration += (*i).duration;
195 : }
196 10523 : return duration;
197 : }
198 :
199 :
200 : void
201 5440 : NBTrafficLightLogic::closeBuilding(bool checkVarDurations) {
202 27725 : for (int i = 0; i < (int)myPhases.size() - 1;) {
203 22285 : 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) {
204 : ++i;
205 21301 : continue;
206 : }
207 984 : myPhases[i].duration += myPhases[i + 1].duration;
208 984 : if (myPhases[i + 1].minDur != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
209 188 : if (myPhases[i].minDur != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
210 164 : myPhases[i].minDur += myPhases[i + 1].minDur;
211 : } else {
212 24 : myPhases[i].minDur = myPhases[i + 1].minDur;
213 : }
214 : }
215 984 : if (myPhases[i + 1].maxDur != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
216 14 : if (myPhases[i].maxDur != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
217 14 : myPhases[i].maxDur += myPhases[i + 1].maxDur;
218 : } else {
219 0 : myPhases[i].maxDur = myPhases[i + 1].maxDur;
220 : }
221 : }
222 984 : myPhases.erase(myPhases.begin() + i + 1);
223 : }
224 : // check if actuated lights are defined correctly
225 5440 : if (checkVarDurations) {
226 4466 : if (myType != TrafficLightType::STATIC) {
227 : bool found = false;
228 954 : for (auto p : myPhases) {
229 951 : if (p.minDur != NBTrafficLightDefinition::UNSPECIFIED_DURATION
230 18 : || p.maxDur != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
231 : found = true;
232 : break;
233 : }
234 951 : }
235 : if (!found) {
236 10 : WRITE_WARNINGF(TL("Non-static traffic light '%' does not define variable phase length."), getID());
237 : }
238 : }
239 : }
240 5440 : }
241 :
242 :
243 : void
244 2839 : NBTrafficLightLogic::setPhaseState(int phaseIndex, int tlIndex, LinkState linkState) {
245 : assert(phaseIndex < (int)myPhases.size());
246 2839 : std::string& phaseState = myPhases[phaseIndex].state;
247 : assert(tlIndex < (int)phaseState.size());
248 2839 : phaseState[tlIndex] = (char)linkState;
249 2839 : }
250 :
251 :
252 : void
253 10083 : NBTrafficLightLogic::setPhaseDuration(int phaseIndex, SUMOTime duration) {
254 : assert(phaseIndex < (int)myPhases.size());
255 10083 : myPhases[phaseIndex].duration = duration;
256 10083 : }
257 :
258 :
259 : void
260 4 : NBTrafficLightLogic::setPhaseMinDuration(int phaseIndex, SUMOTime duration) {
261 : assert(phaseIndex < (int)myPhases.size());
262 4 : myPhases[phaseIndex].minDur = duration;
263 4 : }
264 :
265 :
266 : void
267 10 : NBTrafficLightLogic::setPhaseMaxDuration(int phaseIndex, SUMOTime duration) {
268 : assert(phaseIndex < (int)myPhases.size());
269 10 : myPhases[phaseIndex].maxDur = duration;
270 10 : }
271 :
272 :
273 : void
274 0 : NBTrafficLightLogic::setPhaseEarliestEnd(int phaseIndex, SUMOTime duration) {
275 : assert(phaseIndex < (int)myPhases.size());
276 0 : myPhases[phaseIndex].earliestEnd = duration;
277 0 : }
278 :
279 :
280 : void
281 0 : NBTrafficLightLogic::setPhaseLatestEnd(int phaseIndex, SUMOTime duration) {
282 : assert(phaseIndex < (int)myPhases.size());
283 0 : myPhases[phaseIndex].latestEnd = duration;
284 0 : }
285 :
286 :
287 : void
288 0 : NBTrafficLightLogic::setPhaseVehExt(int phaseIndex, SUMOTime duration) {
289 : assert(phaseIndex < (int)myPhases.size());
290 0 : myPhases[phaseIndex].vehExt = duration;
291 0 : }
292 :
293 :
294 : void
295 0 : NBTrafficLightLogic::setPhaseYellow(int phaseIndex, SUMOTime duration) {
296 : assert(phaseIndex < (int)myPhases.size());
297 0 : myPhases[phaseIndex].yellow = duration;
298 0 : }
299 :
300 :
301 : void
302 0 : NBTrafficLightLogic::setPhaseRed(int phaseIndex, SUMOTime duration) {
303 : assert(phaseIndex < (int)myPhases.size());
304 0 : myPhases[phaseIndex].red = duration;
305 0 : }
306 :
307 :
308 : void
309 0 : NBTrafficLightLogic::setPhaseNext(int phaseIndex, const std::vector<int>& next) {
310 : assert(phaseIndex < (int)myPhases.size());
311 0 : myPhases[phaseIndex].next = next;
312 0 : }
313 :
314 :
315 : void
316 0 : NBTrafficLightLogic::setPhaseName(int phaseIndex, const std::string& name) {
317 : assert(phaseIndex < (int)myPhases.size());
318 0 : myPhases[phaseIndex].name = name;
319 0 : }
320 :
321 :
322 : void
323 0 : NBTrafficLightLogic::overrideState(int phaseIndex, const char c) {
324 : assert(phaseIndex < (int)myPhases.size());
325 0 : for (int i = 0; i < (int)myPhases[phaseIndex].state.size(); i++) {
326 0 : myPhases[phaseIndex].state[i] = c;
327 : }
328 0 : }
329 :
330 : /****************************************************************************/
|