LCOV - code coverage report
Current view: top level - src/microsim - MSNet.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 95.0 % 918 872
Test Date: 2025-11-13 15:38:19 Functions: 94.4 % 71 67

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

Generated by: LCOV version 2.0-1