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

Generated by: LCOV version 2.0-1