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 42907 : NLJunctionControlBuilder::NLJunctionControlBuilder(MSNet& net, NLDetectorBuilder& db) :
70 42907 : myNet(net),
71 42907 : myDetectorBuilder(db),
72 42907 : myOffset(0),
73 42907 : myJunctions(new MSJunctionControl()),
74 171628 : myNetIsLoaded(false) {
75 42907 : myLogicControl = new MSTLLogicControl();
76 42907 : }
77 :
78 :
79 42907 : NLJunctionControlBuilder::~NLJunctionControlBuilder() {
80 42907 : delete myLogicControl;
81 42907 : delete myJunctions;
82 128721 : }
83 :
84 :
85 : void
86 561297 : 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 561297 : myActiveInternalLanes = internalLanes;
95 561297 : myActiveIncomingLanes = incomingLanes;
96 561297 : myActiveID = id;
97 561297 : myActiveKey = key;
98 561297 : myType = type;
99 : myPosition.set(pos);
100 : myShape = shape;
101 561297 : myActiveName = name;
102 : myAdditionalParameter.clear();
103 561297 : }
104 :
105 :
106 : void
107 561297 : NLJunctionControlBuilder::closeJunction(const std::string& basePath) {
108 561297 : if (myCurrentHasError) {
109 : // had an error before...
110 : return;
111 : }
112 561297 : if (myRequestSize != NO_REQUEST_SIZE && myRequestItemNumber != myRequestSize) {
113 0 : throw InvalidArgument("The description for the junction logic '" + myActiveKey + "' is malicious.");
114 : }
115 561297 : if (myJunctions == nullptr) {
116 0 : throw ProcessError(TL("Information about the number of nodes was missing."));
117 : }
118 : MSJunction* junction = nullptr;
119 561297 : switch (myType) {
120 58075 : 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 58075 : if (!myActiveLogic.empty()) {
126 120 : WRITE_WARNINGF(TL("Ignoring junction logic for junction '%'."), myActiveID)
127 : }
128 58075 : junction = buildNoLogicJunction();
129 58075 : break;
130 314363 : 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 314363 : junction = buildLogicJunction(new MSBitsetLogic(myRequestSize, myActiveLogic, myActiveFoes, myActiveConts));
139 : break;
140 185245 : case SumoXMLNodeType::INTERNAL:
141 185245 : if (MSGlobals::gUsingInternalLanes) {
142 152444 : if (!myActiveLogic.empty()) {
143 18 : WRITE_WARNINGF(TL("Ignoring junction logic for junction '%'."), myActiveID)
144 : }
145 152444 : junction = buildInternalJunction();
146 : }
147 : break;
148 3614 : case SumoXMLNodeType::RAIL_SIGNAL:
149 : case SumoXMLNodeType::RAIL_CROSSING:
150 3614 : myOffset = 0;
151 3614 : myActiveKey = myActiveID;
152 3614 : myActiveProgram = "0";
153 3614 : myLogicType = myType == SumoXMLNodeType::RAIL_SIGNAL ? TrafficLightType::RAIL_SIGNAL : TrafficLightType::RAIL_CROSSING;
154 3614 : closeTrafficLightLogic(basePath);
155 3614 : junction = buildLogicJunction(new MSBitsetLogic(myRequestSize, myActiveLogic, myActiveFoes, myActiveConts));
156 : break;
157 0 : default:
158 0 : throw InvalidArgument("False junction logic type.");
159 : }
160 528496 : if (junction != nullptr) {
161 528496 : if (!myJunctions->add(myActiveID, junction)) {
162 12 : throw InvalidArgument("Another junction with the id '" + myActiveID + "' exists.");
163 : }
164 528490 : junction->updateParameters(myAdditionalParameter);
165 : }
166 : }
167 :
168 :
169 : MSJunctionControl*
170 42486 : NLJunctionControlBuilder::build() const {
171 42486 : MSJunctionControl* js = myJunctions;
172 42486 : myJunctions = nullptr;
173 42486 : return js;
174 : }
175 :
176 :
177 : MSJunction*
178 58075 : NLJunctionControlBuilder::buildNoLogicJunction() {
179 58075 : return new MSNoLogicJunction(myActiveID, myType, myPosition, myShape, myActiveName,
180 58075 : myActiveIncomingLanes, myActiveInternalLanes);
181 : }
182 :
183 :
184 : MSJunction*
185 317977 : NLJunctionControlBuilder::buildLogicJunction(MSJunctionLogic* const logic) {
186 317977 : return new MSRightOfWayJunction(myActiveID, myType, myPosition, myShape, myActiveName,
187 317977 : myActiveIncomingLanes, myActiveInternalLanes, logic);
188 : }
189 :
190 :
191 : MSJunction*
192 152444 : NLJunctionControlBuilder::buildInternalJunction() {
193 : // build the junction
194 304888 : return new MSInternalJunction(myActiveID, myType, myPosition, myShape, myActiveIncomingLanes,
195 152444 : myActiveInternalLanes);
196 : }
197 :
198 :
199 : MSTLLogicControl::TLSLogicVariants&
200 1594559 : NLJunctionControlBuilder::getTLLogic(const std::string& id) const {
201 1594559 : return getTLLogicControlToUse().get(id);
202 : }
203 :
204 :
205 : void
206 113605 : NLJunctionControlBuilder::closeTrafficLightLogic(const std::string& basePath) {
207 113605 : 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 113568 : MSTrafficLightLogic* existing = getTLLogicControlToUse().get(myActiveKey, myActiveProgram);
221 113568 : if (existing != nullptr && (existing->getLogicType() == TrafficLightType::RAIL_SIGNAL || existing->getLogicType() == TrafficLightType::RAIL_CROSSING)) {
222 35 : existing->updateParameters(myAdditionalParameter);
223 35 : return;
224 : } else {
225 113533 : if (myLogicType != TrafficLightType::RAIL_SIGNAL && myLogicType != TrafficLightType::RAIL_CROSSING) {
226 109919 : 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 109824 : } 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 109917 : if (myOffset >= 0) {
242 109858 : offset = (myNet.getCurrentTimeStep() + myAbsDuration - (myOffset % myAbsDuration)) % myAbsDuration;
243 : } else {
244 59 : offset = (myNet.getCurrentTimeStep() + ((-myOffset) % myAbsDuration)) % myAbsDuration;
245 : }
246 111143 : while (offset >= (*i)->duration) {
247 1226 : step++;
248 1226 : offset -= (*i)->duration;
249 : ++i;
250 : }
251 109917 : firstEventOffset = (*i)->duration - offset + myNet.getCurrentTimeStep();
252 109917 : 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 113437 : if (myActiveProgram == "") {
265 : myActiveProgram = "default";
266 : }
267 113437 : MSTrafficLightLogic* tlLogic = nullptr;
268 : // build the tls-logic in dependence to its type
269 113437 : 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 479 : case TrafficLightType::ACTUATED:
293 : // @note it is unclear how to apply the given offset in the context
294 : // of variable-length phases
295 479 : tlLogic = new MSActuatedTrafficLightLogic(getTLLogicControlToUse(),
296 : myActiveKey, myActiveProgram, myOffset,
297 479 : myActivePhases, step, (*i)->minDuration + myNet.getCurrentTimeStep(),
298 479 : myAdditionalParameter, basePath, myActiveConditions, myActiveAssignments, myActiveFunctions);
299 479 : 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 109057 : case TrafficLightType::STATIC:
313 109057 : tlLogic = new MSSimpleTrafficLightLogic(getTLLogicControlToUse(),
314 : myActiveKey, myActiveProgram, myOffset,
315 : TrafficLightType::STATIC,
316 109057 : myActivePhases, step, firstEventOffset,
317 109057 : myAdditionalParameter);
318 109057 : break;
319 3481 : case TrafficLightType::RAIL_SIGNAL:
320 3481 : tlLogic = new MSRailSignal(getTLLogicControlToUse(),
321 3481 : myActiveKey, myActiveProgram, myNet.getCurrentTimeStep(),
322 3481 : myAdditionalParameter);
323 3481 : 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 113437 : if (tlLogic != nullptr) {
337 113437 : if (getTLLogicControlToUse().add(myActiveKey, myActiveProgram, tlLogic)) {
338 113431 : if (myNetIsLoaded) {
339 14091 : myAdditionalLogics.push_back(tlLogic);
340 99340 : } 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 3481 : myRailSignals.push_back(tlLogic);
344 : } else {
345 95859 : 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 561297 : NLJunctionControlBuilder::initJunctionLogic(const std::string& id) {
356 561297 : myActiveKey = id;
357 561297 : myActiveProgram = "";
358 : myActiveLogic.clear();
359 : myActiveFoes.clear();
360 : myActiveConts.reset();
361 561297 : myRequestSize = NO_REQUEST_SIZE; // seems not to be used
362 561297 : myRequestItemNumber = 0;
363 561297 : myCurrentHasError = false;
364 561297 : }
365 :
366 :
367 : void
368 1615306 : NLJunctionControlBuilder::addLogicItem(int request,
369 : const std::string& response,
370 : const std::string& foes,
371 : bool cont) {
372 1615306 : if (myCurrentHasError) {
373 : // had an error
374 : return;
375 : }
376 1615306 : 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 1615306 : if (myRequestSize == NO_REQUEST_SIZE) {
382 : // initialize
383 318023 : myRequestSize = (int)response.size();
384 : }
385 1615306 : 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 1615306 : 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 1615306 : myActiveLogic.push_back(std::bitset<SUMO_MAX_CONNECTIONS>(response));
400 : // add the read junction-internal foes for the given request index
401 1615306 : myActiveFoes.push_back(std::bitset<SUMO_MAX_CONNECTIONS>(foes));
402 : // add whether the vehicle may drive a little bit further
403 1615306 : myActiveConts.set(request, cont);
404 : // increse number of set information
405 1615306 : myRequestItemNumber++;
406 : }
407 :
408 :
409 : void
410 109991 : NLJunctionControlBuilder::initTrafficLightLogic(const std::string& id, const std::string& programID,
411 : TrafficLightType type, SUMOTime offset) {
412 109991 : myActiveKey = id;
413 109991 : myActiveProgram = programID;
414 : myActivePhases.clear();
415 : myActiveConditions.clear();
416 : myActiveAssignments.clear();
417 : myActiveFunctions.clear();
418 109991 : myAbsDuration = 0;
419 109991 : myRequestSize = NO_REQUEST_SIZE;
420 109991 : myLogicType = type;
421 109991 : myOffset = offset;
422 : myAdditionalParameter.clear();
423 109991 : }
424 :
425 :
426 : void
427 514145 : NLJunctionControlBuilder::addPhase(MSPhaseDefinition* phase) {
428 : // build and add the phase definition to the list
429 514145 : myActivePhases.push_back(phase);
430 : // add phase duration to the absolute duration
431 514145 : myAbsDuration += phase->duration;
432 514145 : }
433 :
434 :
435 : bool
436 92 : NLJunctionControlBuilder::addCondition(const std::string& id, const std::string& value) {
437 : if (myActiveConditions.count(id) == 0) {
438 92 : myActiveConditions[id] = value;
439 92 : 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 42476 : NLJunctionControlBuilder::buildTLLogics() {
473 42476 : if (!myLogicControl->closeNetworkReading()) {
474 0 : throw ProcessError(TL("Traffic lights could not be built."));
475 : }
476 45957 : for (MSTrafficLightLogic* const logic : myRailSignals) {
477 3481 : logic->init(myDetectorBuilder);
478 : }
479 42476 : MSTLLogicControl* ret = myLogicControl;
480 42476 : myNetIsLoaded = true;
481 42476 : myLogicControl = nullptr;
482 42476 : return ret;
483 : }
484 :
485 :
486 : void
487 10279 : NLJunctionControlBuilder::addParam(const std::string& key,
488 : const std::string& value) {
489 10279 : myAdditionalParameter[key] = value;
490 10279 : }
491 :
492 :
493 : MSTLLogicControl&
494 2045662 : NLJunctionControlBuilder::getTLLogicControlToUse() const {
495 2045662 : if (myLogicControl != nullptr) {
496 : return *myLogicControl;
497 : }
498 57916 : return myNet.getTLSControl();
499 : }
500 :
501 :
502 : const std::string&
503 1028293 : NLJunctionControlBuilder::getActiveKey() const {
504 1028293 : return myActiveKey;
505 : }
506 :
507 :
508 : const std::string&
509 1 : NLJunctionControlBuilder::getActiveSubKey() const {
510 1 : return myActiveProgram;
511 : }
512 :
513 :
514 : void
515 41725 : NLJunctionControlBuilder::postLoadInitialization() {
516 129824 : for (MSTrafficLightLogic* const logic : myNetworkLogics) {
517 88125 : logic->init(myDetectorBuilder);
518 : }
519 55770 : for (MSTrafficLightLogic* const logic : myAdditionalLogics) {
520 14076 : logic->init(myDetectorBuilder);
521 : }
522 : // delay parameter loading until initialization
523 41787 : for (auto item : myLogicParams) {
524 93 : item.first->updateParameters(item.second);
525 : }
526 41694 : }
527 :
528 :
529 : MSJunction*
530 3469142 : NLJunctionControlBuilder::retrieve(const std::string id) {
531 3469142 : if (myJunctions != nullptr) {
532 : return myJunctions->get(id);
533 : } else {
534 : return nullptr;
535 : }
536 : }
537 :
538 :
539 : /****************************************************************************/
|