LCOV - code coverage report
Current view: top level - src/microsim - MSNet.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 94.6 % 864 817
Test Date: 2024-11-22 15:46:21 Functions: 94.0 % 67 63

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2024 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/SUMOVehicleParserHelper.h>
      63              : #include <utils/xml/XMLSubSys.h>
      64              : #include <traci-server/TraCIServer.h>
      65              : #include <libsumo/Helper.h>
      66              : #include <libsumo/Simulation.h>
      67              : #include <mesosim/MELoop.h>
      68              : #include <mesosim/MESegment.h>
      69              : #include <microsim/output/MSDetectorControl.h>
      70              : #include <microsim/MSVehicleTransfer.h>
      71              : #include <microsim/devices/MSRoutingEngine.h>
      72              : #include <microsim/devices/MSDevice_Vehroutes.h>
      73              : #include <microsim/devices/MSDevice_Tripinfo.h>
      74              : #include <microsim/devices/MSDevice_BTsender.h>
      75              : #include <microsim/devices/MSDevice_SSM.h>
      76              : #include <microsim/devices/MSDevice_ElecHybrid.h>
      77              : #include <microsim/devices/MSDevice_ToC.h>
      78              : #include <microsim/devices/MSDevice_Taxi.h>
      79              : #include <microsim/output/MSBatteryExport.h>
      80              : #include <microsim/output/MSChargingStationExport.h>
      81              : #include <microsim/output/MSElecHybridExport.h>
      82              : #include <microsim/output/MSEmissionExport.h>
      83              : #include <microsim/output/MSFCDExport.h>
      84              : #include <microsim/output/MSFullExport.h>
      85              : #include <microsim/output/MSQueueExport.h>
      86              : #include <microsim/output/MSVTKExport.h>
      87              : #include <microsim/output/MSXMLRawOut.h>
      88              : #include <microsim/output/MSAmitranTrajectories.h>
      89              : #include <microsim/output/MSStopOut.h>
      90              : #include <microsim/transportables/MSPModel.h>
      91              : #include <microsim/transportables/MSPerson.h>
      92              : #include <microsim/traffic_lights/MSTrafficLightLogic.h>
      93              : #include <microsim/transportables/MSTransportableControl.h>
      94              : #include <microsim/traffic_lights/MSRailSignal.h>
      95              : #include <microsim/traffic_lights/MSRailSignalConstraint.h>
      96              : #include <microsim/traffic_lights/MSRailSignalControl.h>
      97              : #include <microsim/traffic_lights/MSTLLogicControl.h>
      98              : #include <microsim/traffic_lights/MSDriveWay.h>
      99              : #include <microsim/trigger/MSCalibrator.h>
     100              : #include <microsim/trigger/MSChargingStation.h>
     101              : #include <microsim/trigger/MSLaneSpeedTrigger.h>
     102              : #include <microsim/trigger/MSOverheadWire.h>
     103              : #include <microsim/trigger/MSTriggeredRerouter.h>
     104              : #include <utils/router/FareModul.h>
     105              : #include <netload/NLBuilder.h>
     106              : 
     107              : #include "MSEdgeControl.h"
     108              : #include "MSJunctionControl.h"
     109              : #include "MSInsertionControl.h"
     110              : #include "MSDynamicShapeUpdater.h"
     111              : #include "MSEventControl.h"
     112              : #include "MSEdge.h"
     113              : #include "MSJunction.h"
     114              : #include "MSJunctionLogic.h"
     115              : #include "MSLane.h"
     116              : #include "MSVehicleControl.h"
     117              : #include "MSVehicleTransfer.h"
     118              : #include "MSRoute.h"
     119              : #include "MSGlobals.h"
     120              : #include "MSEdgeWeightsStorage.h"
     121              : #include "MSStateHandler.h"
     122              : #include "MSFrame.h"
     123              : #include "MSParkingArea.h"
     124              : #include "MSStoppingPlace.h"
     125              : #include "MSNet.h"
     126              : 
     127              : 
     128              : // ===========================================================================
     129              : // debug constants
     130              : // ===========================================================================
     131              : //#define DEBUG_SIMSTEP
     132              : 
     133              : 
     134              : // ===========================================================================
     135              : // static member definitions
     136              : // ===========================================================================
     137              : MSNet* MSNet::myInstance = nullptr;
     138              : 
     139              : const std::string MSNet::STAGE_EVENTS("events");
     140              : const std::string MSNet::STAGE_MOVEMENTS("move");
     141              : const std::string MSNet::STAGE_LANECHANGE("laneChange");
     142              : const std::string MSNet::STAGE_INSERTIONS("insertion");
     143              : const std::string MSNet::STAGE_REMOTECONTROL("remoteControl");
     144              : 
     145              : const NamedObjectCont<MSStoppingPlace*> MSNet::myEmptyStoppingPlaceCont;
     146              : 
     147              : // ===========================================================================
     148              : // static member method definitions
     149              : // ===========================================================================
     150              : double
     151          178 : MSNet::getEffort(const MSEdge* const e, const SUMOVehicle* const v, double t) {
     152              :     double value;
     153          178 :     const MSVehicle* const veh = dynamic_cast<const MSVehicle* const>(v);
     154          178 :     if (veh != nullptr && veh->getWeightsStorage().retrieveExistingEffort(e, t, value)) {
     155            2 :         return value;
     156              :     }
     157          176 :     if (getInstance()->getWeightsStorage().retrieveExistingEffort(e, t, value)) {
     158            2 :         return value;
     159              :     }
     160              :     return 0;
     161              : }
     162              : 
     163              : 
     164              : double
     165      5181801 : MSNet::getTravelTime(const MSEdge* const e, const SUMOVehicle* const v, double t) {
     166              :     double value;
     167      5181801 :     const MSVehicle* const veh = dynamic_cast<const MSVehicle* const>(v);
     168      5180812 :     if (veh != nullptr && veh->getWeightsStorage().retrieveExistingTravelTime(e, t, value)) {
     169          317 :         return value;
     170              :     }
     171      5181484 :     if (getInstance()->getWeightsStorage().retrieveExistingTravelTime(e, t, value)) {
     172          155 :         return value;
     173              :     }
     174      5181329 :     if (veh != nullptr && veh->getRoutingMode() == libsumo::ROUTING_MODE_AGGREGATED_CUSTOM) {
     175         1755 :         return MSRoutingEngine::getEffortExtra(e, v, t);
     176              :     }
     177      5179574 :     return e->getMinimumTravelTime(v);
     178              : }
     179              : 
     180              : 
     181              : // ---------------------------------------------------------------------------
     182              : // MSNet - methods
     183              : // ---------------------------------------------------------------------------
     184              : MSNet*
     185   4802820594 : MSNet::getInstance(void) {
     186   4802820594 :     if (myInstance != nullptr) {
     187   4802820549 :         return myInstance;
     188              :     }
     189           90 :     throw ProcessError(TL("A network was not yet constructed."));
     190              : }
     191              : 
     192              : void
     193        42995 : MSNet::initStatic() {
     194        42995 :     MSDriveWay::init();
     195        42995 : }
     196              : 
     197              : void
     198        40024 : MSNet::cleanupStatic() {
     199        40024 :     if (!MSGlobals::gUseMesoSim) {
     200        34693 :         MSVehicle::Influencer::cleanup();
     201              :     }
     202        40024 : }
     203              : 
     204              : 
     205        42995 : MSNet::MSNet(MSVehicleControl* vc, MSEventControl* beginOfTimestepEvents,
     206              :              MSEventControl* endOfTimestepEvents,
     207              :              MSEventControl* insertionEvents,
     208        42995 :              ShapeContainer* shapeCont):
     209        42995 :     myAmInterrupted(false),
     210        42995 :     myVehiclesMoved(0),
     211        42995 :     myPersonsMoved(0),
     212        42995 :     myHavePermissions(false),
     213        42995 :     myHasInternalLinks(false),
     214        42995 :     myJunctionHigherSpeeds(false),
     215        42995 :     myHasElevation(false),
     216        42995 :     myHasPedestrianNetwork(false),
     217        42995 :     myHasBidiEdges(false),
     218        42995 :     myEdgeDataEndTime(-1),
     219        42995 :     myDynamicShapeUpdater(nullptr) {
     220        42995 :     if (myInstance != nullptr) {
     221            0 :         throw ProcessError(TL("A network was already constructed."));
     222              :     }
     223        42995 :     OptionsCont& oc = OptionsCont::getOptions();
     224        42995 :     myStep = string2time(oc.getString("begin"));
     225        42995 :     myMaxTeleports = oc.getInt("max-num-teleports");
     226        42995 :     myLogExecutionTime = !oc.getBool("no-duration-log");
     227        42995 :     myLogStepNumber = !oc.getBool("no-step-log");
     228        42995 :     myLogStepPeriod = oc.getInt("step-log.period");
     229       171980 :     myInserter = new MSInsertionControl(*vc, string2time(oc.getString("max-depart-delay")), oc.getBool("eager-insert"), oc.getInt("max-num-vehicles"),
     230       171980 :                                         string2time(oc.getString("random-depart-offset")));
     231        42995 :     myVehicleControl = vc;
     232        42995 :     myDetectorControl = new MSDetectorControl();
     233        42995 :     myEdges = nullptr;
     234        42995 :     myJunctions = nullptr;
     235        42995 :     myRouteLoaders = nullptr;
     236        42995 :     myLogics = nullptr;
     237        42995 :     myPersonControl = nullptr;
     238        42995 :     myContainerControl = nullptr;
     239        42995 :     myEdgeWeights = nullptr;
     240        42995 :     myShapeContainer = shapeCont == nullptr ? new ShapeContainer() : shapeCont;
     241              : 
     242        42995 :     myBeginOfTimestepEvents = beginOfTimestepEvents;
     243        42995 :     myEndOfTimestepEvents = endOfTimestepEvents;
     244        42995 :     myInsertionEvents = insertionEvents;
     245        42995 :     myLanesRTree.first = false;
     246              : 
     247        42995 :     if (MSGlobals::gUseMesoSim) {
     248        10858 :         MSGlobals::gMesoNet = new MELoop(string2time(oc.getString("meso-recheck")));
     249              :     }
     250        42995 :     myInstance = this;
     251        42995 :     initStatic();
     252        42995 : }
     253              : 
     254              : 
     255              : void
     256        42556 : MSNet::closeBuilding(const OptionsCont& oc, MSEdgeControl* edges, MSJunctionControl* junctions,
     257              :                      SUMORouteLoaderControl* routeLoaders,
     258              :                      MSTLLogicControl* tlc,
     259              :                      std::vector<SUMOTime> stateDumpTimes,
     260              :                      std::vector<std::string> stateDumpFiles,
     261              :                      bool hasInternalLinks,
     262              :                      bool junctionHigherSpeeds,
     263              :                      const MMVersion& version) {
     264        42556 :     myEdges = edges;
     265        42556 :     myJunctions = junctions;
     266        42556 :     myRouteLoaders = routeLoaders;
     267        42556 :     myLogics = tlc;
     268              :     // save the time the network state shall be saved at
     269        42556 :     myStateDumpTimes = stateDumpTimes;
     270        42556 :     myStateDumpFiles = stateDumpFiles;
     271        42556 :     myStateDumpPeriod = string2time(oc.getString("save-state.period"));
     272        42556 :     myStateDumpPrefix = oc.getString("save-state.prefix");
     273        42556 :     myStateDumpSuffix = oc.getString("save-state.suffix");
     274              : 
     275              :     // initialise performance computation
     276        42556 :     mySimBeginMillis = SysUtils::getCurrentMillis();
     277        42556 :     myTraCIMillis = 0;
     278        42556 :     myHasInternalLinks = hasInternalLinks;
     279        42556 :     myJunctionHigherSpeeds = junctionHigherSpeeds;
     280        42556 :     myHasElevation = checkElevation();
     281        42556 :     myHasPedestrianNetwork = checkWalkingarea();
     282        42556 :     myHasBidiEdges = checkBidiEdges();
     283              :     myVersion = version;
     284        42556 :     if ((!MSGlobals::gUsingInternalLanes || !myHasInternalLinks)
     285        16312 :             && MSGlobals::gWeightsSeparateTurns > 0) {
     286           20 :         throw ProcessError(TL("Option weights.separate-turns is only supported when simulating with internal lanes"));
     287              :     }
     288        42546 : }
     289              : 
     290              : 
     291        72536 : MSNet::~MSNet() {
     292        40024 :     cleanupStatic();
     293              :     // delete controls
     294        40024 :     delete myJunctions;
     295        40024 :     delete myDetectorControl;
     296              :     // delete mean data
     297        40024 :     delete myEdges;
     298        40024 :     delete myInserter;
     299        40024 :     myInserter = nullptr;
     300        40024 :     delete myLogics;
     301        40024 :     delete myRouteLoaders;
     302        40024 :     if (myPersonControl != nullptr) {
     303         6923 :         delete myPersonControl;
     304         6923 :         myPersonControl = nullptr; // just to have that clear for later cleanups
     305              :     }
     306        40024 :     if (myContainerControl != nullptr) {
     307          739 :         delete myContainerControl;
     308          739 :         myContainerControl = nullptr; // just to have that clear for later cleanups
     309              :     }
     310        40024 :     delete myVehicleControl; // must happen after deleting transportables
     311              :     // delete events late so that vehicles can get rid of references first
     312        40024 :     delete myBeginOfTimestepEvents;
     313        40024 :     myBeginOfTimestepEvents = nullptr;
     314        40024 :     delete myEndOfTimestepEvents;
     315        40024 :     myEndOfTimestepEvents = nullptr;
     316        40024 :     delete myInsertionEvents;
     317        40024 :     myInsertionEvents = nullptr;
     318        40024 :     delete myShapeContainer;
     319        40024 :     delete myEdgeWeights;
     320        41853 :     for (auto& router : myRouterTT) {
     321         1829 :         delete router.second;
     322              :     }
     323              :     myRouterTT.clear();
     324        40035 :     for (auto& router : myRouterEffort) {
     325           11 :         delete router.second;
     326              :     }
     327              :     myRouterEffort.clear();
     328        42651 :     for (auto& router : myPedestrianRouter) {
     329         2627 :         delete router.second;
     330              :     }
     331              :     myPedestrianRouter.clear();
     332        43460 :     for (auto& router : myIntermodalRouter) {
     333         3436 :         delete router.second;
     334              :     }
     335              :     myIntermodalRouter.clear();
     336              :     myLanesRTree.second.RemoveAll();
     337        40024 :     clearAll();
     338        40024 :     if (MSGlobals::gUseMesoSim) {
     339         5331 :         delete MSGlobals::gMesoNet;
     340              :     }
     341        40024 :     myInstance = nullptr;
     342       152584 : }
     343              : 
     344              : 
     345              : void
     346          217 : MSNet::addRestriction(const std::string& id, const SUMOVehicleClass svc, const double speed) {
     347          217 :     myRestrictions[id][svc] = speed;
     348          217 : }
     349              : 
     350              : 
     351              : const std::map<SUMOVehicleClass, double>*
     352      2162886 : MSNet::getRestrictions(const std::string& id) const {
     353              :     std::map<std::string, std::map<SUMOVehicleClass, double> >::const_iterator i = myRestrictions.find(id);
     354      2162886 :     if (i == myRestrictions.end()) {
     355              :         return nullptr;
     356              :     }
     357         1094 :     return &i->second;
     358              : }
     359              : 
     360              : void
     361           22 : MSNet::addMesoType(const std::string& typeID, const MESegment::MesoEdgeType& edgeType) {
     362           22 :     myMesoEdgeTypes[typeID] = edgeType;
     363           22 : }
     364              : 
     365              : const MESegment::MesoEdgeType&
     366       597989 : MSNet::getMesoType(const std::string& typeID) {
     367              :     if (myMesoEdgeTypes.count(typeID) == 0) {
     368              :         // init defaults
     369         5813 :         const OptionsCont& oc = OptionsCont::getOptions();
     370              :         MESegment::MesoEdgeType edgeType;
     371         5813 :         edgeType.tauff = string2time(oc.getString("meso-tauff"));
     372         5813 :         edgeType.taufj = string2time(oc.getString("meso-taufj"));
     373         5813 :         edgeType.taujf = string2time(oc.getString("meso-taujf"));
     374         5813 :         edgeType.taujj = string2time(oc.getString("meso-taujj"));
     375         5813 :         edgeType.jamThreshold = oc.getFloat("meso-jam-threshold");
     376         5813 :         edgeType.junctionControl = oc.getBool("meso-junction-control");
     377         5813 :         edgeType.tlsPenalty = oc.getFloat("meso-tls-penalty");
     378         5813 :         edgeType.tlsFlowPenalty = oc.getFloat("meso-tls-flow-penalty");
     379         5813 :         edgeType.minorPenalty = string2time(oc.getString("meso-minor-penalty"));
     380         5813 :         edgeType.overtaking = oc.getBool("meso-overtaking");
     381         5813 :         myMesoEdgeTypes[typeID] = edgeType;
     382              :     }
     383       597989 :     return myMesoEdgeTypes[typeID];
     384              : }
     385              : 
     386              : 
     387              : bool
     388      7046480 : MSNet::hasFlow(const std::string& id) const {
     389              :     // inserter is deleted at the end of the simulation
     390      7046480 :     return myInserter != nullptr && myInserter->hasFlow(id);
     391              : }
     392              : 
     393              : 
     394              : MSNet::SimulationState
     395        31063 : MSNet::simulate(SUMOTime start, SUMOTime stop) {
     396              :     // report the begin when wished
     397        62126 :     WRITE_MESSAGEF(TL("Simulation version % started with time: %."), VERSION_STRING, time2string(start));
     398              :     // the simulation loop
     399              :     SimulationState state = SIMSTATE_RUNNING;
     400              :     // state loading may have changed the start time so we need to reinit it
     401        31063 :     myStep = start;
     402              :     int numSteps = 0;
     403              :     bool doStepLog = false;
     404     85885328 :     while (state == SIMSTATE_RUNNING) {
     405     85854581 :         doStepLog = myLogStepNumber && (numSteps % myLogStepPeriod == 0);
     406              :         if (doStepLog) {
     407          113 :             preSimStepOutput();
     408              :         }
     409     85854581 :         simulationStep();
     410     85854265 :         if (doStepLog) {
     411          113 :             postSimStepOutput();
     412              :         }
     413     85854265 :         state = adaptToState(simulationState(stop));
     414              : #ifdef DEBUG_SIMSTEP
     415              :         std::cout << SIMTIME << " MSNet::simulate(" << start << ", " << stop << ")"
     416              :                   << "\n simulation state: " << getStateMessage(state)
     417              :                   << std::endl;
     418              : #endif
     419     85854265 :         numSteps++;
     420              :     }
     421        30747 :     if (myLogStepNumber && !doStepLog) {
     422              :         // ensure some output on the last step
     423           16 :         preSimStepOutput();
     424           16 :         postSimStepOutput();
     425              :     }
     426              :     // exit simulation loop
     427        30747 :     if (myLogStepNumber) {
     428              :         // start new line for final verbose output
     429           20 :         std::cout << "\n";
     430              :     }
     431        30747 :     closeSimulation(start, getStateMessage(state));
     432        30747 :     return state;
     433              : }
     434              : 
     435              : 
     436              : void
     437     91813778 : MSNet::loadRoutes() {
     438     91813778 :     myRouteLoaders->loadNext(myStep);
     439     91810723 : }
     440              : 
     441              : 
     442              : const std::string
     443        11496 : MSNet::generateStatistics(const SUMOTime start, const long now) {
     444        11496 :     std::ostringstream msg;
     445        11496 :     if (myLogExecutionTime) {
     446        11191 :         const long duration = now - mySimBeginMillis;
     447              :         // print performance notice
     448        22382 :         msg << "Performance:\n" << " Duration: " << elapsedMs2string(duration) << "\n";
     449        11191 :         if (duration != 0) {
     450        11115 :             if (TraCIServer::getInstance() != nullptr) {
     451         4119 :                 msg << " TraCI-Duration: " << elapsedMs2string(myTraCIMillis) << "\n";
     452              :             }
     453        11115 :             msg << " Real time factor: " << (STEPS2TIME(myStep - start) * 1000. / (double)duration) << "\n";
     454              :             msg.setf(std::ios::fixed, std::ios::floatfield);     // use decimal format
     455              :             msg.setf(std::ios::showpoint);    // print decimal point
     456        11115 :             msg << " UPS: " << ((double)myVehiclesMoved / ((double)duration / 1000)) << "\n";
     457        11115 :             if (myPersonsMoved > 0) {
     458         2108 :                 msg << " UPS-Persons: " << ((double)myPersonsMoved / ((double)duration / 1000)) << "\n";
     459              :             }
     460              :         }
     461              :         // print vehicle statistics
     462        11191 :         const std::string discardNotice = ((myVehicleControl->getLoadedVehicleNo() != myVehicleControl->getDepartedVehicleNo()) ?
     463        15109 :                                            " (Loaded: " + toString(myVehicleControl->getLoadedVehicleNo()) + ")" : "");
     464              :         msg << "Vehicles:\n"
     465        11191 :             << " Inserted: " << myVehicleControl->getDepartedVehicleNo() << discardNotice << "\n"
     466        22382 :             << " Running: " << myVehicleControl->getRunningVehicleNo() << "\n"
     467        22382 :             << " Waiting: " << myInserter->getWaitingVehicleNo() << "\n";
     468              : 
     469        11191 :         if (myVehicleControl->getTeleportCount() > 0 || myVehicleControl->getCollisionCount() > 0) {
     470              :             // print optional teleport statistics
     471              :             std::vector<std::string> reasons;
     472          617 :             if (myVehicleControl->getCollisionCount() > 0) {
     473          618 :                 reasons.push_back("Collisions: " + toString(myVehicleControl->getCollisionCount()));
     474              :             }
     475          617 :             if (myVehicleControl->getTeleportsJam() > 0) {
     476          326 :                 reasons.push_back("Jam: " + toString(myVehicleControl->getTeleportsJam()));
     477              :             }
     478          617 :             if (myVehicleControl->getTeleportsYield() > 0) {
     479          192 :                 reasons.push_back("Yield: " + toString(myVehicleControl->getTeleportsYield()));
     480              :             }
     481          617 :             if (myVehicleControl->getTeleportsWrongLane() > 0) {
     482          256 :                 reasons.push_back("Wrong Lane: " + toString(myVehicleControl->getTeleportsWrongLane()));
     483              :             }
     484         1851 :             msg << " Teleports: " << myVehicleControl->getTeleportCount() << " (" << joinToString(reasons, ", ") << ")\n";
     485          617 :         }
     486        11191 :         if (myVehicleControl->getEmergencyStops() > 0) {
     487           53 :             msg << " Emergency Stops: " << myVehicleControl->getEmergencyStops() << "\n";
     488              :         }
     489        11191 :         if (myVehicleControl->getEmergencyBrakingCount() > 0) {
     490          277 :             msg << " Emergency Braking: " << myVehicleControl->getEmergencyBrakingCount() << "\n";
     491              :         }
     492        11191 :         if (myPersonControl != nullptr && myPersonControl->getLoadedNumber() > 0) {
     493              :             msg << "Persons:\n"
     494         2130 :                 << " Inserted: " << myPersonControl->getLoadedNumber() << "\n"
     495         4260 :                 << " Running: " << myPersonControl->getRunningNumber() << "\n";
     496         2130 :             if (myPersonControl->getJammedNumber() > 0) {
     497           56 :                 msg << " Jammed: " << myPersonControl->getJammedNumber() << "\n";
     498              :             }
     499         2130 :             if (myPersonControl->getTeleportCount() > 0) {
     500              :                 std::vector<std::string> reasons;
     501            7 :                 if (myPersonControl->getTeleportsAbortWait() > 0) {
     502            0 :                     reasons.push_back("Abort Wait: " + toString(myPersonControl->getTeleportsAbortWait()));
     503              :                 }
     504            7 :                 if (myPersonControl->getTeleportsWrongDest() > 0) {
     505           14 :                     reasons.push_back("Wrong Dest: " + toString(myPersonControl->getTeleportsWrongDest()));
     506              :                 }
     507           21 :                 msg << " Teleports: " << myPersonControl->getTeleportCount() << " (" << joinToString(reasons, ", ") << ")\n";
     508            7 :             }
     509              :         }
     510        11191 :         if (myContainerControl != nullptr && myContainerControl->getLoadedNumber() > 0) {
     511              :             msg << "Containers:\n"
     512           76 :                 << " Inserted: " << myContainerControl->getLoadedNumber() << "\n"
     513          152 :                 << " Running: " << myContainerControl->getRunningNumber() << "\n";
     514           76 :             if (myContainerControl->getJammedNumber() > 0) {
     515            0 :                 msg << " Jammed: " << myContainerControl->getJammedNumber() << "\n";
     516              :             }
     517           76 :             if (myContainerControl->getTeleportCount() > 0) {
     518              :                 std::vector<std::string> reasons;
     519            0 :                 if (myContainerControl->getTeleportsAbortWait() > 0) {
     520            0 :                     reasons.push_back("Abort Wait: " + toString(myContainerControl->getTeleportsAbortWait()));
     521              :                 }
     522            0 :                 if (myContainerControl->getTeleportsWrongDest() > 0) {
     523            0 :                     reasons.push_back("Wrong Dest: " + toString(myContainerControl->getTeleportsWrongDest()));
     524              :                 }
     525            0 :                 msg << " Teleports: " << myContainerControl->getTeleportCount() << " (" << joinToString(reasons, ", ") << ")\n";
     526            0 :             }
     527              :         }
     528              :     }
     529        22992 :     if (OptionsCont::getOptions().getBool("duration-log.statistics")) {
     530         5316 :         msg << MSDevice_Tripinfo::printStatistics();
     531              :     }
     532              :     std::string result = msg.str();
     533              :     result.erase(result.end() - 1);
     534        11496 :     return result;
     535        11496 : }
     536              : 
     537              : 
     538              : void
     539        10356 : MSNet::writeCollisions() const {
     540        20712 :     OutputDevice& od = OutputDevice::getDeviceByOption("collision-output");
     541        10539 :     for (const auto& item : myCollisions) {
     542          366 :         for (const auto& c : item.second) {
     543          366 :             od.openTag("collision");
     544          366 :             od.writeAttr("time", time2string(getCurrentTimeStep()));
     545          183 :             od.writeAttr("type", c.type);
     546          183 :             od.writeAttr("lane", c.lane->getID());
     547          183 :             od.writeAttr("pos", c.pos);
     548          183 :             od.writeAttr("collider", item.first);
     549          183 :             od.writeAttr("victim", c.victim);
     550          183 :             od.writeAttr("colliderType", c.colliderType);
     551          183 :             od.writeAttr("victimType", c.victimType);
     552          183 :             od.writeAttr("colliderSpeed", c.colliderSpeed);
     553          183 :             od.writeAttr("victimSpeed", c.victimSpeed);
     554          366 :             od.closeTag();
     555              :         }
     556              :     }
     557        10356 : }
     558              : 
     559              : 
     560              : void
     561          366 : MSNet::writeStatistics(const SUMOTime start, const long now) const {
     562          366 :     const long duration = now - mySimBeginMillis;
     563          366 :     OutputDevice& od = OutputDevice::getDeviceByOption("statistic-output");
     564          366 :     od.openTag("performance");
     565          732 :     od.writeAttr("clockBegin", time2string(mySimBeginMillis));
     566          732 :     od.writeAttr("clockEnd", time2string(now));
     567          732 :     od.writeAttr("clockDuration", time2string(duration));
     568          732 :     od.writeAttr("traciDuration", time2string(myTraCIMillis));
     569          366 :     od.writeAttr("realTimeFactor", duration != 0 ? (double)(myStep - start) / (double)duration : -1);
     570          366 :     od.writeAttr("vehicleUpdatesPerSecond", duration != 0 ? (double)myVehiclesMoved / ((double)duration / 1000) : -1);
     571          366 :     od.writeAttr("personUpdatesPerSecond", duration != 0 ? (double)myPersonsMoved / ((double)duration / 1000) : -1);
     572          732 :     od.writeAttr("begin", time2string(start));
     573          732 :     od.writeAttr("end", time2string(myStep));
     574          732 :     od.writeAttr("duration", time2string(myStep - start));
     575          366 :     od.closeTag();
     576          366 :     od.openTag("vehicles");
     577          366 :     od.writeAttr("loaded", myVehicleControl->getLoadedVehicleNo());
     578          366 :     od.writeAttr("inserted", myVehicleControl->getDepartedVehicleNo());
     579          366 :     od.writeAttr("running", myVehicleControl->getRunningVehicleNo());
     580          366 :     od.writeAttr("waiting", myInserter->getWaitingVehicleNo());
     581          366 :     od.closeTag();
     582          366 :     od.openTag("teleports");
     583          366 :     od.writeAttr("total", myVehicleControl->getTeleportCount());
     584          366 :     od.writeAttr("jam", myVehicleControl->getTeleportsJam());
     585          366 :     od.writeAttr("yield", myVehicleControl->getTeleportsYield());
     586          366 :     od.writeAttr("wrongLane", myVehicleControl->getTeleportsWrongLane());
     587          366 :     od.closeTag();
     588          366 :     od.openTag("safety");
     589          366 :     od.writeAttr("collisions", myVehicleControl->getCollisionCount());
     590          366 :     od.writeAttr("emergencyStops", myVehicleControl->getEmergencyStops());
     591          366 :     od.writeAttr("emergencyBraking", myVehicleControl->getEmergencyBrakingCount());
     592          366 :     od.closeTag();
     593          366 :     od.openTag("persons");
     594          370 :     od.writeAttr("loaded", myPersonControl != nullptr ? myPersonControl->getLoadedNumber() : 0);
     595          370 :     od.writeAttr("running", myPersonControl != nullptr ? myPersonControl->getRunningNumber() : 0);
     596          370 :     od.writeAttr("jammed", myPersonControl != nullptr ? myPersonControl->getJammedNumber() : 0);
     597          366 :     od.closeTag();
     598          366 :     od.openTag("personTeleports");
     599          370 :     od.writeAttr("total", myPersonControl != nullptr ? myPersonControl->getTeleportCount() : 0);
     600          370 :     od.writeAttr("abortWait", myPersonControl != nullptr ? myPersonControl->getTeleportsAbortWait() : 0);
     601          370 :     od.writeAttr("wrongDest", myPersonControl != nullptr ? myPersonControl->getTeleportsWrongDest() : 0);
     602          366 :     od.closeTag();
     603          579 :     if (OptionsCont::getOptions().isSet("tripinfo-output") || OptionsCont::getOptions().getBool("duration-log.statistics")) {
     604          262 :         MSDevice_Tripinfo::writeStatistics(od);
     605              :     }
     606              : 
     607          366 : }
     608              : 
     609              : 
     610              : void
     611     91771613 : MSNet::writeSummaryOutput() {
     612              :     // summary output
     613     91771613 :     const OptionsCont& oc = OptionsCont::getOptions();
     614     91771613 :     const bool hasOutput = oc.isSet("summary-output");
     615     91771613 :     const bool hasPersonOutput = oc.isSet("person-summary-output");
     616     91771613 :     if (hasOutput || hasPersonOutput) {
     617       528578 :         const SUMOTime period = string2time(oc.getString("summary-output.period"));
     618       528578 :         const SUMOTime begin = string2time(oc.getString("begin"));
     619       528578 :         if (period > 0 && (myStep - begin) % period != 0) {
     620              :             return;
     621              :         }
     622              :     }
     623       522638 :     if (hasOutput) {
     624       517886 :         OutputDevice& od = OutputDevice::getDeviceByOption("summary-output");
     625       517886 :         int departedVehiclesNumber = myVehicleControl->getDepartedVehicleNo();
     626       517886 :         const double meanWaitingTime = departedVehiclesNumber != 0 ? myVehicleControl->getTotalDepartureDelay() / (double) departedVehiclesNumber : -1.;
     627              :         int endedVehicleNumber = myVehicleControl->getEndedVehicleNo();
     628       517886 :         const double meanTravelTime = endedVehicleNumber != 0 ? myVehicleControl->getTotalTravelTime() / (double) endedVehicleNumber : -1.;
     629       517886 :         od.openTag("step");
     630      1035772 :         od.writeAttr("time", time2string(myStep));
     631       517886 :         od.writeAttr("loaded", myVehicleControl->getLoadedVehicleNo());
     632       517886 :         od.writeAttr("inserted", myVehicleControl->getDepartedVehicleNo());
     633       517886 :         od.writeAttr("running", myVehicleControl->getRunningVehicleNo());
     634       517886 :         od.writeAttr("waiting", myInserter->getWaitingVehicleNo());
     635       517886 :         od.writeAttr("ended", myVehicleControl->getEndedVehicleNo());
     636       517886 :         od.writeAttr("arrived", myVehicleControl->getArrivedVehicleNo());
     637       517886 :         od.writeAttr("collisions", myVehicleControl->getCollisionCount());
     638       517886 :         od.writeAttr("teleports", myVehicleControl->getTeleportCount());
     639       517886 :         od.writeAttr("halting", myVehicleControl->getHaltingVehicleNo());
     640       517886 :         od.writeAttr("stopped", myVehicleControl->getStoppedVehiclesCount());
     641       517886 :         od.writeAttr("meanWaitingTime", meanWaitingTime);
     642       517886 :         od.writeAttr("meanTravelTime", meanTravelTime);
     643       517886 :         std::pair<double, double> meanSpeed = myVehicleControl->getVehicleMeanSpeeds();
     644       517886 :         od.writeAttr("meanSpeed", meanSpeed.first);
     645       517886 :         od.writeAttr("meanSpeedRelative", meanSpeed.second);
     646       517886 :         if (myLogExecutionTime) {
     647       466884 :             od.writeAttr("duration", mySimStepDuration);
     648              :         }
     649      1035772 :         od.closeTag();
     650              :     }
     651     91765673 :     if (hasPersonOutput) {
     652         4752 :         OutputDevice& od = OutputDevice::getDeviceByOption("person-summary-output");
     653         4752 :         MSTransportableControl& pc = getPersonControl();
     654         4752 :         od.openTag("step");
     655         9504 :         od.writeAttr("time", time2string(myStep));
     656         4752 :         od.writeAttr("loaded", pc.getLoadedNumber());
     657         4752 :         od.writeAttr("inserted", pc.getDepartedNumber());
     658         9504 :         od.writeAttr("walking", pc.getMovingNumber());
     659         4752 :         od.writeAttr("waitingForRide", pc.getWaitingForVehicleNumber());
     660         9504 :         od.writeAttr("riding", pc.getRidingNumber());
     661         9504 :         od.writeAttr("stopping", pc.getWaitingUntilNumber());
     662         9504 :         od.writeAttr("jammed", pc.getJammedNumber());
     663         9504 :         od.writeAttr("ended", pc.getEndedNumber());
     664         9504 :         od.writeAttr("arrived", pc.getArrivedNumber());
     665         4752 :         od.writeAttr("teleports", pc.getTeleportCount());
     666         4752 :         if (myLogExecutionTime) {
     667            0 :             od.writeAttr("duration", mySimStepDuration);
     668              :         }
     669         9504 :         od.closeTag();
     670              :     }
     671              : }
     672              : 
     673              : 
     674              : void
     675        38573 : MSNet::closeSimulation(SUMOTime start, const std::string& reason) {
     676              :     // report the end when wished
     677        77146 :     WRITE_MESSAGE(TLF("Simulation ended at time: %.", time2string(getCurrentTimeStep())));
     678        38573 :     if (reason != "") {
     679        76318 :         WRITE_MESSAGE(TL("Reason: ") + reason);
     680              :     }
     681        38573 :     myDetectorControl->close(myStep);
     682        39794 :     if (MSStopOut::active() && OptionsCont::getOptions().getBool("stop-output.write-unfinished")) {
     683          111 :         MSStopOut::getInstance()->generateOutputForUnfinished();
     684              :     }
     685        38573 :     MSDevice_Vehroutes::writePendingOutput(OptionsCont::getOptions().getBool("vehroute-output.write-unfinished"));
     686        77146 :     if (OptionsCont::getOptions().getBool("tripinfo-output.write-unfinished")) {
     687          828 :         MSDevice_Tripinfo::generateOutputForUnfinished();
     688              :     }
     689        77146 :     if (OptionsCont::getOptions().isSet("chargingstations-output")) {
     690          176 :         if (!OptionsCont::getOptions().getBool("chargingstations-output.aggregated")) {
     691           76 :             writeChargingStationOutput();
     692           24 :         } else if (OptionsCont::getOptions().getBool("chargingstations-output.aggregated.write-unfinished")) {
     693           12 :             MSChargingStationExport::write(OutputDevice::getDeviceByOption("chargingstations-output"), true);
     694              :         }
     695              :     }
     696        77146 :     if (OptionsCont::getOptions().isSet("overheadwiresegments-output")) {
     697            5 :         writeOverheadWireSegmentOutput();
     698              :     }
     699        77146 :     if (OptionsCont::getOptions().isSet("substations-output")) {
     700            5 :         writeSubstationOutput();
     701              :     }
     702        38573 :     writeRailSignalBlocks();
     703        38573 :     const long now = SysUtils::getCurrentMillis();
     704        65955 :     if (myLogExecutionTime || OptionsCont::getOptions().getBool("duration-log.statistics")) {
     705        22992 :         WRITE_MESSAGE(generateStatistics(start, now));
     706              :     }
     707        77146 :     if (OptionsCont::getOptions().isSet("statistic-output")) {
     708          366 :         writeStatistics(start, now);
     709              :     }
     710        38573 : }
     711              : 
     712              : 
     713              : void
     714     91774498 : MSNet::simulationStep(const bool onlyMove) {
     715     91774498 :     if (myStepCompletionMissing) {
     716            4 :         postMoveStep();
     717            4 :         myStepCompletionMissing = false;
     718         2461 :         return;
     719              :     }
     720              : #ifdef DEBUG_SIMSTEP
     721              :     std::cout << SIMTIME << ": MSNet::simulationStep() called"
     722              :               << ", myStep = " << myStep
     723              :               << std::endl;
     724              : #endif
     725              :     TraCIServer* t = TraCIServer::getInstance();
     726              :     int lastTraCICmd = 0;
     727     91774494 :     if (t != nullptr) {
     728      8093848 :         if (myLogExecutionTime) {
     729      7925131 :             myTraCIStepDuration = SysUtils::getCurrentMillis();
     730              :         }
     731      8093848 :         lastTraCICmd = t->processCommands(myStep);
     732              : #ifdef DEBUG_SIMSTEP
     733              :         bool loadRequested = !TraCI::getLoadArgs().empty();
     734              :         assert(t->getTargetTime() >= myStep || loadRequested || TraCIServer::wasClosed());
     735              : #endif
     736      8093823 :         if (myLogExecutionTime) {
     737      7925115 :             myTraCIStepDuration = SysUtils::getCurrentMillis() - myTraCIStepDuration;
     738              :         }
     739      8093823 :         if (TraCIServer::wasClosed() || !t->getLoadArgs().empty()) {
     740              :             return;
     741              :         }
     742              :     }
     743              : #ifdef DEBUG_SIMSTEP
     744              :     std::cout << SIMTIME << ": TraCI target time: " << t->getTargetTime() << std::endl;
     745              : #endif
     746              :     // execute beginOfTimestepEvents
     747     91772016 :     if (myLogExecutionTime) {
     748     51796543 :         mySimStepDuration = SysUtils::getCurrentMillis();
     749              :     }
     750              :     // simulation state output
     751     91772016 :     std::vector<SUMOTime>::iterator timeIt = std::find(myStateDumpTimes.begin(), myStateDumpTimes.end(), myStep);
     752     91772016 :     if (timeIt != myStateDumpTimes.end()) {
     753          270 :         const int dist = (int)distance(myStateDumpTimes.begin(), timeIt);
     754          270 :         MSStateHandler::saveState(myStateDumpFiles[dist], myStep);
     755              :     }
     756     91772016 :     if (myStateDumpPeriod > 0 && myStep % myStateDumpPeriod == 0) {
     757           84 :         std::string timeStamp = time2string(myStep);
     758              :         std::replace(timeStamp.begin(), timeStamp.end(), ':', '-');
     759           84 :         const std::string filename = myStateDumpPrefix + "_" + timeStamp + myStateDumpSuffix;
     760           84 :         MSStateHandler::saveState(filename, myStep);
     761           84 :         myPeriodicStateFiles.push_back(filename);
     762           84 :         int keep = OptionsCont::getOptions().getInt("save-state.period.keep");
     763           84 :         if (keep > 0 && (int)myPeriodicStateFiles.size() > keep) {
     764            0 :             std::remove(myPeriodicStateFiles.front().c_str());
     765              :             myPeriodicStateFiles.erase(myPeriodicStateFiles.begin());
     766              :         }
     767              :     }
     768     91772016 :     myBeginOfTimestepEvents->execute(myStep);
     769     91772011 :     if (MSRailSignalControl::hasInstance()) {
     770      7972581 :         MSRailSignalControl::getInstance().updateSignals(myStep);
     771              :     }
     772              : #ifdef HAVE_FOX
     773     91772011 :     MSRoutingEngine::waitForAll();
     774              : #endif
     775     91772011 :     if (MSGlobals::gCheck4Accidents && !MSGlobals::gUseMesoSim) {
     776     80112737 :         myEdges->detectCollisions(myStep, STAGE_EVENTS);
     777              :     }
     778              :     // check whether the tls programs need to be switched
     779     91772011 :     myLogics->check2Switch(myStep);
     780              : 
     781     91772011 :     if (MSGlobals::gUseMesoSim) {
     782     11659274 :         MSGlobals::gMesoNet->simulate(myStep);
     783              :     } else {
     784              :         // assure all lanes with vehicles are 'active'
     785     80112737 :         myEdges->patchActiveLanes();
     786              : 
     787              :         // compute safe velocities for all vehicles for the next few lanes
     788              :         // also register ApproachingVehicleInformation for all links
     789     80112737 :         myEdges->planMovements(myStep);
     790              : 
     791              :         // register junction approaches based on planned velocities as basis for right-of-way decision
     792     80112737 :         myEdges->setJunctionApproaches(myStep);
     793              : 
     794              :         // decide right-of-way and execute movements
     795     80112737 :         myEdges->executeMovements(myStep);
     796     80112732 :         if (MSGlobals::gCheck4Accidents) {
     797     80112732 :             myEdges->detectCollisions(myStep, STAGE_MOVEMENTS);
     798              :         }
     799              : 
     800              :         // vehicles may change lanes
     801     80112732 :         myEdges->changeLanes(myStep);
     802              : 
     803     80112732 :         if (MSGlobals::gCheck4Accidents) {
     804     80112732 :             myEdges->detectCollisions(myStep, STAGE_LANECHANGE);
     805              :         }
     806              :     }
     807              :     // flush arrived meso vehicles and micro vehicles that were removed due to collision
     808     91772006 :     myVehicleControl->removePending();
     809     91772006 :     loadRoutes();
     810              : 
     811              :     // persons
     812     91771990 :     if (myPersonControl != nullptr && myPersonControl->hasTransportables()) {
     813      4789052 :         myPersonControl->checkWaiting(this, myStep);
     814              :     }
     815              :     // containers
     816     91771947 :     if (myContainerControl != nullptr && myContainerControl->hasTransportables()) {
     817      1061723 :         myContainerControl->checkWaiting(this, myStep);
     818              :     }
     819     91771947 :     if (MSRailSignalControl::hasInstance()) {
     820      7972581 :         MSRailSignalControl::getInstance().resetWaitRelations();
     821              :         // preserve waitRelation from insertion for the next step
     822              :     }
     823              :     // insert vehicles
     824     91771947 :     myInserter->determineCandidates(myStep);
     825     91771902 :     myInsertionEvents->execute(myStep);
     826              : #ifdef HAVE_FOX
     827     91771805 :     MSRoutingEngine::waitForAll();
     828              : #endif
     829     91771781 :     myInserter->emitVehicles(myStep);
     830     91771637 :     if (MSGlobals::gCheck4Accidents && !MSGlobals::gUseMesoSim) {
     831              :         //myEdges->patchActiveLanes(); // @note required to detect collisions on lanes that were empty before insertion. wasteful?
     832     80112466 :         myEdges->detectCollisions(myStep, STAGE_INSERTIONS);
     833              :     }
     834     91771637 :     MSVehicleTransfer::getInstance()->checkInsertions(myStep);
     835              : 
     836              :     // execute endOfTimestepEvents
     837     91771637 :     myEndOfTimestepEvents->execute(myStep);
     838              : 
     839     91771628 :     if (myLogExecutionTime) {
     840     51796379 :         myTraCIStepDuration -= SysUtils::getCurrentMillis();
     841              :     }
     842     91771628 :     if (onlyMove) {
     843            4 :         myStepCompletionMissing = true;
     844            4 :         return;
     845              :     }
     846     91771624 :     if (t != nullptr && lastTraCICmd == libsumo::CMD_EXECUTEMOVE) {
     847            6 :         t->processCommands(myStep, true);
     848              :     }
     849     91771624 :     postMoveStep();
     850              : }
     851              : 
     852              : 
     853              : void
     854     91771628 : MSNet::postMoveStep() {
     855     91771628 :     const int numControlled = libsumo::Helper::postProcessRemoteControl();
     856     91771628 :     if (numControlled > 0 && MSGlobals::gCheck4Accidents) {
     857        10045 :         myEdges->detectCollisions(myStep, STAGE_REMOTECONTROL);
     858              :     }
     859     91771628 :     if (myLogExecutionTime) {
     860     51796379 :         myTraCIStepDuration += SysUtils::getCurrentMillis();
     861     51796379 :         myTraCIMillis += myTraCIStepDuration;
     862              :     }
     863     91771628 :     if (MSGlobals::gCheck4Accidents && !MSGlobals::gUseMesoSim) {
     864              :         // collisions from the previous step were kept to avoid duplicate
     865              :         // warnings. we must remove them now to ensure correct output.
     866     80112461 :         removeOutdatedCollisions();
     867              :     }
     868              :     // update and write (if needed) detector values
     869     91771628 :     mySimStepDuration = SysUtils::getCurrentMillis() - mySimStepDuration;
     870     91771628 :     writeOutput();
     871              : 
     872     91771613 :     if (myLogExecutionTime) {
     873     51796379 :         myVehiclesMoved += myVehicleControl->getRunningVehicleNo();
     874     51796379 :         if (myPersonControl != nullptr) {
     875      2571680 :             myPersonsMoved += myPersonControl->getRunningNumber();
     876              :         }
     877              :     }
     878     91771613 :     myStep += DELTA_T;
     879     91771613 : }
     880              : 
     881              : 
     882              : MSNet::SimulationState
     883     91697908 : MSNet::simulationState(SUMOTime stopTime) const {
     884     91697908 :     if (TraCIServer::wasClosed()) {
     885              :         return SIMSTATE_CONNECTION_CLOSED;
     886              :     }
     887     91695375 :     if (TraCIServer::getInstance() != nullptr && !TraCIServer::getInstance()->getLoadArgs().empty()) {
     888              :         return SIMSTATE_LOADING;
     889              :     }
     890     91695362 :     if ((stopTime < 0 || myStep > stopTime) && TraCIServer::getInstance() == nullptr && (stopTime > 0 || myStep > myEdgeDataEndTime)) {
     891     45179755 :         if ((myVehicleControl->getActiveVehicleCount() == 0)
     892      3912815 :                 && (myInserter->getPendingFlowCount() == 0)
     893      1181475 :                 && (myPersonControl == nullptr || !myPersonControl->hasNonWaiting())
     894       148883 :                 && (myContainerControl == nullptr || !myContainerControl->hasNonWaiting())
     895     45221790 :                 && !MSDevice_Taxi::hasServableReservations()) {
     896              :             return SIMSTATE_NO_FURTHER_VEHICLES;
     897              :         }
     898              :     }
     899     91658193 :     if (stopTime >= 0 && myStep >= stopTime) {
     900              :         return SIMSTATE_END_STEP_REACHED;
     901              :     }
     902     91634000 :     if (myMaxTeleports >= 0 && myVehicleControl->getTeleportCount() > myMaxTeleports) {
     903              :         return SIMSTATE_TOO_MANY_TELEPORTS;
     904              :     }
     905     91633992 :     if (myAmInterrupted) {
     906           13 :         return SIMSTATE_INTERRUPTED;
     907              :     }
     908              :     return SIMSTATE_RUNNING;
     909              : }
     910              : 
     911              : 
     912              : MSNet::SimulationState
     913     91690647 : MSNet::adaptToState(MSNet::SimulationState state, const bool isLibsumo) const {
     914     91690647 :     if (state == SIMSTATE_LOADING) {
     915           13 :         OptionsIO::setArgs(TraCIServer::getInstance()->getLoadArgs());
     916              :         TraCIServer::getInstance()->getLoadArgs().clear();
     917     91690634 :     } else if (state != SIMSTATE_RUNNING && ((TraCIServer::getInstance() != nullptr && !TraCIServer::wasClosed()) || isLibsumo)) {
     918              :         // overrides SIMSTATE_END_STEP_REACHED, e.g. (TraCI / Libsumo ignore SUMO's --end option)
     919        19833 :         return SIMSTATE_RUNNING;
     920     91670801 :     } else if (state == SIMSTATE_NO_FURTHER_VEHICLES) {
     921        20063 :         if (myPersonControl != nullptr) {
     922         3578 :             myPersonControl->abortAnyWaitingForVehicle();
     923              :         }
     924        20063 :         if (myContainerControl != nullptr) {
     925          367 :             myContainerControl->abortAnyWaitingForVehicle();
     926              :         }
     927        20063 :         myVehicleControl->abortWaiting();
     928              :     }
     929              :     return state;
     930              : }
     931              : 
     932              : 
     933              : std::string
     934        38008 : MSNet::getStateMessage(MSNet::SimulationState state) {
     935        38008 :     switch (state) {
     936              :         case MSNet::SIMSTATE_RUNNING:
     937          414 :             return "";
     938              :         case MSNet::SIMSTATE_END_STEP_REACHED:
     939        14718 :             return TL("The final simulation step has been reached.");
     940              :         case MSNet::SIMSTATE_NO_FURTHER_VEHICLES:
     941        20404 :             return TL("All vehicles have left the simulation.");
     942              :         case MSNet::SIMSTATE_CONNECTION_CLOSED:
     943         2440 :             return TL("TraCI requested termination.");
     944              :         case MSNet::SIMSTATE_ERROR_IN_SIM:
     945            0 :             return TL("An error occurred (see log).");
     946              :         case MSNet::SIMSTATE_INTERRUPTED:
     947           13 :             return TL("Interrupted.");
     948              :         case MSNet::SIMSTATE_TOO_MANY_TELEPORTS:
     949            6 :             return TL("Too many teleports.");
     950              :         case MSNet::SIMSTATE_LOADING:
     951           13 :             return TL("TraCI issued load command.");
     952              :         default:
     953            0 :             return TL("Unknown reason.");
     954              :     }
     955              : }
     956              : 
     957              : 
     958              : void
     959        40275 : MSNet::clearAll() {
     960              :     // clear container
     961        40275 :     MSEdge::clear();
     962        40275 :     MSLane::clear();
     963        40275 :     MSRoute::clear();
     964        40275 :     delete MSVehicleTransfer::getInstance();
     965        40275 :     MSDevice::cleanupAll();
     966        40275 :     MSCalibrator::cleanup();
     967        81026 :     while (!MSLaneSpeedTrigger::getInstances().empty()) {
     968          476 :         delete MSLaneSpeedTrigger::getInstances().begin()->second;
     969              :     }
     970        43614 :     while (!MSTriggeredRerouter::getInstances().empty()) {
     971         3339 :         delete MSTriggeredRerouter::getInstances().begin()->second;
     972              :     }
     973        40275 :     MSDevice_BTsender::cleanup();
     974        40275 :     MSDevice_SSM::cleanup();
     975        40275 :     MSDevice_ToC::cleanup();
     976        40275 :     MSStopOut::cleanup();
     977        40275 :     MSRailSignalConstraint::cleanup();
     978        40275 :     MSRailSignalControl::cleanup();
     979        40275 :     MSDriveWay::cleanup();
     980              :     TraCIServer* t = TraCIServer::getInstance();
     981        40275 :     if (t != nullptr) {
     982         2480 :         t->cleanup();
     983              :     }
     984        40275 :     libsumo::Helper::cleanup();
     985        40275 :     OutputDevice::closeAll(true);
     986        40275 : }
     987              : 
     988              : 
     989              : void
     990          177 : MSNet::clearState(const SUMOTime step, bool quickReload) {
     991          177 :     MSGlobals::gClearState = true;
     992          177 :     if (MSGlobals::gUseMesoSim) {
     993            2 :         MSGlobals::gMesoNet->clearState();
     994          259 :         for (MSEdge* const edge : MSEdge::getAllEdges()) {
     995          534 :             for (MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge); s != nullptr; s = s->getNextSegment()) {
     996          277 :                 s->clearState();
     997              :             }
     998              :         }
     999              :     } else {
    1000         8008 :         for (MSEdge* const edge : MSEdge::getAllEdges()) {
    1001        17442 :             for (MSLane* const lane : edge->getLanes()) {
    1002         9609 :                 lane->getVehiclesSecure();
    1003         9609 :                 lane->clearState();
    1004         9609 :                 lane->releaseVehicles();
    1005              :             }
    1006         7833 :             edge->clearState();
    1007              :         }
    1008              :     }
    1009          177 :     myInserter->clearState();
    1010              :     // detectors may still reference persons/vehicles
    1011          177 :     myDetectorControl->updateDetectors(myStep);
    1012          177 :     myDetectorControl->writeOutput(myStep, true);
    1013          177 :     myDetectorControl->clearState(step);
    1014              : 
    1015          177 :     if (myPersonControl != nullptr) {
    1016           25 :         myPersonControl->clearState();
    1017              :     }
    1018          177 :     if (myContainerControl != nullptr) {
    1019            0 :         myContainerControl->clearState();
    1020              :     }
    1021              :     // delete vtypes after transportables have removed their types
    1022          177 :     myVehicleControl->clearState(true);
    1023          177 :     MSVehicleTransfer::getInstance()->clearState();
    1024          177 :     myLogics->clearState(step, quickReload);
    1025              :     // delete all routes after vehicles and detector output is done
    1026          177 :     MSRoute::dict_clearState();
    1027          217 :     for (auto& item : myStoppingPlaces) {
    1028           80 :         for (auto& item2 : item.second) {
    1029           40 :             item2.second->clearState();
    1030              :         }
    1031              :     }
    1032          177 :     myShapeContainer->clearState();
    1033          177 :     myBeginOfTimestepEvents->clearState(myStep, step);
    1034          177 :     myEndOfTimestepEvents->clearState(myStep, step);
    1035          177 :     myInsertionEvents->clearState(myStep, step);
    1036          177 :     MSRailSignalControl::clearState();
    1037          177 :     MSDriveWay::clearState();
    1038          177 :     myStep = step;
    1039          177 :     MSGlobals::gClearState = false;
    1040          177 : }
    1041              : 
    1042              : 
    1043              : void
    1044     91771628 : MSNet::writeOutput() {
    1045              :     // update detector values
    1046     91771628 :     myDetectorControl->updateDetectors(myStep);
    1047     91771619 :     const OptionsCont& oc = OptionsCont::getOptions();
    1048              : 
    1049              :     // check state dumps
    1050    183543238 :     if (oc.isSet("netstate-dump")) {
    1051       303502 :         MSXMLRawOut::write(OutputDevice::getDeviceByOption("netstate-dump"), *myEdges, myStep,
    1052              :                            oc.getInt("netstate-dump.precision"));
    1053              :     }
    1054              : 
    1055              :     // check fcd dumps
    1056    183543238 :     if (OptionsCont::getOptions().isSet("fcd-output")) {
    1057      1539222 :         MSFCDExport::write(OutputDevice::getDeviceByOption("fcd-output"), myStep, myHasElevation);
    1058              :     }
    1059              : 
    1060              :     // check emission dumps
    1061    183543238 :     if (OptionsCont::getOptions().isSet("emission-output")) {
    1062       185048 :         MSEmissionExport::write(OutputDevice::getDeviceByOption("emission-output"), myStep,
    1063              :                                 oc.getInt("emission-output.precision"));
    1064              :     }
    1065              : 
    1066              :     // battery dumps
    1067    183543238 :     if (OptionsCont::getOptions().isSet("battery-output")) {
    1068       253590 :         MSBatteryExport::write(OutputDevice::getDeviceByOption("battery-output"), myStep,
    1069              :                                oc.getInt("battery-output.precision"));
    1070              :     }
    1071              : 
    1072              :     // charging station aggregated dumps
    1073     91828795 :     if (OptionsCont::getOptions().isSet("chargingstations-output") && OptionsCont::getOptions().getBool("chargingstations-output.aggregated")) {
    1074         5608 :         MSChargingStationExport::write(OutputDevice::getDeviceByOption("chargingstations-output"));
    1075              :     }
    1076              : 
    1077              :     // elecHybrid dumps
    1078    183543238 :     if (OptionsCont::getOptions().isSet("elechybrid-output")) {
    1079          450 :         std::string output = OptionsCont::getOptions().getString("elechybrid-output");
    1080              : 
    1081          900 :         if (oc.getBool("elechybrid-output.aggregated")) {
    1082              :             // build a xml file with aggregated device.elechybrid output
    1083          600 :             MSElecHybridExport::writeAggregated(OutputDevice::getDeviceByOption("elechybrid-output"), myStep,
    1084              :                                                 oc.getInt("elechybrid-output.precision"));
    1085              :         } else {
    1086              :             // build a separate xml file for each vehicle equipped with device.elechybrid
    1087              :             // RICE_TODO: Does this have to be placed here in MSNet.cpp ?
    1088          150 :             MSVehicleControl& vc = MSNet::getInstance()->getVehicleControl();
    1089          204 :             for (MSVehicleControl::constVehIt it = vc.loadedVehBegin(); it != vc.loadedVehEnd(); ++it) {
    1090           54 :                 const SUMOVehicle* veh = it->second;
    1091           54 :                 if (!veh->isOnRoad()) {
    1092            0 :                     continue;
    1093              :                 }
    1094           54 :                 if (static_cast<MSDevice_ElecHybrid*>(veh->getDevice(typeid(MSDevice_ElecHybrid))) != nullptr) {
    1095              :                     std::string vehID = veh->getID();
    1096           54 :                     std::string filename2 = output + "_" + vehID + ".xml";
    1097           54 :                     OutputDevice& dev = OutputDevice::getDevice(filename2);
    1098              :                     std::map<SumoXMLAttr, std::string> attrs;
    1099           54 :                     attrs[SUMO_ATTR_VEHICLE] = vehID;
    1100           54 :                     attrs[SUMO_ATTR_MAXIMUMBATTERYCAPACITY] = toString(dynamic_cast<MSDevice_ElecHybrid*>(veh->getDevice(typeid(MSDevice_ElecHybrid)))->getMaximumBatteryCapacity());
    1101           54 :                     attrs[SUMO_ATTR_RECUPERATIONENABLE] = toString(MSGlobals::gOverheadWireRecuperation);
    1102          108 :                     dev.writeXMLHeader("elecHybrid-export", "", attrs);
    1103          108 :                     MSElecHybridExport::write(OutputDevice::getDevice(filename2), veh, myStep, oc.getInt("elechybrid-output.precision"));
    1104              :                 }
    1105              :             }
    1106              :         }
    1107              :     }
    1108              : 
    1109              : 
    1110              :     // check full dumps
    1111    183543238 :     if (OptionsCont::getOptions().isSet("full-output")) {
    1112          960 :         MSGlobals::gHaveEmissions = true;
    1113         1920 :         MSFullExport::write(OutputDevice::getDeviceByOption("full-output"), myStep);
    1114              :     }
    1115              : 
    1116              :     // check queue dumps
    1117    183543238 :     if (OptionsCont::getOptions().isSet("queue-output")) {
    1118       324414 :         MSQueueExport::write(OutputDevice::getDeviceByOption("queue-output"), myStep);
    1119              :     }
    1120              : 
    1121              :     // check amitran dumps
    1122    183543238 :     if (OptionsCont::getOptions().isSet("amitran-output")) {
    1123         2340 :         MSAmitranTrajectories::write(OutputDevice::getDeviceByOption("amitran-output"), myStep);
    1124              :     }
    1125              : 
    1126              :     // check vtk dumps
    1127    183543238 :     if (OptionsCont::getOptions().isSet("vtk-output")) {
    1128              : 
    1129            6 :         if (MSNet::getInstance()->getVehicleControl().getRunningVehicleNo() > 0) {
    1130            6 :             std::string timestep = time2string(myStep);
    1131            6 :             timestep = timestep.substr(0, timestep.length() - 3);
    1132           12 :             std::string output = OptionsCont::getOptions().getString("vtk-output");
    1133           12 :             std::string filename = output + "_" + timestep + ".vtp";
    1134              : 
    1135            6 :             OutputDevice_File dev(filename, false);
    1136              : 
    1137              :             //build a huge mass of xml files
    1138            0 :             MSVTKExport::write(dev, myStep);
    1139              : 
    1140            0 :         }
    1141              : 
    1142              :     }
    1143              : 
    1144     91771613 :     writeSummaryOutput();
    1145              : 
    1146              :     // write detector values
    1147     91771613 :     myDetectorControl->writeOutput(myStep + DELTA_T, false);
    1148              : 
    1149              :     // write link states
    1150    183543226 :     if (OptionsCont::getOptions().isSet("link-output")) {
    1151         3704 :         OutputDevice& od = OutputDevice::getDeviceByOption("link-output");
    1152         3704 :         od.openTag("timestep");
    1153         3704 :         od.writeAttr(SUMO_ATTR_ID, STEPS2TIME(myStep));
    1154        70088 :         for (const MSEdge* const edge : myEdges->getEdges()) {
    1155       143648 :             for (const MSLane* const lane : edge->getLanes()) {
    1156       158588 :                 for (const MSLink* const link : lane->getLinkCont()) {
    1157       162648 :                     link->writeApproaching(od, lane->getID());
    1158              :                 }
    1159              :             }
    1160              :         }
    1161         7408 :         od.closeTag();
    1162              :     }
    1163              : 
    1164              :     // write SSM output
    1165     94009874 :     for (MSDevice_SSM* dev : MSDevice_SSM::getInstances()) {
    1166      2238261 :         dev->updateAndWriteOutput();
    1167              :     }
    1168              : 
    1169              :     // write ToC output
    1170     91787332 :     for (MSDevice_ToC* dev : MSDevice_ToC::getInstances()) {
    1171        15719 :         if (dev->generatesOutput()) {
    1172        15513 :             dev->writeOutput();
    1173              :         }
    1174              :     }
    1175              : 
    1176    183543226 :     if (OptionsCont::getOptions().isSet("collision-output")) {
    1177        10356 :         writeCollisions();
    1178              :     }
    1179     91771613 : }
    1180              : 
    1181              : 
    1182              : bool
    1183            0 : MSNet::logSimulationDuration() const {
    1184            0 :     return myLogExecutionTime;
    1185              : }
    1186              : 
    1187              : 
    1188              : MSTransportableControl&
    1189     10385973 : MSNet::getPersonControl() {
    1190     10385973 :     if (myPersonControl == nullptr) {
    1191         5552 :         myPersonControl = new MSTransportableControl(true);
    1192              :     }
    1193     10385952 :     return *myPersonControl;
    1194              : }
    1195              : 
    1196              : 
    1197              : MSTransportableControl&
    1198       616232 : MSNet::getContainerControl() {
    1199       616232 :     if (myContainerControl == nullptr) {
    1200          577 :         myContainerControl = new MSTransportableControl(false);
    1201              :     }
    1202       616232 :     return *myContainerControl;
    1203              : }
    1204              : 
    1205              : MSDynamicShapeUpdater*
    1206           24 : MSNet::makeDynamicShapeUpdater() {
    1207           24 :     myDynamicShapeUpdater = std::unique_ptr<MSDynamicShapeUpdater> (new MSDynamicShapeUpdater(*myShapeContainer));
    1208           24 :     return myDynamicShapeUpdater.get();
    1209              : }
    1210              : 
    1211              : MSEdgeWeightsStorage&
    1212      5181933 : MSNet::getWeightsStorage() {
    1213      5181933 :     if (myEdgeWeights == nullptr) {
    1214         1507 :         myEdgeWeights = new MSEdgeWeightsStorage();
    1215              :     }
    1216      5181933 :     return *myEdgeWeights;
    1217              : }
    1218              : 
    1219              : 
    1220              : void
    1221          129 : MSNet::preSimStepOutput() const {
    1222          129 :     std::cout << "Step #" << time2string(myStep);
    1223          129 : }
    1224              : 
    1225              : 
    1226              : void
    1227          129 : MSNet::postSimStepOutput() const {
    1228          129 :     if (myLogExecutionTime) {
    1229          127 :         std::ostringstream oss;
    1230              :         oss.setf(std::ios::fixed, std::ios::floatfield);     // use decimal format
    1231              :         oss.setf(std::ios::showpoint);    // print decimal point
    1232          127 :         oss << std::setprecision(gPrecision);
    1233          127 :         if (mySimStepDuration != 0) {
    1234           75 :             const double durationSec = (double)mySimStepDuration / 1000.;
    1235           75 :             oss << " (" << mySimStepDuration << "ms ~= "
    1236           75 :                 << (TS / durationSec) << "*RT, ~"
    1237           75 :                 << ((double) myVehicleControl->getRunningVehicleNo() / durationSec);
    1238              :         } else {
    1239           52 :             oss << " (0ms ?*RT. ?";
    1240              :         }
    1241          127 :         oss << "UPS, ";
    1242          127 :         if (TraCIServer::getInstance() != nullptr) {
    1243           79 :             oss << "TraCI: " << myTraCIStepDuration << "ms, ";
    1244              :         }
    1245          127 :         oss << "vehicles TOT " << myVehicleControl->getDepartedVehicleNo()
    1246          254 :             << " ACT " << myVehicleControl->getRunningVehicleNo()
    1247          127 :             << " BUF " << myInserter->getWaitingVehicleNo()
    1248          127 :             << ")                                              ";
    1249          254 :         std::string prev = "Step #" + time2string(myStep - DELTA_T);
    1250          254 :         std::cout << oss.str().substr(0, 90 - prev.length());
    1251          127 :     }
    1252          129 :     std::cout << '\r';
    1253          129 : }
    1254              : 
    1255              : 
    1256              : void
    1257         9804 : MSNet::addVehicleStateListener(VehicleStateListener* listener) {
    1258         9804 :     if (find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener) == myVehicleStateListeners.end()) {
    1259         9804 :         myVehicleStateListeners.push_back(listener);
    1260              :     }
    1261         9804 : }
    1262              : 
    1263              : 
    1264              : void
    1265           59 : MSNet::removeVehicleStateListener(VehicleStateListener* listener) {
    1266           59 :     std::vector<VehicleStateListener*>::iterator i = std::find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener);
    1267           59 :     if (i != myVehicleStateListeners.end()) {
    1268           59 :         myVehicleStateListeners.erase(i);
    1269              :     }
    1270           59 : }
    1271              : 
    1272              : 
    1273              : void
    1274     14164759 : MSNet::informVehicleStateListener(const SUMOVehicle* const vehicle, VehicleState to, const std::string& info) {
    1275              : #ifdef HAVE_FOX
    1276     14164759 :     ScopedLocker<> lock(myVehicleStateListenerMutex, MSGlobals::gNumThreads > 1);
    1277              : #endif
    1278     14747658 :     for (VehicleStateListener* const listener : myVehicleStateListeners) {
    1279       582899 :         listener->vehicleStateChanged(vehicle, to, info);
    1280              :     }
    1281     14164759 : }
    1282              : 
    1283              : 
    1284              : void
    1285         3540 : MSNet::addTransportableStateListener(TransportableStateListener* listener) {
    1286         3540 :     if (find(myTransportableStateListeners.begin(), myTransportableStateListeners.end(), listener) == myTransportableStateListeners.end()) {
    1287         3540 :         myTransportableStateListeners.push_back(listener);
    1288              :     }
    1289         3540 : }
    1290              : 
    1291              : 
    1292              : void
    1293            0 : MSNet::removeTransportableStateListener(TransportableStateListener* listener) {
    1294            0 :     std::vector<TransportableStateListener*>::iterator i = std::find(myTransportableStateListeners.begin(), myTransportableStateListeners.end(), listener);
    1295            0 :     if (i != myTransportableStateListeners.end()) {
    1296            0 :         myTransportableStateListeners.erase(i);
    1297              :     }
    1298            0 : }
    1299              : 
    1300              : 
    1301              : void
    1302       821343 : MSNet::informTransportableStateListener(const MSTransportable* const transportable, TransportableState to, const std::string& info) {
    1303              : #ifdef HAVE_FOX
    1304       821343 :     ScopedLocker<> lock(myTransportableStateListenerMutex, MSGlobals::gNumThreads > 1);
    1305              : #endif
    1306       823884 :     for (TransportableStateListener* const listener : myTransportableStateListeners) {
    1307         2541 :         listener->transportableStateChanged(transportable, to, info);
    1308              :     }
    1309       821343 : }
    1310              : 
    1311              : 
    1312              : bool
    1313        10648 : MSNet::registerCollision(const SUMOTrafficObject* collider, const SUMOTrafficObject* victim, const std::string& collisionType, const MSLane* lane, double pos) {
    1314              :     auto it = myCollisions.find(collider->getID());
    1315        10648 :     if (it != myCollisions.end()) {
    1316         5108 :         for (Collision& old : it->second) {
    1317         4979 :             if (old.victim == victim->getID()) {
    1318              :                 // collision from previous step continues
    1319         4139 :                 old.colliderSpeed = collider->getSpeed();
    1320         4139 :                 old.victimSpeed = victim->getSpeed();
    1321         4139 :                 old.type = collisionType;
    1322         4139 :                 old.lane = lane;
    1323         4139 :                 old.pos = pos;
    1324         4139 :                 old.time = myStep;
    1325              :                 return false;
    1326              :             }
    1327              :         }
    1328              :     }
    1329              :     Collision c;
    1330              :     c.victim = victim->getID();
    1331         6509 :     c.colliderType = collider->getVehicleType().getID();
    1332         6509 :     c.victimType = victim->getVehicleType().getID();
    1333         6509 :     c.colliderSpeed = collider->getSpeed();
    1334         6509 :     c.victimSpeed = victim->getSpeed();
    1335              :     c.type = collisionType;
    1336         6509 :     c.lane = lane;
    1337         6509 :     c.pos = pos;
    1338         6509 :     c.time = myStep;
    1339         6509 :     myCollisions[collider->getID()].push_back(c);
    1340              :     return true;
    1341         6509 : }
    1342              : 
    1343              : 
    1344              : void
    1345     80112461 : MSNet::removeOutdatedCollisions() {
    1346     80126809 :     for (auto it = myCollisions.begin(); it != myCollisions.end();) {
    1347        28942 :         for (auto it2 = it->second.begin(); it2 != it->second.end();) {
    1348        14594 :             if (it2->time != myStep) {
    1349         6498 :                 it2 = it->second.erase(it2);
    1350              :             } else {
    1351              :                 it2++;
    1352              :             }
    1353              :         }
    1354        14348 :         if (it->second.size() == 0) {
    1355              :             it = myCollisions.erase(it);
    1356              :         } else {
    1357              :             it++;
    1358              :         }
    1359              :     }
    1360     80112461 : }
    1361              : 
    1362              : 
    1363              : bool
    1364        63723 : MSNet::addStoppingPlace(const SumoXMLTag category, MSStoppingPlace* stop) {
    1365        73923 :     return myStoppingPlaces[category == SUMO_TAG_TRAIN_STOP ? SUMO_TAG_BUS_STOP : category].add(stop->getID(), stop);
    1366              : }
    1367              : 
    1368              : 
    1369              : bool
    1370            8 : MSNet::addTractionSubstation(MSTractionSubstation* substation) {
    1371            8 :     if (find(myTractionSubstations.begin(), myTractionSubstations.end(), substation) == myTractionSubstations.end()) {
    1372            8 :         myTractionSubstations.push_back(substation);
    1373            8 :         return true;
    1374              :     }
    1375              :     return false;
    1376              : }
    1377              : 
    1378              : 
    1379              : MSStoppingPlace*
    1380       897248 : MSNet::getStoppingPlace(const std::string& id, const SumoXMLTag category) const {
    1381              :     if (myStoppingPlaces.count(category) > 0) {
    1382              :         return myStoppingPlaces.find(category)->second.get(id);
    1383              :     }
    1384              :     return nullptr;
    1385              : }
    1386              : 
    1387              : 
    1388              : MSStoppingPlace*
    1389           30 : MSNet::getStoppingPlace(const std::string& id) const {
    1390           50 :     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})) {
    1391           50 :         MSStoppingPlace* result = getStoppingPlace(id, category);
    1392           50 :         if (result != nullptr) {
    1393              :             return result;
    1394              :         }
    1395           30 :     }
    1396            0 :     return nullptr;
    1397              : }
    1398              : 
    1399              : 
    1400              : std::string
    1401       375384 : MSNet::getStoppingPlaceID(const MSLane* lane, const double pos, const SumoXMLTag category) const {
    1402              :     if (myStoppingPlaces.count(category) > 0) {
    1403       520693 :         for (const auto& it : myStoppingPlaces.find(category)->second) {
    1404       450696 :             MSStoppingPlace* stop = it.second;
    1405       450696 :             if (&stop->getLane() == lane && stop->getBeginLanePosition() - POSITION_EPS <= pos && stop->getEndLanePosition() + POSITION_EPS >= pos) {
    1406              :                 return stop->getID();
    1407              :             }
    1408              :         }
    1409              :     }
    1410       339712 :     return "";
    1411              : }
    1412              : 
    1413              : 
    1414              : const NamedObjectCont<MSStoppingPlace*>&
    1415         5571 : MSNet::getStoppingPlaces(SumoXMLTag category) const {
    1416              :     auto it = myStoppingPlaces.find(category);
    1417         5571 :     if (it != myStoppingPlaces.end()) {
    1418         5286 :         return it->second;
    1419              :     } else {
    1420              :         return myEmptyStoppingPlaceCont;
    1421              :     }
    1422              : }
    1423              : 
    1424              : 
    1425              : void
    1426           76 : MSNet::writeChargingStationOutput() const {
    1427              :     if (myStoppingPlaces.count(SUMO_TAG_CHARGING_STATION) > 0) {
    1428          144 :         OutputDevice& output = OutputDevice::getDeviceByOption("chargingstations-output");
    1429          424 :         for (const auto& it : myStoppingPlaces.find(SUMO_TAG_CHARGING_STATION)->second) {
    1430          352 :             static_cast<MSChargingStation*>(it.second)->writeChargingStationOutput(output);
    1431              :         }
    1432              :     }
    1433           76 : }
    1434              : 
    1435              : 
    1436              : void
    1437        38573 : MSNet::writeRailSignalBlocks() const {
    1438        77146 :     if (OptionsCont::getOptions().isSet("railsignal-block-output")) {
    1439          988 :         OutputDevice& output = OutputDevice::getDeviceByOption("railsignal-block-output");
    1440         3543 :         for (auto tls : myLogics->getAllLogics()) {
    1441         2555 :             MSRailSignal* rs = dynamic_cast<MSRailSignal*>(tls);
    1442         2555 :             if (rs != nullptr) {
    1443         2524 :                 rs->writeBlocks(output, false);
    1444              :             }
    1445          988 :         }
    1446          988 :         MSDriveWay::writeDepatureBlocks(output, false);
    1447              :     }
    1448        77146 :     if (OptionsCont::getOptions().isSet("railsignal-vehicle-output")) {
    1449           75 :         OutputDevice& output = OutputDevice::getDeviceByOption("railsignal-vehicle-output");
    1450          326 :         for (auto tls : myLogics->getAllLogics()) {
    1451          251 :             MSRailSignal* rs = dynamic_cast<MSRailSignal*>(tls);
    1452          251 :             if (rs != nullptr) {
    1453          251 :                 rs->writeBlocks(output, true);
    1454              :             }
    1455           75 :         }
    1456           75 :         MSDriveWay::writeDepatureBlocks(output, true);
    1457              :     }
    1458        38573 : }
    1459              : 
    1460              : 
    1461              : void
    1462            5 : MSNet::writeOverheadWireSegmentOutput() const {
    1463              :     if (myStoppingPlaces.count(SUMO_TAG_OVERHEAD_WIRE_SEGMENT) > 0) {
    1464           10 :         OutputDevice& output = OutputDevice::getDeviceByOption("overheadwiresegments-output");
    1465           53 :         for (const auto& it : myStoppingPlaces.find(SUMO_TAG_OVERHEAD_WIRE_SEGMENT)->second) {
    1466           48 :             static_cast<MSOverheadWire*>(it.second)->writeOverheadWireSegmentOutput(output);
    1467              :         }
    1468              :     }
    1469            5 : }
    1470              : 
    1471              : 
    1472              : void
    1473            5 : MSNet::writeSubstationOutput() const {
    1474            5 :     if (myTractionSubstations.size() > 0) {
    1475            5 :         OutputDevice& output = OutputDevice::getDeviceByOption("substations-output");
    1476           10 :         output.setPrecision(OptionsCont::getOptions().getInt("substations-output.precision"));
    1477           13 :         for (auto& it : myTractionSubstations) {
    1478            8 :             it->writeTractionSubstationOutput(output);
    1479              :         }
    1480              :     }
    1481            5 : }
    1482              : 
    1483              : 
    1484              : MSTractionSubstation*
    1485           19 : MSNet::findTractionSubstation(const std::string& substationId) {
    1486           22 :     for (std::vector<MSTractionSubstation*>::iterator it = myTractionSubstations.begin(); it != myTractionSubstations.end(); ++it) {
    1487           22 :         if ((*it)->getID() == substationId) {
    1488              :             return *it;
    1489              :         }
    1490              :     }
    1491              :     return nullptr;
    1492              : }
    1493              : 
    1494              : 
    1495              : bool
    1496            0 : MSNet::existTractionSubstation(const std::string& substationId) {
    1497            0 :     for (std::vector<MSTractionSubstation*>::iterator it = myTractionSubstations.begin(); it != myTractionSubstations.end(); ++it) {
    1498            0 :         if ((*it)->getID() == substationId) {
    1499              :             return true;
    1500              :         }
    1501              :     }
    1502              :     return false;
    1503              : }
    1504              : 
    1505              : 
    1506              : MSVehicleRouter&
    1507        54728 : MSNet::getRouterTT(const int rngIndex, const MSEdgeVector& prohibited) const {
    1508              :     if (myRouterTT.count(rngIndex) == 0) {
    1509         1830 :         const std::string routingAlgorithm = OptionsCont::getOptions().getString("routing-algorithm");
    1510         1830 :         if (routingAlgorithm == "dijkstra") {
    1511         1604 :             myRouterTT[rngIndex] = new DijkstraRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, &MSNet::getTravelTime, nullptr, false, nullptr, true);
    1512              :         } else {
    1513          226 :             if (routingAlgorithm != "astar") {
    1514            0 :                 WRITE_WARNINGF(TL("TraCI and Triggers cannot use routing algorithm '%'. using 'astar' instead."), routingAlgorithm);
    1515              :             }
    1516          226 :             myRouterTT[rngIndex] = new AStarRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, &MSNet::getTravelTime, nullptr, true);
    1517              :         }
    1518              :     }
    1519        54728 :     myRouterTT[rngIndex]->prohibit(prohibited);
    1520        54728 :     return *myRouterTT[rngIndex];
    1521              : }
    1522              : 
    1523              : 
    1524              : MSVehicleRouter&
    1525           11 : MSNet::getRouterEffort(const int rngIndex, const MSEdgeVector& prohibited) const {
    1526              :     if (myRouterEffort.count(rngIndex) == 0) {
    1527           11 :         myRouterEffort[rngIndex] = new DijkstraRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, &MSNet::getEffort, &MSNet::getTravelTime, false, nullptr, true);
    1528              :     }
    1529           11 :     myRouterEffort[rngIndex]->prohibit(prohibited);
    1530           11 :     return *myRouterEffort[rngIndex];
    1531              : }
    1532              : 
    1533              : 
    1534              : MSPedestrianRouter&
    1535       817866 : MSNet::getPedestrianRouter(const int rngIndex, const MSEdgeVector& prohibited) const {
    1536              :     if (myPedestrianRouter.count(rngIndex) == 0) {
    1537         2627 :         myPedestrianRouter[rngIndex] = new MSPedestrianRouter();
    1538              :     }
    1539       817866 :     myPedestrianRouter[rngIndex]->prohibit(prohibited);
    1540       817866 :     return *myPedestrianRouter[rngIndex];
    1541              : }
    1542              : 
    1543              : 
    1544              : MSTransportableRouter&
    1545       181600 : MSNet::getIntermodalRouter(const int rngIndex, const int routingMode, const MSEdgeVector& prohibited) const {
    1546       181600 :     const OptionsCont& oc = OptionsCont::getOptions();
    1547       181600 :     const int key = rngIndex * oc.getInt("thread-rngs") + routingMode;
    1548              :     if (myIntermodalRouter.count(key) == 0) {
    1549         3437 :         const int carWalk = SUMOVehicleParserHelper::parseCarWalkTransfer(oc, MSDevice_Taxi::getTaxi() != nullptr);
    1550         3437 :         const std::string routingAlgorithm = OptionsCont::getOptions().getString("routing-algorithm");
    1551         3437 :         const double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
    1552         3437 :         if (routingMode == libsumo::ROUTING_MODE_COMBINED) {
    1553            0 :             myIntermodalRouter[key] = new MSTransportableRouter(MSNet::adaptIntermodalRouter, carWalk, taxiWait, routingAlgorithm, routingMode, new FareModul());
    1554              :         } else {
    1555         3437 :             myIntermodalRouter[key] = new MSTransportableRouter(MSNet::adaptIntermodalRouter, carWalk, taxiWait, routingAlgorithm, routingMode);
    1556              :         }
    1557              :     }
    1558       181600 :     myIntermodalRouter[key]->prohibit(prohibited);
    1559       181600 :     return *myIntermodalRouter[key];
    1560              : }
    1561              : 
    1562              : 
    1563              : void
    1564         4247 : MSNet::adaptIntermodalRouter(MSTransportableRouter& router) {
    1565         8494 :     double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
    1566              :     // add access to all parking areas
    1567              :     EffortCalculator* const external = router.getExternalEffort();
    1568        12653 :     for (const auto& stopType : myInstance->myStoppingPlaces) {
    1569              :         // add access to all stopping places
    1570         8406 :         const SumoXMLTag element = stopType.first;
    1571        30921 :         for (const auto& i : stopType.second) {
    1572        22515 :             const MSEdge* const edge = &i.second->getLane().getEdge();
    1573        22515 :             router.getNetwork()->addAccess(i.first, edge, i.second->getBeginLanePosition(), i.second->getEndLanePosition(),
    1574              :                                            0., element, false, taxiWait);
    1575        22515 :             if (element == SUMO_TAG_BUS_STOP) {
    1576              :                 // add access to all public transport stops
    1577        10918 :                 for (const auto& a : i.second->getAllAccessPos()) {
    1578         1007 :                     router.getNetwork()->addAccess(i.first, &a.lane->getEdge(), a.startPos, a.endPos, a.length, element, true, taxiWait);
    1579              :                 }
    1580         9911 :                 if (external != nullptr) {
    1581            0 :                     external->addStop(router.getNetwork()->getStopEdge(i.first)->getNumericalID(), *i.second);
    1582              :                 }
    1583              :             }
    1584              :         }
    1585              :     }
    1586         4247 :     myInstance->getInsertionControl().adaptIntermodalRouter(router);
    1587         4247 :     myInstance->getVehicleControl().adaptIntermodalRouter(router);
    1588              :     // add access to transfer from walking to taxi-use
    1589         4247 :     if ((router.getCarWalkTransfer() & ModeChangeOptions::TAXI_PICKUP_ANYWHERE) != 0) {
    1590        24224 :         for (MSEdge* edge : myInstance->getEdgeControl().getEdges()) {
    1591        24136 :             if ((edge->getPermissions() & SVC_PEDESTRIAN) != 0 && (edge->getPermissions() & SVC_TAXI) != 0) {
    1592        11456 :                 router.getNetwork()->addCarAccess(edge, SVC_TAXI, taxiWait);
    1593              :             }
    1594              :         }
    1595              :     }
    1596         4247 : }
    1597              : 
    1598              : 
    1599              : bool
    1600        42556 : MSNet::checkElevation() {
    1601        42556 :     const MSEdgeVector& edges = myEdges->getEdges();
    1602      1773401 :     for (MSEdgeVector::const_iterator e = edges.begin(); e != edges.end(); ++e) {
    1603      3882001 :         for (std::vector<MSLane*>::const_iterator i = (*e)->getLanes().begin(); i != (*e)->getLanes().end(); ++i) {
    1604      2151156 :             if ((*i)->getShape().hasElevation()) {
    1605              :                 return true;
    1606              :             }
    1607              :         }
    1608              :     }
    1609              :     return false;
    1610              : }
    1611              : 
    1612              : 
    1613              : bool
    1614        42556 : MSNet::checkWalkingarea() {
    1615      1374755 :     for (const MSEdge* e : myEdges->getEdges()) {
    1616      1340149 :         if (e->getFunction() == SumoXMLEdgeFunc::WALKINGAREA) {
    1617              :             return true;
    1618              :         }
    1619              :     }
    1620              :     return false;
    1621              : }
    1622              : 
    1623              : 
    1624              : bool
    1625        42556 : MSNet::checkBidiEdges() {
    1626      1720863 :     for (const MSEdge* e : myEdges->getEdges()) {
    1627      1679172 :         if (e->getBidiEdge() != nullptr) {
    1628              :             return true;
    1629              :         }
    1630              :     }
    1631              :     return false;
    1632              : }
    1633              : 
    1634              : bool
    1635          291 : MSNet::warnOnce(const std::string& typeAndID) {
    1636          291 :     if (myWarnedOnce.find(typeAndID) == myWarnedOnce.end()) {
    1637          278 :         myWarnedOnce[typeAndID] = true;
    1638          278 :         return true;
    1639              :     }
    1640              :     return false;
    1641              : }
    1642              : 
    1643              : void
    1644            0 : MSNet::quickReload() {
    1645            0 :     const OptionsCont& oc = OptionsCont::getOptions();
    1646            0 :     clearState(string2time(oc.getString("begin")), true);
    1647            0 :     NLBuilder::initRandomness();
    1648              :     // load traffic from additional files
    1649            0 :     for (std::string file : oc.getStringVector("additional-files")) {
    1650              :         // ignore failure on parsing calibrator flow
    1651            0 :         MSRouteHandler rh(file, true);
    1652            0 :         const long before = PROGRESS_BEGIN_TIME_MESSAGE("Loading traffic from '" + file + "'");
    1653            0 :         if (!XMLSubSys::runParser(rh, file, false)) {
    1654            0 :             throw ProcessError(TLF("Loading of % failed.", file));
    1655              :         }
    1656            0 :         PROGRESS_TIME_MESSAGE(before);
    1657            0 :     }
    1658            0 :     delete myRouteLoaders;
    1659            0 :     myRouteLoaders = NLBuilder::buildRouteLoaderControl(OptionsCont::getOptions());
    1660            0 :     updateGUI();
    1661            0 : }
    1662              : 
    1663              : 
    1664              : SUMOTime
    1665          187 : MSNet::loadState(const std::string& fileName, const bool catchExceptions) {
    1666              :     // load time only
    1667          187 :     const SUMOTime newTime = MSStateHandler::MSStateTimeHandler::getTime(fileName);
    1668              :     // clean up state
    1669          177 :     clearState(newTime);
    1670              :     // load state
    1671          177 :     MSStateHandler h(fileName, 0);
    1672          177 :     XMLSubSys::runParser(h, fileName, false, false, false, catchExceptions);
    1673          177 :     if (MsgHandler::getErrorInstance()->wasInformed()) {
    1674            0 :         throw ProcessError(TLF("Loading state from '%' failed.", fileName));
    1675              :     }
    1676              :     // reset route loaders
    1677          177 :     delete myRouteLoaders;
    1678          177 :     myRouteLoaders = NLBuilder::buildRouteLoaderControl(OptionsCont::getOptions());
    1679              :     // prevent loading errors on rewound route file
    1680          177 :     MSGlobals::gStateLoaded = true;
    1681              : 
    1682          177 :     updateGUI();
    1683          177 :     return newTime;
    1684          177 : }
    1685              : 
    1686              : 
    1687              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1