LCOV - code coverage report
Current view: top level - src/microsim - MSNet.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 95.5 % 958 915
Test Date: 2026-09-20 15:45:03 Functions: 95.9 % 74 71

            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    MSNet.cpp
      15              : /// @author  Christian Roessel
      16              : /// @author  Daniel Krajzewicz
      17              : /// @author  Jakob Erdmann
      18              : /// @author  Clemens Honomichl
      19              : /// @author  Eric Nicolay
      20              : /// @author  Mario Krumnow
      21              : /// @author  Michael Behrisch
      22              : /// @author  Christoph Sommer
      23              : /// @date    Tue, 06 Mar 2001
      24              : ///
      25              : // The simulated network and simulation performer
      26              : /****************************************************************************/
      27              : #include <config.h>
      28              : 
      29              : #ifdef HAVE_VERSION_H
      30              : #include <version.h>
      31              : #endif
      32              : 
      33              : #include <string>
      34              : #include <iostream>
      35              : #include <sstream>
      36              : #include <typeinfo>
      37              : #include <algorithm>
      38              : #include <cassert>
      39              : #include <vector>
      40              : #include <ctime>
      41              : 
      42              : #ifdef HAVE_FOX
      43              : #include <utils/common/ScopedLocker.h>
      44              : #endif
      45              : #include <utils/common/MsgHandler.h>
      46              : #include <utils/common/ToString.h>
      47              : #include <utils/common/SysUtils.h>
      48              : #include <utils/common/UtilExceptions.h>
      49              : #include <utils/common/WrappingCommand.h>
      50              : #include <utils/common/SystemFrame.h>
      51              : #include <utils/geom/GeoConvHelper.h>
      52              : #include <utils/iodevices/OutputDevice_File.h>
      53              : #include <utils/iodevices/OutputDevice.h>
      54              : #include <utils/options/OptionsCont.h>
      55              : #include <utils/options/OptionsIO.h>
      56              : #include <utils/shapes/ShapeContainer.h>
      57              : #include <utils/router/DijkstraRouter.h>
      58              : #include <utils/router/AStarRouter.h>
      59              : #include <utils/router/IntermodalRouter.h>
      60              : #include <utils/router/PedestrianRouter.h>
      61              : #include <utils/vehicle/SUMORouteLoaderControl.h>
      62              : #include <utils/vehicle/SUMORouteLoader.h>
      63              : #include <utils/vehicle/SUMOVehicleParserHelper.h>
      64              : #include <utils/xml/XMLSubSys.h>
      65              : #include <traci-server/TraCIServer.h>
      66              : #include <libsumo/Helper.h>
      67              : #include <libsumo/Simulation.h>
      68              : #include <mesosim/MELoop.h>
      69              : #include <mesosim/MESegment.h>
      70              : #include <microsim/output/MSDetectorControl.h>
      71              : #include <microsim/MSVehicleTransfer.h>
      72              : #include <microsim/devices/MSRoutingEngine.h>
      73              : #include <microsim/devices/MSDevice_Vehroutes.h>
      74              : #include <microsim/devices/MSDevice_Tripinfo.h>
      75              : #include <microsim/devices/MSDevice_BTsender.h>
      76              : #include <microsim/devices/MSDevice_SSM.h>
      77              : #include <microsim/devices/MSDevice_ElecHybrid.h>
      78              : #include <microsim/devices/MSDevice_ToC.h>
      79              : #include <microsim/devices/MSDevice_Taxi.h>
      80              : #include <microsim/output/MSBatteryExport.h>
      81              : #include <microsim/output/MSChargingStationExport.h>
      82              : #include <microsim/output/MSElecHybridExport.h>
      83              : #include <microsim/output/MSEmissionExport.h>
      84              : #include <microsim/output/MSFCDExport.h>
      85              : #include <microsim/output/MSFullExport.h>
      86              : #include <microsim/output/MSQueueExport.h>
      87              : #include <microsim/output/MSVTKExport.h>
      88              : #include <microsim/output/MSXMLRawOut.h>
      89              : #include <microsim/output/MSAmitranTrajectories.h>
      90              : #include <microsim/output/MSStopOut.h>
      91              : #include <microsim/transportables/MSPModel.h>
      92              : #include <microsim/transportables/MSPerson.h>
      93              : #include <microsim/traffic_lights/MSTrafficLightLogic.h>
      94              : #include <microsim/transportables/MSTransportableControl.h>
      95              : #include <microsim/traffic_lights/MSRailSignal.h>
      96              : #include <microsim/traffic_lights/MSRailSignalConstraint.h>
      97              : #include <microsim/traffic_lights/MSRailSignalControl.h>
      98              : #include <microsim/traffic_lights/MSTLLogicControl.h>
      99              : #include <microsim/traffic_lights/MSDriveWay.h>
     100              : #include <microsim/trigger/MSCalibrator.h>
     101              : #include <microsim/trigger/MSChargingStation.h>
     102              : #include <microsim/trigger/MSLaneSpeedTrigger.h>
     103              : #include <microsim/trigger/MSOverheadWire.h>
     104              : #include <microsim/trigger/MSTriggeredRerouter.h>
     105              : #include <utils/router/FareModul.h>
     106              : #include <netload/NLBuilder.h>
     107              : 
     108              : #include "MSEdgeControl.h"
     109              : #include "MSJunctionControl.h"
     110              : #include "MSInsertionControl.h"
     111              : #include "MSDynamicShapeUpdater.h"
     112              : #include "MSEventControl.h"
     113              : #include "MSEdge.h"
     114              : #include "MSJunction.h"
     115              : #include "MSJunctionLogic.h"
     116              : #include "MSLane.h"
     117              : #include "MSVehicleControl.h"
     118              : #include "MSVehicleTransfer.h"
     119              : #include "MSRoute.h"
     120              : #include "MSGlobals.h"
     121              : #include "MSEdgeWeightsStorage.h"
     122              : #include "MSStateHandler.h"
     123              : #include "MSFrame.h"
     124              : #include "MSParkingArea.h"
     125              : #include "MSStoppingPlace.h"
     126              : #include "MSNet.h"
     127              : 
     128              : 
     129              : // ===========================================================================
     130              : // debug constants
     131              : // ===========================================================================
     132              : //#define DEBUG_SIMSTEP
     133              : 
     134              : 
     135              : // ===========================================================================
     136              : // static member definitions
     137              : // ===========================================================================
     138              : MSNet* MSNet::myInstance = nullptr;
     139              : 
     140              : const std::string MSNet::STAGE_EVENTS("events");
     141              : const std::string MSNet::STAGE_MOVEMENTS("move");
     142              : const std::string MSNet::STAGE_LANECHANGE("laneChange");
     143              : const std::string MSNet::STAGE_INSERTIONS("insertion");
     144              : const std::string MSNet::STAGE_REMOTECONTROL("remoteControl");
     145              : 
     146              : const NamedObjectCont<MSStoppingPlace*> MSNet::myEmptyStoppingPlaceCont;
     147              : const std::vector<MSStoppingPlace*> MSNet::myEmptyStoppingPlaceVector;
     148              : 
     149              : // ===========================================================================
     150              : // static member method definitions
     151              : // ===========================================================================
     152              : double
     153          336 : MSNet::getEffort(const MSEdge* const e, const SUMOVehicle* const v, double t) {
     154              :     double value;
     155          336 :     const MSVehicle* const veh = dynamic_cast<const MSVehicle* const>(v);
     156          336 :     if (veh != nullptr && veh->getWeightsStorage().retrieveExistingEffort(e, t, value)) {
     157            2 :         return value;
     158              :     }
     159          334 :     if (getInstance()->getWeightsStorage().retrieveExistingEffort(e, t, value)) {
     160            2 :         return value;
     161              :     }
     162              :     return 0;
     163              : }
     164              : 
     165              : 
     166              : double
     167      7051554 : MSNet::getTravelTime(const MSEdge* const e, const SUMOVehicle* const v, double t) {
     168              :     double value;
     169      7051554 :     const MSVehicle* const veh = dynamic_cast<const MSVehicle* const>(v);
     170      7050631 :     if (veh != nullptr && veh->getWeightsStorage().retrieveExistingTravelTime(e, t, value)) {
     171          522 :         return value;
     172              :     }
     173      7051032 :     if (getInstance()->getWeightsStorage().retrieveExistingTravelTime(e, t, value)) {
     174          177 :         return value;
     175              :     }
     176      7050855 :     if (veh != nullptr) {
     177      6864725 :         if ((veh->getRoutingMode() & libsumo::ROUTING_MODE_AGGREGATED_CUSTOM) != 0) {
     178         3471 :             return MSRoutingEngine::getEffortExtra(e, v, t);
     179      6861254 :         } else if ((veh->getRoutingMode() & libsumo::ROUTING_MODE_AGGREGATED) != 0) {
     180          567 :             if (MSRoutingEngine::hasBikeSpeeds() && v->getVClass() == SVC_BICYCLE) {
     181            0 :                 return MSRoutingEngine::getEffortBike(e, v, t);
     182              :             } else {
     183          567 :                 return MSRoutingEngine::getEffort(e, v, t);
     184              :             }
     185      6860687 :         } else if (MSRoutingEngine::haveExtras()) {
     186      6860687 :             double tt = e->getMinimumTravelTime(v);
     187      6860687 :             MSRoutingEngine::applyExtras(e, v, SIMSTEP, tt);
     188      6860687 :             return tt;
     189              :         }
     190              :     }
     191       186130 :     return e->getMinimumTravelTime(v);
     192              : }
     193              : 
     194              : 
     195              : // ---------------------------------------------------------------------------
     196              : // MSNet - methods
     197              : // ---------------------------------------------------------------------------
     198              : MSNet*
     199   6161761732 : MSNet::getInstance(void) {
     200   6161761732 :     if (myInstance != nullptr) {
     201   6161761687 :         return myInstance;
     202              :     }
     203           90 :     throw ProcessError(TL("A network was not yet constructed."));
     204              : }
     205              : 
     206              : void
     207        42946 : MSNet::initStatic() {
     208        42946 :     gRoutingPreferences = false;
     209        42946 :     MSDriveWay::init();
     210        42946 : }
     211              : 
     212              : void
     213        42328 : MSNet::cleanupStatic() {
     214        42328 :     if (!MSGlobals::gUseMesoSim) {
     215        35390 :         MSVehicle::Influencer::cleanup();
     216              :     }
     217        42328 : }
     218              : 
     219              : 
     220        42946 : MSNet::MSNet(MSVehicleControl* vc, MSEventControl* beginOfTimestepEvents,
     221              :              MSEventControl* endOfTimestepEvents,
     222              :              MSEventControl* insertionEvents,
     223        42946 :              ShapeContainer* shapeCont):
     224        42946 :     myAmInterrupted(false),
     225        42946 :     myVehiclesMoved(0),
     226        42946 :     myPersonsMoved(0),
     227        42946 :     myHavePermissions(false),
     228        42946 :     myHasInternalLinks(false),
     229        42946 :     myJunctionHigherSpeeds(false),
     230        42946 :     myHasElevation(false),
     231        42946 :     myHasPedestrianNetwork(false),
     232        42946 :     myHasBidiEdges(false),
     233        42946 :     myEdgeDataEndTime(-1),
     234        42946 :     myDynamicShapeUpdater(nullptr) {
     235        42946 :     if (myInstance != nullptr) {
     236            0 :         throw ProcessError(TL("A network was already constructed."));
     237              :     }
     238        42946 :     OptionsCont& oc = OptionsCont::getOptions();
     239        42946 :     myStep = string2time(oc.getString("begin"));
     240        42946 :     myStateLoaderTime = myStep - 1,
     241        42946 :     myMaxTeleports = oc.getInt("max-num-teleports");
     242        42946 :     myLogExecutionTime = !oc.getBool("no-duration-log");
     243        42946 :     myLogStepNumber = !oc.getBool("no-step-log");
     244        42946 :     myLogStepPeriod = oc.getInt("step-log.period");
     245       171784 :     myInserter = new MSInsertionControl(*vc, string2time(oc.getString("max-depart-delay")), oc.getBool("eager-insert"), oc.getInt("max-num-vehicles"),
     246       171784 :                                         string2time(oc.getString("random-depart-offset")));
     247        42946 :     myVehicleControl = vc;
     248        42946 :     myDetectorControl = new MSDetectorControl();
     249        42946 :     myEdges = nullptr;
     250        42946 :     myJunctions = nullptr;
     251        42946 :     myRouteLoaders = nullptr;
     252        42946 :     myLogics = nullptr;
     253        42946 :     myPersonControl = nullptr;
     254        42946 :     myContainerControl = nullptr;
     255        42946 :     myEdgeWeights = nullptr;
     256        42946 :     myShapeContainer = shapeCont == nullptr ? new ShapeContainer() : shapeCont;
     257              : 
     258        42946 :     myBeginOfTimestepEvents = beginOfTimestepEvents;
     259        42946 :     myEndOfTimestepEvents = endOfTimestepEvents;
     260        42946 :     myInsertionEvents = insertionEvents;
     261        42946 :     myLanesRTree.first = false;
     262              : 
     263        42946 :     if (MSGlobals::gUseMesoSim) {
     264        14076 :         MSGlobals::gMesoNet = new MELoop(string2time(oc.getString("meso-recheck")));
     265              :     }
     266        42946 :     myInstance = this;
     267        42946 :     initStatic();
     268        42946 : }
     269              : 
     270              : 
     271              : void
     272        42464 : MSNet::closeBuilding(const OptionsCont& oc, MSEdgeControl* edges, MSJunctionControl* junctions,
     273              :                      SUMORouteLoaderControl* routeLoaders,
     274              :                      MSTLLogicControl* tlc,
     275              :                      std::vector<SUMOTime> stateDumpTimes,
     276              :                      std::vector<std::string> stateDumpFiles,
     277              :                      bool hasInternalLinks,
     278              :                      bool junctionHigherSpeeds,
     279              :                      const MMVersion& version) {
     280        42464 :     myEdges = edges;
     281        42464 :     myJunctions = junctions;
     282        42464 :     myRouteLoaders = routeLoaders;
     283        42464 :     myLogics = tlc;
     284              :     // save the time the network state shall be saved at
     285        42464 :     myStateDumpTimes = stateDumpTimes;
     286        42464 :     myStateDumpFiles = stateDumpFiles;
     287        42464 :     myStateDumpPeriod = string2time(oc.getString("save-state.period"));
     288        42464 :     myStateDumpPrefix = oc.getString("save-state.prefix");
     289        42464 :     myStateDumpSuffix = oc.getString("save-state.suffix");
     290              : 
     291              :     // initialise performance computation
     292        42464 :     mySimBeginMillis = SysUtils::getCurrentMillis();
     293        42464 :     myTraCIMillis = 0;
     294        42464 :     myHasInternalLinks = hasInternalLinks;
     295        42464 :     myJunctionHigherSpeeds = junctionHigherSpeeds;
     296        42464 :     myHasElevation = checkElevation();
     297        42464 :     myHasPedestrianNetwork = checkWalkingarea();
     298        42464 :     myHasBidiEdges = checkBidiEdges();
     299              :     myVersion = version;
     300        42464 :     if ((!MSGlobals::gUsingInternalLanes || !myHasInternalLinks)
     301        15099 :             && MSGlobals::gWeightsSeparateTurns > 0) {
     302            0 :         throw ProcessError(TL("Option weights.separate-turns is only supported when simulating with internal lanes"));
     303              :     }
     304        42464 : }
     305              : 
     306              : 
     307        75717 : MSNet::~MSNet() {
     308        42328 :     cleanupStatic();
     309              :     // delete controls
     310        42328 :     delete myJunctions;
     311        42328 :     delete myDetectorControl;
     312              :     // delete mean data
     313        42328 :     delete myEdges;
     314        42328 :     delete myInserter;
     315        42328 :     myInserter = nullptr;
     316        42328 :     delete myLogics;
     317        42328 :     delete myRouteLoaders;
     318        42328 :     if (myPersonControl != nullptr) {
     319         8235 :         delete myPersonControl;
     320         8235 :         myPersonControl = nullptr; // just to have that clear for later cleanups
     321              :     }
     322        42328 :     if (myContainerControl != nullptr) {
     323         1950 :         delete myContainerControl;
     324         1950 :         myContainerControl = nullptr; // just to have that clear for later cleanups
     325              :     }
     326        42328 :     delete myVehicleControl; // must happen after deleting transportables
     327              :     // ShapeContainer registers polygon-update commands with the event controls.
     328              :     // It must be torn down before the event controls so that ~ShapeContainer
     329              :     // can still deschedule() its (live) commands; the event controls then
     330              :     // delete the commands themselves.
     331        42328 :     delete myShapeContainer;
     332        42328 :     myShapeContainer = nullptr;
     333              :     // delete events late so that vehicles can get rid of references first
     334        42328 :     delete myBeginOfTimestepEvents;
     335        42328 :     myBeginOfTimestepEvents = nullptr;
     336        42328 :     delete myEndOfTimestepEvents;
     337        42328 :     myEndOfTimestepEvents = nullptr;
     338        42328 :     delete myInsertionEvents;
     339        42328 :     myInsertionEvents = nullptr;
     340        42328 :     delete myEdgeWeights;
     341        43799 :     for (auto& router : myRouterTT) {
     342         1471 :         delete router.second;
     343              :     }
     344              :     myRouterTT.clear();
     345        42339 :     for (auto& router : myRouterEffort) {
     346           11 :         delete router.second;
     347              :     }
     348              :     myRouterEffort.clear();
     349        45154 :     for (auto& router : myPedestrianRouter) {
     350         2826 :         delete router.second;
     351              :     }
     352              :     myPedestrianRouter.clear();
     353        42328 :     resetIntermodalRouter();
     354              :     myLanesRTree.second.RemoveAll();
     355        42345 :     for (MSTractionSubstation* sub : myTractionSubstations) {
     356           17 :         delete sub;
     357              :     }
     358              :     myTractionSubstations.clear();
     359        42328 :     clearAll();
     360        42328 :     if (MSGlobals::gUseMesoSim) {
     361         6938 :         delete MSGlobals::gMesoNet;
     362              :     }
     363        42328 :     myInstance = nullptr;
     364       160373 : }
     365              : 
     366              : 
     367              : void
     368          221 : MSNet::addRestriction(const std::string& id, const SUMOVehicleClass svc, const double speed) {
     369          221 :     myRestrictions[id][svc] = speed;
     370          221 : }
     371              : 
     372              : 
     373              : const std::map<SUMOVehicleClass, double>*
     374      2159863 : MSNet::getRestrictions(const std::string& id) const {
     375              :     std::map<std::string, std::map<SUMOVehicleClass, double> >::const_iterator i = myRestrictions.find(id);
     376      2159863 :     if (i == myRestrictions.end()) {
     377              :         return nullptr;
     378              :     }
     379         1130 :     return &i->second;
     380              : }
     381              : 
     382              : 
     383              : double
     384         5337 : MSNet::getPreference(const std::string& routingType, const SUMOVTypeParameter& pars) const {
     385         5337 :     if (gRoutingPreferences) {
     386         5337 :         auto it = myVTypePreferences.find(pars.id);
     387         5337 :         if (it != myVTypePreferences.end()) {
     388              :             auto it2 = it->second.find(routingType);
     389          224 :             if (it2 != it->second.end()) {
     390           56 :                 return it2->second;
     391              :             }
     392              :         }
     393              :         auto it3 = myVClassPreferences.find(pars.vehicleClass);
     394         5281 :         if (it3 != myVClassPreferences.end()) {
     395              :             auto it4 = it3->second.find(routingType);
     396          336 :             if (it4 != it3->second.end()) {
     397           84 :                 return it4->second;
     398              :             }
     399              :         }
     400              :         // fallback to generel preferences
     401         5197 :         it = myVTypePreferences.find("");
     402         5197 :         if (it != myVTypePreferences.end()) {
     403              :             auto it2 = it->second.find(routingType);
     404         4021 :             if (it2 != it->second.end()) {
     405         1165 :                 return it2->second;
     406              :             }
     407              :         }
     408              :     }
     409              :     return 1;
     410              : }
     411              : 
     412              : 
     413              : void
     414           28 : MSNet::addPreference(const std::string& routingType, SUMOVehicleClass svc, double prio) {
     415           28 :     myVClassPreferences[svc][routingType] = prio;
     416           28 :     gRoutingPreferences = true;
     417           28 : }
     418              : 
     419              : 
     420              : void
     421           90 : MSNet::addPreference(const std::string& routingType, std::string vType, double prio) {
     422           90 :     myVTypePreferences[vType][routingType] = prio;
     423           90 :     gRoutingPreferences = true;
     424           90 : }
     425              : 
     426              : void
     427           24 : MSNet::addMesoType(const std::string& typeID, const MESegment::MesoEdgeType& edgeType) {
     428           24 :     myMesoEdgeTypes[typeID] = edgeType;
     429           24 : }
     430              : 
     431              : const MESegment::MesoEdgeType&
     432       925560 : MSNet::getMesoType(const std::string& typeID) {
     433              :     if (myMesoEdgeTypes.count(typeID) == 0) {
     434              :         // init defaults
     435         7550 :         const OptionsCont& oc = OptionsCont::getOptions();
     436              :         MESegment::MesoEdgeType edgeType;
     437         7550 :         edgeType.tauff = string2time(oc.getString("meso-tauff"));
     438         7550 :         edgeType.taufj = string2time(oc.getString("meso-taufj"));
     439         7550 :         edgeType.taujf = string2time(oc.getString("meso-taujf"));
     440         7550 :         edgeType.taujj = string2time(oc.getString("meso-taujj"));
     441         7550 :         edgeType.jamThreshold = oc.getFloat("meso-jam-threshold");
     442         7550 :         edgeType.junctionControl = oc.getBool("meso-junction-control");
     443         7550 :         edgeType.tlsPenalty = oc.getFloat("meso-tls-penalty");
     444         7550 :         edgeType.tlsFlowPenalty = oc.getFloat("meso-tls-flow-penalty");
     445         7550 :         edgeType.minorPenalty = string2time(oc.getString("meso-minor-penalty"));
     446         7550 :         edgeType.overtaking = oc.getBool("meso-overtaking");
     447         7550 :         edgeType.edgeLength = oc.getFloat("meso-edgelength");
     448         7550 :         myMesoEdgeTypes[typeID] = edgeType;
     449              :     }
     450       925560 :     return myMesoEdgeTypes[typeID];
     451              : }
     452              : 
     453              : 
     454              : bool
     455      7338634 : MSNet::hasFlow(const std::string& id) const {
     456              :     // inserter is deleted at the end of the simulation
     457      7338634 :     return myInserter != nullptr && myInserter->hasFlow(id);
     458              : }
     459              : 
     460              : 
     461              : MSNet::SimulationState
     462        31963 : MSNet::simulate(SUMOTime start, SUMOTime stop) {
     463              :     // report the begin when wished
     464        63926 :     WRITE_MESSAGEF(TL("Simulation version % started with time: %."), VERSION_STRING, time2string(start));
     465              :     // the simulation loop
     466              :     SimulationState state = SIMSTATE_RUNNING;
     467              :     // state loading may have changed the start time so we need to reinit it
     468        31963 :     myStep = start;
     469              :     int numSteps = 0;
     470              :     bool doStepLog = false;
     471    125178350 :     while (state == SIMSTATE_RUNNING) {
     472    125146787 :         doStepLog = myLogStepNumber && (numSteps % myLogStepPeriod == 0);
     473              :         if (doStepLog) {
     474          110 :             preSimStepOutput();
     475              :         }
     476    125146787 :         simulationStep();
     477    125146387 :         if (doStepLog) {
     478          110 :             postSimStepOutput();
     479              :         }
     480    125146387 :         state = adaptToState(simulationState(stop));
     481              : #ifdef DEBUG_SIMSTEP
     482              :         std::cout << SIMTIME << " MSNet::simulate(" << start << ", " << stop << ")"
     483              :                   << "\n simulation state: " << getStateMessage(state)
     484              :                   << std::endl;
     485              : #endif
     486    125146387 :         numSteps++;
     487              :     }
     488        31563 :     if (myLogStepNumber && !doStepLog) {
     489              :         // ensure some output on the last step
     490           17 :         preSimStepOutput();
     491           17 :         postSimStepOutput();
     492              :     }
     493              :     // exit simulation loop
     494        31563 :     if (myLogStepNumber) {
     495              :         // start new line for final verbose output
     496           20 :         std::cout << "\n";
     497              :     }
     498        31563 :     closeSimulation(start, getStateMessage(state));
     499        31563 :     return state;
     500              : }
     501              : 
     502              : 
     503              : void
     504    138451253 : MSNet::loadRoutes() {
     505    138451253 :     myRouteLoaders->loadNext(myStep);
     506    138450667 : }
     507              : 
     508              : 
     509              : const std::string
     510        13365 : MSNet::generateStatistics(const SUMOTime start, const long now) {
     511        13365 :     std::ostringstream msg;
     512        13365 :     if (myLogExecutionTime) {
     513        12951 :         const long duration = now - mySimBeginMillis;
     514              :         // print performance notice
     515        25902 :         msg << "Performance:\n" << " Duration: " << elapsedMs2string(duration) << "\n";
     516        12951 :         if (duration != 0) {
     517        12767 :             if (TraCIServer::getInstance() != nullptr) {
     518         4299 :                 msg << " TraCI-Duration: " << elapsedMs2string(myTraCIMillis) << "\n";
     519              :             }
     520        12767 :             msg << " Real time factor: " << (STEPS2TIME(myStep - start) * 1000. / (double)duration) << "\n";
     521              :             msg.setf(std::ios::fixed, std::ios::floatfield);     // use decimal format
     522              :             msg.setf(std::ios::showpoint);    // print decimal point
     523        12767 :             msg << " UPS: " << ((double)myVehiclesMoved / ((double)duration / 1000)) << "\n";
     524        12767 :             if (myPersonsMoved > 0) {
     525         2362 :                 msg << " UPS-Persons: " << ((double)myPersonsMoved / ((double)duration / 1000)) << "\n";
     526              :             }
     527              :         }
     528              :         // print vehicle statistics
     529        12951 :         const std::string vehDiscardNotice = ((myVehicleControl->getLoadedVehicleNo() != myVehicleControl->getDepartedVehicleNo()) ?
     530        17166 :                                               " (Loaded: " + toString(myVehicleControl->getLoadedVehicleNo()) + ")" : "");
     531              :         msg << "Vehicles:\n"
     532        12951 :             << " Inserted: " << myVehicleControl->getDepartedVehicleNo() << vehDiscardNotice << "\n"
     533        25902 :             << " Running: " << myVehicleControl->getRunningVehicleNo() << "\n"
     534        25902 :             << " Waiting: " << myInserter->getWaitingVehicleNo() << "\n";
     535              : 
     536        12951 :         if (myVehicleControl->getTeleportCount() > 0 || myVehicleControl->getCollisionCount() > 0) {
     537              :             // print optional teleport statistics
     538              :             std::vector<std::string> reasons;
     539          697 :             if (myVehicleControl->getCollisionCount() > 0) {
     540          648 :                 reasons.push_back("Collisions: " + toString(myVehicleControl->getCollisionCount()));
     541              :             }
     542          697 :             if (myVehicleControl->getTeleportsJam() > 0) {
     543          488 :                 reasons.push_back("Jam: " + toString(myVehicleControl->getTeleportsJam()));
     544              :             }
     545          697 :             if (myVehicleControl->getTeleportsYield() > 0) {
     546          240 :                 reasons.push_back("Yield: " + toString(myVehicleControl->getTeleportsYield()));
     547              :             }
     548          697 :             if (myVehicleControl->getTeleportsWrongLane() > 0) {
     549          262 :                 reasons.push_back("Wrong Lane: " + toString(myVehicleControl->getTeleportsWrongLane()));
     550              :             }
     551         2091 :             msg << " Teleports: " << myVehicleControl->getTeleportCount() << " (" << joinToString(reasons, ", ") << ")\n";
     552          697 :         }
     553        12951 :         if (myVehicleControl->getEmergencyStops() > 0) {
     554           66 :             msg << " Emergency Stops: " << myVehicleControl->getEmergencyStops() << "\n";
     555              :         }
     556        12951 :         if (myVehicleControl->getEmergencyBrakingCount() > 0) {
     557          302 :             msg << " Emergency Braking: " << myVehicleControl->getEmergencyBrakingCount() << "\n";
     558              :         }
     559        12951 :         if (myPersonControl != nullptr && myPersonControl->getLoadedNumber() > 0) {
     560         2426 :             const std::string discardNotice = ((myPersonControl->getLoadedNumber() != myPersonControl->getDepartedNumber()) ?
     561         2804 :                                                " (Loaded: " + toString(myPersonControl->getLoadedNumber()) + ")" : "");
     562              :             msg << "Persons:\n"
     563         2426 :                 << " Inserted: " << myPersonControl->getDepartedNumber() << discardNotice << "\n"
     564         4852 :                 << " Running: " << myPersonControl->getRunningNumber() << "\n";
     565         2426 :             if (myPersonControl->getJammedNumber() > 0) {
     566           56 :                 msg << " Jammed: " << myPersonControl->getJammedNumber() << "\n";
     567              :             }
     568         2426 :             if (myPersonControl->getTeleportCount() > 0) {
     569              :                 std::vector<std::string> reasons;
     570            7 :                 if (myPersonControl->getTeleportsAbortWait() > 0) {
     571            0 :                     reasons.push_back("Abort Wait: " + toString(myPersonControl->getTeleportsAbortWait()));
     572              :                 }
     573            7 :                 if (myPersonControl->getTeleportsWrongDest() > 0) {
     574           14 :                     reasons.push_back("Wrong Dest: " + toString(myPersonControl->getTeleportsWrongDest()));
     575              :                 }
     576           21 :                 msg << " Teleports: " << myPersonControl->getTeleportCount() << " (" << joinToString(reasons, ", ") << ")\n";
     577            7 :             }
     578              :         }
     579        12951 :         if (myContainerControl != nullptr && myContainerControl->getLoadedNumber() > 0) {
     580           76 :             const std::string discardNotice = ((myContainerControl->getLoadedNumber() != myContainerControl->getDepartedNumber()) ?
     581           76 :                                                " (Loaded: " + toString(myContainerControl->getLoadedNumber()) + ")" : "");
     582              :             msg << "Containers:\n"
     583           76 :                 << " Inserted: " << myContainerControl->getDepartedNumber() << "\n"
     584          152 :                 << " Running: " << myContainerControl->getRunningNumber() << "\n";
     585           76 :             if (myContainerControl->getJammedNumber() > 0) {
     586            0 :                 msg << " Jammed: " << myContainerControl->getJammedNumber() << "\n";
     587              :             }
     588           76 :             if (myContainerControl->getTeleportCount() > 0) {
     589              :                 std::vector<std::string> reasons;
     590            0 :                 if (myContainerControl->getTeleportsAbortWait() > 0) {
     591            0 :                     reasons.push_back("Abort Wait: " + toString(myContainerControl->getTeleportsAbortWait()));
     592              :                 }
     593            0 :                 if (myContainerControl->getTeleportsWrongDest() > 0) {
     594            0 :                     reasons.push_back("Wrong Dest: " + toString(myContainerControl->getTeleportsWrongDest()));
     595              :                 }
     596            0 :                 msg << " Teleports: " << myContainerControl->getTeleportCount() << " (" << joinToString(reasons, ", ") << ")\n";
     597            0 :             }
     598              :         }
     599              :     }
     600        26730 :     if (OptionsCont::getOptions().getBool("duration-log.statistics")) {
     601         7006 :         msg << MSDevice_Tripinfo::printStatistics();
     602              :     }
     603              :     std::string result = msg.str();
     604              :     result.erase(result.end() - 1);
     605        13365 :     return result;
     606        13365 : }
     607              : 
     608              : 
     609              : void
     610        10390 : MSNet::writeCollisions() const {
     611        20780 :     OutputDevice& od = OutputDevice::getDeviceByOption("collision-output");
     612        10543 :     for (const auto& item : myCollisions) {
     613          306 :         for (const auto& c : item.second) {
     614          153 :             if (c.time != SIMSTEP) {
     615           13 :                 continue;
     616              :             }
     617          280 :             od.openTag("collision");
     618          140 :             od.writeAttr("time", time2string(getCurrentTimeStep()));
     619          140 :             od.writeAttr("type", c.type);
     620          140 :             od.writeAttr("lane", c.lane->getID());
     621          140 :             od.writeAttr("pos", c.pos);
     622          140 :             od.writeAttr("collider", item.first);
     623          140 :             od.writeAttr("victim", c.victim);
     624          140 :             od.writeAttr("colliderType", c.colliderType);
     625          140 :             od.writeAttr("victimType", c.victimType);
     626          140 :             od.writeAttr("colliderSpeed", c.colliderSpeed);
     627          140 :             od.writeAttr("victimSpeed", c.victimSpeed);
     628          140 :             od.writeAttr("colliderFront", c.colliderFront);
     629          140 :             od.writeAttr("colliderBack", c.colliderBack);
     630          140 :             od.writeAttr("victimFront", c.victimFront);
     631          140 :             od.writeAttr("victimBack", c.victimBack);
     632          280 :             od.closeTag();
     633              :         }
     634              :     }
     635        10390 : }
     636              : 
     637              : 
     638              : void
     639          377 : MSNet::writeStatistics(const SUMOTime start, const long now) const {
     640          377 :     const long duration = now - mySimBeginMillis;
     641          377 :     OutputDevice& od = OutputDevice::getDeviceByOption("statistic-output");
     642          377 :     od.openTag("performance");
     643          377 :     od.writeAttr("clockBegin", time2string(mySimBeginMillis));
     644          377 :     od.writeAttr("clockEnd", time2string(now));
     645          377 :     od.writeAttr("clockDuration", time2string(duration));
     646          377 :     od.writeAttr("traciDuration", time2string(myTraCIMillis));
     647          377 :     od.writeAttr("realTimeFactor", duration != 0 ? (double)(myStep - start) / (double)duration : -1);
     648          377 :     od.writeAttr("vehicleUpdatesPerSecond", duration != 0 ? (double)myVehiclesMoved / ((double)duration / 1000) : -1);
     649          377 :     od.writeAttr("personUpdatesPerSecond", duration != 0 ? (double)myPersonsMoved / ((double)duration / 1000) : -1);
     650          377 :     od.writeAttr("begin", time2string(start));
     651          377 :     od.writeAttr("end", time2string(myStep));
     652          377 :     od.writeAttr("duration", time2string(myStep - start));
     653          377 :     od.closeTag();
     654          377 :     od.openTag("vehicles");
     655          377 :     od.writeAttr("loaded", myVehicleControl->getLoadedVehicleNo());
     656          377 :     od.writeAttr("inserted", myVehicleControl->getDepartedVehicleNo());
     657          377 :     od.writeAttr("running", myVehicleControl->getRunningVehicleNo());
     658          377 :     od.writeAttr("waiting", myInserter->getWaitingVehicleNo());
     659          377 :     od.closeTag();
     660          377 :     od.openTag("teleports");
     661          377 :     od.writeAttr("total", myVehicleControl->getTeleportCount());
     662          377 :     od.writeAttr("jam", myVehicleControl->getTeleportsJam());
     663          377 :     od.writeAttr("yield", myVehicleControl->getTeleportsYield());
     664          377 :     od.writeAttr("wrongLane", myVehicleControl->getTeleportsWrongLane());
     665          377 :     od.closeTag();
     666          377 :     od.openTag("safety");
     667          377 :     od.writeAttr("collisions", myVehicleControl->getCollisionCount());
     668          377 :     od.writeAttr("emergencyStops", myVehicleControl->getEmergencyStops());
     669          377 :     od.writeAttr("emergencyBraking", myVehicleControl->getEmergencyBrakingCount());
     670          377 :     od.closeTag();
     671          377 :     od.openTag("persons");
     672          383 :     od.writeAttr("loaded", myPersonControl != nullptr ? myPersonControl->getLoadedNumber() : 0);
     673          383 :     od.writeAttr("running", myPersonControl != nullptr ? myPersonControl->getRunningNumber() : 0);
     674          383 :     od.writeAttr("jammed", myPersonControl != nullptr ? myPersonControl->getJammedNumber() : 0);
     675          377 :     od.closeTag();
     676          377 :     od.openTag("personTeleports");
     677          383 :     od.writeAttr("total", myPersonControl != nullptr ? myPersonControl->getTeleportCount() : 0);
     678          383 :     od.writeAttr("abortWait", myPersonControl != nullptr ? myPersonControl->getTeleportsAbortWait() : 0);
     679          383 :     od.writeAttr("wrongDest", myPersonControl != nullptr ? myPersonControl->getTeleportsWrongDest() : 0);
     680          377 :     od.closeTag();
     681          599 :     if (OptionsCont::getOptions().isSet("tripinfo-output") || OptionsCont::getOptions().getBool("duration-log.statistics")) {
     682          264 :         MSDevice_Tripinfo::writeStatistics(od);
     683              :     }
     684          377 : }
     685              : 
     686              : 
     687              : void
     688    138450018 : MSNet::writeSummaryOutput(bool finalStep) {
     689              :     // summary output
     690    138450018 :     const OptionsCont& oc = OptionsCont::getOptions();
     691    138450018 :     const bool hasOutput = oc.isSet("summary-output");
     692    138450018 :     const bool hasPersonOutput = oc.isSet("person-summary-output");
     693    138450018 :     if (hasOutput || hasPersonOutput) {
     694       531916 :         const SUMOTime period = string2time(oc.getString("summary-output.period"));
     695       531916 :         const SUMOTime begin = string2time(oc.getString("begin"));
     696       531916 :         if ((period > 0 && (myStep - begin) % period != 0 && !finalStep)
     697              :                 // it's the final step but we already wrote output
     698       530996 :                 || (finalStep && (period <= 0 || (myStep - begin) % period == 0))) {
     699              :             return;
     700              :         }
     701              :     }
     702       530473 :     if (hasOutput) {
     703       522721 :         OutputDevice& od = OutputDevice::getDeviceByOption("summary-output");
     704       522721 :         int departedVehiclesNumber = myVehicleControl->getDepartedVehicleNo();
     705       522721 :         const double meanWaitingTime = departedVehiclesNumber != 0 ? myVehicleControl->getTotalDepartureDelay() / (double) departedVehiclesNumber : -1.;
     706              :         int endedVehicleNumber = myVehicleControl->getEndedVehicleNo();
     707       522721 :         const double meanTravelTime = endedVehicleNumber != 0 ? myVehicleControl->getTotalTravelTime() / (double) endedVehicleNumber : -1.;
     708       522721 :         od.openTag("step");
     709       522721 :         od.writeAttr("time", time2string(myStep));
     710       522721 :         od.writeAttr("loaded", myVehicleControl->getLoadedVehicleNo());
     711       522721 :         od.writeAttr("inserted", myVehicleControl->getDepartedVehicleNo());
     712       522721 :         od.writeAttr("running", myVehicleControl->getRunningVehicleNo());
     713       522721 :         od.writeAttr("waiting", myInserter->getWaitingVehicleNo());
     714       522721 :         od.writeAttr("ended", myVehicleControl->getEndedVehicleNo());
     715       522721 :         od.writeAttr("arrived", myVehicleControl->getArrivedVehicleNo());
     716       522721 :         od.writeAttr("collisions", myVehicleControl->getCollisionCount());
     717       522721 :         od.writeAttr("teleports", myVehicleControl->getTeleportCount());
     718       522721 :         od.writeAttr("halting", myVehicleControl->getHaltingVehicleNo());
     719       522721 :         od.writeAttr("stopped", myVehicleControl->getStoppedVehiclesCount());
     720       522721 :         od.writeAttr("meanWaitingTime", meanWaitingTime);
     721       522721 :         od.writeAttr("meanTravelTime", meanTravelTime);
     722       522721 :         std::pair<double, double> meanSpeed = myVehicleControl->getVehicleMeanSpeeds();
     723       522721 :         od.writeAttr("meanSpeed", meanSpeed.first);
     724       522721 :         od.writeAttr("meanSpeedRelative", meanSpeed.second);
     725       522721 :         od.writeAttr("discarded", myVehicleControl->getDiscardedVehicleNo());
     726       522721 :         if (myLogExecutionTime) {
     727       235433 :             od.writeAttr("duration", mySimStepDuration);
     728              :         }
     729      1045442 :         od.closeTag();
     730              :     }
     731    138448575 :     if (hasPersonOutput) {
     732         7752 :         OutputDevice& od = OutputDevice::getDeviceByOption("person-summary-output");
     733         7752 :         MSTransportableControl& pc = getPersonControl();
     734         7752 :         od.openTag("step");
     735        15504 :         od.writeAttr("time", time2string(myStep));
     736         7752 :         od.writeAttr("loaded", pc.getLoadedNumber());
     737         7752 :         od.writeAttr("inserted", pc.getDepartedNumber());
     738         7752 :         od.writeAttr("walking", pc.getMovingNumber());
     739         7752 :         od.writeAttr("waitingForRide", pc.getWaitingForVehicleNumber());
     740         7752 :         od.writeAttr("riding", pc.getRidingNumber());
     741         7752 :         od.writeAttr("stopping", pc.getWaitingUntilNumber());
     742         7752 :         od.writeAttr("jammed", pc.getJammedNumber());
     743         7752 :         od.writeAttr("ended", pc.getEndedNumber());
     744         7752 :         od.writeAttr("arrived", pc.getArrivedNumber());
     745         7752 :         od.writeAttr("teleports", pc.getTeleportCount());
     746         7752 :         od.writeAttr("discarded", pc.getDiscardedNumber());
     747         7752 :         if (myLogExecutionTime) {
     748            0 :             od.writeAttr("duration", mySimStepDuration);
     749              :         }
     750        15504 :         od.closeTag();
     751              :     }
     752              : }
     753              : 
     754              : 
     755              : void
     756        40817 : MSNet::closeSimulation(SUMOTime start, const std::string& reason) {
     757              :     // report the end when wished
     758        81634 :     WRITE_MESSAGE(TLF("Simulation ended at time: %.", time2string(getCurrentTimeStep())));
     759        40817 :     if (reason != "") {
     760        80752 :         WRITE_MESSAGE(TL("Reason: ") + reason);
     761              :     }
     762        40817 :     myDetectorControl->close(myStep);
     763        81634 :     if (OptionsCont::getOptions().isSet("queue-output")) {
     764          358 :         MSQueueExport::finish(OutputDevice::getDeviceByOption("queue-output"), myStep);
     765              :     }
     766        42278 :     if (MSStopOut::active() && OptionsCont::getOptions().getBool("stop-output.write-unfinished")) {
     767          122 :         MSStopOut::getInstance()->generateOutputForUnfinished();
     768              :     }
     769        40817 :     MSDevice_Vehroutes::writePendingOutput(OptionsCont::getOptions().getBool("vehroute-output.write-unfinished"));
     770        81634 :     if (OptionsCont::getOptions().getBool("tripinfo-output.write-unfinished")) {
     771         1110 :         MSDevice_Tripinfo::generateOutputForUnfinished();
     772              :     }
     773        81634 :     if (OptionsCont::getOptions().isSet("chargingstations-output")) {
     774          252 :         if (!OptionsCont::getOptions().getBool("chargingstations-output.aggregated")) {
     775          106 :             writeChargingStationOutput();
     776           40 :         } else if (OptionsCont::getOptions().getBool("chargingstations-output.aggregated.write-unfinished")) {
     777           12 :             MSChargingStationExport::write(OutputDevice::getDeviceByOption("chargingstations-output"), true);
     778              :         }
     779              :     }
     780        81634 :     if (OptionsCont::getOptions().isSet("overheadwiresegments-output")) {
     781            5 :         writeOverheadWireSegmentOutput();
     782              :     }
     783        81634 :     if (OptionsCont::getOptions().isSet("substations-output")) {
     784            5 :         writeSubstationOutput();
     785              :     }
     786        40817 :     writeRailSignalBlocks();
     787        40817 :     const long now = SysUtils::getCurrentMillis();
     788        68683 :     if (myLogExecutionTime || OptionsCont::getOptions().getBool("duration-log.statistics")) {
     789        26730 :         WRITE_MESSAGE(generateStatistics(start, now));
     790              :     }
     791        81634 :     if (OptionsCont::getOptions().isSet("statistic-output")) {
     792          377 :         writeStatistics(start, now);
     793              :     }
     794              :     // maybe write a final line of output if reporting is periodic
     795        40817 :     writeSummaryOutput(true);
     796        40817 : }
     797              : 
     798              : 
     799              : void
     800    138412384 : MSNet::simulationStep(const bool onlyMove) {
     801    138412384 :     if (myStepCompletionMissing) {
     802            4 :         postMoveStep();
     803            4 :         myStepCompletionMissing = false;
     804         2663 :         return;
     805              :     }
     806              : #ifdef DEBUG_SIMSTEP
     807              :     std::cout << SIMTIME << ": MSNet::simulationStep() called"
     808              :               << ", myStep = " << myStep
     809              :               << std::endl;
     810              : #endif
     811              :     TraCIServer* t = TraCIServer::getInstance();
     812              :     int lastTraCICmd = 0;
     813    138412380 :     if (t != nullptr) {
     814     12362827 :         if (myLogExecutionTime) {
     815     12165860 :             myTraCIStepDuration = SysUtils::getCurrentMillis();
     816              :         }
     817     12362827 :         lastTraCICmd = t->processCommands(myStep);
     818              : #ifdef DEBUG_SIMSTEP
     819              :         bool loadRequested = !TraCI::getLoadArgs().empty();
     820              :         assert(t->getTargetTime() >= myStep || loadRequested || TraCIServer::wasClosed());
     821              : #endif
     822     12362723 :         if (myLogExecutionTime) {
     823     12165783 :             myTraCIStepDuration = SysUtils::getCurrentMillis() - myTraCIStepDuration;
     824              :         }
     825     12362723 :         if (TraCIServer::wasClosed() || !t->getLoadArgs().empty()) {
     826              :             return;
     827              :         }
     828              :     }
     829              : #ifdef DEBUG_SIMSTEP
     830              :     std::cout << SIMTIME << ": TraCI target time: " << t->getTargetTime() << std::endl;
     831              : #endif
     832              :     // execute beginOfTimestepEvents
     833    138409621 :     if (myLogExecutionTime) {
     834    100243134 :         mySimStepDuration = SysUtils::getCurrentMillis();
     835              :     }
     836              :     // simulation state output
     837    138409621 :     std::vector<SUMOTime>::iterator timeIt = std::find(myStateDumpTimes.begin(), myStateDumpTimes.end(), myStep);
     838    138409621 :     if (timeIt != myStateDumpTimes.end()) {
     839          375 :         const int dist = (int)distance(myStateDumpTimes.begin(), timeIt);
     840          375 :         MSStateHandler::saveState(myStateDumpFiles[dist], myStep);
     841              :     }
     842    138409621 :     if (myStateDumpPeriod > 0 && myStep % myStateDumpPeriod == 0) {
     843           84 :         std::string timeStamp = time2string(myStep);
     844              :         std::replace(timeStamp.begin(), timeStamp.end(), ':', '-');
     845           84 :         const std::string filename = myStateDumpPrefix + "_" + timeStamp + myStateDumpSuffix;
     846           84 :         MSStateHandler::saveState(filename, myStep);
     847           84 :         myPeriodicStateFiles.push_back(filename);
     848           84 :         int keep = OptionsCont::getOptions().getInt("save-state.period.keep");
     849           84 :         if (keep > 0 && (int)myPeriodicStateFiles.size() > keep) {
     850            0 :             std::remove(myPeriodicStateFiles.front().c_str());
     851              :             myPeriodicStateFiles.erase(myPeriodicStateFiles.begin());
     852              :         }
     853              :     }
     854    138409621 :     myBeginOfTimestepEvents->execute(myStep);
     855    138409613 :     if (MSRailSignalControl::hasInstance()) {
     856     10190680 :         MSRailSignalControl::getInstance().updateSignals(myStep);
     857              :     }
     858              : #ifdef HAVE_FOX
     859    138409613 :     MSRoutingEngine::waitForAll();
     860              : #endif
     861    138409613 :     if (MSGlobals::gCheck4Accidents && !MSGlobals::gUseMesoSim) {
     862    115157038 :         myEdges->detectCollisions(myStep, STAGE_EVENTS);
     863              :     }
     864              :     // check whether the tls programs need to be switched
     865    138409613 :     myLogics->check2Switch(myStep);
     866              : 
     867    138409613 :     if (MSGlobals::gUseMesoSim) {
     868     23252575 :         MSGlobals::gMesoNet->simulate(myStep);
     869              :     } else {
     870              :         // assure all lanes with vehicles are 'active'
     871    115157038 :         myEdges->patchActiveLanes();
     872              : 
     873              :         // compute safe velocities for all vehicles for the next few lanes
     874              :         // also register ApproachingVehicleInformation for all links
     875    115157038 :         myEdges->planMovements(myStep);
     876              : 
     877              :         // register junction approaches based on planned velocities as basis for right-of-way decision
     878    115157038 :         myEdges->setJunctionApproaches();
     879              : 
     880              :         // decide right-of-way and execute movements
     881    115157038 :         myEdges->executeMovements(myStep);
     882    115157035 :         if (MSGlobals::gCheck4Accidents) {
     883    115157035 :             myEdges->detectCollisions(myStep, STAGE_MOVEMENTS);
     884              :         }
     885              : 
     886              :         // vehicles may change lanes
     887    115157035 :         myEdges->changeLanes(myStep);
     888              : 
     889    115157035 :         if (MSGlobals::gCheck4Accidents) {
     890    115157035 :             myEdges->detectCollisions(myStep, STAGE_LANECHANGE);
     891              :         }
     892              :     }
     893              :     // flush arrived meso vehicles and micro vehicles that were removed due to collision
     894    138409610 :     myVehicleControl->removePending();
     895    138409610 :     loadRoutes();
     896              : 
     897              :     // persons
     898    138409594 :     if (myPersonControl != nullptr && myPersonControl->hasTransportables()) {
     899     76456642 :         myPersonControl->checkWaiting(this, myStep);
     900              :     }
     901              :     // containers
     902    138409546 :     if (myContainerControl != nullptr && myContainerControl->hasTransportables()) {
     903      4821155 :         myContainerControl->checkWaiting(this, myStep);
     904              :     }
     905              : #ifdef HAVE_FOX
     906    138409546 :     MSRoutingEngine::waitForAll();
     907    138409546 :     if (myPersonControl != nullptr) {
     908     78185628 :         myPersonControl->processPendingRouting(this, myStep);
     909              :     }
     910    138409538 :     if (myContainerControl != nullptr) {
     911      4882183 :         myContainerControl->processPendingRouting(this, myStep);
     912              :     }
     913              : #endif
     914    138409538 :     if (MSRailSignalControl::hasInstance()) {
     915     10190680 :         MSRailSignalControl::getInstance().resetWaitRelations();
     916              :         // preserve waitRelation from insertion for the next step
     917              :     }
     918              :     // insert vehicles
     919    138409538 :     myInserter->determineCandidates(myStep);
     920    138409491 :     myInsertionEvents->execute(myStep);
     921              : #ifdef HAVE_FOX
     922    138409396 :     MSRoutingEngine::waitForAll();
     923              : #endif
     924    138409372 :     myInserter->emitVehicles(myStep);
     925    138409226 :     if (MSGlobals::gCheck4Accidents && !MSGlobals::gUseMesoSim) {
     926              :         //myEdges->patchActiveLanes(); // @note required to detect collisions on lanes that were empty before insertion. wasteful?
     927    115156759 :         myEdges->detectCollisions(myStep, STAGE_INSERTIONS);
     928              :     }
     929    138409226 :     MSVehicleTransfer::getInstance()->checkInsertions(myStep);
     930              : 
     931              :     // execute endOfTimestepEvents
     932    138409226 :     myEndOfTimestepEvents->execute(myStep);
     933              : 
     934    138409216 :     if (myLogExecutionTime) {
     935    100242960 :         myTraCIStepDuration -= SysUtils::getCurrentMillis();
     936              :     }
     937    138409216 :     if (onlyMove) {
     938            4 :         myStepCompletionMissing = true;
     939            4 :         return;
     940              :     }
     941    138409212 :     if (t != nullptr && lastTraCICmd == libsumo::CMD_EXECUTEMOVE) {
     942            6 :         t->processCommands(myStep, true);
     943              :     }
     944    138409212 :     postMoveStep();
     945              : }
     946              : 
     947              : 
     948              : void
     949    138409216 : MSNet::postMoveStep() {
     950    138409216 :     const int numControlled = libsumo::Helper::postProcessRemoteControl();
     951    138409216 :     if (numControlled > 0 && MSGlobals::gCheck4Accidents) {
     952      2213821 :         myEdges->detectCollisions(myStep, STAGE_REMOTECONTROL);
     953              :     }
     954    138409216 :     if (myLogExecutionTime) {
     955    100242960 :         myTraCIStepDuration += SysUtils::getCurrentMillis();
     956    100242960 :         myTraCIMillis += myTraCIStepDuration;
     957              :     }
     958    138409216 :     if (MSGlobals::gCheck4Accidents && !MSGlobals::gUseMesoSim) {
     959              :         // collisions from the previous step were kept to avoid duplicate
     960              :         // warnings. we must remove them now to ensure correct output.
     961    115156754 :         removeOutdatedCollisions();
     962              :     }
     963              :     // update and write (if needed) detector values
     964    138409216 :     mySimStepDuration = SysUtils::getCurrentMillis() - mySimStepDuration;
     965    138409216 :     writeOutput();
     966              : 
     967    138409200 :     if (myLogExecutionTime) {
     968    100242960 :         myVehiclesMoved += myVehicleControl->getRunningVehicleNo();
     969    100242960 :         if (myPersonControl != nullptr) {
     970     75654297 :             myPersonsMoved += myPersonControl->getRunningNumber();
     971              :         }
     972              :     }
     973    138409200 :     myStep += DELTA_T;
     974    138409200 : }
     975              : 
     976              : 
     977              : MSNet::SimulationState
     978    138313447 : MSNet::simulationState(SUMOTime stopTime) const {
     979    138313447 :     if (TraCIServer::wasClosed()) {
     980              :         return SIMSTATE_CONNECTION_CLOSED;
     981              :     }
     982    138310669 :     if (TraCIServer::getInstance() != nullptr && !TraCIServer::getInstance()->getLoadArgs().empty()) {
     983              :         return SIMSTATE_LOADING;
     984              :     }
     985    138310656 :     if ((stopTime < 0 || myStep > stopTime) && TraCIServer::getInstance() == nullptr && (stopTime > 0 || myStep > myEdgeDataEndTime)) {
     986    104507752 :         if ((myVehicleControl->getActiveVehicleCount() == 0)
     987     76848379 :                 && (myInserter->getPendingFlowCount() == 0)
     988     72654841 :                 && (myPersonControl == nullptr || !myPersonControl->hasNonWaiting())
     989       412347 :                 && (myContainerControl == nullptr || !myContainerControl->hasNonWaiting())
     990    104570885 :                 && !MSDevice_Taxi::hasServableReservations()) {
     991              :             return SIMSTATE_NO_FURTHER_VEHICLES;
     992              :         }
     993              :     }
     994    138264389 :     if (stopTime >= 0 && myStep >= stopTime) {
     995              :         return SIMSTATE_END_STEP_REACHED;
     996              :     }
     997    138243278 :     if (myMaxTeleports >= 0 && myVehicleControl->getTeleportCount() > myMaxTeleports) {
     998              :         return SIMSTATE_TOO_MANY_TELEPORTS;
     999              :     }
    1000    138243270 :     if (myAmInterrupted) {
    1001            8 :         return SIMSTATE_INTERRUPTED;
    1002              :     }
    1003              :     return SIMSTATE_RUNNING;
    1004              : }
    1005              : 
    1006              : 
    1007              : MSNet::SimulationState
    1008    138304799 : MSNet::adaptToState(MSNet::SimulationState state, const bool isLibsumo) const {
    1009    138304799 :     if (state == SIMSTATE_LOADING) {
    1010           13 :         OptionsIO::setArgs(TraCIServer::getInstance()->getLoadArgs());
    1011              :         TraCIServer::getInstance()->getLoadArgs().clear();
    1012    138304786 :     } else if (state != SIMSTATE_RUNNING && ((TraCIServer::getInstance() != nullptr && !TraCIServer::wasClosed()) || isLibsumo)) {
    1013              :         // overrides SIMSTATE_END_STEP_REACHED, e.g. (TraCI / Libsumo ignore SUMO's --end option)
    1014        22573 :         return SIMSTATE_RUNNING;
    1015    138282213 :     } else if (state == SIMSTATE_NO_FURTHER_VEHICLES) {
    1016        28479 :         if (myPersonControl != nullptr) {
    1017         6873 :             myPersonControl->abortAnyWaitingForVehicle();
    1018              :         }
    1019        28479 :         if (myContainerControl != nullptr) {
    1020         1863 :             myContainerControl->abortAnyWaitingForVehicle();
    1021              :         }
    1022        28479 :         myVehicleControl->abortWaiting();
    1023              :     }
    1024              :     return state;
    1025              : }
    1026              : 
    1027              : 
    1028              : std::string
    1029        40211 : MSNet::getStateMessage(MSNet::SimulationState state) {
    1030        40211 :     switch (state) {
    1031              :         case MSNet::SIMSTATE_RUNNING:
    1032          441 :             return "";
    1033              :         case MSNet::SIMSTATE_END_STEP_REACHED:
    1034         8261 :             return TL("The final simulation step has been reached.");
    1035              :         case MSNet::SIMSTATE_NO_FURTHER_VEHICLES:
    1036        28840 :             return TL("All vehicles have left the simulation.");
    1037              :         case MSNet::SIMSTATE_CONNECTION_CLOSED:
    1038         2642 :             return TL("TraCI requested termination.");
    1039              :         case MSNet::SIMSTATE_ERROR_IN_SIM:
    1040            0 :             return TL("An error occurred (see log).");
    1041              :         case MSNet::SIMSTATE_INTERRUPTED:
    1042            8 :             return TL("Interrupted.");
    1043              :         case MSNet::SIMSTATE_TOO_MANY_TELEPORTS:
    1044            6 :             return TL("Too many teleports.");
    1045              :         case MSNet::SIMSTATE_LOADING:
    1046           13 :             return TL("TraCI issued load command.");
    1047              :         default:
    1048            0 :             return TL("Unknown reason.");
    1049              :     }
    1050              : }
    1051              : 
    1052              : 
    1053              : void
    1054        42619 : MSNet::clearAll() {
    1055              :     // clear container
    1056        42619 :     MSEdge::clear();
    1057        42619 :     MSLane::clear();
    1058        42619 :     MSRoute::clear();
    1059        42619 :     delete MSVehicleTransfer::getInstance();
    1060        42619 :     MSDevice::cleanupAll();
    1061        42619 :     MSCalibrator::cleanup();
    1062        85738 :     while (!MSLaneSpeedTrigger::getInstances().empty()) {
    1063          500 :         delete MSLaneSpeedTrigger::getInstances().begin()->second;
    1064              :     }
    1065        46816 :     while (!MSTriggeredRerouter::getInstances().empty()) {
    1066         4197 :         delete MSTriggeredRerouter::getInstances().begin()->second;
    1067              :     }
    1068        42619 :     MSDevice_BTsender::cleanup();
    1069        42619 :     MSDevice_SSM::cleanup();
    1070        42619 :     MSDevice_ToC::cleanup();
    1071        42619 :     MSStopOut::cleanup();
    1072        42619 :     MSRailSignalConstraint::cleanup();
    1073        42619 :     MSRailSignalControl::cleanup();
    1074        42619 :     MSDriveWay::cleanup();
    1075              :     TraCIServer* t = TraCIServer::getInstance();
    1076        42619 :     if (t != nullptr) {
    1077         2760 :         t->cleanup();
    1078              :     }
    1079        42619 :     libsumo::Helper::cleanup();
    1080        42619 :     OutputDevice::closeAll(true);
    1081        42619 : }
    1082              : 
    1083              : 
    1084              : void
    1085          162 : MSNet::clearState(const SUMOTime step, bool quickReload) {
    1086          162 :     MSGlobals::gClearState = true;
    1087          162 :     if (MSGlobals::gUseMesoSim) {
    1088           12 :         MSGlobals::gMesoNet->clearState();
    1089          390 :         for (MSEdge* const edge : MSEdge::getAllEdges()) {
    1090          776 :             for (MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge); s != nullptr; s = s->getNextSegment()) {
    1091          398 :                 s->clearState();
    1092              :             }
    1093              :         }
    1094              :     } else {
    1095         7110 :         for (MSEdge* const edge : MSEdge::getAllEdges()) {
    1096        15408 :             for (MSLane* const lane : edge->getLanes()) {
    1097         8448 :                 lane->getVehiclesSecure();
    1098         8448 :                 lane->clearState();
    1099         8448 :                 lane->releaseVehicles();
    1100              :             }
    1101         6960 :             edge->clearState();
    1102              :         }
    1103              :     }
    1104          162 :     myInserter->clearState();
    1105              :     // detectors may still reference persons/vehicles
    1106          162 :     myDetectorControl->updateDetectors(myStep);
    1107          162 :     myDetectorControl->writeOutput(myStep, true);
    1108          162 :     myDetectorControl->clearState(step);
    1109              : 
    1110          162 :     if (myPersonControl != nullptr) {
    1111           18 :         myPersonControl->clearState();
    1112              :     }
    1113          162 :     if (myContainerControl != nullptr) {
    1114            0 :         myContainerControl->clearState();
    1115              :     }
    1116              :     // delete vtypes after transportables have removed their types
    1117          162 :     myVehicleControl->clearState(true);
    1118          162 :     MSVehicleTransfer::getInstance()->clearState();
    1119          162 :     myLogics->clearState(step, quickReload);
    1120              :     // delete all routes after vehicles and detector output is done
    1121          162 :     MSRoute::dict_clearState();
    1122          203 :     for (auto& item : myStoppingPlaces) {
    1123           82 :         for (auto& item2 : item.second) {
    1124           41 :             item2.second->clearState();
    1125              :         }
    1126              :     }
    1127          162 :     myShapeContainer->clearState();
    1128          162 :     myBeginOfTimestepEvents->clearState(myStep, step);
    1129          162 :     myEndOfTimestepEvents->clearState(myStep, step);
    1130          162 :     myInsertionEvents->clearState(myStep, step);
    1131          162 :     MSRailSignalControl::clearState();
    1132          162 :     MSDriveWay::clearState();
    1133          162 :     myStep = step;
    1134          162 :     MSGlobals::gClearState = false;
    1135          162 : }
    1136              : 
    1137              : 
    1138              : SUMOTime
    1139          570 : MSNet::getLoaderTime() const {
    1140          570 :     return myRouteLoaders->getCurrentLoadTime();
    1141              : }
    1142              : 
    1143              : void
    1144          710 : MSNet::setLoaderTime(SUMOTime time) {
    1145          710 :     myRouteLoaders->setCurrentLoadTime(time);
    1146          710 :     myStateLoaderTime = MAX2(myStateLoaderTime, time);
    1147          710 : }
    1148              : 
    1149              : void
    1150    138409216 : MSNet::writeOutput() {
    1151              :     // update detector values
    1152    138409216 :     myDetectorControl->updateDetectors(myStep);
    1153    138409207 :     const OptionsCont& oc = OptionsCont::getOptions();
    1154              : 
    1155              :     // check state dumps
    1156    276818414 :     if (oc.isSet("netstate-dump")) {
    1157        12936 :         MSXMLRawOut::write(OutputDevice::getDeviceByOption("netstate-dump"), *myEdges, myStep,
    1158              :                            oc.getInt("netstate-dump.precision"));
    1159              :     }
    1160              : 
    1161              :     // check fcd dumps
    1162    276818414 :     if (OptionsCont::getOptions().isSet("fcd-output")) {
    1163     14578106 :         if (OptionsCont::getOptions().isSet("person-fcd-output")) {
    1164           24 :             MSFCDExport::write(OutputDevice::getDeviceByOption("fcd-output"), myStep, SUMO_TAG_VEHICLE);
    1165           48 :             MSFCDExport::write(OutputDevice::getDeviceByOption("person-fcd-output"), myStep, SUMO_TAG_PERSON);
    1166              :         } else {
    1167     14578058 :             MSFCDExport::write(OutputDevice::getDeviceByOption("fcd-output"), myStep);
    1168              :         }
    1169              :     }
    1170              : 
    1171              :     // check emission dumps
    1172    276818414 :     if (OptionsCont::getOptions().isSet("emission-output")) {
    1173       215992 :         MSEmissionExport::write(OutputDevice::getDeviceByOption("emission-output"), myStep);
    1174              :     }
    1175              : 
    1176              :     // battery dumps
    1177    276818414 :     if (OptionsCont::getOptions().isSet("battery-output")) {
    1178       148254 :         MSBatteryExport::write(OutputDevice::getDeviceByOption("battery-output"), myStep,
    1179              :                                oc.getInt("battery-output.precision"));
    1180              :     }
    1181              : 
    1182              :     // charging station aggregated dumps
    1183    138500321 :     if (OptionsCont::getOptions().isSet("chargingstations-output") && OptionsCont::getOptions().getBool("chargingstations-output.aggregated")) {
    1184        22248 :         MSChargingStationExport::write(OutputDevice::getDeviceByOption("chargingstations-output"));
    1185              :     }
    1186              : 
    1187              :     // elecHybrid dumps
    1188    276818414 :     if (OptionsCont::getOptions().isSet("elechybrid-output")) {
    1189          450 :         std::string output = OptionsCont::getOptions().getString("elechybrid-output");
    1190              : 
    1191          900 :         if (oc.getBool("elechybrid-output.aggregated")) {
    1192              :             // build a xml file with aggregated device.elechybrid output
    1193          600 :             MSElecHybridExport::writeAggregated(OutputDevice::getDeviceByOption("elechybrid-output"), myStep,
    1194              :                                                 oc.getInt("elechybrid-output.precision"));
    1195              :         } else {
    1196              :             // build a separate xml file for each vehicle equipped with device.elechybrid
    1197              :             // RICE_TODO: Does this have to be placed here in MSNet.cpp ?
    1198          150 :             MSVehicleControl& vc = MSNet::getInstance()->getVehicleControl();
    1199          204 :             for (MSVehicleControl::constVehIt it = vc.loadedVehBegin(); it != vc.loadedVehEnd(); ++it) {
    1200           54 :                 const SUMOVehicle* veh = it->second;
    1201           54 :                 if (!veh->isOnRoad()) {
    1202            0 :                     continue;
    1203              :                 }
    1204           54 :                 if (static_cast<MSDevice_ElecHybrid*>(veh->getDevice(typeid(MSDevice_ElecHybrid))) != nullptr) {
    1205              :                     std::string vehID = veh->getID();
    1206           54 :                     std::string filename2 = output + "_" + vehID + ".xml";
    1207           54 :                     OutputDevice& dev = OutputDevice::getDevice(filename2);
    1208              :                     std::map<SumoXMLAttr, std::string> attrs;
    1209           54 :                     attrs[SUMO_ATTR_VEHICLE] = vehID;
    1210           54 :                     attrs[SUMO_ATTR_MAXIMUMBATTERYCAPACITY] = toString(dynamic_cast<MSDevice_ElecHybrid*>(veh->getDevice(typeid(MSDevice_ElecHybrid)))->getMaximumBatteryCapacity());
    1211           54 :                     attrs[SUMO_ATTR_RECUPERATIONENABLE] = toString(MSGlobals::gOverheadWireRecuperation);
    1212          108 :                     dev.writeXMLHeader("elecHybrid-export", "", attrs);
    1213          108 :                     MSElecHybridExport::write(OutputDevice::getDevice(filename2), veh, myStep, oc.getInt("elechybrid-output.precision"));
    1214              :                 }
    1215              :             }
    1216              :         }
    1217              :     }
    1218              : 
    1219              : 
    1220              :     // check full dumps
    1221    276818414 :     if (OptionsCont::getOptions().isSet("full-output")) {
    1222         1138 :         MSGlobals::gHaveEmissions = true;
    1223         2276 :         MSFullExport::write(OutputDevice::getDeviceByOption("full-output"), myStep);
    1224              :     }
    1225              : 
    1226              :     // check queue dumps
    1227    276818414 :     if (OptionsCont::getOptions().isSet("queue-output")) {
    1228       330534 :         MSQueueExport::write(OutputDevice::getDeviceByOption("queue-output"), myStep);
    1229              :     }
    1230              : 
    1231              :     // check amitran dumps
    1232    276818414 :     if (OptionsCont::getOptions().isSet("amitran-output")) {
    1233         2040 :         MSAmitranTrajectories::write(OutputDevice::getDeviceByOption("amitran-output"), myStep);
    1234              :     }
    1235              : 
    1236              :     // check vtk dumps
    1237    276818414 :     if (OptionsCont::getOptions().isSet("vtk-output")) {
    1238              : 
    1239           60 :         if (MSNet::getInstance()->getVehicleControl().getRunningVehicleNo() > 0) {
    1240           60 :             std::string timestep = time2string(myStep);
    1241           60 :             if (TS >= 1.0) {
    1242           48 :                 timestep = timestep.substr(0, timestep.length() - 3);
    1243           36 :             } else if (DELTA_T % 100 == 0) {
    1244           72 :                 timestep = timestep.substr(0, timestep.length() - 1);
    1245              :             }
    1246           66 :             std::string output = OptionsCont::getOptions().getString("vtk-output");
    1247           66 :             std::string filename = output + "_" + timestep + ".vtp";
    1248              : 
    1249           60 :             OutputDevice_File dev(filename);
    1250              : 
    1251              :             //build a huge mass of xml files
    1252           54 :             MSVTKExport::write(dev, myStep);
    1253              : 
    1254           54 :         }
    1255              : 
    1256              :     }
    1257              : 
    1258    138409201 :     writeSummaryOutput();
    1259              : 
    1260              :     // write detector values
    1261    138409201 :     myDetectorControl->writeOutput(myStep + DELTA_T, false);
    1262              : 
    1263              :     // write link states
    1264    276818400 :     if (OptionsCont::getOptions().isSet("link-output")) {
    1265         4048 :         OutputDevice& od = OutputDevice::getDeviceByOption("link-output");
    1266         4048 :         od.openTag("timestep");
    1267         4048 :         od.writeAttr(SUMO_ATTR_ID, STEPS2TIME(myStep));
    1268        85848 :         for (const MSEdge* const edge : myEdges->getEdges()) {
    1269       180200 :             for (const MSLane* const lane : edge->getLanes()) {
    1270       212304 :                 for (const MSLink* const link : lane->getLinkCont()) {
    1271       227808 :                     link->writeApproaching(od, lane->getID());
    1272              :                 }
    1273              :             }
    1274              :         }
    1275         8096 :         od.closeTag();
    1276              :     }
    1277              : 
    1278              :     // write SSM output
    1279    140942262 :     for (MSDevice_SSM* dev : MSDevice_SSM::getInstances()) {
    1280      2533062 :         dev->updateAndWriteOutput();
    1281              :     }
    1282              : 
    1283              :     // write ToC output
    1284    138424919 :     for (MSDevice_ToC* dev : MSDevice_ToC::getInstances()) {
    1285        15719 :         if (dev->generatesOutput()) {
    1286        15513 :             dev->writeOutput();
    1287              :         }
    1288              :     }
    1289              : 
    1290    276818400 :     if (OptionsCont::getOptions().isSet("collision-output")) {
    1291        10390 :         writeCollisions();
    1292              :     }
    1293    138409200 : }
    1294              : 
    1295              : 
    1296              : bool
    1297            0 : MSNet::logSimulationDuration() const {
    1298            0 :     return myLogExecutionTime;
    1299              : }
    1300              : 
    1301              : 
    1302              : MSTransportableControl&
    1303     30590359 : MSNet::getPersonControl() {
    1304     30590359 :     if (myPersonControl == nullptr) {
    1305         6684 :         myPersonControl = new MSTransportableControl(true);
    1306              :     }
    1307     30590335 :     return *myPersonControl;
    1308              : }
    1309              : 
    1310              : 
    1311              : MSTransportableControl&
    1312      8820240 : MSNet::getContainerControl() {
    1313      8820240 :     if (myContainerControl == nullptr) {
    1314         1782 :         myContainerControl = new MSTransportableControl(false);
    1315              :     }
    1316      8820240 :     return *myContainerControl;
    1317              : }
    1318              : 
    1319              : MSDynamicShapeUpdater*
    1320           23 : MSNet::makeDynamicShapeUpdater() {
    1321           23 :     myDynamicShapeUpdater = std::unique_ptr<MSDynamicShapeUpdater> (new MSDynamicShapeUpdater(*myShapeContainer));
    1322           23 :     return myDynamicShapeUpdater.get();
    1323              : }
    1324              : 
    1325              : MSEdgeWeightsStorage&
    1326      7051655 : MSNet::getWeightsStorage() {
    1327      7051655 :     if (myEdgeWeights == nullptr) {
    1328         1961 :         myEdgeWeights = new MSEdgeWeightsStorage();
    1329              :     }
    1330      7051655 :     return *myEdgeWeights;
    1331              : }
    1332              : 
    1333              : 
    1334              : void
    1335          127 : MSNet::preSimStepOutput() const {
    1336          127 :     std::cout << "Step #" << time2string(myStep);
    1337          127 : }
    1338              : 
    1339              : 
    1340              : void
    1341          127 : MSNet::postSimStepOutput() const {
    1342          127 :     if (myLogExecutionTime) {
    1343          125 :         std::ostringstream oss;
    1344              :         oss.setf(std::ios::fixed, std::ios::floatfield);     // use decimal format
    1345              :         oss.setf(std::ios::showpoint);    // print decimal point
    1346          125 :         oss << std::setprecision(gPrecision);
    1347          125 :         if (mySimStepDuration != 0) {
    1348           71 :             const double durationSec = (double)mySimStepDuration / 1000.;
    1349           71 :             oss << " (" << mySimStepDuration << "ms ~= "
    1350           71 :                 << (TS / durationSec) << "*RT, ~"
    1351           71 :                 << ((double) myVehicleControl->getRunningVehicleNo() / durationSec);
    1352              :         } else {
    1353           54 :             oss << " (0ms ?*RT. ?";
    1354              :         }
    1355          125 :         oss << "UPS, ";
    1356          125 :         if (TraCIServer::getInstance() != nullptr) {
    1357           79 :             oss << "TraCI: " << myTraCIStepDuration << "ms, ";
    1358              :         }
    1359          125 :         oss << "vehicles TOT " << myVehicleControl->getDepartedVehicleNo()
    1360          250 :             << " ACT " << myVehicleControl->getRunningVehicleNo()
    1361          125 :             << " BUF " << myInserter->getWaitingVehicleNo()
    1362          125 :             << ")                                              ";
    1363          250 :         std::string prev = "Step #" + time2string(myStep - DELTA_T);
    1364          250 :         std::cout << oss.str().substr(0, 90 - prev.length());
    1365          125 :     }
    1366          127 :     std::cout << '\r';
    1367          127 : }
    1368              : 
    1369              : 
    1370              : void
    1371        11602 : MSNet::addVehicleStateListener(VehicleStateListener* listener) {
    1372        11602 :     if (find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener) == myVehicleStateListeners.end()) {
    1373        11602 :         myVehicleStateListeners.push_back(listener);
    1374              :     }
    1375        11602 : }
    1376              : 
    1377              : 
    1378              : void
    1379           58 : MSNet::removeVehicleStateListener(VehicleStateListener* listener) {
    1380           58 :     std::vector<VehicleStateListener*>::iterator i = std::find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener);
    1381           58 :     if (i != myVehicleStateListeners.end()) {
    1382           58 :         myVehicleStateListeners.erase(i);
    1383              :     }
    1384           58 : }
    1385              : 
    1386              : 
    1387              : void
    1388     16035833 : MSNet::informVehicleStateListener(const SUMOVehicle* const vehicle, VehicleState to, const std::string& info) {
    1389              : #ifdef HAVE_FOX
    1390     16035833 :     ScopedLocker<> lock(myVehicleStateListenerMutex, MSGlobals::gNumThreads > 1);
    1391              : #endif
    1392     16728211 :     for (VehicleStateListener* const listener : myVehicleStateListeners) {
    1393       692378 :         listener->vehicleStateChanged(vehicle, to, info);
    1394              :     }
    1395     16035833 : }
    1396              : 
    1397              : 
    1398              : void
    1399         3908 : MSNet::addTransportableStateListener(TransportableStateListener* listener) {
    1400         3908 :     if (find(myTransportableStateListeners.begin(), myTransportableStateListeners.end(), listener) == myTransportableStateListeners.end()) {
    1401         3908 :         myTransportableStateListeners.push_back(listener);
    1402              :     }
    1403         3908 : }
    1404              : 
    1405              : 
    1406              : void
    1407            0 : MSNet::removeTransportableStateListener(TransportableStateListener* listener) {
    1408            0 :     std::vector<TransportableStateListener*>::iterator i = std::find(myTransportableStateListeners.begin(), myTransportableStateListeners.end(), listener);
    1409            0 :     if (i != myTransportableStateListeners.end()) {
    1410            0 :         myTransportableStateListeners.erase(i);
    1411              :     }
    1412            0 : }
    1413              : 
    1414              : 
    1415              : void
    1416      1009687 : MSNet::informTransportableStateListener(const MSTransportable* const transportable, TransportableState to, const std::string& info) {
    1417              : #ifdef HAVE_FOX
    1418      1009687 :     ScopedLocker<> lock(myTransportableStateListenerMutex, MSGlobals::gNumThreads > 1);
    1419              : #endif
    1420      1012495 :     for (TransportableStateListener* const listener : myTransportableStateListeners) {
    1421         2808 :         listener->transportableStateChanged(transportable, to, info);
    1422              :     }
    1423      1009687 : }
    1424              : 
    1425              : 
    1426              : bool
    1427        19420 : MSNet::registerCollision(const SUMOTrafficObject* collider, const SUMOTrafficObject* victim, const std::string& collisionType, const MSLane* lane, double pos) {
    1428              :     auto it = myCollisions.find(collider->getID());
    1429        19420 :     if (it != myCollisions.end()) {
    1430        12561 :         for (Collision& old : it->second) {
    1431        12442 :             if (old.victim == victim->getID()) {
    1432              :                 // collision from previous step continues
    1433        11063 :                 old.continuationTime = myStep;
    1434              :                 return false;
    1435              :             }
    1436              :         }
    1437              :     } else {
    1438              :         // maybe the roles have been reversed
    1439              :         auto it2 = myCollisions.find(victim->getID());
    1440         8238 :         if (it2 != myCollisions.end()) {
    1441         2041 :             for (Collision& old : it2->second) {
    1442         1884 :                 if (old.victim == collider->getID()) {
    1443              :                     // collision from previous step continues (keep the old roles)
    1444         1717 :                     old.continuationTime = myStep;
    1445              :                     return false;
    1446              :                 }
    1447              :             }
    1448              :         }
    1449              :     }
    1450              :     Collision c;
    1451              :     c.victim = victim->getID();
    1452         6640 :     c.colliderType = collider->getVehicleType().getID();
    1453         6640 :     c.victimType = victim->getVehicleType().getID();
    1454         6640 :     c.colliderSpeed = collider->getSpeed();
    1455         6640 :     c.victimSpeed = victim->getSpeed();
    1456         6640 :     c.colliderFront = collider->getPosition();
    1457         6640 :     c.victimFront = victim->getPosition();
    1458         6640 :     c.colliderBack = collider->getPosition(-collider->getVehicleType().getLength());
    1459         6640 :     c.victimBack = victim->getPosition(-victim->getVehicleType().getLength());
    1460              :     c.type = collisionType;
    1461         6640 :     c.lane = lane;
    1462         6640 :     c.pos = pos;
    1463         6640 :     c.time = myStep;
    1464         6640 :     c.continuationTime = myStep;
    1465         6640 :     myCollisions[collider->getID()].push_back(c);
    1466              :     return true;
    1467         6640 : }
    1468              : 
    1469              : 
    1470              : void
    1471    115156754 : MSNet::removeOutdatedCollisions() {
    1472    115175637 :     for (auto it = myCollisions.begin(); it != myCollisions.end();) {
    1473        38573 :         for (auto it2 = it->second.begin(); it2 != it->second.end();) {
    1474        19690 :             if (it2->continuationTime != myStep) {
    1475         6627 :                 it2 = it->second.erase(it2);
    1476              :             } else {
    1477              :                 it2++;
    1478              :             }
    1479              :         }
    1480        18883 :         if (it->second.size() == 0) {
    1481              :             it = myCollisions.erase(it);
    1482              :         } else {
    1483              :             it++;
    1484              :         }
    1485              :     }
    1486    115156754 : }
    1487              : 
    1488              : 
    1489              : bool
    1490        83957 : MSNet::addStoppingPlace(SumoXMLTag category, MSStoppingPlace* stop) {
    1491        83957 :     if (category == SUMO_TAG_TRAIN_STOP) {
    1492        14049 :         category = SUMO_TAG_BUS_STOP;
    1493              :     }
    1494        83957 :     const bool isNew = myStoppingPlaces[category].add(stop->getID(), stop);
    1495        83957 :     if (isNew && stop->getMyName() != "") {
    1496        15969 :         myNamedStoppingPlaces[category][stop->getMyName()].push_back(stop);
    1497              :     }
    1498        83957 :     return isNew;
    1499              : }
    1500              : 
    1501              : 
    1502              : bool
    1503           17 : MSNet::addTractionSubstation(MSTractionSubstation* substation) {
    1504           17 :     if (find(myTractionSubstations.begin(), myTractionSubstations.end(), substation) == myTractionSubstations.end()) {
    1505           17 :         myTractionSubstations.push_back(substation);
    1506           17 :         return true;
    1507              :     }
    1508              :     return false;
    1509              : }
    1510              : 
    1511              : 
    1512              : MSStoppingPlace*
    1513      1602380 : MSNet::getStoppingPlace(const std::string& id, const SumoXMLTag category) const {
    1514              :     if (myStoppingPlaces.count(category) > 0) {
    1515              :         return myStoppingPlaces.find(category)->second.get(id);
    1516              :     }
    1517              :     return nullptr;
    1518              : }
    1519              : 
    1520              : 
    1521              : MSStoppingPlace*
    1522       172580 : MSNet::getStoppingPlace(const std::string& id) const {
    1523       855583 :     for (SumoXMLTag category : std::vector<SumoXMLTag>({SUMO_TAG_BUS_STOP, SUMO_TAG_PARKING_AREA, SUMO_TAG_CONTAINER_STOP, SUMO_TAG_CHARGING_STATION, SUMO_TAG_OVERHEAD_WIRE_SEGMENT})) {
    1524       719493 :         MSStoppingPlace* result = getStoppingPlace(id, category);
    1525       719493 :         if (result != nullptr) {
    1526              :             return result;
    1527              :         }
    1528       172580 :     }
    1529       136090 :     return nullptr;
    1530              : }
    1531              : 
    1532              : 
    1533              : std::string
    1534       465942 : MSNet::getStoppingPlaceID(const MSLane* lane, const double pos, const SumoXMLTag category) const {
    1535              :     if (myStoppingPlaces.count(category) > 0) {
    1536       955672 :         for (const auto& it : myStoppingPlaces.find(category)->second) {
    1537       875373 :             MSStoppingPlace* stop = it.second;
    1538       875373 :             if (&stop->getLane() == lane && stop->getBeginLanePosition() - POSITION_EPS <= pos && stop->getEndLanePosition() + POSITION_EPS >= pos) {
    1539              :                 return stop->getID();
    1540              :             }
    1541              :         }
    1542              :     }
    1543       359997 :     return "";
    1544              : }
    1545              : 
    1546              : 
    1547              : const std::vector<MSStoppingPlace*>&
    1548         1590 : MSNet::getStoppingPlaceAlternatives(const std::string& name, SumoXMLTag category) const {
    1549         1590 :     if (category == SUMO_TAG_TRAIN_STOP) {
    1550              :         category = SUMO_TAG_BUS_STOP;
    1551              :     }
    1552              :     auto it = myNamedStoppingPlaces.find(category);
    1553         1590 :     if (it != myNamedStoppingPlaces.end()) {
    1554              :         auto it2 = it->second.find(name);
    1555         1515 :         if (it2 != it->second.end()) {
    1556         1515 :             return it2->second;
    1557              :         }
    1558              :     }
    1559              :     return myEmptyStoppingPlaceVector;
    1560              : }
    1561              : 
    1562              : 
    1563              : const NamedObjectCont<MSStoppingPlace*>&
    1564        14009 : MSNet::getStoppingPlaces(SumoXMLTag category) const {
    1565              :     auto it = myStoppingPlaces.find(category);
    1566        14009 :     if (it != myStoppingPlaces.end()) {
    1567        13724 :         return it->second;
    1568              :     } else {
    1569              :         return myEmptyStoppingPlaceCont;
    1570              :     }
    1571              : }
    1572              : 
    1573              : 
    1574              : void
    1575          106 : MSNet::writeChargingStationOutput() const {
    1576              :     if (myStoppingPlaces.count(SUMO_TAG_CHARGING_STATION) > 0) {
    1577          204 :         OutputDevice& output = OutputDevice::getDeviceByOption("chargingstations-output");
    1578          586 :         for (const auto& it : myStoppingPlaces.find(SUMO_TAG_CHARGING_STATION)->second) {
    1579          484 :             static_cast<MSChargingStation*>(it.second)->writeChargingStationOutput(output);
    1580              :         }
    1581              :     }
    1582          106 : }
    1583              : 
    1584              : 
    1585              : void
    1586        40817 : MSNet::writeRailSignalBlocks() const {
    1587        81634 :     if (OptionsCont::getOptions().isSet("railsignal-block-output")) {
    1588         1367 :         OutputDevice& output = OutputDevice::getDeviceByOption("railsignal-block-output");
    1589         5420 :         for (auto tls : myLogics->getAllLogics()) {
    1590         4053 :             MSRailSignal* rs = dynamic_cast<MSRailSignal*>(tls);
    1591         4053 :             if (rs != nullptr) {
    1592         4009 :                 rs->writeBlocks(output, false);
    1593              :             }
    1594         1367 :         }
    1595         1367 :         MSDriveWay::writeDepatureBlocks(output, false);
    1596              :     }
    1597        81634 :     if (OptionsCont::getOptions().isSet("railsignal-vehicle-output")) {
    1598          185 :         OutputDevice& output = OutputDevice::getDeviceByOption("railsignal-vehicle-output");
    1599          599 :         for (auto tls : myLogics->getAllLogics()) {
    1600          414 :             MSRailSignal* rs = dynamic_cast<MSRailSignal*>(tls);
    1601          414 :             if (rs != nullptr) {
    1602          414 :                 rs->writeBlocks(output, true);
    1603              :             }
    1604          185 :         }
    1605          185 :         MSDriveWay::writeDepatureBlocks(output, true);
    1606              :     }
    1607        40817 : }
    1608              : 
    1609              : 
    1610              : void
    1611            5 : MSNet::writeOverheadWireSegmentOutput() const {
    1612              :     if (myStoppingPlaces.count(SUMO_TAG_OVERHEAD_WIRE_SEGMENT) > 0) {
    1613           10 :         OutputDevice& output = OutputDevice::getDeviceByOption("overheadwiresegments-output");
    1614           53 :         for (const auto& it : myStoppingPlaces.find(SUMO_TAG_OVERHEAD_WIRE_SEGMENT)->second) {
    1615           48 :             static_cast<MSOverheadWire*>(it.second)->writeOverheadWireSegmentOutput(output);
    1616              :         }
    1617              :     }
    1618            5 : }
    1619              : 
    1620              : 
    1621              : void
    1622            5 : MSNet::writeSubstationOutput() const {
    1623            5 :     if (myTractionSubstations.size() > 0) {
    1624            5 :         OutputDevice& output = OutputDevice::getDeviceByOption("substations-output");
    1625           10 :         output.setPrecision(OptionsCont::getOptions().getInt("substations-output.precision"));
    1626           13 :         for (auto& it : myTractionSubstations) {
    1627            8 :             it->writeTractionSubstationOutput(output);
    1628              :         }
    1629              :     }
    1630            5 : }
    1631              : 
    1632              : 
    1633              : MSTractionSubstation*
    1634           19 : MSNet::findTractionSubstation(const std::string& substationId) {
    1635           22 :     for (std::vector<MSTractionSubstation*>::iterator it = myTractionSubstations.begin(); it != myTractionSubstations.end(); ++it) {
    1636           22 :         if ((*it)->getID() == substationId) {
    1637              :             return *it;
    1638              :         }
    1639              :     }
    1640              :     return nullptr;
    1641              : }
    1642              : 
    1643              : 
    1644              : MSVehicleRouter&
    1645       127276 : MSNet::getRouterTT(int rngIndex, const Prohibitions& prohibited) const {
    1646       127276 :     if (MSGlobals::gNumSimThreads == 1) {
    1647       108372 :         rngIndex = 0;
    1648              :     }
    1649              :     if (myRouterTT.count(rngIndex) == 0) {
    1650         1472 :         const std::string routingAlgorithm = OptionsCont::getOptions().getString("routing-algorithm");
    1651         1472 :         if (routingAlgorithm == "dijkstra") {
    1652         1374 :             myRouterTT[rngIndex] = new DijkstraRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, &MSNet::getTravelTime, nullptr, false, nullptr, true);
    1653              :         } else {
    1654           98 :             if (routingAlgorithm != "astar") {
    1655            0 :                 WRITE_WARNINGF(TL("TraCI and Triggers cannot use routing algorithm '%'. using 'astar' instead."), routingAlgorithm);
    1656              :             }
    1657           98 :             myRouterTT[rngIndex] = new AStarRouter<MSEdge, SUMOVehicle, MSMapMatcher>(MSEdge::getAllEdges(), true, &MSNet::getTravelTime, nullptr, true);
    1658              :         }
    1659              :     }
    1660       127276 :     myRouterTT[rngIndex]->prohibit(prohibited);
    1661       127276 :     return *myRouterTT[rngIndex];
    1662              : }
    1663              : 
    1664              : 
    1665              : MSVehicleRouter&
    1666           11 : MSNet::getRouterEffort(int rngIndex, const Prohibitions& prohibited) const {
    1667           11 :     if (MSGlobals::gNumSimThreads == 1) {
    1668           11 :         rngIndex = 0;
    1669              :     }
    1670              :     if (myRouterEffort.count(rngIndex) == 0) {
    1671           11 :         myRouterEffort[rngIndex] = new DijkstraRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, &MSNet::getEffort, &MSNet::getTravelTime, false, nullptr, true);
    1672              :     }
    1673           11 :     myRouterEffort[rngIndex]->prohibit(prohibited);
    1674           11 :     return *myRouterEffort[rngIndex];
    1675              : }
    1676              : 
    1677              : 
    1678              : MSPedestrianRouter&
    1679       816099 : MSNet::getPedestrianRouter(int rngIndex, const Prohibitions& prohibited) const {
    1680       816099 :     if (MSGlobals::gNumSimThreads == 1) {
    1681       727216 :         rngIndex = 0;
    1682              :     }
    1683              :     if (myPedestrianRouter.count(rngIndex) == 0) {
    1684         2826 :         myPedestrianRouter[rngIndex] = new MSPedestrianRouter();
    1685              :     }
    1686       816099 :     myPedestrianRouter[rngIndex]->prohibit(prohibited);
    1687       816099 :     return *myPedestrianRouter[rngIndex];
    1688              : }
    1689              : 
    1690              : 
    1691              : MSTransportableRouter&
    1692       164543 : MSNet::getIntermodalRouter(int rngIndex, const int routingMode, const Prohibitions& prohibited) const {
    1693       164543 :     if (MSGlobals::gNumSimThreads == 1) {
    1694              :         rngIndex = 0;
    1695              :     }
    1696       164543 :     const OptionsCont& oc = OptionsCont::getOptions();
    1697       164543 :     const int key = rngIndex * oc.getInt("thread-rngs") + routingMode;
    1698              :     if (myIntermodalRouter.count(key) == 0) {
    1699         3892 :         const int carWalk = SUMOVehicleParserHelper::parseCarWalkTransfer(oc, MSDevice_Taxi::hasFleet() || myInserter->hasTaxiFlow());
    1700         3712 :         const std::string routingAlgorithm = OptionsCont::getOptions().getString("routing-algorithm");
    1701         3712 :         const double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
    1702         3712 :         if (routingMode == libsumo::ROUTING_MODE_COMBINED) {
    1703            0 :             myIntermodalRouter[key] = new MSTransportableRouter(MSNet::adaptIntermodalRouter, carWalk, taxiWait, routingAlgorithm, routingMode, new FareModul());
    1704              :         } else {
    1705         3712 :             myIntermodalRouter[key] = new MSTransportableRouter(MSNet::adaptIntermodalRouter, carWalk, taxiWait, routingAlgorithm, routingMode);
    1706              :         }
    1707              :     }
    1708       164543 :     myIntermodalRouter[key]->prohibit(prohibited);
    1709       164543 :     return *myIntermodalRouter[key];
    1710              : }
    1711              : 
    1712              : 
    1713              : void
    1714        42425 : MSNet::resetIntermodalRouter() const {
    1715        46136 :     for (auto& router : myIntermodalRouter) {
    1716         3711 :         delete router.second;
    1717              :     }
    1718              :     myIntermodalRouter.clear();
    1719        42425 : }
    1720              : 
    1721              : 
    1722              : void
    1723         4847 : MSNet::adaptIntermodalRouter(MSTransportableRouter& router) {
    1724         9694 :     double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
    1725              :     // add access to all parking areas
    1726              :     EffortCalculator* const external = router.getExternalEffort();
    1727        14536 :     for (const auto& stopType : myInstance->myStoppingPlaces) {
    1728              :         // add access to all stopping places
    1729         9689 :         const SumoXMLTag element = stopType.first;
    1730        35748 :         for (const auto& i : stopType.second) {
    1731        26059 :             const MSEdge* const edge = &i.second->getLane().getEdge();
    1732        26059 :             router.getNetwork()->addAccess(i.first, edge, i.second->getBeginLanePosition(), i.second->getEndLanePosition(),
    1733              :                                            0., element, false, taxiWait);
    1734        26059 :             if (element == SUMO_TAG_BUS_STOP) {
    1735              :                 // add access to all public transport stops
    1736        12550 :                 for (const auto& a : i.second->getAllAccessPos()) {
    1737         1123 :                     router.getNetwork()->addAccess(i.first, &a.lane->getEdge(), a.startPos, a.endPos, a.length, element, true, taxiWait);
    1738              :                 }
    1739        11427 :                 if (external != nullptr) {
    1740            0 :                     external->addStop(router.getNetwork()->getStopEdge(i.first)->getNumericalID(), *i.second);
    1741              :                 }
    1742              :             }
    1743              :         }
    1744              :     }
    1745         4847 :     myInstance->getInsertionControl().adaptIntermodalRouter(router);
    1746         4847 :     myInstance->getVehicleControl().adaptIntermodalRouter(router);
    1747              :     // add access to transfer from walking to taxi-use
    1748         4847 :     if ((router.getCarWalkTransfer() & ModeChangeOptions::TAXI_PICKUP_ANYWHERE) != 0) {
    1749        61243 :         for (MSEdge* edge : myInstance->getEdgeControl().getEdges()) {
    1750        61013 :             if ((edge->getPermissions() & SVC_PEDESTRIAN) != 0 && (edge->getPermissions() & SVC_TAXI) != 0) {
    1751        20301 :                 router.getNetwork()->addCarAccess(edge, SVC_TAXI, taxiWait);
    1752              :             }
    1753              :         }
    1754              :     }
    1755         4847 : }
    1756              : 
    1757              : 
    1758              : bool
    1759        42464 : MSNet::checkElevation() {
    1760        42464 :     const MSEdgeVector& edges = myEdges->getEdges();
    1761      1826616 :     for (MSEdgeVector::const_iterator e = edges.begin(); e != edges.end(); ++e) {
    1762      3929866 :         for (std::vector<MSLane*>::const_iterator i = (*e)->getLanes().begin(); i != (*e)->getLanes().end(); ++i) {
    1763      2145714 :             if ((*i)->getShape().hasElevation()) {
    1764              :                 return true;
    1765              :             }
    1766              :         }
    1767              :     }
    1768              :     return false;
    1769              : }
    1770              : 
    1771              : 
    1772              : bool
    1773        42464 : MSNet::checkWalkingarea() {
    1774      1256709 :     for (const MSEdge* e : myEdges->getEdges()) {
    1775      1224828 :         if (e->getFunction() == SumoXMLEdgeFunc::WALKINGAREA) {
    1776              :             return true;
    1777              :         }
    1778              :     }
    1779              :     return false;
    1780              : }
    1781              : 
    1782              : 
    1783              : bool
    1784        42464 : MSNet::checkBidiEdges() {
    1785      1763535 :     for (const MSEdge* e : myEdges->getEdges()) {
    1786      1722327 :         if (e->getBidiEdge() != nullptr) {
    1787              :             return true;
    1788              :         }
    1789              :     }
    1790              :     return false;
    1791              : }
    1792              : 
    1793              : bool
    1794          303 : MSNet::warnOnce(const std::string& typeAndID) {
    1795          303 :     if (myWarnedOnce.find(typeAndID) == myWarnedOnce.end()) {
    1796          303 :         myWarnedOnce[typeAndID] = true;
    1797          303 :         return true;
    1798              :     }
    1799              :     return false;
    1800              : }
    1801              : 
    1802              : 
    1803              : MSMapMatcher*
    1804           35 : MSNet::getMapMatcher() const {
    1805           35 :     auto loader = myRouteLoaders->getFirstLoader();
    1806           35 :     if (loader != nullptr) {
    1807           35 :         return dynamic_cast<MSMapMatcher*>(loader->getRouteHandler());
    1808              :     } else {
    1809              :         return nullptr;
    1810              :     }
    1811              : }
    1812              : 
    1813              : void
    1814            0 : MSNet::quickReload() {
    1815            0 :     const OptionsCont& oc = OptionsCont::getOptions();
    1816            0 :     clearState(string2time(oc.getString("begin")), true);
    1817            0 :     NLBuilder::initRandomness();
    1818              :     // load traffic from additional files
    1819            0 :     for (std::string file : oc.getStringVector("additional-files")) {
    1820              :         // ignore failure on parsing calibrator flow
    1821            0 :         MSRouteHandler rh(file, true);
    1822            0 :         const long before = PROGRESS_BEGIN_TIME_MESSAGE("Loading traffic from '" + file + "'");
    1823            0 :         if (!XMLSubSys::runParser(rh, file, false)) {
    1824            0 :             throw ProcessError(TLF("Loading of % failed.", file));
    1825              :         }
    1826            0 :         PROGRESS_TIME_MESSAGE(before);
    1827            0 :     }
    1828            0 :     delete myRouteLoaders;
    1829            0 :     myRouteLoaders = NLBuilder::buildRouteLoaderControl(OptionsCont::getOptions());
    1830            0 :     updateGUI();
    1831            0 : }
    1832              : 
    1833              : 
    1834              : SUMOTime
    1835          172 : MSNet::loadState(const std::string& fileName, const bool catchExceptions) {
    1836              :     // load time only
    1837          172 :     const SUMOTime newTime = MSStateHandler::MSStateTimeHandler::getTime(fileName);
    1838              :     // clean up state
    1839          162 :     clearState(newTime);
    1840              :     // load state
    1841          162 :     MSStateHandler h(fileName, 0);
    1842          162 :     XMLSubSys::runParser(h, fileName, false, false, false, catchExceptions);
    1843          158 :     if (MsgHandler::getErrorInstance()->wasInformed()) {
    1844            0 :         throw ProcessError(TLF("Loading state from '%' failed.", fileName));
    1845              :     }
    1846              :     // reset route loaders
    1847          158 :     delete myRouteLoaders;
    1848          158 :     myRouteLoaders = NLBuilder::buildRouteLoaderControl(OptionsCont::getOptions());
    1849              :     // prevent loading errors on rewound route file
    1850          158 :     MSGlobals::gStateLoaded = true;
    1851              : 
    1852          158 :     updateGUI();
    1853          158 :     return newTime;
    1854          162 : }
    1855              : 
    1856              : 
    1857              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1