Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2026 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 41511 : NLJunctionControlBuilder::NLJunctionControlBuilder(MSNet& net, NLDetectorBuilder& db) :
70 41511 : myNet(net),
71 41511 : myDetectorBuilder(db),
72 41511 : myOffset(0),
73 41511 : myJunctions(new MSJunctionControl()),
74 166044 : myNetIsLoaded(false) {
75 41511 : myLogicControl = new MSTLLogicControl();
76 41511 : }
77 :
78 :
79 41511 : NLJunctionControlBuilder::~NLJunctionControlBuilder() {
80 41511 : delete myLogicControl;
81 41511 : delete myJunctions;
82 124533 : }
83 :
84 :
85 : void
86 551772 : 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 551772 : myActiveInternalLanes = internalLanes;
95 551772 : myActiveIncomingLanes = incomingLanes;
96 551772 : myActiveID = id;
97 551772 : myActiveKey = key;
98 551772 : myType = type;
99 : myPosition.set(pos);
100 : myShape = shape;
101 551772 : myActiveName = name;
102 : myAdditionalParameter.clear();
103 551772 : }
104 :
105 :
106 : void
107 551772 : NLJunctionControlBuilder::closeJunction(const std::string& basePath) {
108 551772 : if (myCurrentHasError) {
109 : // had an error before...
110 : return;
111 : }
112 551772 : if (myRequestSize != NO_REQUEST_SIZE && myRequestItemNumber != myRequestSize) {
113 0 : throw InvalidArgument("The description for the junction logic '" + myActiveKey + "' is malicious.");
114 : }
115 551772 : if (myJunctions == nullptr) {
116 0 : throw ProcessError(TL("Information about the number of nodes was missing."));
117 : }
118 : MSJunction* junction = nullptr;
119 551772 : switch (myType) {
120 63126 : 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 63126 : if (!myActiveLogic.empty()) {
126 120 : WRITE_WARNINGF(TL("Ignoring junction logic for junction '%'."), myActiveID)
127 : }
128 63126 : junction = buildNoLogicJunction();
129 63126 : break;
130 295481 : 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 295481 : junction = buildLogicJunction(new MSBitsetLogic(myRequestSize, myActiveLogic, myActiveFoes, myActiveConts));
139 : break;
140 188303 : case SumoXMLNodeType::INTERNAL:
141 188303 : if (MSGlobals::gUsingInternalLanes) {
142 148548 : if (!myActiveLogic.empty()) {
143 18 : WRITE_WARNINGF(TL("Ignoring junction logic for junction '%'."), myActiveID)
144 : }
145 148548 : junction = buildInternalJunction();
146 : }
147 : break;
148 4862 : case SumoXMLNodeType::RAIL_SIGNAL:
149 : case SumoXMLNodeType::RAIL_CROSSING:
150 4862 : myOffset = 0;
151 4862 : myActiveKey = myActiveID;
152 4862 : myActiveProgram = "0";
153 4862 : myLogicType = myType == SumoXMLNodeType::RAIL_SIGNAL ? TrafficLightType::RAIL_SIGNAL : TrafficLightType::RAIL_CROSSING;
154 4862 : closeTrafficLightLogic(basePath);
155 4862 : junction = buildLogicJunction(new MSBitsetLogic(myRequestSize, myActiveLogic, myActiveFoes, myActiveConts));
156 : break;
157 0 : default:
158 0 : throw InvalidArgument("False junction logic type.");
159 : }
160 512017 : if (junction != nullptr) {
161 512017 : if (!myJunctions->add(myActiveID, junction)) {
162 6 : delete junction;
163 18 : throw InvalidArgument("Another junction with the id '" + myActiveID + "' exists.");
164 : }
165 512011 : junction->updateParameters(myAdditionalParameter);
166 : }
167 : }
168 :
169 :
170 : MSJunctionControl*
171 41170 : NLJunctionControlBuilder::build() const {
172 41170 : MSJunctionControl* js = myJunctions;
173 41170 : myJunctions = nullptr;
174 41170 : return js;
175 : }
176 :
177 :
178 : MSJunction*
179 63126 : NLJunctionControlBuilder::buildNoLogicJunction() {
180 63126 : return new MSNoLogicJunction(myActiveID, myType, myPosition, myShape, myActiveName,
181 63126 : myActiveIncomingLanes, myActiveInternalLanes);
182 : }
183 :
184 :
185 : MSJunction*
186 300343 : NLJunctionControlBuilder::buildLogicJunction(MSJunctionLogic* const logic) {
187 300343 : return new MSRightOfWayJunction(myActiveID, myType, myPosition, myShape, myActiveName,
188 300343 : myActiveIncomingLanes, myActiveInternalLanes, logic);
189 : }
190 :
191 :
192 : MSJunction*
193 148548 : NLJunctionControlBuilder::buildInternalJunction() {
194 : // build the junction
195 297096 : return new MSInternalJunction(myActiveID, myType, myPosition, myShape, myActiveIncomingLanes,
196 148548 : myActiveInternalLanes);
197 : }
198 :
199 :
200 : MSTLLogicControl::TLSLogicVariants&
201 1739681 : NLJunctionControlBuilder::getTLLogic(const std::string& id) const {
202 1739681 : return getTLLogicControlToUse().get(id);
203 : }
204 :
205 :
206 : void
207 121873 : NLJunctionControlBuilder::closeTrafficLightLogic(const std::string& basePath) {
208 121873 : if (myActiveProgram == "off") {
209 38 : if (myAbsDuration > 0) {
210 0 : throw InvalidArgument("The off program for TLS '" + myActiveKey + "' has phases.");
211 : }
212 38 : MSOffTrafficLightLogic* off = new MSOffTrafficLightLogic(getTLLogicControlToUse(), myActiveKey);
213 38 : if (!getTLLogicControlToUse().add(myActiveKey, myActiveProgram, off)) {
214 0 : throw InvalidArgument("Another logic with id '" + myActiveKey + "' and programID '" + myActiveProgram + "' exists.");
215 : }
216 189 : return;
217 : }
218 : SUMOTime firstEventOffset = 0;
219 : int step = 0;
220 : MSSimpleTrafficLightLogic::Phases::const_iterator i = myActivePhases.begin();
221 121835 : MSTrafficLightLogic* existing = getTLLogicControlToUse().get(myActiveKey, myActiveProgram);
222 121835 : if (existing != nullptr && (existing->getLogicType() == TrafficLightType::RAIL_SIGNAL || existing->getLogicType() == TrafficLightType::RAIL_CROSSING)) {
223 35 : existing->updateParameters(myAdditionalParameter);
224 35 : return;
225 : } else {
226 121800 : if (myLogicType != TrafficLightType::RAIL_SIGNAL && myLogicType != TrafficLightType::RAIL_CROSSING) {
227 116938 : if (myAbsDuration == 0) {
228 118 : if (existing == nullptr) {
229 6 : throw InvalidArgument("TLS program '" + myActiveProgram + "' for TLS '" + myActiveKey + "' has a duration of 0.");
230 : } else {
231 : // only modify the offset of an existing logic
232 116 : myAbsDuration = existing->getDefaultCycleTime();
233 116 : i = existing->getPhases().begin();
234 : }
235 116820 : } else if (existing != nullptr) {
236 6 : throw InvalidArgument("Another logic with id '" + myActiveKey + "' and programID '" + myActiveProgram + "' exists.");
237 : }
238 : // compute the initial step and first switch time of the tls-logic
239 : // a positive offset delays all phases by x (advance by absDuration - x) while a negative offset advances all phases by x seconds
240 : // @note The implementation of % for negative values is implementation defined in ISO1998
241 : SUMOTime offset; // the time to run the traffic light in advance
242 116934 : if (myOffset >= 0) {
243 116821 : offset = (myNet.getCurrentTimeStep() + myAbsDuration - (myOffset % myAbsDuration)) % myAbsDuration;
244 : } else {
245 113 : offset = (myNet.getCurrentTimeStep() + ((-myOffset) % myAbsDuration)) % myAbsDuration;
246 : }
247 118629 : while (offset >= (*i)->duration) {
248 1695 : step++;
249 1695 : offset -= (*i)->duration;
250 : ++i;
251 : }
252 116934 : firstEventOffset = (*i)->duration - offset + myNet.getCurrentTimeStep();
253 116934 : if (existing != nullptr) {
254 116 : existing->changeStepAndDuration(getTLLogicControlToUse(),
255 : myNet.getCurrentTimeStep(), step, (*i)->duration - offset);
256 : // parameters that are used when initializing a logic will not take
257 : // effect but parameters that are checked at runtime can be used
258 : // here (i.e. device.glosa.range)
259 116 : myLogicParams[existing] = myAdditionalParameter;
260 : if (myAdditionalParameter.count(MESegment::OVERRIDE_TLS_PENALTIES) != 0) {
261 : // value must be available when calling setMesoTypes and before setting the rest in postLoadInitialization
262 4 : existing->setParameter(MESegment::OVERRIDE_TLS_PENALTIES, myAdditionalParameter[MESegment::OVERRIDE_TLS_PENALTIES]);
263 : }
264 116 : return;
265 : }
266 : }
267 : }
268 :
269 121680 : if (myActiveProgram == "") {
270 : myActiveProgram = "default";
271 : }
272 121680 : MSTrafficLightLogic* tlLogic = nullptr;
273 : // build the tls-logic in dependence to its type
274 121680 : switch (myLogicType) {
275 16 : case TrafficLightType::SWARM_BASED:
276 16 : firstEventOffset = DELTA_T; //this is needed because swarm needs to update the pheromone on the lanes at every step
277 16 : tlLogic = new MSSwarmTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myActivePhases, step, firstEventOffset, myAdditionalParameter);
278 16 : break;
279 0 : case TrafficLightType::HILVL_DETERMINISTIC:
280 0 : tlLogic = new MSDeterministicHiLevelTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myActivePhases, step, firstEventOffset, myAdditionalParameter);
281 0 : break;
282 16 : case TrafficLightType::SOTL_REQUEST:
283 16 : tlLogic = new MSSOTLPolicyBasedTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myLogicType, myActivePhases, step, firstEventOffset, myAdditionalParameter, new MSSOTLRequestPolicy(myAdditionalParameter));
284 16 : break;
285 16 : case TrafficLightType::SOTL_PLATOON:
286 16 : tlLogic = new MSSOTLPolicyBasedTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myLogicType, myActivePhases, step, firstEventOffset, myAdditionalParameter, new MSSOTLPlatoonPolicy(myAdditionalParameter));
287 16 : break;
288 16 : case TrafficLightType::SOTL_WAVE:
289 16 : tlLogic = new MSSOTLWaveTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myActivePhases, step, firstEventOffset, myAdditionalParameter);
290 16 : break;
291 16 : case TrafficLightType::SOTL_PHASE:
292 16 : tlLogic = new MSSOTLPolicyBasedTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myLogicType, myActivePhases, step, firstEventOffset, myAdditionalParameter, new MSSOTLPhasePolicy(myAdditionalParameter));
293 16 : break;
294 16 : case TrafficLightType::SOTL_MARCHING:
295 16 : tlLogic = new MSSOTLPolicyBasedTrafficLightLogic(getTLLogicControlToUse(), myActiveKey, myActiveProgram, myLogicType, myActivePhases, step, firstEventOffset, myAdditionalParameter, new MSSOTLMarchingPolicy(myAdditionalParameter));
296 16 : break;
297 637 : case TrafficLightType::ACTUATED:
298 : // @note it is unclear how to apply the given offset in the context
299 : // of variable-length phases
300 637 : tlLogic = new MSActuatedTrafficLightLogic(getTLLogicControlToUse(),
301 : myActiveKey, myActiveProgram, myOffset,
302 637 : myActivePhases, step, (*i)->minDuration + myNet.getCurrentTimeStep(),
303 637 : myAdditionalParameter, basePath, myActiveConditions, myActiveAssignments, myActiveFunctions);
304 637 : break;
305 122 : case TrafficLightType::NEMA:
306 122 : tlLogic = new NEMALogic(getTLLogicControlToUse(),
307 : myActiveKey, myActiveProgram, myOffset,
308 122 : myActivePhases, step, (*i)->minDuration + myNet.getCurrentTimeStep(),
309 122 : myAdditionalParameter, basePath);
310 122 : break;
311 170 : case TrafficLightType::DELAYBASED:
312 170 : tlLogic = new MSDelayBasedTrafficLightLogic(getTLLogicControlToUse(),
313 : myActiveKey, myActiveProgram, myOffset,
314 170 : myActivePhases, step, (*i)->minDuration + myNet.getCurrentTimeStep(),
315 170 : myAdditionalParameter, basePath);
316 170 : break;
317 115793 : case TrafficLightType::STATIC:
318 115793 : tlLogic = new MSSimpleTrafficLightLogic(getTLLogicControlToUse(),
319 : myActiveKey, myActiveProgram, myOffset,
320 : TrafficLightType::STATIC,
321 115793 : myActivePhases, step, firstEventOffset,
322 115793 : myAdditionalParameter);
323 115793 : break;
324 4723 : case TrafficLightType::RAIL_SIGNAL:
325 4723 : tlLogic = new MSRailSignal(getTLLogicControlToUse(),
326 4723 : myActiveKey, myActiveProgram, myNet.getCurrentTimeStep(),
327 4723 : myAdditionalParameter);
328 4723 : break;
329 139 : case TrafficLightType::RAIL_CROSSING:
330 139 : tlLogic = new MSRailCrossing(getTLLogicControlToUse(),
331 139 : myActiveKey, myActiveProgram, myNet.getCurrentTimeStep(),
332 139 : myAdditionalParameter);
333 139 : break;
334 0 : case TrafficLightType::OFF:
335 0 : tlLogic = new MSOffTrafficLightLogic(getTLLogicControlToUse(), myActiveKey);
336 0 : break;
337 0 : case TrafficLightType::INVALID:
338 0 : throw ProcessError(TLF("Invalid traffic light type '%'", toString(myLogicType)));
339 : }
340 : myActivePhases.clear();
341 121680 : if (tlLogic != nullptr) {
342 121680 : if (getTLLogicControlToUse().add(myActiveKey, myActiveProgram, tlLogic)) {
343 121674 : if (myNetIsLoaded) {
344 9521 : myAdditionalLogics.push_back(tlLogic);
345 112153 : } else if (myLogicType == TrafficLightType::RAIL_SIGNAL) {
346 : // special case: intialize earlier because signals are already used when
347 : // loading train routes in additional files
348 4723 : myRailSignals.push_back(tlLogic);
349 : } else {
350 107430 : myNetworkLogics.push_back(tlLogic);
351 : }
352 : } else {
353 0 : WRITE_ERRORF(TL("Another logic with id '%' and programID '%' exists."), myActiveKey, myActiveProgram);
354 : }
355 : }
356 : }
357 :
358 :
359 : void
360 551772 : NLJunctionControlBuilder::initJunctionLogic(const std::string& id) {
361 551772 : myActiveKey = id;
362 551772 : myActiveProgram = "";
363 : myActiveLogic.clear();
364 : myActiveFoes.clear();
365 : myActiveConts.reset();
366 551772 : myRequestSize = NO_REQUEST_SIZE; // seems not to be used
367 551772 : myRequestItemNumber = 0;
368 551772 : myCurrentHasError = false;
369 551772 : }
370 :
371 :
372 : void
373 1581513 : NLJunctionControlBuilder::addLogicItem(int request,
374 : const std::string& response,
375 : const std::string& foes,
376 : bool cont) {
377 1581513 : if (myCurrentHasError) {
378 : // had an error
379 : return;
380 : }
381 1581513 : if (request >= SUMO_MAX_CONNECTIONS) {
382 : // bad request
383 0 : myCurrentHasError = true;
384 0 : throw InvalidArgument("Junction logic '" + myActiveKey + "' is larger than allowed; recheck the network.");
385 : }
386 1581513 : if (myRequestSize == NO_REQUEST_SIZE) {
387 : // initialize
388 300389 : myRequestSize = (int)response.size();
389 : }
390 1581513 : if (static_cast<int>(response.size()) != myRequestSize) {
391 0 : myCurrentHasError = true;
392 0 : throw InvalidArgument("Invalid response size " + toString(response.size()) +
393 0 : " in Junction logic '" + myActiveKey + "' (expected " + toString(myRequestSize) + ")");
394 : }
395 1581513 : if (static_cast<int>(foes.size()) != myRequestSize) {
396 0 : myCurrentHasError = true;
397 0 : throw InvalidArgument("Invalid foes size " + toString(foes.size()) +
398 0 : " in Junction logic '" + myActiveKey + "' (expected " + toString(myRequestSize) + ")");
399 : }
400 : // assert that the logicitems come ordered by their request index
401 : assert((int)myActiveLogic.size() == request);
402 : assert((int)myActiveFoes.size() == request);
403 : // add the read response for the given request index
404 1581513 : myActiveLogic.push_back(std::bitset<SUMO_MAX_CONNECTIONS>(response));
405 : // add the read junction-internal foes for the given request index
406 1581513 : myActiveFoes.push_back(std::bitset<SUMO_MAX_CONNECTIONS>(foes));
407 : // add whether the vehicle may drive a little bit further
408 1581513 : myActiveConts.set(request, cont);
409 : // increse number of set information
410 1581513 : myRequestItemNumber++;
411 : }
412 :
413 :
414 : void
415 117011 : NLJunctionControlBuilder::initTrafficLightLogic(const std::string& id, const std::string& programID,
416 : TrafficLightType type, SUMOTime offset) {
417 117011 : myActiveKey = id;
418 117011 : myActiveProgram = programID;
419 : myActivePhases.clear();
420 : myActiveConditions.clear();
421 : myActiveAssignments.clear();
422 : myActiveFunctions.clear();
423 117011 : myAbsDuration = 0;
424 117011 : myRequestSize = NO_REQUEST_SIZE;
425 117011 : myLogicType = type;
426 117011 : myOffset = offset;
427 : myAdditionalParameter.clear();
428 117011 : }
429 :
430 :
431 : void
432 593152 : NLJunctionControlBuilder::addPhase(MSPhaseDefinition* phase) {
433 : // build and add the phase definition to the list
434 593152 : myActivePhases.push_back(phase);
435 : // add phase duration to the absolute duration
436 593152 : myAbsDuration += phase->duration;
437 593152 : }
438 :
439 :
440 : bool
441 178 : NLJunctionControlBuilder::addCondition(const std::string& id, const std::string& value) {
442 : if (myActiveConditions.count(id) == 0) {
443 178 : myActiveConditions[id] = value;
444 178 : return true;
445 : } else {
446 0 : return false;
447 : }
448 : }
449 :
450 :
451 : void
452 120 : NLJunctionControlBuilder::addAssignment(const std::string& id, const std::string& check, const std::string& value) {
453 120 : if (myActiveFunction.id == "") {
454 204 : myActiveAssignments.push_back(std::make_tuple(id, check, value));
455 : } else {
456 36 : myActiveFunction.assignments.push_back(std::make_tuple(id, check, value));
457 : }
458 120 : }
459 :
460 :
461 : void
462 8 : NLJunctionControlBuilder::addFunction(const std::string& id, int nArgs) {
463 8 : myActiveFunction.id = id;
464 8 : myActiveFunction.nArgs = nArgs;
465 8 : }
466 :
467 :
468 : void
469 8 : NLJunctionControlBuilder::closeFunction() {
470 8 : myActiveFunctions[myActiveFunction.id] = myActiveFunction;
471 : myActiveFunction.id = "";
472 : myActiveFunction.assignments.clear();
473 8 : }
474 :
475 :
476 : MSTLLogicControl*
477 41045 : NLJunctionControlBuilder::buildTLLogics() {
478 41045 : if (!myLogicControl->closeNetworkReading()) {
479 0 : throw ProcessError(TL("Traffic lights could not be built."));
480 : }
481 45768 : for (MSTrafficLightLogic* const logic : myRailSignals) {
482 4723 : logic->init(myDetectorBuilder);
483 : }
484 41045 : MSTLLogicControl* ret = myLogicControl;
485 41045 : myNetIsLoaded = true;
486 41045 : myLogicControl = nullptr;
487 41045 : return ret;
488 : }
489 :
490 :
491 : void
492 10874 : NLJunctionControlBuilder::addParam(const std::string& key,
493 : const std::string& value) {
494 10874 : myAdditionalParameter[key] = value;
495 10874 : }
496 :
497 :
498 : MSTLLogicControl&
499 2223000 : NLJunctionControlBuilder::getTLLogicControlToUse() const {
500 2223000 : if (myLogicControl != nullptr) {
501 : return *myLogicControl;
502 : }
503 40126 : return myNet.getTLSControl();
504 : }
505 :
506 :
507 : const std::string&
508 1186310 : NLJunctionControlBuilder::getActiveKey() const {
509 1186310 : return myActiveKey;
510 : }
511 :
512 :
513 : const std::string&
514 2 : NLJunctionControlBuilder::getActiveSubKey() const {
515 2 : return myActiveProgram;
516 : }
517 :
518 :
519 : void
520 40267 : NLJunctionControlBuilder::postLoadInitialization() {
521 139616 : for (MSTrafficLightLogic* const logic : myNetworkLogics) {
522 99359 : logic->init(myDetectorBuilder);
523 : }
524 49738 : for (MSTrafficLightLogic* const logic : myAdditionalLogics) {
525 9491 : logic->init(myDetectorBuilder);
526 : }
527 : // delay parameter loading until initialization
528 40361 : for (auto item : myLogicParams) {
529 114 : item.first->updateParameters(item.second);
530 : }
531 40247 : }
532 :
533 :
534 : MSJunction*
535 3441214 : NLJunctionControlBuilder::retrieve(const std::string id) {
536 3441214 : if (myJunctions != nullptr) {
537 : return myJunctions->get(id);
538 : } else {
539 : return nullptr;
540 : }
541 : }
542 :
543 :
544 : /****************************************************************************/
|