Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2025 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 NLJunctionControlBuilder.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Sascha Krieg
18 : /// @author Michael Behrisch
19 : /// @date Mon, 9 Jul 2001
20 : ///
21 : // Builder of microsim-junctions and tls
22 : /****************************************************************************/
23 : #include <config.h>
24 :
25 : #include <map>
26 : #include <string>
27 : #include <vector>
28 : #include <list>
29 : #include <algorithm>
30 : #include <utils/xml/SUMOXMLDefinitions.h>
31 : #include <utils/common/UtilExceptions.h>
32 : #include <utils/common/ToString.h>
33 : #include <microsim/MSGlobals.h>
34 : #include <microsim/MSNet.h>
35 : #include <microsim/MSJunctionLogic.h>
36 : #include <microsim/MSNoLogicJunction.h>
37 : #include <microsim/MSRightOfWayJunction.h>
38 : #include <microsim/MSInternalJunction.h>
39 : #include <microsim/MSJunctionControl.h>
40 : #include <microsim/MSEventControl.h>
41 : #include <microsim/traffic_lights/MSTrafficLightLogic.h>
42 : #include <microsim/traffic_lights/MSSimpleTrafficLightLogic.h>
43 : #include <microsim/traffic_lights/MSRailSignal.h>
44 : #include <microsim/traffic_lights/MSRailCrossing.h>
45 : #include <microsim/traffic_lights/MSSOTLPolicyBasedTrafficLightLogic.h>
46 : #include <microsim/traffic_lights/MSSOTLPlatoonPolicy.h>
47 : #include <microsim/traffic_lights/MSSOTLRequestPolicy.h>
48 : #include <microsim/traffic_lights/MSSOTLPhasePolicy.h>
49 : #include <microsim/traffic_lights/MSSOTLMarchingPolicy.h>
50 : #include <microsim/traffic_lights/MSSwarmTrafficLightLogic.h>
51 : #include <microsim/traffic_lights/MSDeterministicHiLevelTrafficLightLogic.h>
52 : #include <microsim/traffic_lights/MSSOTLWaveTrafficLightLogic.h>
53 : #include <microsim/traffic_lights/MSDelayBasedTrafficLightLogic.h>
54 : #include <microsim/traffic_lights/MSOffTrafficLightLogic.h>
55 : #include <microsim/traffic_lights/MSTLLogicControl.h>
56 : #include "NLBuilder.h"
57 : #include "NLJunctionControlBuilder.h"
58 : #include "microsim/traffic_lights/NEMAController.h"
59 :
60 :
61 : // ===========================================================================
62 : // static members
63 : // ===========================================================================
64 : const int NLJunctionControlBuilder::NO_REQUEST_SIZE = -1;
65 :
66 : // ===========================================================================
67 : // method definitions
68 : // ===========================================================================
69 44136 : NLJunctionControlBuilder::NLJunctionControlBuilder(MSNet& net, NLDetectorBuilder& db) :
70 44136 : myNet(net),
71 44136 : myDetectorBuilder(db),
72 44136 : myOffset(0),
73 44136 : myJunctions(new MSJunctionControl()),
74 176544 : myNetIsLoaded(false) {
75 44136 : myLogicControl = new MSTLLogicControl();
76 44136 : }
77 :
78 :
79 44136 : NLJunctionControlBuilder::~NLJunctionControlBuilder() {
80 44136 : delete myLogicControl;
81 44136 : delete myJunctions;
82 132408 : }
83 :
84 :
85 : void
86 581579 : NLJunctionControlBuilder::openJunction(const std::string& id,
87 : const std::string& key,
88 : const SumoXMLNodeType type,
89 : const Position pos,
90 : const PositionVector& shape,
91 : const std::vector<MSLane*>& incomingLanes,
92 : const std::vector<MSLane*>& internalLanes,
93 : const std::string& name) {
94 581579 : myActiveInternalLanes = internalLanes;
95 581579 : myActiveIncomingLanes = incomingLanes;
96 581579 : myActiveID = id;
97 581579 : myActiveKey = key;
98 581579 : myType = type;
99 : myPosition.set(pos);
100 : myShape = shape;
101 581579 : myActiveName = name;
102 : myAdditionalParameter.clear();
103 581579 : }
104 :
105 :
106 : void
107 581579 : NLJunctionControlBuilder::closeJunction(const std::string& basePath) {
108 581579 : if (myCurrentHasError) {
109 : // had an error before...
110 : return;
111 : }
112 581579 : if (myRequestSize != NO_REQUEST_SIZE && myRequestItemNumber != myRequestSize) {
113 0 : throw InvalidArgument("The description for the junction logic '" + myActiveKey + "' is malicious.");
114 : }
115 581579 : if (myJunctions == nullptr) {
116 0 : throw ProcessError(TL("Information about the number of nodes was missing."));
117 : }
118 : MSJunction* junction = nullptr;
119 581579 : switch (myType) {
120 61680 : case SumoXMLNodeType::NOJUNCTION:
121 : case SumoXMLNodeType::DEAD_END:
122 : case SumoXMLNodeType::DEAD_END_DEPRECATED:
123 : case SumoXMLNodeType::DISTRICT:
124 : case SumoXMLNodeType::TRAFFIC_LIGHT_NOJUNCTION:
125 61680 : if (!myActiveLogic.empty()) {
126 120 : WRITE_WARNINGF(TL("Ignoring junction logic for junction '%'."), myActiveID)
127 : }
128 61680 : junction = buildNoLogicJunction();
129 61680 : break;
130 321768 : case SumoXMLNodeType::TRAFFIC_LIGHT:
131 : case SumoXMLNodeType::TRAFFIC_LIGHT_RIGHT_ON_RED:
132 : case SumoXMLNodeType::RIGHT_BEFORE_LEFT:
133 : case SumoXMLNodeType::LEFT_BEFORE_RIGHT:
134 : case SumoXMLNodeType::PRIORITY:
135 : case SumoXMLNodeType::PRIORITY_STOP:
136 : case SumoXMLNodeType::ALLWAY_STOP:
137 : case SumoXMLNodeType::ZIPPER:
138 321768 : junction = buildLogicJunction(new MSBitsetLogic(myRequestSize, myActiveLogic, myActiveFoes, myActiveConts));
139 : break;
140 193715 : case SumoXMLNodeType::INTERNAL:
141 193715 : if (MSGlobals::gUsingInternalLanes) {
142 158901 : if (!myActiveLogic.empty()) {
143 18 : WRITE_WARNINGF(TL("Ignoring junction logic for junction '%'."), myActiveID)
144 : }
145 158901 : junction = buildInternalJunction();
146 : }
147 : break;
148 4416 : case SumoXMLNodeType::RAIL_SIGNAL:
149 : case SumoXMLNodeType::RAIL_CROSSING:
150 4416 : myOffset = 0;
151 4416 : myActiveKey = myActiveID;
152 4416 : myActiveProgram = "0";
153 4416 : myLogicType = myType == SumoXMLNodeType::RAIL_SIGNAL ? TrafficLightType::RAIL_SIGNAL : TrafficLightType::RAIL_CROSSING;
154 4416 : closeTrafficLightLogic(basePath);
155 4416 : junction = buildLogicJunction(new MSBitsetLogic(myRequestSize, myActiveLogic, myActiveFoes, myActiveConts));
156 : break;
157 0 : default:
158 0 : throw InvalidArgument("False junction logic type.");
159 : }
160 546765 : if (junction != nullptr) {
161 546765 : if (!myJunctions->add(myActiveID, junction)) {
162 12 : throw InvalidArgument("Another junction with the id '" + myActiveID + "' exists.");
163 : }
164 546759 : junction->updateParameters(myAdditionalParameter);
165 : }
166 : }
167 :
168 :
169 : MSJunctionControl*
170 43718 : NLJunctionControlBuilder::build() const {
171 43718 : MSJunctionControl* js = myJunctions;
172 43718 : myJunctions = nullptr;
173 43718 : return js;
174 : }
175 :
176 :
177 : MSJunction*
178 61680 : NLJunctionControlBuilder::buildNoLogicJunction() {
179 61680 : return new MSNoLogicJunction(myActiveID, myType, myPosition, myShape, myActiveName,
180 61680 : myActiveIncomingLanes, myActiveInternalLanes);
181 : }
182 :
183 :
184 : MSJunction*
185 326184 : NLJunctionControlBuilder::buildLogicJunction(MSJunctionLogic* const logic) {
186 326184 : return new MSRightOfWayJunction(myActiveID, myType, myPosition, myShape, myActiveName,
187 326184 : myActiveIncomingLanes, myActiveInternalLanes, logic);
188 : }
189 :
190 :
191 : MSJunction*
192 158901 : NLJunctionControlBuilder::buildInternalJunction() {
193 : // build the junction
194 317802 : return new MSInternalJunction(myActiveID, myType, myPosition, myShape, myActiveIncomingLanes,
195 158901 : myActiveInternalLanes);
196 : }
197 :
198 :
199 : MSTLLogicControl::TLSLogicVariants&
200 1621207 : NLJunctionControlBuilder::getTLLogic(const std::string& id) const {
201 1621207 : return getTLLogicControlToUse().get(id);
202 : }
203 :
204 :
205 : void
206 115826 : NLJunctionControlBuilder::closeTrafficLightLogic(const std::string& basePath) {
207 115826 : if (myActiveProgram == "off") {
208 37 : if (myAbsDuration > 0) {
209 0 : throw InvalidArgument("The off program for TLS '" + myActiveKey + "' has phases.");
210 : }
211 37 : MSOffTrafficLightLogic* off = new MSOffTrafficLightLogic(getTLLogicControlToUse(), myActiveKey);
212 37 : if (!getTLLogicControlToUse().add(myActiveKey, myActiveProgram, off)) {
213 0 : throw InvalidArgument("Another logic with id '" + myActiveKey + "' and programID '" + myActiveProgram + "' exists.");
214 : }
215 182 : return;
216 : }
217 : SUMOTime firstEventOffset = 0;
218 : int step = 0;
219 : MSSimpleTrafficLightLogic::Phases::const_iterator i = myActivePhases.begin();
220 115789 : MSTrafficLightLogic* existing = getTLLogicControlToUse().get(myActiveKey, myActiveProgram);
221 115789 : if (existing != nullptr && (existing->getLogicType() == TrafficLightType::RAIL_SIGNAL || existing->getLogicType() == TrafficLightType::RAIL_CROSSING)) {
222 35 : existing->updateParameters(myAdditionalParameter);
223 35 : return;
224 : } else {
225 115754 : if (myLogicType != TrafficLightType::RAIL_SIGNAL && myLogicType != TrafficLightType::RAIL_CROSSING) {
226 111338 : if (myAbsDuration == 0) {
227 111 : if (existing == nullptr) {
228 2 : throw InvalidArgument("TLS program '" + myActiveProgram + "' for TLS '" + myActiveKey + "' has a duration of 0.");
229 : } else {
230 : // only modify the offset of an existing logic
231 110 : myAbsDuration = existing->getDefaultCycleTime();
232 110 : i = existing->getPhases().begin();
233 : }
234 111227 : } else if (existing != nullptr) {
235 2 : throw InvalidArgument("Another logic with id '" + myActiveKey + "' and programID '" + myActiveProgram + "' exists.");
236 : }
237 : // compute the initial step and first switch time of the tls-logic
238 : // a positive offset delays all phases by x (advance by absDuration - x) while a negative offset advances all phases by x seconds
239 : // @note The implementation of % for negative values is implementation defined in ISO1998
240 : SUMOTime offset; // the time to run the traffic light in advance
241 111336 : if (myOffset >= 0) {
242 111277 : offset = (myNet.getCurrentTimeStep() + myAbsDuration - (myOffset % myAbsDuration)) % myAbsDuration;
243 : } else {
244 59 : offset = (myNet.getCurrentTimeStep() + ((-myOffset) % myAbsDuration)) % myAbsDuration;
245 : }
246 112682 : while (offset >= (*i)->duration) {
247 1346 : step++;
248 1346 : offset -= (*i)->duration;
249 : ++i;
250 : }
251 111336 : firstEventOffset = (*i)->duration - offset + myNet.getCurrentTimeStep();
252 111336 : if (existing != nullptr) {
253 110 : existing->changeStepAndDuration(getTLLogicControlToUse(),
254 : myNet.getCurrentTimeStep(), step, (*i)->duration - offset);
255 : // parameters that are used when initializing a logic will not take
256 : // effect but parameters that are checked at runtime can be used
257 : // here (i.e. device.glosa.range)
258 110 : myLogicParams[existing] = myAdditionalParameter;
259 : if (myAdditionalParameter.count(MESegment::OVERRIDE_TLS_PENALTIES) != 0) {
260 : // value must be available when calling setMesoTypes and before setting the rest in postLoadInitialization
261 4 : existing->setParameter(MESegment::OVERRIDE_TLS_PENALTIES, myAdditionalParameter[MESegment::OVERRIDE_TLS_PENALTIES]);
262 : }
263 110 : return;
264 : }
265 : }
266 : }
267 :
268 115642 : if (myActiveProgram == "") {
269 : myActiveProgram = "default";
270 : }
271 115642 : MSTrafficLightLogic* tlLogic = nullptr;
272 : // build the tls-logic in dependence to its type
273 115642 : switch (myLogicType) {
274 16 : case TrafficLightType::SWARM_BASED:
275 16 : firstEventOffset = DELTA_T; //this is needed because swarm needs to update the pheromone on the lanes at every step
276 16 : tlLogic = new MSSwarmTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myActivePhases, step, firstEventOffset, myAdditionalParameter);
277 16 : break;
278 0 : case TrafficLightType::HILVL_DETERMINISTIC:
279 0 : tlLogic = new MSDeterministicHiLevelTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myActivePhases, step, firstEventOffset, myAdditionalParameter);
280 0 : break;
281 16 : case TrafficLightType::SOTL_REQUEST:
282 16 : tlLogic = new MSSOTLPolicyBasedTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myLogicType, myActivePhases, step, firstEventOffset, myAdditionalParameter, new MSSOTLRequestPolicy(myAdditionalParameter));
283 16 : break;
284 16 : case TrafficLightType::SOTL_PLATOON:
285 16 : tlLogic = new MSSOTLPolicyBasedTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myLogicType, myActivePhases, step, firstEventOffset, myAdditionalParameter, new MSSOTLPlatoonPolicy(myAdditionalParameter));
286 16 : break;
287 16 : case TrafficLightType::SOTL_WAVE:
288 16 : tlLogic = new MSSOTLWaveTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myActivePhases, step, firstEventOffset, myAdditionalParameter);
289 16 : break;
290 16 : case TrafficLightType::SOTL_PHASE:
291 16 : tlLogic = new MSSOTLPolicyBasedTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myLogicType, myActivePhases, step, firstEventOffset, myAdditionalParameter, new MSSOTLPhasePolicy(myAdditionalParameter));
292 16 : break;
293 16 : case TrafficLightType::SOTL_MARCHING:
294 16 : tlLogic = new MSSOTLPolicyBasedTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myLogicType, myActivePhases, step, firstEventOffset, myAdditionalParameter, new MSSOTLMarchingPolicy(myAdditionalParameter));
295 16 : break;
296 494 : case TrafficLightType::ACTUATED:
297 : // @note it is unclear how to apply the given offset in the context
298 : // of variable-length phases
299 494 : tlLogic = new MSActuatedTrafficLightLogic(getTLLogicControlToUse(),
300 : myActiveKey, myActiveProgram, myOffset,
301 494 : myActivePhases, step, (*i)->minDuration + myNet.getCurrentTimeStep(),
302 494 : myAdditionalParameter, basePath, myActiveConditions, myActiveAssignments, myActiveFunctions);
303 494 : break;
304 94 : case TrafficLightType::NEMA:
305 94 : tlLogic = new NEMALogic(getTLLogicControlToUse(),
306 : myActiveKey, myActiveProgram, myOffset,
307 94 : myActivePhases, step, (*i)->minDuration + myNet.getCurrentTimeStep(),
308 94 : myAdditionalParameter, basePath);
309 94 : break;
310 106 : case TrafficLightType::DELAYBASED:
311 106 : tlLogic = new MSDelayBasedTrafficLightLogic(getTLLogicControlToUse(),
312 : myActiveKey, myActiveProgram, myOffset,
313 106 : myActivePhases, step, (*i)->minDuration + myNet.getCurrentTimeStep(),
314 106 : myAdditionalParameter, basePath);
315 106 : break;
316 110436 : case TrafficLightType::STATIC:
317 110436 : tlLogic = new MSSimpleTrafficLightLogic(getTLLogicControlToUse(),
318 : myActiveKey, myActiveProgram, myOffset,
319 : TrafficLightType::STATIC,
320 110436 : myActivePhases, step, firstEventOffset,
321 110436 : myAdditionalParameter);
322 110436 : break;
323 4265 : case TrafficLightType::RAIL_SIGNAL:
324 4265 : tlLogic = new MSRailSignal(getTLLogicControlToUse(),
325 4265 : myActiveKey, myActiveProgram, myNet.getCurrentTimeStep(),
326 4265 : myAdditionalParameter);
327 4265 : break;
328 151 : case TrafficLightType::RAIL_CROSSING:
329 151 : tlLogic = new MSRailCrossing(getTLLogicControlToUse(),
330 151 : myActiveKey, myActiveProgram, myNet.getCurrentTimeStep(),
331 151 : myAdditionalParameter);
332 151 : break;
333 0 : case TrafficLightType::OFF:
334 0 : tlLogic = new MSOffTrafficLightLogic(getTLLogicControlToUse(), myActiveKey);
335 0 : break;
336 0 : case TrafficLightType::INVALID:
337 0 : throw ProcessError(TLF("Invalid traffic light type '%'", toString(myLogicType)));
338 : }
339 : myActivePhases.clear();
340 115642 : if (tlLogic != nullptr) {
341 115642 : if (getTLLogicControlToUse().add(myActiveKey, myActiveProgram, tlLogic)) {
342 115636 : if (myNetIsLoaded) {
343 14137 : myAdditionalLogics.push_back(tlLogic);
344 101499 : } else if (myLogicType == TrafficLightType::RAIL_SIGNAL) {
345 : // special case: intialize earlier because signals are already used when
346 : // loading train routes in additional files
347 4265 : myRailSignals.push_back(tlLogic);
348 : } else {
349 97234 : myNetworkLogics.push_back(tlLogic);
350 : }
351 : } else {
352 0 : WRITE_ERRORF(TL("Another logic with id '%' and programID '%' exists."), myActiveKey, myActiveProgram);
353 : }
354 : }
355 : }
356 :
357 :
358 : void
359 581579 : NLJunctionControlBuilder::initJunctionLogic(const std::string& id) {
360 581579 : myActiveKey = id;
361 581579 : myActiveProgram = "";
362 : myActiveLogic.clear();
363 : myActiveFoes.clear();
364 : myActiveConts.reset();
365 581579 : myRequestSize = NO_REQUEST_SIZE; // seems not to be used
366 581579 : myRequestItemNumber = 0;
367 581579 : myCurrentHasError = false;
368 581579 : }
369 :
370 :
371 : void
372 1659317 : NLJunctionControlBuilder::addLogicItem(int request,
373 : const std::string& response,
374 : const std::string& foes,
375 : bool cont) {
376 1659317 : if (myCurrentHasError) {
377 : // had an error
378 : return;
379 : }
380 1659317 : if (request >= SUMO_MAX_CONNECTIONS) {
381 : // bad request
382 0 : myCurrentHasError = true;
383 0 : throw InvalidArgument("Junction logic '" + myActiveKey + "' is larger than allowed; recheck the network.");
384 : }
385 1659317 : if (myRequestSize == NO_REQUEST_SIZE) {
386 : // initialize
387 326230 : myRequestSize = (int)response.size();
388 : }
389 1659317 : if (static_cast<int>(response.size()) != myRequestSize) {
390 0 : myCurrentHasError = true;
391 0 : throw InvalidArgument("Invalid response size " + toString(response.size()) +
392 0 : " in Junction logic '" + myActiveKey + "' (expected " + toString(myRequestSize) + ")");
393 : }
394 1659317 : if (static_cast<int>(foes.size()) != myRequestSize) {
395 0 : myCurrentHasError = true;
396 0 : throw InvalidArgument("Invalid foes size " + toString(foes.size()) +
397 0 : " in Junction logic '" + myActiveKey + "' (expected " + toString(myRequestSize) + ")");
398 : }
399 : // assert that the logicitems come ordered by their request index
400 : assert((int)myActiveLogic.size() == request);
401 : assert((int)myActiveFoes.size() == request);
402 : // add the read response for the given request index
403 1659317 : myActiveLogic.push_back(std::bitset<SUMO_MAX_CONNECTIONS>(response));
404 : // add the read junction-internal foes for the given request index
405 1659317 : myActiveFoes.push_back(std::bitset<SUMO_MAX_CONNECTIONS>(foes));
406 : // add whether the vehicle may drive a little bit further
407 1659317 : myActiveConts.set(request, cont);
408 : // increse number of set information
409 1659317 : myRequestItemNumber++;
410 : }
411 :
412 :
413 : void
414 111410 : NLJunctionControlBuilder::initTrafficLightLogic(const std::string& id, const std::string& programID,
415 : TrafficLightType type, SUMOTime offset) {
416 111410 : myActiveKey = id;
417 111410 : myActiveProgram = programID;
418 : myActivePhases.clear();
419 : myActiveConditions.clear();
420 : myActiveAssignments.clear();
421 : myActiveFunctions.clear();
422 111410 : myAbsDuration = 0;
423 111410 : myRequestSize = NO_REQUEST_SIZE;
424 111410 : myLogicType = type;
425 111410 : myOffset = offset;
426 : myAdditionalParameter.clear();
427 111410 : }
428 :
429 :
430 : void
431 520826 : NLJunctionControlBuilder::addPhase(MSPhaseDefinition* phase) {
432 : // build and add the phase definition to the list
433 520826 : myActivePhases.push_back(phase);
434 : // add phase duration to the absolute duration
435 520826 : myAbsDuration += phase->duration;
436 520826 : }
437 :
438 :
439 : bool
440 94 : NLJunctionControlBuilder::addCondition(const std::string& id, const std::string& value) {
441 : if (myActiveConditions.count(id) == 0) {
442 94 : myActiveConditions[id] = value;
443 94 : return true;
444 : } else {
445 0 : return false;
446 : }
447 : }
448 :
449 :
450 : void
451 60 : NLJunctionControlBuilder::addAssignment(const std::string& id, const std::string& check, const std::string& value) {
452 60 : if (myActiveFunction.id == "") {
453 102 : myActiveAssignments.push_back(std::make_tuple(id, check, value));
454 : } else {
455 18 : myActiveFunction.assignments.push_back(std::make_tuple(id, check, value));
456 : }
457 60 : }
458 :
459 :
460 : void
461 4 : NLJunctionControlBuilder::addFunction(const std::string& id, int nArgs) {
462 4 : myActiveFunction.id = id;
463 4 : myActiveFunction.nArgs = nArgs;
464 4 : }
465 :
466 :
467 : void
468 4 : NLJunctionControlBuilder::closeFunction() {
469 4 : myActiveFunctions[myActiveFunction.id] = myActiveFunction;
470 : myActiveFunction.id = "";
471 : myActiveFunction.assignments.clear();
472 4 : }
473 :
474 :
475 : MSTLLogicControl*
476 43710 : NLJunctionControlBuilder::buildTLLogics() {
477 43710 : if (!myLogicControl->closeNetworkReading()) {
478 0 : throw ProcessError(TL("Traffic lights could not be built."));
479 : }
480 47975 : for (MSTrafficLightLogic* const logic : myRailSignals) {
481 4265 : logic->init(myDetectorBuilder);
482 : }
483 43710 : MSTLLogicControl* ret = myLogicControl;
484 43710 : myNetIsLoaded = true;
485 43710 : myLogicControl = nullptr;
486 43710 : return ret;
487 : }
488 :
489 :
490 : void
491 10315 : NLJunctionControlBuilder::addParam(const std::string& key,
492 : const std::string& value) {
493 10315 : myAdditionalParameter[key] = value;
494 10315 : }
495 :
496 :
497 : MSTLLogicControl&
498 2080376 : NLJunctionControlBuilder::getTLLogicControlToUse() const {
499 2080376 : if (myLogicControl != nullptr) {
500 : return *myLogicControl;
501 : }
502 58148 : return myNet.getTLSControl();
503 : }
504 :
505 :
506 : const std::string&
507 1041655 : NLJunctionControlBuilder::getActiveKey() const {
508 1041655 : return myActiveKey;
509 : }
510 :
511 :
512 : const std::string&
513 1 : NLJunctionControlBuilder::getActiveSubKey() const {
514 1 : return myActiveProgram;
515 : }
516 :
517 :
518 : void
519 42823 : NLJunctionControlBuilder::postLoadInitialization() {
520 132137 : for (MSTrafficLightLogic* const logic : myNetworkLogics) {
521 89340 : logic->init(myDetectorBuilder);
522 : }
523 56914 : for (MSTrafficLightLogic* const logic : myAdditionalLogics) {
524 14122 : logic->init(myDetectorBuilder);
525 : }
526 : // delay parameter loading until initialization
527 42901 : for (auto item : myLogicParams) {
528 109 : item.first->updateParameters(item.second);
529 : }
530 42792 : }
531 :
532 :
533 : MSJunction*
534 3599432 : NLJunctionControlBuilder::retrieve(const std::string id) {
535 3599432 : if (myJunctions != nullptr) {
536 : return myJunctions->get(id);
537 : } else {
538 : return nullptr;
539 : }
540 : }
541 :
542 :
543 : /****************************************************************************/
|