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 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 35455 : NLJunctionControlBuilder::NLJunctionControlBuilder(MSNet& net, NLDetectorBuilder& db) :
70 35455 : myNet(net),
71 35455 : myDetectorBuilder(db),
72 35455 : myOffset(0),
73 35455 : myJunctions(new MSJunctionControl()),
74 141820 : myNetIsLoaded(false) {
75 35455 : myLogicControl = new MSTLLogicControl();
76 35455 : }
77 :
78 :
79 35455 : NLJunctionControlBuilder::~NLJunctionControlBuilder() {
80 35455 : delete myLogicControl;
81 35455 : delete myJunctions;
82 106365 : }
83 :
84 :
85 : void
86 480279 : 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 480279 : myActiveInternalLanes = internalLanes;
95 480279 : myActiveIncomingLanes = incomingLanes;
96 480279 : myActiveID = id;
97 480279 : myActiveKey = key;
98 480279 : myType = type;
99 : myPosition.set(pos);
100 : myShape = shape;
101 480279 : myActiveName = name;
102 : myAdditionalParameter.clear();
103 480279 : }
104 :
105 :
106 : void
107 480279 : NLJunctionControlBuilder::closeJunction(const std::string& basePath) {
108 480279 : if (myCurrentHasError) {
109 : // had an error before...
110 : return;
111 : }
112 480279 : if (myRequestSize != NO_REQUEST_SIZE && myRequestItemNumber != myRequestSize) {
113 0 : throw InvalidArgument("The description for the junction logic '" + myActiveKey + "' is malicious.");
114 : }
115 480279 : if (myJunctions == nullptr) {
116 0 : throw ProcessError(TL("Information about the number of nodes was missing."));
117 : }
118 : MSJunction* junction = nullptr;
119 480279 : switch (myType) {
120 62883 : 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 62883 : if (!myActiveLogic.empty()) {
126 120 : WRITE_WARNINGF(TL("Ignoring junction logic for junction '%'."), myActiveID)
127 : }
128 62883 : junction = buildNoLogicJunction();
129 62883 : break;
130 246486 : 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 246486 : junction = buildLogicJunction(new MSBitsetLogic(myRequestSize, myActiveLogic, myActiveFoes, myActiveConts));
139 246486 : break;
140 168008 : case SumoXMLNodeType::INTERNAL:
141 168008 : if (MSGlobals::gUsingInternalLanes) {
142 134263 : if (!myActiveLogic.empty()) {
143 18 : WRITE_WARNINGF(TL("Ignoring junction logic for junction '%'."), myActiveID)
144 : }
145 134263 : junction = buildInternalJunction();
146 : }
147 : break;
148 2902 : case SumoXMLNodeType::RAIL_SIGNAL:
149 : case SumoXMLNodeType::RAIL_CROSSING:
150 2902 : myOffset = 0;
151 2902 : myActiveKey = myActiveID;
152 2902 : myActiveProgram = "0";
153 2902 : myLogicType = myType == SumoXMLNodeType::RAIL_SIGNAL ? TrafficLightType::RAIL_SIGNAL : TrafficLightType::RAIL_CROSSING;
154 2902 : closeTrafficLightLogic(basePath);
155 2902 : junction = buildLogicJunction(new MSBitsetLogic(myRequestSize, myActiveLogic, myActiveFoes, myActiveConts));
156 2902 : break;
157 0 : default:
158 0 : throw InvalidArgument("False junction logic type.");
159 : }
160 446534 : if (junction != nullptr) {
161 446534 : if (!myJunctions->add(myActiveID, junction)) {
162 172 : throw InvalidArgument("Another junction with the id '" + myActiveID + "' exists.");
163 : }
164 446448 : junction->updateParameters(myAdditionalParameter);
165 : }
166 : }
167 :
168 :
169 : MSJunctionControl*
170 34684 : NLJunctionControlBuilder::build() const {
171 34684 : MSJunctionControl* js = myJunctions;
172 34684 : myJunctions = nullptr;
173 34684 : return js;
174 : }
175 :
176 :
177 : MSJunction*
178 62883 : NLJunctionControlBuilder::buildNoLogicJunction() {
179 62883 : return new MSNoLogicJunction(myActiveID, myType, myPosition, myShape, myActiveName,
180 169260 : myActiveIncomingLanes, myActiveInternalLanes);
181 : }
182 :
183 :
184 : MSJunction*
185 249388 : NLJunctionControlBuilder::buildLogicJunction(MSJunctionLogic* const logic) {
186 249388 : return new MSRightOfWayJunction(myActiveID, myType, myPosition, myShape, myActiveName,
187 748164 : myActiveIncomingLanes, myActiveInternalLanes, logic);
188 : }
189 :
190 :
191 : MSJunction*
192 134263 : NLJunctionControlBuilder::buildInternalJunction() {
193 : // build the junction
194 268526 : return new MSInternalJunction(myActiveID, myType, myPosition, myShape, myActiveIncomingLanes,
195 402789 : myActiveInternalLanes);
196 : }
197 :
198 :
199 : MSTLLogicControl::TLSLogicVariants&
200 1662825 : NLJunctionControlBuilder::getTLLogic(const std::string& id) const {
201 1662825 : return getTLLogicControlToUse().get(id);
202 : }
203 :
204 :
205 : void
206 109198 : NLJunctionControlBuilder::closeTrafficLightLogic(const std::string& basePath) {
207 109198 : 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 218 : return;
216 : }
217 : SUMOTime firstEventOffset = 0;
218 : int step = 0;
219 : MSSimpleTrafficLightLogic::Phases::const_iterator i = myActivePhases.begin();
220 109161 : MSTrafficLightLogic* existing = getTLLogicControlToUse().get(myActiveKey, myActiveProgram);
221 109161 : if (existing != nullptr && (existing->getLogicType() == TrafficLightType::RAIL_SIGNAL || existing->getLogicType() == TrafficLightType::RAIL_CROSSING)) {
222 35 : existing->updateParameters(myAdditionalParameter);
223 35 : return;
224 : } else {
225 109126 : if (myLogicType != TrafficLightType::RAIL_SIGNAL && myLogicType != TrafficLightType::RAIL_CROSSING) {
226 106224 : if (myAbsDuration == 0) {
227 147 : 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 146 : myAbsDuration = existing->getDefaultCycleTime();
232 146 : i = existing->getPhases().begin();
233 : }
234 106077 : } 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 106222 : if (myOffset >= 0) {
242 106151 : offset = (myNet.getCurrentTimeStep() + myAbsDuration - (myOffset % myAbsDuration)) % myAbsDuration;
243 : } else {
244 71 : offset = (myNet.getCurrentTimeStep() + ((-myOffset) % myAbsDuration)) % myAbsDuration;
245 : }
246 107618 : while (offset >= (*i)->duration) {
247 1396 : step++;
248 1396 : offset -= (*i)->duration;
249 : ++i;
250 : }
251 106222 : firstEventOffset = (*i)->duration - offset + myNet.getCurrentTimeStep();
252 106222 : if (existing != nullptr) {
253 146 : 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 146 : myLogicParams[existing] = myAdditionalParameter;
259 146 : return;
260 : }
261 : }
262 : }
263 :
264 108978 : if (myActiveProgram == "") {
265 : myActiveProgram = "default";
266 : }
267 108978 : MSTrafficLightLogic* tlLogic = nullptr;
268 : // build the tls-logic in dependence to its type
269 108978 : switch (myLogicType) {
270 32 : case TrafficLightType::SWARM_BASED:
271 32 : firstEventOffset = DELTA_T; //this is needed because swarm needs to update the pheromone on the lanes at every step
272 32 : tlLogic = new MSSwarmTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myActivePhases, step, firstEventOffset, myAdditionalParameter);
273 32 : break;
274 0 : case TrafficLightType::HILVL_DETERMINISTIC:
275 0 : tlLogic = new MSDeterministicHiLevelTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myActivePhases, step, firstEventOffset, myAdditionalParameter);
276 0 : break;
277 32 : case TrafficLightType::SOTL_REQUEST:
278 32 : tlLogic = new MSSOTLPolicyBasedTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myLogicType, myActivePhases, step, firstEventOffset, myAdditionalParameter, new MSSOTLRequestPolicy(myAdditionalParameter));
279 32 : break;
280 32 : case TrafficLightType::SOTL_PLATOON:
281 32 : tlLogic = new MSSOTLPolicyBasedTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myLogicType, myActivePhases, step, firstEventOffset, myAdditionalParameter, new MSSOTLPlatoonPolicy(myAdditionalParameter));
282 32 : break;
283 32 : case TrafficLightType::SOTL_WAVE:
284 32 : tlLogic = new MSSOTLWaveTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myActivePhases, step, firstEventOffset, myAdditionalParameter);
285 32 : break;
286 32 : case TrafficLightType::SOTL_PHASE:
287 32 : tlLogic = new MSSOTLPolicyBasedTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myLogicType, myActivePhases, step, firstEventOffset, myAdditionalParameter, new MSSOTLPhasePolicy(myAdditionalParameter));
288 32 : break;
289 32 : case TrafficLightType::SOTL_MARCHING:
290 32 : tlLogic = new MSSOTLPolicyBasedTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myLogicType, myActivePhases, step, firstEventOffset, myAdditionalParameter, new MSSOTLMarchingPolicy(myAdditionalParameter));
291 32 : break;
292 582 : case TrafficLightType::ACTUATED:
293 : // @note it is unclear how to apply the given offset in the context
294 : // of variable-length phases
295 582 : tlLogic = new MSActuatedTrafficLightLogic(getTLLogicControlToUse(),
296 : myActiveKey, myActiveProgram, myOffset,
297 582 : myActivePhases, step, (*i)->minDuration + myNet.getCurrentTimeStep(),
298 582 : myAdditionalParameter, basePath, myActiveConditions, myActiveAssignments, myActiveFunctions);
299 582 : break;
300 97 : case TrafficLightType::NEMA:
301 97 : tlLogic = new NEMALogic(getTLLogicControlToUse(),
302 : myActiveKey, myActiveProgram, myOffset,
303 97 : myActivePhases, step, (*i)->minDuration + myNet.getCurrentTimeStep(),
304 97 : myAdditionalParameter, basePath);
305 97 : break;
306 105 : case TrafficLightType::DELAYBASED:
307 105 : tlLogic = new MSDelayBasedTrafficLightLogic(getTLLogicControlToUse(),
308 : myActiveKey, myActiveProgram, myOffset,
309 105 : myActivePhases, step, (*i)->minDuration + myNet.getCurrentTimeStep(),
310 105 : myAdditionalParameter, basePath);
311 105 : break;
312 105100 : case TrafficLightType::STATIC:
313 105100 : tlLogic = new MSSimpleTrafficLightLogic(getTLLogicControlToUse(),
314 : myActiveKey, myActiveProgram, myOffset,
315 : TrafficLightType::STATIC,
316 105100 : myActivePhases, step, firstEventOffset,
317 105100 : myAdditionalParameter);
318 105100 : break;
319 2727 : case TrafficLightType::RAIL_SIGNAL:
320 2727 : tlLogic = new MSRailSignal(getTLLogicControlToUse(),
321 5454 : myActiveKey, myActiveProgram, myNet.getCurrentTimeStep(),
322 2727 : myAdditionalParameter);
323 2727 : break;
324 175 : case TrafficLightType::RAIL_CROSSING:
325 175 : tlLogic = new MSRailCrossing(getTLLogicControlToUse(),
326 175 : myActiveKey, myActiveProgram, myNet.getCurrentTimeStep(),
327 175 : myAdditionalParameter);
328 175 : break;
329 0 : case TrafficLightType::OFF:
330 0 : tlLogic = new MSOffTrafficLightLogic(getTLLogicControlToUse(), myActiveKey);
331 0 : break;
332 0 : case TrafficLightType::INVALID:
333 0 : throw ProcessError(TLF("Invalid traffic light type '%'", toString(myLogicType)));
334 : }
335 : myActivePhases.clear();
336 108978 : if (tlLogic != nullptr) {
337 108978 : if (getTLLogicControlToUse().add(myActiveKey, myActiveProgram, tlLogic)) {
338 108972 : if (myNetIsLoaded) {
339 15318 : myAdditionalLogics.push_back(tlLogic);
340 93654 : } else if (myLogicType == TrafficLightType::RAIL_SIGNAL) {
341 : // special case: intialize earlier because signals are already used when
342 : // loading train routes in additional files
343 2727 : myRailSignals.push_back(tlLogic);
344 : } else {
345 90927 : myNetworkLogics.push_back(tlLogic);
346 : }
347 : } else {
348 0 : WRITE_ERRORF(TL("Another logic with id '%' and programID '%' exists."), myActiveKey, myActiveProgram);
349 : }
350 : }
351 : }
352 :
353 :
354 : void
355 480279 : NLJunctionControlBuilder::initJunctionLogic(const std::string& id) {
356 480279 : myActiveKey = id;
357 480279 : myActiveProgram = "";
358 : myActiveLogic.clear();
359 : myActiveFoes.clear();
360 : myActiveConts.reset();
361 480279 : myRequestSize = NO_REQUEST_SIZE; // seems not to be used
362 480279 : myRequestItemNumber = 0;
363 480279 : myCurrentHasError = false;
364 480279 : }
365 :
366 :
367 : void
368 1505503 : NLJunctionControlBuilder::addLogicItem(int request,
369 : const std::string& response,
370 : const std::string& foes,
371 : bool cont) {
372 1505503 : if (myCurrentHasError) {
373 : // had an error
374 : return;
375 : }
376 1505503 : if (request >= SUMO_MAX_CONNECTIONS) {
377 : // bad request
378 0 : myCurrentHasError = true;
379 0 : throw InvalidArgument("Junction logic '" + myActiveKey + "' is larger than allowed; recheck the network.");
380 : }
381 1505503 : if (myRequestSize == NO_REQUEST_SIZE) {
382 : // initialize
383 249434 : myRequestSize = (int)response.size();
384 : }
385 1505503 : if (static_cast<int>(response.size()) != myRequestSize) {
386 0 : myCurrentHasError = true;
387 0 : throw InvalidArgument("Invalid response size " + toString(response.size()) +
388 0 : " in Junction logic '" + myActiveKey + "' (expected " + toString(myRequestSize) + ")");
389 : }
390 1505503 : if (static_cast<int>(foes.size()) != myRequestSize) {
391 0 : myCurrentHasError = true;
392 0 : throw InvalidArgument("Invalid foes size " + toString(foes.size()) +
393 0 : " in Junction logic '" + myActiveKey + "' (expected " + toString(myRequestSize) + ")");
394 : }
395 : // assert that the logicitems come ordered by their request index
396 : assert((int)myActiveLogic.size() == request);
397 : assert((int)myActiveFoes.size() == request);
398 : // add the read response for the given request index
399 1505503 : myActiveLogic.push_back(std::bitset<SUMO_MAX_CONNECTIONS>(response));
400 : // add the read junction-internal foes for the given request index
401 1505503 : myActiveFoes.push_back(std::bitset<SUMO_MAX_CONNECTIONS>(foes));
402 : // add whether the vehicle may drive a little bit further
403 1505503 : myActiveConts.set(request, cont);
404 : // increse number of set information
405 1505503 : myRequestItemNumber++;
406 : }
407 :
408 :
409 : void
410 106296 : NLJunctionControlBuilder::initTrafficLightLogic(const std::string& id, const std::string& programID,
411 : TrafficLightType type, SUMOTime offset) {
412 106296 : myActiveKey = id;
413 106296 : myActiveProgram = programID;
414 : myActivePhases.clear();
415 : myActiveConditions.clear();
416 : myActiveAssignments.clear();
417 : myActiveFunctions.clear();
418 106296 : myAbsDuration = 0;
419 106296 : myRequestSize = NO_REQUEST_SIZE;
420 106296 : myLogicType = type;
421 106296 : myOffset = offset;
422 : myAdditionalParameter.clear();
423 106296 : }
424 :
425 :
426 : void
427 553615 : NLJunctionControlBuilder::addPhase(MSPhaseDefinition* phase) {
428 : // build and add the phase definition to the list
429 553615 : myActivePhases.push_back(phase);
430 : // add phase duration to the absolute duration
431 553615 : myAbsDuration += phase->duration;
432 553615 : }
433 :
434 :
435 : bool
436 96 : NLJunctionControlBuilder::addCondition(const std::string& id, const std::string& value) {
437 : if (myActiveConditions.count(id) == 0) {
438 96 : myActiveConditions[id] = value;
439 96 : return true;
440 : } else {
441 0 : return false;
442 : }
443 : }
444 :
445 :
446 : void
447 60 : NLJunctionControlBuilder::addAssignment(const std::string& id, const std::string& check, const std::string& value) {
448 60 : if (myActiveFunction.id == "") {
449 102 : myActiveAssignments.push_back(std::make_tuple(id, check, value));
450 : } else {
451 18 : myActiveFunction.assignments.push_back(std::make_tuple(id, check, value));
452 : }
453 60 : }
454 :
455 :
456 : void
457 4 : NLJunctionControlBuilder::addFunction(const std::string& id, int nArgs) {
458 4 : myActiveFunction.id = id;
459 4 : myActiveFunction.nArgs = nArgs;
460 4 : }
461 :
462 :
463 : void
464 4 : NLJunctionControlBuilder::closeFunction() {
465 4 : myActiveFunctions[myActiveFunction.id] = myActiveFunction;
466 : myActiveFunction.id = "";
467 : myActiveFunction.assignments.clear();
468 4 : }
469 :
470 :
471 : MSTLLogicControl*
472 34665 : NLJunctionControlBuilder::buildTLLogics() {
473 34665 : if (!myLogicControl->closeNetworkReading()) {
474 0 : throw ProcessError(TL("Traffic lights could not be built."));
475 : }
476 37392 : for (MSTrafficLightLogic* const logic : myRailSignals) {
477 2727 : logic->init(myDetectorBuilder);
478 : }
479 34665 : MSTLLogicControl* ret = myLogicControl;
480 34665 : myNetIsLoaded = true;
481 34665 : myLogicControl = nullptr;
482 34665 : return ret;
483 : }
484 :
485 :
486 : void
487 14385 : NLJunctionControlBuilder::addParam(const std::string& key,
488 : const std::string& value) {
489 14385 : myAdditionalParameter[key] = value;
490 14385 : }
491 :
492 :
493 : MSTLLogicControl&
494 2096892 : NLJunctionControlBuilder::getTLLogicControlToUse() const {
495 2096892 : if (myLogicControl != nullptr) {
496 : return *myLogicControl;
497 : }
498 63424 : return myNet.getTLSControl();
499 : }
500 :
501 :
502 : const std::string&
503 1107233 : NLJunctionControlBuilder::getActiveKey() const {
504 1107233 : return myActiveKey;
505 : }
506 :
507 :
508 : const std::string&
509 1 : NLJunctionControlBuilder::getActiveSubKey() const {
510 1 : return myActiveProgram;
511 : }
512 :
513 :
514 : void
515 33933 : NLJunctionControlBuilder::postLoadInitialization() {
516 117082 : for (MSTrafficLightLogic* const logic : myNetworkLogics) {
517 83176 : logic->init(myDetectorBuilder);
518 : }
519 49204 : for (MSTrafficLightLogic* const logic : myAdditionalLogics) {
520 15303 : logic->init(myDetectorBuilder);
521 : }
522 : // delay parameter loading until initialization
523 34046 : for (auto item : myLogicParams) {
524 145 : item.first->updateParameters(item.second);
525 : }
526 33901 : }
527 :
528 :
529 : MSJunction*
530 2881282 : NLJunctionControlBuilder::retrieve(const std::string id) {
531 2881282 : if (myJunctions != nullptr) {
532 : return myJunctions->get(id);
533 : } else {
534 : return nullptr;
535 : }
536 : }
537 :
538 :
539 : /****************************************************************************/
|