LCOV - code coverage report
Current view: top level - src/netload - NLJunctionControlBuilder.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 90.0 % 251 226
Test Date: 2026-04-16 16:39:47 Functions: 96.2 % 26 25

            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        41777 : NLJunctionControlBuilder::NLJunctionControlBuilder(MSNet& net, NLDetectorBuilder& db) :
      70        41777 :     myNet(net),
      71        41777 :     myDetectorBuilder(db),
      72        41777 :     myOffset(0),
      73        41777 :     myJunctions(new MSJunctionControl()),
      74       167108 :     myNetIsLoaded(false) {
      75        41777 :     myLogicControl = new MSTLLogicControl();
      76        41777 : }
      77              : 
      78              : 
      79        41777 : NLJunctionControlBuilder::~NLJunctionControlBuilder() {
      80        41777 :     delete myLogicControl;
      81        41777 :     delete myJunctions;
      82       125331 : }
      83              : 
      84              : 
      85              : void
      86       555770 : 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       555770 :     myActiveInternalLanes = internalLanes;
      95       555770 :     myActiveIncomingLanes = incomingLanes;
      96       555770 :     myActiveID = id;
      97       555770 :     myActiveKey = key;
      98       555770 :     myType = type;
      99              :     myPosition.set(pos);
     100              :     myShape = shape;
     101       555770 :     myActiveName = name;
     102              :     myAdditionalParameter.clear();
     103       555770 : }
     104              : 
     105              : 
     106              : void
     107       555770 : NLJunctionControlBuilder::closeJunction(const std::string& basePath) {
     108       555770 :     if (myCurrentHasError) {
     109              :         // had an error before...
     110              :         return;
     111              :     }
     112       555770 :     if (myRequestSize != NO_REQUEST_SIZE && myRequestItemNumber != myRequestSize) {
     113            0 :         throw InvalidArgument("The description for the junction logic '" + myActiveKey + "' is malicious.");
     114              :     }
     115       555770 :     if (myJunctions == nullptr) {
     116            0 :         throw ProcessError(TL("Information about the number of nodes was missing."));
     117              :     }
     118              :     MSJunction* junction = nullptr;
     119       555770 :     switch (myType) {
     120        63463 :         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        63463 :             if (!myActiveLogic.empty()) {
     126          120 :                 WRITE_WARNINGF(TL("Ignoring junction logic for junction '%'."), myActiveID)
     127              :             }
     128        63463 :             junction = buildNoLogicJunction();
     129        63463 :             break;
     130       297315 :         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       297315 :             junction = buildLogicJunction(new MSBitsetLogic(myRequestSize, myActiveLogic, myActiveFoes, myActiveConts));
     139              :             break;
     140       189788 :         case SumoXMLNodeType::INTERNAL:
     141       189788 :             if (MSGlobals::gUsingInternalLanes) {
     142       189715 :                 if (!myActiveLogic.empty()) {
     143           18 :                     WRITE_WARNINGF(TL("Ignoring junction logic for junction '%'."), myActiveID)
     144              :                 }
     145       189715 :                 junction = buildInternalJunction();
     146              :             }
     147              :             break;
     148         5204 :         case SumoXMLNodeType::RAIL_SIGNAL:
     149              :         case SumoXMLNodeType::RAIL_CROSSING:
     150         5204 :             myOffset = 0;
     151         5204 :             myActiveKey = myActiveID;
     152         5204 :             myActiveProgram = "0";
     153         5204 :             myLogicType = myType == SumoXMLNodeType::RAIL_SIGNAL ? TrafficLightType::RAIL_SIGNAL : TrafficLightType::RAIL_CROSSING;
     154         5204 :             closeTrafficLightLogic(basePath);
     155         5204 :             junction = buildLogicJunction(new MSBitsetLogic(myRequestSize, myActiveLogic, myActiveFoes, myActiveConts));
     156              :             break;
     157            0 :         default:
     158            0 :             throw InvalidArgument("False junction logic type.");
     159              :     }
     160       555697 :     if (junction != nullptr) {
     161       555697 :         if (!myJunctions->add(myActiveID, junction)) {
     162            6 :             delete junction;
     163           18 :             throw InvalidArgument("Another junction with the id '" + myActiveID + "' exists.");
     164              :         }
     165       555691 :         junction->updateParameters(myAdditionalParameter);
     166              :     }
     167              : }
     168              : 
     169              : 
     170              : MSJunctionControl*
     171        41436 : NLJunctionControlBuilder::build() const {
     172        41436 :     MSJunctionControl* js = myJunctions;
     173        41436 :     myJunctions = nullptr;
     174        41436 :     return js;
     175              : }
     176              : 
     177              : 
     178              : MSJunction*
     179        63463 : NLJunctionControlBuilder::buildNoLogicJunction() {
     180        63463 :     return new MSNoLogicJunction(myActiveID, myType, myPosition, myShape, myActiveName,
     181        63463 :                                  myActiveIncomingLanes, myActiveInternalLanes);
     182              : }
     183              : 
     184              : 
     185              : MSJunction*
     186       302519 : NLJunctionControlBuilder::buildLogicJunction(MSJunctionLogic* const logic) {
     187       302519 :     return new MSRightOfWayJunction(myActiveID, myType, myPosition, myShape, myActiveName,
     188       302519 :                                     myActiveIncomingLanes, myActiveInternalLanes, logic);
     189              : }
     190              : 
     191              : 
     192              : MSJunction*
     193       189715 : NLJunctionControlBuilder::buildInternalJunction() {
     194              :     // build the junction
     195       379430 :     return new MSInternalJunction(myActiveID, myType, myPosition, myShape, myActiveIncomingLanes,
     196       189715 :                                   myActiveInternalLanes);
     197              : }
     198              : 
     199              : 
     200              : MSTLLogicControl::TLSLogicVariants&
     201      1745097 : NLJunctionControlBuilder::getTLLogic(const std::string& id) const {
     202      1745097 :     return getTLLogicControlToUse().get(id);
     203              : }
     204              : 
     205              : 
     206              : void
     207       122395 : NLJunctionControlBuilder::closeTrafficLightLogic(const std::string& basePath) {
     208       122395 :     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       122357 :     MSTrafficLightLogic* existing = getTLLogicControlToUse().get(myActiveKey, myActiveProgram);
     222       122357 :     if (existing != nullptr && (existing->getLogicType() == TrafficLightType::RAIL_SIGNAL || existing->getLogicType() == TrafficLightType::RAIL_CROSSING)) {
     223           35 :         existing->updateParameters(myAdditionalParameter);
     224           35 :         return;
     225              :     } else {
     226       122322 :         if (myLogicType != TrafficLightType::RAIL_SIGNAL && myLogicType != TrafficLightType::RAIL_CROSSING) {
     227       117118 :             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       117000 :             } 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       117114 :             if (myOffset >= 0) {
     243       117001 :                 offset = (myNet.getCurrentTimeStep() + myAbsDuration - (myOffset % myAbsDuration)) % myAbsDuration;
     244              :             } else {
     245          113 :                 offset = (myNet.getCurrentTimeStep() + ((-myOffset) % myAbsDuration)) % myAbsDuration;
     246              :             }
     247       118863 :             while (offset >= (*i)->duration) {
     248         1749 :                 step++;
     249         1749 :                 offset -= (*i)->duration;
     250              :                 ++i;
     251              :             }
     252       117114 :             firstEventOffset = (*i)->duration - offset + myNet.getCurrentTimeStep();
     253       117114 :             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       122202 :     if (myActiveProgram == "") {
     270              :         myActiveProgram = "default";
     271              :     }
     272       122202 :     MSTrafficLightLogic* tlLogic = nullptr;
     273              :     // build the tls-logic in dependence to its type
     274       122202 :     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       115973 :         case TrafficLightType::STATIC:
     318       115973 :             tlLogic = new MSSimpleTrafficLightLogic(getTLLogicControlToUse(),
     319              :                                                     myActiveKey, myActiveProgram, myOffset,
     320              :                                                     TrafficLightType::STATIC,
     321       115973 :                                                     myActivePhases, step, firstEventOffset,
     322       115973 :                                                     myAdditionalParameter);
     323       115973 :             break;
     324         5065 :         case TrafficLightType::RAIL_SIGNAL:
     325         5065 :             tlLogic = new MSRailSignal(getTLLogicControlToUse(),
     326         5065 :                                        myActiveKey, myActiveProgram, myNet.getCurrentTimeStep(),
     327         5065 :                                        myAdditionalParameter);
     328         5065 :             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       122202 :     if (tlLogic != nullptr) {
     342       122202 :         if (getTLLogicControlToUse().add(myActiveKey, myActiveProgram, tlLogic)) {
     343       122196 :             if (myNetIsLoaded) {
     344         9529 :                 myAdditionalLogics.push_back(tlLogic);
     345       112667 :             } 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         5065 :                 myRailSignals.push_back(tlLogic);
     349              :             } else {
     350       107602 :                 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       555770 : NLJunctionControlBuilder::initJunctionLogic(const std::string& id) {
     361       555770 :     myActiveKey = id;
     362       555770 :     myActiveProgram = "";
     363              :     myActiveLogic.clear();
     364              :     myActiveFoes.clear();
     365              :     myActiveConts.reset();
     366       555770 :     myRequestSize = NO_REQUEST_SIZE; // seems not to be used
     367       555770 :     myRequestItemNumber = 0;
     368       555770 :     myCurrentHasError = false;
     369       555770 : }
     370              : 
     371              : 
     372              : void
     373      1590999 : NLJunctionControlBuilder::addLogicItem(int request,
     374              :                                        const std::string& response,
     375              :                                        const std::string& foes,
     376              :                                        bool cont) {
     377      1590999 :     if (myCurrentHasError) {
     378              :         // had an error
     379              :         return;
     380              :     }
     381      1590999 :     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      1590999 :     if (myRequestSize == NO_REQUEST_SIZE) {
     387              :         // initialize
     388       302565 :         myRequestSize = (int)response.size();
     389              :     }
     390      1590999 :     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      1590999 :     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      1590999 :     myActiveLogic.push_back(std::bitset<SUMO_MAX_CONNECTIONS>(response));
     405              :     // add the read junction-internal foes for the given request index
     406      1590999 :     myActiveFoes.push_back(std::bitset<SUMO_MAX_CONNECTIONS>(foes));
     407              :     // add whether the vehicle may drive a little bit further
     408      1590999 :     myActiveConts.set(request, cont);
     409              :     // increse number of set information
     410      1590999 :     myRequestItemNumber++;
     411              : }
     412              : 
     413              : 
     414              : void
     415       117191 : NLJunctionControlBuilder::initTrafficLightLogic(const std::string& id, const std::string& programID,
     416              :         TrafficLightType type, SUMOTime offset) {
     417       117191 :     myActiveKey = id;
     418       117191 :     myActiveProgram = programID;
     419              :     myActivePhases.clear();
     420              :     myActiveConditions.clear();
     421              :     myActiveAssignments.clear();
     422              :     myActiveFunctions.clear();
     423       117191 :     myAbsDuration = 0;
     424       117191 :     myRequestSize = NO_REQUEST_SIZE;
     425       117191 :     myLogicType = type;
     426       117191 :     myOffset = offset;
     427              :     myAdditionalParameter.clear();
     428       117191 : }
     429              : 
     430              : 
     431              : void
     432       594231 : NLJunctionControlBuilder::addPhase(MSPhaseDefinition* phase) {
     433              :     // build and add the phase definition to the list
     434       594231 :     myActivePhases.push_back(phase);
     435              :     // add phase duration to the absolute duration
     436       594231 :     myAbsDuration += phase->duration;
     437       594231 : }
     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        41311 : NLJunctionControlBuilder::buildTLLogics() {
     478        41311 :     if (!myLogicControl->closeNetworkReading()) {
     479            0 :         throw ProcessError(TL("Traffic lights could not be built."));
     480              :     }
     481        46376 :     for (MSTrafficLightLogic* const logic : myRailSignals) {
     482         5065 :         logic->init(myDetectorBuilder);
     483              :     }
     484        41311 :     MSTLLogicControl* ret = myLogicControl;
     485        41311 :     myNetIsLoaded = true;
     486        41311 :     myLogicControl = nullptr;
     487        41311 :     return ret;
     488              : }
     489              : 
     490              : 
     491              : void
     492        10872 : NLJunctionControlBuilder::addParam(const std::string& key,
     493              :                                    const std::string& value) {
     494        10872 :     myAdditionalParameter[key] = value;
     495        10872 : }
     496              : 
     497              : 
     498              : MSTLLogicControl&
     499      2230190 : NLJunctionControlBuilder::getTLLogicControlToUse() const {
     500      2230190 :     if (myLogicControl != nullptr) {
     501              :         return *myLogicControl;
     502              :     }
     503        40186 :     return myNet.getTLSControl();
     504              : }
     505              : 
     506              : 
     507              : const std::string&
     508      1188468 : NLJunctionControlBuilder::getActiveKey() const {
     509      1188468 :     return myActiveKey;
     510              : }
     511              : 
     512              : 
     513              : const std::string&
     514            2 : NLJunctionControlBuilder::getActiveSubKey() const {
     515            2 :     return myActiveProgram;
     516              : }
     517              : 
     518              : 
     519              : void
     520        40551 : NLJunctionControlBuilder::postLoadInitialization() {
     521       140122 :     for (MSTrafficLightLogic* const logic : myNetworkLogics) {
     522        99581 :         logic->init(myDetectorBuilder);
     523              :     }
     524        50030 :     for (MSTrafficLightLogic* const logic : myAdditionalLogics) {
     525         9499 :         logic->init(myDetectorBuilder);
     526              :     }
     527              :     // delay parameter loading until initialization
     528        40645 :     for (auto item : myLogicParams) {
     529          114 :         item.first->updateParameters(item.second);
     530              :     }
     531        40531 : }
     532              : 
     533              : 
     534              : MSJunction*
     535      3498878 : NLJunctionControlBuilder::retrieve(const std::string id) {
     536      3498878 :     if (myJunctions != nullptr) {
     537              :         return myJunctions->get(id);
     538              :     } else {
     539              :         return nullptr;
     540              :     }
     541              : }
     542              : 
     543              : 
     544              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1