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 42766 : NLJunctionControlBuilder::NLJunctionControlBuilder(MSNet& net, NLDetectorBuilder& db) :
70 42766 : myNet(net),
71 42766 : myDetectorBuilder(db),
72 42766 : myOffset(0),
73 42766 : myJunctions(new MSJunctionControl()),
74 171064 : myNetIsLoaded(false) {
75 42766 : myLogicControl = new MSTLLogicControl();
76 42766 : }
77 :
78 :
79 42766 : NLJunctionControlBuilder::~NLJunctionControlBuilder() {
80 42766 : delete myLogicControl;
81 42766 : delete myJunctions;
82 128298 : }
83 :
84 :
85 : void
86 559860 : 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 559860 : myActiveInternalLanes = internalLanes;
95 559860 : myActiveIncomingLanes = incomingLanes;
96 559860 : myActiveID = id;
97 559860 : myActiveKey = key;
98 559860 : myType = type;
99 : myPosition.set(pos);
100 : myShape = shape;
101 559860 : myActiveName = name;
102 : myAdditionalParameter.clear();
103 559860 : }
104 :
105 :
106 : void
107 559860 : NLJunctionControlBuilder::closeJunction(const std::string& basePath) {
108 559860 : if (myCurrentHasError) {
109 : // had an error before...
110 : return;
111 : }
112 559860 : if (myRequestSize != NO_REQUEST_SIZE && myRequestItemNumber != myRequestSize) {
113 0 : throw InvalidArgument("The description for the junction logic '" + myActiveKey + "' is malicious.");
114 : }
115 559860 : if (myJunctions == nullptr) {
116 0 : throw ProcessError(TL("Information about the number of nodes was missing."));
117 : }
118 : MSJunction* junction = nullptr;
119 559860 : switch (myType) {
120 58257 : 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 58257 : if (!myActiveLogic.empty()) {
126 120 : WRITE_WARNINGF(TL("Ignoring junction logic for junction '%'."), myActiveID)
127 : }
128 58257 : junction = buildNoLogicJunction();
129 58257 : break;
130 313430 : 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 313430 : junction = buildLogicJunction(new MSBitsetLogic(myRequestSize, myActiveLogic, myActiveFoes, myActiveConts));
139 : break;
140 184555 : case SumoXMLNodeType::INTERNAL:
141 184555 : if (MSGlobals::gUsingInternalLanes) {
142 151788 : if (!myActiveLogic.empty()) {
143 18 : WRITE_WARNINGF(TL("Ignoring junction logic for junction '%'."), myActiveID)
144 : }
145 151788 : junction = buildInternalJunction();
146 : }
147 : break;
148 3618 : case SumoXMLNodeType::RAIL_SIGNAL:
149 : case SumoXMLNodeType::RAIL_CROSSING:
150 3618 : myOffset = 0;
151 3618 : myActiveKey = myActiveID;
152 3618 : myActiveProgram = "0";
153 3618 : myLogicType = myType == SumoXMLNodeType::RAIL_SIGNAL ? TrafficLightType::RAIL_SIGNAL : TrafficLightType::RAIL_CROSSING;
154 3618 : closeTrafficLightLogic(basePath);
155 3618 : junction = buildLogicJunction(new MSBitsetLogic(myRequestSize, myActiveLogic, myActiveFoes, myActiveConts));
156 : break;
157 0 : default:
158 0 : throw InvalidArgument("False junction logic type.");
159 : }
160 527093 : if (junction != nullptr) {
161 527093 : if (!myJunctions->add(myActiveID, junction)) {
162 12 : throw InvalidArgument("Another junction with the id '" + myActiveID + "' exists.");
163 : }
164 527087 : junction->updateParameters(myAdditionalParameter);
165 : }
166 : }
167 :
168 :
169 : MSJunctionControl*
170 42345 : NLJunctionControlBuilder::build() const {
171 42345 : MSJunctionControl* js = myJunctions;
172 42345 : myJunctions = nullptr;
173 42345 : return js;
174 : }
175 :
176 :
177 : MSJunction*
178 58257 : NLJunctionControlBuilder::buildNoLogicJunction() {
179 58257 : return new MSNoLogicJunction(myActiveID, myType, myPosition, myShape, myActiveName,
180 58257 : myActiveIncomingLanes, myActiveInternalLanes);
181 : }
182 :
183 :
184 : MSJunction*
185 317048 : NLJunctionControlBuilder::buildLogicJunction(MSJunctionLogic* const logic) {
186 317048 : return new MSRightOfWayJunction(myActiveID, myType, myPosition, myShape, myActiveName,
187 317048 : myActiveIncomingLanes, myActiveInternalLanes, logic);
188 : }
189 :
190 :
191 : MSJunction*
192 151788 : NLJunctionControlBuilder::buildInternalJunction() {
193 : // build the junction
194 303576 : return new MSInternalJunction(myActiveID, myType, myPosition, myShape, myActiveIncomingLanes,
195 151788 : myActiveInternalLanes);
196 : }
197 :
198 :
199 : MSTLLogicControl::TLSLogicVariants&
200 1595243 : NLJunctionControlBuilder::getTLLogic(const std::string& id) const {
201 1595243 : return getTLLogicControlToUse().get(id);
202 : }
203 :
204 :
205 : void
206 113649 : NLJunctionControlBuilder::closeTrafficLightLogic(const std::string& basePath) {
207 113649 : 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 166 : return;
216 : }
217 : SUMOTime firstEventOffset = 0;
218 : int step = 0;
219 : MSSimpleTrafficLightLogic::Phases::const_iterator i = myActivePhases.begin();
220 113612 : MSTrafficLightLogic* existing = getTLLogicControlToUse().get(myActiveKey, myActiveProgram);
221 113612 : if (existing != nullptr && (existing->getLogicType() == TrafficLightType::RAIL_SIGNAL || existing->getLogicType() == TrafficLightType::RAIL_CROSSING)) {
222 35 : existing->updateParameters(myAdditionalParameter);
223 35 : return;
224 : } else {
225 113577 : if (myLogicType != TrafficLightType::RAIL_SIGNAL && myLogicType != TrafficLightType::RAIL_CROSSING) {
226 109959 : if (myAbsDuration == 0) {
227 95 : 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 94 : myAbsDuration = existing->getDefaultCycleTime();
232 94 : i = existing->getPhases().begin();
233 : }
234 109864 : } 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 109957 : if (myOffset >= 0) {
242 109898 : offset = (myNet.getCurrentTimeStep() + myAbsDuration - (myOffset % myAbsDuration)) % myAbsDuration;
243 : } else {
244 59 : offset = (myNet.getCurrentTimeStep() + ((-myOffset) % myAbsDuration)) % myAbsDuration;
245 : }
246 111205 : while (offset >= (*i)->duration) {
247 1248 : step++;
248 1248 : offset -= (*i)->duration;
249 : ++i;
250 : }
251 109957 : firstEventOffset = (*i)->duration - offset + myNet.getCurrentTimeStep();
252 109957 : if (existing != nullptr) {
253 94 : 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 94 : myLogicParams[existing] = myAdditionalParameter;
259 94 : return;
260 : }
261 : }
262 : }
263 :
264 113481 : if (myActiveProgram == "") {
265 : myActiveProgram = "default";
266 : }
267 113481 : MSTrafficLightLogic* tlLogic = nullptr;
268 : // build the tls-logic in dependence to its type
269 113481 : switch (myLogicType) {
270 16 : case TrafficLightType::SWARM_BASED:
271 16 : firstEventOffset = DELTA_T; //this is needed because swarm needs to update the pheromone on the lanes at every step
272 16 : tlLogic = new MSSwarmTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myActivePhases, step, firstEventOffset, myAdditionalParameter);
273 16 : break;
274 0 : case TrafficLightType::HILVL_DETERMINISTIC:
275 0 : tlLogic = new MSDeterministicHiLevelTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myActivePhases, step, firstEventOffset, myAdditionalParameter);
276 0 : break;
277 16 : case TrafficLightType::SOTL_REQUEST:
278 16 : tlLogic = new MSSOTLPolicyBasedTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myLogicType, myActivePhases, step, firstEventOffset, myAdditionalParameter, new MSSOTLRequestPolicy(myAdditionalParameter));
279 16 : break;
280 16 : case TrafficLightType::SOTL_PLATOON:
281 16 : tlLogic = new MSSOTLPolicyBasedTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myLogicType, myActivePhases, step, firstEventOffset, myAdditionalParameter, new MSSOTLPlatoonPolicy(myAdditionalParameter));
282 16 : break;
283 16 : case TrafficLightType::SOTL_WAVE:
284 16 : tlLogic = new MSSOTLWaveTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myActivePhases, step, firstEventOffset, myAdditionalParameter);
285 16 : break;
286 16 : case TrafficLightType::SOTL_PHASE:
287 16 : tlLogic = new MSSOTLPolicyBasedTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myLogicType, myActivePhases, step, firstEventOffset, myAdditionalParameter, new MSSOTLPhasePolicy(myAdditionalParameter));
288 16 : break;
289 16 : case TrafficLightType::SOTL_MARCHING:
290 16 : tlLogic = new MSSOTLPolicyBasedTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myLogicType, myActivePhases, step, firstEventOffset, myAdditionalParameter, new MSSOTLMarchingPolicy(myAdditionalParameter));
291 16 : break;
292 487 : case TrafficLightType::ACTUATED:
293 : // @note it is unclear how to apply the given offset in the context
294 : // of variable-length phases
295 487 : tlLogic = new MSActuatedTrafficLightLogic(getTLLogicControlToUse(),
296 : myActiveKey, myActiveProgram, myOffset,
297 487 : myActivePhases, step, (*i)->minDuration + myNet.getCurrentTimeStep(),
298 487 : myAdditionalParameter, basePath, myActiveConditions, myActiveAssignments, myActiveFunctions);
299 487 : break;
300 93 : case TrafficLightType::NEMA:
301 93 : tlLogic = new NEMALogic(getTLLogicControlToUse(),
302 : myActiveKey, myActiveProgram, myOffset,
303 93 : myActivePhases, step, (*i)->minDuration + myNet.getCurrentTimeStep(),
304 93 : myAdditionalParameter, basePath);
305 93 : break;
306 98 : case TrafficLightType::DELAYBASED:
307 98 : tlLogic = new MSDelayBasedTrafficLightLogic(getTLLogicControlToUse(),
308 : myActiveKey, myActiveProgram, myOffset,
309 98 : myActivePhases, step, (*i)->minDuration + myNet.getCurrentTimeStep(),
310 98 : myAdditionalParameter, basePath);
311 98 : break;
312 109089 : case TrafficLightType::STATIC:
313 109089 : tlLogic = new MSSimpleTrafficLightLogic(getTLLogicControlToUse(),
314 : myActiveKey, myActiveProgram, myOffset,
315 : TrafficLightType::STATIC,
316 109089 : myActivePhases, step, firstEventOffset,
317 109089 : myAdditionalParameter);
318 109089 : break;
319 3485 : case TrafficLightType::RAIL_SIGNAL:
320 3485 : tlLogic = new MSRailSignal(getTLLogicControlToUse(),
321 3485 : myActiveKey, myActiveProgram, myNet.getCurrentTimeStep(),
322 3485 : myAdditionalParameter);
323 3485 : break;
324 133 : case TrafficLightType::RAIL_CROSSING:
325 133 : tlLogic = new MSRailCrossing(getTLLogicControlToUse(),
326 133 : myActiveKey, myActiveProgram, myNet.getCurrentTimeStep(),
327 133 : myAdditionalParameter);
328 133 : 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 113481 : if (tlLogic != nullptr) {
337 113481 : if (getTLLogicControlToUse().add(myActiveKey, myActiveProgram, tlLogic)) {
338 113475 : if (myNetIsLoaded) {
339 14098 : myAdditionalLogics.push_back(tlLogic);
340 99377 : } 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 3485 : myRailSignals.push_back(tlLogic);
344 : } else {
345 95892 : 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 559860 : NLJunctionControlBuilder::initJunctionLogic(const std::string& id) {
356 559860 : myActiveKey = id;
357 559860 : myActiveProgram = "";
358 : myActiveLogic.clear();
359 : myActiveFoes.clear();
360 : myActiveConts.reset();
361 559860 : myRequestSize = NO_REQUEST_SIZE; // seems not to be used
362 559860 : myRequestItemNumber = 0;
363 559860 : myCurrentHasError = false;
364 559860 : }
365 :
366 :
367 : void
368 1612901 : NLJunctionControlBuilder::addLogicItem(int request,
369 : const std::string& response,
370 : const std::string& foes,
371 : bool cont) {
372 1612901 : if (myCurrentHasError) {
373 : // had an error
374 : return;
375 : }
376 1612901 : 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 1612901 : if (myRequestSize == NO_REQUEST_SIZE) {
382 : // initialize
383 317094 : myRequestSize = (int)response.size();
384 : }
385 1612901 : 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 1612901 : 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 1612901 : myActiveLogic.push_back(std::bitset<SUMO_MAX_CONNECTIONS>(response));
400 : // add the read junction-internal foes for the given request index
401 1612901 : myActiveFoes.push_back(std::bitset<SUMO_MAX_CONNECTIONS>(foes));
402 : // add whether the vehicle may drive a little bit further
403 1612901 : myActiveConts.set(request, cont);
404 : // increse number of set information
405 1612901 : myRequestItemNumber++;
406 : }
407 :
408 :
409 : void
410 110031 : NLJunctionControlBuilder::initTrafficLightLogic(const std::string& id, const std::string& programID,
411 : TrafficLightType type, SUMOTime offset) {
412 110031 : myActiveKey = id;
413 110031 : myActiveProgram = programID;
414 : myActivePhases.clear();
415 : myActiveConditions.clear();
416 : myActiveAssignments.clear();
417 : myActiveFunctions.clear();
418 110031 : myAbsDuration = 0;
419 110031 : myRequestSize = NO_REQUEST_SIZE;
420 110031 : myLogicType = type;
421 110031 : myOffset = offset;
422 : myAdditionalParameter.clear();
423 110031 : }
424 :
425 :
426 : void
427 514350 : NLJunctionControlBuilder::addPhase(MSPhaseDefinition* phase) {
428 : // build and add the phase definition to the list
429 514350 : myActivePhases.push_back(phase);
430 : // add phase duration to the absolute duration
431 514350 : myAbsDuration += phase->duration;
432 514350 : }
433 :
434 :
435 : bool
436 94 : NLJunctionControlBuilder::addCondition(const std::string& id, const std::string& value) {
437 : if (myActiveConditions.count(id) == 0) {
438 94 : myActiveConditions[id] = value;
439 94 : 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 42335 : NLJunctionControlBuilder::buildTLLogics() {
473 42335 : if (!myLogicControl->closeNetworkReading()) {
474 0 : throw ProcessError(TL("Traffic lights could not be built."));
475 : }
476 45820 : for (MSTrafficLightLogic* const logic : myRailSignals) {
477 3485 : logic->init(myDetectorBuilder);
478 : }
479 42335 : MSTLLogicControl* ret = myLogicControl;
480 42335 : myNetIsLoaded = true;
481 42335 : myLogicControl = nullptr;
482 42335 : return ret;
483 : }
484 :
485 :
486 : void
487 10281 : NLJunctionControlBuilder::addParam(const std::string& key,
488 : const std::string& value) {
489 10281 : myAdditionalParameter[key] = value;
490 10281 : }
491 :
492 :
493 : MSTLLogicControl&
494 2046518 : NLJunctionControlBuilder::getTLLogicControlToUse() const {
495 2046518 : if (myLogicControl != nullptr) {
496 : return *myLogicControl;
497 : }
498 57944 : return myNet.getTLSControl();
499 : }
500 :
501 :
502 : const std::string&
503 1028703 : NLJunctionControlBuilder::getActiveKey() const {
504 1028703 : return myActiveKey;
505 : }
506 :
507 :
508 : const std::string&
509 1 : NLJunctionControlBuilder::getActiveSubKey() const {
510 1 : return myActiveProgram;
511 : }
512 :
513 :
514 : void
515 41584 : NLJunctionControlBuilder::postLoadInitialization() {
516 129716 : for (MSTrafficLightLogic* const logic : myNetworkLogics) {
517 88158 : logic->init(myDetectorBuilder);
518 : }
519 55636 : for (MSTrafficLightLogic* const logic : myAdditionalLogics) {
520 14083 : logic->init(myDetectorBuilder);
521 : }
522 : // delay parameter loading until initialization
523 41646 : for (auto item : myLogicParams) {
524 93 : item.first->updateParameters(item.second);
525 : }
526 41553 : }
527 :
528 :
529 : MSJunction*
530 3458332 : NLJunctionControlBuilder::retrieve(const std::string id) {
531 3458332 : if (myJunctions != nullptr) {
532 : return myJunctions->get(id);
533 : } else {
534 : return nullptr;
535 : }
536 : }
537 :
538 :
539 : /****************************************************************************/
|