LCOV - code coverage report
Current view: top level - src/libsumo - Simulation.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 91.0 % 591 538
Test Date: 2025-12-06 15:35:27 Functions: 90.2 % 82 74

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2017-2025 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    Simulation.cpp
      15              : /// @author  Laura Bieker-Walz
      16              : /// @author  Robert Hilbrich
      17              : /// @author  Mirko Barthauer
      18              : /// @date    15.09.2017
      19              : ///
      20              : // C++ TraCI client API implementation
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : #ifdef HAVE_VERSION_H
      24              : #include <version.h>
      25              : #endif
      26              : #include <utils/options/OptionsCont.h>
      27              : #include <utils/common/MsgHandler.h>
      28              : #include <utils/common/StdDefs.h>
      29              : #include <utils/common/StringTokenizer.h>
      30              : #include <utils/common/StringUtils.h>
      31              : #include <utils/common/SystemFrame.h>
      32              : #include <utils/geom/GeoConvHelper.h>
      33              : #include <utils/options/OptionsIO.h>
      34              : #include <utils/router/IntermodalRouter.h>
      35              : #include <utils/router/PedestrianRouter.h>
      36              : #include <utils/xml/XMLSubSys.h>
      37              : #include <microsim/MSNet.h>
      38              : #include <microsim/MSEdgeControl.h>
      39              : #include <microsim/MSInsertionControl.h>
      40              : #include <microsim/MSEdge.h>
      41              : #include <microsim/MSLane.h>
      42              : #include <microsim/MSVehicle.h>
      43              : #include <microsim/MSVehicleControl.h>
      44              : #include <microsim/MSVehicleTransfer.h>
      45              : #include <microsim/transportables/MSTransportableControl.h>
      46              : #include <microsim/MSStateHandler.h>
      47              : #include <microsim/MSStoppingPlace.h>
      48              : #include <microsim/MSParkingArea.h>
      49              : #include <microsim/devices/MSRoutingEngine.h>
      50              : #include <microsim/devices/MSDevice_Taxi.h>
      51              : #include <microsim/trigger/MSChargingStation.h>
      52              : #include <microsim/trigger/MSOverheadWire.h>
      53              : #include <microsim/devices/MSDevice_Tripinfo.h>
      54              : #include <mesosim/MELoop.h>
      55              : #include <mesosim/MESegment.h>
      56              : #include <netload/NLBuilder.h>
      57              : #include <libsumo/Helper.h>
      58              : #include <libsumo/StorageHelper.h>
      59              : #include <libsumo/TraCIConstants.h>
      60              : #ifdef HAVE_LIBSUMOGUI
      61              : #include "GUI.h"
      62              : #endif
      63              : #include "Simulation.h"
      64              : #include <libsumo/TraCIDefs.h>
      65              : 
      66              : 
      67              : namespace libsumo {
      68              : // ===========================================================================
      69              : // static member initializations
      70              : // ===========================================================================
      71              : SubscriptionResults Simulation::mySubscriptionResults;
      72              : ContextSubscriptionResults Simulation::myContextSubscriptionResults;
      73              : #ifdef HAVE_FOX
      74              : FXMutex Simulation::myStepMutex;
      75              : #endif
      76              : 
      77              : 
      78              : // ===========================================================================
      79              : // static member definitions
      80              : // ===========================================================================
      81              : std::pair<int, std::string>
      82            2 : Simulation::init(int /* port */, int /* numRetries */, const std::string& /* host */, const std::string& /* label */, FILE* const /* pipe */) {
      83            4 :     throw TraCIException("Multi client support (including connection switching) is not implemented in libsumo.");
      84              : }
      85              : 
      86              : 
      87              : std::pair<int, std::string>
      88         1111 : Simulation::start(const std::vector<std::string>& cmd, int /* port */, int /* numRetries */, const std::string& /* label */, const bool /* verbose */,
      89              :                   const std::string& /* traceFile */, bool /* traceGetters */, void* /* _stdout */) {
      90              : #ifdef HAVE_LIBSUMOGUI
      91         1111 :     if (GUI::start(cmd)) {
      92          521 :         return getVersion();
      93              :     }
      94              : #endif
      95          590 :     load(std::vector<std::string>(cmd.begin() + 1, cmd.end()));
      96          590 :     return getVersion();
      97              : }
      98              : 
      99              : 
     100              : bool
     101            0 : Simulation::isLibsumo() {
     102            0 :     return true;
     103              : }
     104              : 
     105              : 
     106              : void
     107            0 : Simulation::switchConnection(const std::string& /* label */) {
     108            0 :     throw TraCIException("Multi client support (including connection switching) is not implemented in libsumo.");
     109              : }
     110              : 
     111              : 
     112              : const std::string&
     113            0 : Simulation::getLabel() {
     114            0 :     throw TraCIException("Multi client support (including connection switching) is not implemented in libsumo.");
     115              : }
     116              : 
     117              : 
     118              : void
     119            1 : Simulation::setOrder(int /* order */) {
     120            2 :     throw TraCIException("Multi client support (including connection switching) is not implemented in libsumo.");
     121              : }
     122              : 
     123              : 
     124              : void
     125          597 : Simulation::load(const std::vector<std::string>& args) {
     126              : #ifdef HAVE_LIBSUMOGUI
     127          597 :     if (GUI::load(args)) {
     128              :         return;
     129              :     }
     130              : #endif
     131          595 :     close("Libsumo issued load command.");
     132              :     try {
     133         1190 :         OptionsCont::getOptions().setApplicationName("libsumo", "Eclipse SUMO libsumo " VERSION_STRING);
     134          595 :         gSimulation = true;
     135          595 :         XMLSubSys::init();
     136          595 :         OptionsIO::setArgs(args);
     137          595 :         if (NLBuilder::init(true) != nullptr) {
     138          593 :             const SUMOTime begin = string2time(OptionsCont::getOptions().getString("begin"));
     139          593 :             MSNet::getInstance()->setCurrentTimeStep(begin); // needed for state loading
     140         1186 :             WRITE_MESSAGEF(TL("Simulation version % started via libsumo with time: %."), VERSION_STRING, time2string(begin));
     141              :         }
     142            0 :     } catch (ProcessError& e) {
     143            0 :         throw TraCIException(e.what());
     144            0 :     }
     145            0 : }
     146              : 
     147              : 
     148              : bool
     149            2 : Simulation::hasGUI() {
     150              : #ifdef HAVE_LIBSUMOGUI
     151            2 :     return GUI::hasInstance();
     152              : #else
     153            0 :     return false;
     154              : #endif
     155              : }
     156              : 
     157              : 
     158              : bool
     159            8 : Simulation::isLoaded() {
     160            8 :     return MSNet::hasInstance();
     161              : }
     162              : 
     163              : 
     164              : void
     165       185710 : Simulation::step(const double time) {
     166              : #ifdef HAVE_FOX
     167              :     FXMutexLock lock(myStepMutex);
     168              : #endif
     169       185710 :     Helper::clearStateChanges();
     170       185710 :     const SUMOTime t = TIME2STEPS(time);
     171              : #ifdef HAVE_LIBSUMOGUI
     172       185710 :     if (!GUI::step(t)) {
     173              : #endif
     174       103183 :         if (t == 0) {
     175       103016 :             MSNet::getInstance()->simulationStep();
     176              :         } else {
     177         1859 :             while (SIMSTEP < t) {
     178         1692 :                 MSNet::getInstance()->simulationStep();
     179              :             }
     180              :         }
     181              : #ifdef HAVE_LIBSUMOGUI
     182              :     }
     183              : #endif
     184       185710 :     Helper::handleSubscriptions(SIMSTEP);
     185       185710 : }
     186              : 
     187              : 
     188              : void
     189            4 : Simulation::executeMove() {
     190            4 :     MSNet::getInstance()->simulationStep(true);
     191            4 : }
     192              : 
     193              : 
     194              : void
     195         1681 : Simulation::close(const std::string& reason) {
     196         1681 :     Helper::clearSubscriptions();
     197            0 :     if (
     198              : #ifdef HAVE_LIBSUMOGUI
     199         1681 :         !GUI::close(reason) &&
     200              : #endif
     201              :         MSNet::hasInstance()) {
     202          592 :         MSNet::getInstance()->closeSimulation(0, reason);
     203          592 :         delete MSNet::getInstance();
     204          592 :         SystemFrame::close();
     205              :     }
     206         1680 : }
     207              : 
     208              : 
     209              : void
     210           54 : Simulation::subscribe(const std::vector<int>& varIDs, double begin, double end, const libsumo::TraCIResults& parameters) {
     211           54 :     libsumo::Helper::subscribe(CMD_SUBSCRIBE_SIM_VARIABLE, "", varIDs, begin, end, parameters);
     212           42 : }
     213              : 
     214              : 
     215              : const TraCIResults
     216           58 : Simulation::getSubscriptionResults() {
     217          116 :     return mySubscriptionResults[""];
     218              : }
     219              : 
     220              : 
     221          383 : LIBSUMO_SUBSCRIPTION_IMPLEMENTATION(Simulation, SIM)
     222              : 
     223              : 
     224              : std::pair<int, std::string>
     225         1113 : Simulation::getVersion() {
     226         1113 :     return std::make_pair(libsumo::TRACI_VERSION, "SUMO " VERSION_STRING);
     227              : }
     228              : 
     229              : 
     230              : std::string
     231           14 : Simulation::getOption(const std::string& option) {
     232           14 :     OptionsCont& oc = OptionsCont::getOptions();
     233           14 :     if (!oc.exists(option)) {
     234            0 :         throw TraCIException("The option " + option + " is unknown.");
     235              :     }
     236           14 :     return oc.getValueString(option);
     237              : }
     238              : 
     239              : 
     240              : int
     241           14 : Simulation::getCurrentTime() {
     242           14 :     return (int)MSNet::getInstance()->getCurrentTimeStep();
     243              : }
     244              : 
     245              : 
     246              : double
     247       296500 : Simulation::getTime() {
     248       296500 :     return SIMTIME;
     249              : }
     250              : 
     251              : double
     252           14 : Simulation::getEndTime() {
     253           28 :     return STEPS2TIME(string2time(OptionsCont::getOptions().getString("end")));
     254              : }
     255              : 
     256              : 
     257              : int
     258           10 : Simulation::getLoadedNumber() {
     259           10 :     return (int)Helper::getVehicleStateChanges(MSNet::VehicleState::BUILT).size();
     260              : }
     261              : 
     262              : 
     263              : std::vector<std::string>
     264           50 : Simulation::getLoadedIDList() {
     265           50 :     return Helper::getVehicleStateChanges(MSNet::VehicleState::BUILT);
     266              : }
     267              : 
     268              : 
     269              : int
     270         1362 : Simulation::getDepartedNumber() {
     271         1362 :     return (int)Helper::getVehicleStateChanges(MSNet::VehicleState::DEPARTED).size();
     272              : }
     273              : 
     274              : 
     275              : std::vector<std::string>
     276         6052 : Simulation::getDepartedIDList() {
     277         6052 :     return Helper::getVehicleStateChanges(MSNet::VehicleState::DEPARTED);
     278              : }
     279              : 
     280              : 
     281              : int
     282          346 : Simulation::getArrivedNumber() {
     283          346 :     return (int)Helper::getVehicleStateChanges(MSNet::VehicleState::ARRIVED).size();
     284              : }
     285              : 
     286              : 
     287              : std::vector<std::string>
     288         6032 : Simulation::getArrivedIDList() {
     289         6032 :     return Helper::getVehicleStateChanges(MSNet::VehicleState::ARRIVED);
     290              : }
     291              : 
     292              : 
     293              : int
     294           10 : Simulation::getParkingStartingVehiclesNumber() {
     295           10 :     return (int)Helper::getVehicleStateChanges(MSNet::VehicleState::STARTING_PARKING).size();
     296              : }
     297              : 
     298              : 
     299              : std::vector<std::string>
     300           10 : Simulation::getParkingStartingVehiclesIDList() {
     301           10 :     return Helper::getVehicleStateChanges(MSNet::VehicleState::STARTING_PARKING);
     302              : }
     303              : 
     304              : 
     305              : int
     306           10 : Simulation::getParkingEndingVehiclesNumber() {
     307           10 :     return (int)Helper::getVehicleStateChanges(MSNet::VehicleState::ENDING_PARKING).size();
     308              : }
     309              : 
     310              : 
     311              : std::vector<std::string>
     312           10 : Simulation::getParkingEndingVehiclesIDList() {
     313           10 :     return Helper::getVehicleStateChanges(MSNet::VehicleState::ENDING_PARKING);
     314              : }
     315              : 
     316              : 
     317              : int
     318           10 : Simulation::getStopStartingVehiclesNumber() {
     319           10 :     return (int)Helper::getVehicleStateChanges(MSNet::VehicleState::STARTING_STOP).size();
     320              : }
     321              : 
     322              : 
     323              : std::vector<std::string>
     324           10 : Simulation::getStopStartingVehiclesIDList() {
     325           10 :     return Helper::getVehicleStateChanges(MSNet::VehicleState::STARTING_STOP);
     326              : }
     327              : 
     328              : 
     329              : int
     330           10 : Simulation::getStopEndingVehiclesNumber() {
     331           10 :     return (int)Helper::getVehicleStateChanges(MSNet::VehicleState::ENDING_STOP).size();
     332              : }
     333              : 
     334              : 
     335              : std::vector<std::string>
     336           10 : Simulation::getStopEndingVehiclesIDList() {
     337           10 :     return Helper::getVehicleStateChanges(MSNet::VehicleState::ENDING_STOP);
     338              : }
     339              : 
     340              : 
     341              : int
     342           35 : Simulation::getCollidingVehiclesNumber() {
     343           35 :     return (int)Helper::getVehicleStateChanges(MSNet::VehicleState::COLLISION).size();
     344              : }
     345              : 
     346              : 
     347              : std::vector<std::string>
     348           10 : Simulation::getCollidingVehiclesIDList() {
     349           10 :     return Helper::getVehicleStateChanges(MSNet::VehicleState::COLLISION);
     350              : }
     351              : 
     352              : 
     353              : int
     354           34 : Simulation::getEmergencyStoppingVehiclesNumber() {
     355           34 :     return (int)Helper::getVehicleStateChanges(MSNet::VehicleState::EMERGENCYSTOP).size();
     356              : }
     357              : 
     358              : 
     359              : std::vector<std::string>
     360           10 : Simulation::getEmergencyStoppingVehiclesIDList() {
     361           10 :     return Helper::getVehicleStateChanges(MSNet::VehicleState::EMERGENCYSTOP);
     362              : }
     363              : 
     364              : 
     365              : int
     366           10 : Simulation::getStartingTeleportNumber() {
     367           10 :     return (int)Helper::getVehicleStateChanges(MSNet::VehicleState::STARTING_TELEPORT).size();
     368              : }
     369              : 
     370              : 
     371              : std::vector<std::string>
     372           10 : Simulation::getStartingTeleportIDList() {
     373           10 :     return Helper::getVehicleStateChanges(MSNet::VehicleState::STARTING_TELEPORT);
     374              : }
     375              : 
     376              : 
     377              : int
     378           10 : Simulation::getEndingTeleportNumber() {
     379           10 :     return (int)Helper::getVehicleStateChanges(MSNet::VehicleState::ENDING_TELEPORT).size();
     380              : }
     381              : 
     382              : 
     383              : std::vector<std::string>
     384           10 : Simulation::getEndingTeleportIDList() {
     385           10 :     return Helper::getVehicleStateChanges(MSNet::VehicleState::ENDING_TELEPORT);
     386              : }
     387              : 
     388              : int
     389            8 : Simulation::getDepartedPersonNumber() {
     390            8 :     return (int)Helper::getTransportableStateChanges(MSNet::TransportableState::PERSON_DEPARTED).size();
     391              : }
     392              : 
     393              : 
     394              : std::vector<std::string>
     395            8 : Simulation::getDepartedPersonIDList() {
     396            8 :     return Helper::getTransportableStateChanges(MSNet::TransportableState::PERSON_DEPARTED);
     397              : }
     398              : 
     399              : 
     400              : int
     401            8 : Simulation::getArrivedPersonNumber() {
     402            8 :     return (int)Helper::getTransportableStateChanges(MSNet::TransportableState::PERSON_ARRIVED).size();
     403              : }
     404              : 
     405              : 
     406              : std::vector<std::string>
     407            8 : Simulation::getArrivedPersonIDList() {
     408            8 :     return Helper::getTransportableStateChanges(MSNet::TransportableState::PERSON_ARRIVED);
     409              : }
     410              : 
     411              : std::vector<std::string>
     412           13 : Simulation::getBusStopIDList() {
     413              :     std::vector<std::string> result;
     414           26 :     for (const auto& pair : MSNet::getInstance()->getStoppingPlaces(SUMO_TAG_BUS_STOP)) {
     415           13 :         result.push_back(pair.first);
     416              :     }
     417           13 :     return result;
     418            0 : }
     419              : 
     420              : int
     421           15 : Simulation::getBusStopWaiting(const std::string& stopID) {
     422           15 :     MSStoppingPlace* s = MSNet::getInstance()->getStoppingPlace(stopID, SUMO_TAG_BUS_STOP);
     423           15 :     if (s == nullptr) {
     424           18 :         throw TraCIException("Unknown bus stop '" + stopID + "'.");
     425              :     }
     426            6 :     return s->getTransportableNumber();
     427              : }
     428              : 
     429              : std::vector<std::string>
     430          160 : Simulation::getBusStopWaitingIDList(const std::string& stopID) {
     431          160 :     MSStoppingPlace* s = MSNet::getInstance()->getStoppingPlace(stopID, SUMO_TAG_BUS_STOP);
     432          160 :     if (s == nullptr) {
     433            8 :         throw TraCIException("Unknown bus stop '" + stopID + "'.");
     434              :     }
     435              :     std::vector<std::string> result;
     436          212 :     for (const MSTransportable* t : s->getTransportables()) {
     437           56 :         result.push_back(t->getID());
     438          156 :     }
     439          156 :     return result;
     440            0 : }
     441              : 
     442              : 
     443              : std::vector<std::string>
     444           38 : Simulation::getPendingVehicles() {
     445              :     std::vector<std::string> result;
     446           43 :     for (const SUMOVehicle* veh : MSNet::getInstance()->getInsertionControl().getPendingVehicles()) {
     447            5 :         result.push_back(veh->getID());
     448              :     }
     449           38 :     return result;
     450            0 : }
     451              : 
     452              : 
     453              : std::vector<libsumo::TraCICollision>
     454          346 : Simulation::getCollisions() {
     455              :     std::vector<libsumo::TraCICollision> result;
     456          371 :     for (auto item : MSNet::getInstance()->getCollisions()) {
     457           50 :         for (const MSNet::Collision& c : item.second) {
     458              :             libsumo::TraCICollision c2;
     459              :             c2.collider = item.first;
     460           25 :             c2.victim = c.victim;
     461           25 :             c2.colliderType = c.colliderType;
     462           25 :             c2.victimType = c.victimType;
     463           25 :             c2.colliderSpeed = c.colliderSpeed;
     464           25 :             c2.victimSpeed = c.victimSpeed;
     465           25 :             c2.type = c.type;
     466           25 :             c2.lane = c.lane->getID();
     467           25 :             c2.pos = c.pos;
     468           25 :             result.push_back(c2);
     469           25 :         }
     470              :     }
     471          346 :     return result;
     472            0 : }
     473              : 
     474              : double
     475           13 : Simulation::getScale() {
     476           13 :     return MSNet::getInstance()->getVehicleControl().getScale();
     477              : }
     478              : 
     479              : double
     480          148 : Simulation::getDeltaT() {
     481          148 :     return TS;
     482              : }
     483              : 
     484              : 
     485              : TraCIPositionVector
     486           11 : Simulation::getNetBoundary() {
     487           11 :     Boundary b = GeoConvHelper::getFinal().getConvBoundary();
     488              :     TraCIPositionVector tb;
     489           11 :     TraCIPosition minV;
     490           11 :     TraCIPosition maxV;
     491           11 :     minV.x = b.xmin();
     492           11 :     maxV.x = b.xmax();
     493           11 :     minV.y = b.ymin();
     494           11 :     maxV.y = b.ymax();
     495           11 :     minV.z = b.zmin();
     496           11 :     maxV.z = b.zmax();
     497           11 :     tb.value.push_back(minV);
     498           11 :     tb.value.push_back(maxV);
     499           11 :     return tb;
     500              : }
     501              : 
     502              : 
     503              : int
     504      7732230 : Simulation::getMinExpectedNumber() {
     505      7732230 :     MSNet* net = MSNet::getInstance();
     506              :     return (net->getVehicleControl().getActiveVehicleCount()
     507      7732229 :             + net->getInsertionControl().getPendingFlowCount()
     508      7732229 :             + (net->hasPersons() ? net->getPersonControl().getActiveCount() : 0)
     509      7732229 :             + (net->hasContainers() ? net->getContainerControl().getActiveCount() : 0)
     510      7732229 :             + (MSDevice_Taxi::hasServableReservations() ? 1 : 0));
     511              : }
     512              : 
     513              : 
     514              : TraCIPosition
     515           89 : Simulation::convert2D(const std::string& edgeID, double pos, int laneIndex, bool toGeo) {
     516           89 :     Position result = Helper::getLaneChecking(edgeID, laneIndex, pos)->geometryPositionAtOffset(pos);
     517           89 :     if (toGeo) {
     518            2 :         GeoConvHelper::getFinal().cartesian2geo(result);
     519              :     }
     520              :     result.setz(0.);
     521           89 :     return Helper::makeTraCIPosition(result);
     522              : }
     523              : 
     524              : 
     525              : TraCIPosition
     526            4 : Simulation::convert3D(const std::string& edgeID, double pos, int laneIndex, bool toGeo) {
     527            4 :     Position result = Helper::getLaneChecking(edgeID, laneIndex, pos)->geometryPositionAtOffset(pos);
     528            4 :     if (toGeo) {
     529            2 :         GeoConvHelper::getFinal().cartesian2geo(result);
     530              :     }
     531            4 :     return Helper::makeTraCIPosition(result, true);
     532              : }
     533              : 
     534              : 
     535              : TraCIRoadPosition
     536           52 : Simulation::convertRoad(double x, double y, bool isGeo, const std::string& vClass) {
     537              :     Position pos(x, y);
     538           52 :     if (isGeo) {
     539            6 :         GeoConvHelper::getFinal().x2cartesian_const(pos);
     540              :     }
     541           52 :     if (!SumoVehicleClassStrings.hasString(vClass)) {
     542            0 :         throw TraCIException("Unknown vehicle class '" + vClass + "'.");
     543              :     }
     544           52 :     const SUMOVehicleClass vc = SumoVehicleClassStrings.get(vClass);
     545           52 :     std::pair<MSLane*, double> roadPos = libsumo::Helper::convertCartesianToRoadMap(pos, vc);
     546           52 :     if (roadPos.first == nullptr) {
     547            0 :         throw TraCIException("Cannot convert position to road.");
     548              :     }
     549          104 :     TraCIRoadPosition result;
     550              :     result.edgeID = roadPos.first->getEdge().getID();
     551           52 :     result.laneIndex = roadPos.first->getIndex();
     552           52 :     result.pos = roadPos.second;
     553           52 :     return result;
     554              : }
     555              : 
     556              : 
     557              : TraCIPosition
     558           10 : Simulation::convertGeo(double x, double y, bool fromGeo) {
     559              :     Position pos(x, y);
     560           10 :     if (fromGeo) {
     561            2 :         GeoConvHelper::getFinal().x2cartesian_const(pos);
     562              :     } else {
     563            8 :         GeoConvHelper::getFinal().cartesian2geo(pos);
     564              :     }
     565           10 :     return Helper::makeTraCIPosition(pos);
     566              : }
     567              : 
     568              : 
     569              : double
     570           74 : Simulation::getDistance2D(double x1, double y1, double x2, double y2, bool isGeo, bool isDriving) {
     571              :     Position pos1(x1, y1);
     572              :     Position pos2(x2, y2);
     573           74 :     if (isGeo) {
     574            2 :         GeoConvHelper::getFinal().x2cartesian_const(pos1);
     575            2 :         GeoConvHelper::getFinal().x2cartesian_const(pos2);
     576              :     }
     577           74 :     if (isDriving) {
     578           70 :         std::pair<const MSLane*, double> roadPos1 = libsumo::Helper::convertCartesianToRoadMap(pos1, SVC_IGNORING);
     579           70 :         std::pair<const MSLane*, double> roadPos2 = libsumo::Helper::convertCartesianToRoadMap(pos2, SVC_IGNORING);
     580           70 :         return Helper::getDrivingDistance(roadPos1, roadPos2);
     581              :     } else {
     582            4 :         return pos1.distanceTo(pos2);
     583              :     }
     584              : }
     585              : 
     586              : 
     587              : double
     588           88 : Simulation::getDistanceRoad(const std::string& edgeID1, double pos1, const std::string& edgeID2, double pos2, bool isDriving) {
     589           88 :     std::pair<const MSLane*, double> roadPos1 = std::make_pair(libsumo::Helper::getLaneChecking(edgeID1, 0, pos1), pos1);
     590           88 :     std::pair<const MSLane*, double> roadPos2 = std::make_pair(libsumo::Helper::getLaneChecking(edgeID2, 0, pos2), pos2);
     591           88 :     if (isDriving) {
     592           18 :         return Helper::getDrivingDistance(roadPos1, roadPos2);
     593              :     } else {
     594           70 :         const Position p1 = roadPos1.first->geometryPositionAtOffset(roadPos1.second);
     595           70 :         const Position p2 = roadPos2.first->geometryPositionAtOffset(roadPos2.second);
     596           70 :         return p1.distanceTo(p2);
     597              :     }
     598              : }
     599              : 
     600              : 
     601              : TraCIStage
     602         5437 : Simulation::findRoute(const std::string& from, const std::string& to, const std::string& typeID,
     603              :         double depart, int routingMode, double departPos, double arrivalPos) {
     604        10874 :     TraCIStage result(STAGE_DRIVING);
     605         5437 :     const MSEdge* const fromEdge = MSEdge::dictionary(from);
     606         5437 :     if (fromEdge == nullptr) {
     607           10 :         throw TraCIException("Unknown from edge '" + from + "'.");
     608              :     }
     609         5432 :     const MSEdge* const toEdge = MSEdge::dictionary(to);
     610         5432 :     if (toEdge == nullptr) {
     611            0 :         throw TraCIException("Unknown to edge '" + to + "'.");
     612              :     }
     613              :     MSBaseVehicle* vehicle = nullptr;
     614        10818 :     MSVehicleType* type = MSNet::getInstance()->getVehicleControl().getVType(typeID == "" ? DEFAULT_VTYPE_ID : typeID);
     615         5432 :     if (type == nullptr) {
     616            0 :         throw TraCIException("The vehicle type '" + typeID + "' is not known.");
     617              :     }
     618         5432 :     SUMOVehicleParameter* pars = new SUMOVehicleParameter();
     619         5432 :     pars->id = "simulation.findRoute";
     620              :     try {
     621        10864 :         ConstMSRoutePtr const routeDummy = std::make_shared<MSRoute>("", ConstMSEdgeVector({ fromEdge }), false, nullptr, StopParVector());
     622        10869 :         vehicle = dynamic_cast<MSBaseVehicle*>(MSNet::getInstance()->getVehicleControl().buildVehicle(pars, routeDummy, type, false));
     623              :         std::string msg;
     624         5432 :         if (!vehicle->hasValidRouteStart(msg)) {
     625            5 :             MSNet::getInstance()->getVehicleControl().deleteVehicle(vehicle, true);
     626            5 :             MSNet::getInstance()->getVehicleControl().discountRoutingVehicle();
     627           10 :             throw TraCIException("Invalid departure edge for vehicle type '" + type->getID() + "' (" + msg + ")");
     628              :         }
     629              :         // we need to fix the speed factor here for deterministic results
     630         5427 :         vehicle->setChosenSpeedFactor(type->getSpeedFactor().getParameter(0));
     631              :         vehicle->setRoutingMode(routingMode);
     632            5 :     } catch (ProcessError& e) {
     633            0 :         throw TraCIException("Invalid departure edge for vehicle type '" + type->getID() + "' (" + e.what() + ")");
     634            0 :     }
     635         5427 :     if (abs(departPos) > fromEdge->getLength()) {
     636            0 :         throw TraCIException("Invalid departPos " + toString(departPos) + " on edge '" + fromEdge->getID() + " (length " + toString(fromEdge->getLength()) + ")");
     637              :     }
     638         5427 :     if (departPos < 0) {
     639            5 :         departPos += fromEdge->getLength();
     640              :     }
     641         5427 :     if (arrivalPos == INVALID_DOUBLE_VALUE) {
     642         5412 :         arrivalPos = toEdge->getLength();
     643              :     }
     644         5427 :     if (abs(arrivalPos) > toEdge->getLength()) {
     645            0 :         throw TraCIException("Invalid arrivalPos " + toString(arrivalPos) + " on edge '" + toEdge->getID() + " (length " + toString(toEdge->getLength()) + ")");
     646              :     }
     647         5427 :     if (arrivalPos < 0) {
     648            5 :         arrivalPos += toEdge->getLength();
     649              :     }
     650              :     ConstMSEdgeVector edges;
     651         5427 :     const SUMOTime dep = depart < 0 ? MSNet::getInstance()->getCurrentTimeStep() : TIME2STEPS(depart);
     652        10849 :     SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = routingMode == ROUTING_MODE_AGGREGATED ? MSRoutingEngine::getRouterTT(0, vehicle->getVClass()) : MSNet::getInstance()->getRouterTT(0);
     653         5427 :     router.compute(fromEdge, departPos, toEdge, arrivalPos, vehicle, dep, edges);
     654        28665 :     for (const MSEdge* e : edges) {
     655        23238 :         result.edges.push_back(e->getID());
     656              :     }
     657         5427 :     result.travelTime = result.cost = router.recomputeCostsPos(edges, vehicle, departPos, arrivalPos, dep, &result.length);
     658         5427 :     result.arrivalPos = arrivalPos;
     659         5427 :     result.departPos = departPos;
     660              :     if (vehicle != nullptr) {
     661         5427 :         MSNet::getInstance()->getVehicleControl().deleteVehicle(vehicle, true);
     662         5427 :         MSNet::getInstance()->getVehicleControl().discountRoutingVehicle();
     663              :     }
     664         5427 :     return result;
     665         5437 : }
     666              : 
     667              : 
     668              : std::vector<TraCIStage>
     669          327 : Simulation::findIntermodalRoute(const std::string& from, const std::string& to,
     670              :                                 const std::string& modes, double depart, const int routingMode, double speed, double walkFactor,
     671              :                                 double departPos, double arrivalPos, const double departPosLat,
     672              :                                 const std::string& pType, const std::string& vType, const std::string& destStop) {
     673              :     UNUSED_PARAMETER(departPosLat);
     674              :     std::vector<TraCIStage> result;
     675          327 :     const MSEdge* const fromEdge = MSEdge::dictionary(from);
     676          327 :     if (fromEdge == nullptr) {
     677           10 :         throw TraCIException("Unknown from edge '" + from + "'.");
     678              :     }
     679          322 :     const MSEdge* const toEdge = MSEdge::dictionary(to);
     680          322 :     if (toEdge == nullptr) {
     681            0 :         throw TraCIException("Unknown to edge '" + to + "'.");
     682              :     }
     683          322 :     MSVehicleControl& vehControl = MSNet::getInstance()->getVehicleControl();
     684              :     SVCPermissions modeSet = 0;
     685              :     std::vector<SUMOVehicleParameter*> pars;
     686          322 :     if (vType != "") {
     687          149 :         pars.push_back(new SUMOVehicleParameter());
     688          149 :         pars.back()->vtypeid = vType;
     689          149 :         pars.back()->id = vType;
     690              :         modeSet |= SVC_PASSENGER;
     691              :     }
     692         1020 :     for (StringTokenizer st(modes); st.hasNext();) {
     693          376 :         const std::string mode = st.next();
     694          376 :         if (mode == toString(PersonMode::CAR)) {
     695           70 :             pars.push_back(new SUMOVehicleParameter());
     696           70 :             pars.back()->vtypeid = DEFAULT_VTYPE_ID;
     697           70 :             pars.back()->id = mode;
     698           70 :             modeSet |= SVC_PASSENGER;
     699          306 :         } else if (mode == toString(PersonMode::BICYCLE)) {
     700           80 :             pars.push_back(new SUMOVehicleParameter());
     701           80 :             pars.back()->vtypeid = DEFAULT_BIKETYPE_ID;
     702           80 :             pars.back()->id = mode;
     703           80 :             modeSet |= SVC_BICYCLE;
     704          226 :         } else if (mode == toString(PersonMode::TAXI)) {
     705           16 :             pars.push_back(new SUMOVehicleParameter());
     706           16 :             pars.back()->vtypeid = DEFAULT_TAXITYPE_ID;
     707           16 :             pars.back()->id = mode;
     708           16 :             pars.back()->line = mode;
     709           16 :             modeSet |= SVC_TAXI;
     710          210 :         } else if (mode == toString(PersonMode::PUBLIC)) {
     711          210 :             pars.push_back(nullptr);
     712          210 :             modeSet |= SVC_BUS;
     713            0 :         } else if (mode == toString(PersonMode::WALK)) {
     714              :             // do nothing
     715              :         } else {
     716            0 :             throw TraCIException("Unknown person mode '" + mode + "'.");
     717              :         }
     718          322 :     }
     719          322 :     if (pars.empty()) {
     720           36 :         pars.push_back(nullptr);
     721              :     }
     722              :     // interpret default arguments
     723          322 :     const MSVehicleType* pedType = vehControl.hasVType(pType) ? vehControl.getVType(pType) : vehControl.getVType(DEFAULT_PEDTYPE_ID);
     724          322 :     SUMOTime departStep = TIME2STEPS(depart);
     725          322 :     if (depart < 0) {
     726          318 :         departStep = MSNet::getInstance()->getCurrentTimeStep();
     727              :     }
     728          322 :     if (speed < 0) {
     729              :         speed =  MIN2(pedType->getMaxSpeed(), pedType->getDesiredMaxSpeed());
     730              :     }
     731          322 :     if (walkFactor < 0) {
     732          636 :         walkFactor = OptionsCont::getOptions().getFloat("persontrip.walkfactor");
     733              :     }
     734          644 :     const double externalFactor = StringUtils::toDouble(pedType->getParameter().getParameter("externalEffortFactor", "100"));
     735          322 :     if (departPos < 0) {
     736            0 :         departPos += fromEdge->getLength();
     737              :     }
     738          322 :     if (arrivalPos == INVALID_DOUBLE_VALUE) {
     739           45 :         arrivalPos = toEdge->getLength() / 2;
     740          277 :     } else if (arrivalPos < 0) {
     741            0 :         arrivalPos += toEdge->getLength();
     742              :     }
     743          322 :     if (departPos < 0 || departPos >= fromEdge->getLength()) {
     744           10 :         throw TraCIException("Invalid depart position " + toString(departPos) + " for edge '" + from + "'.");
     745              :     }
     746          317 :     if (arrivalPos < 0 || arrivalPos >= toEdge->getLength()) {
     747            0 :         throw TraCIException("Invalid arrival position " + toString(arrivalPos) + " for edge '" + to + "'.");
     748              :     }
     749              :     double minCost = std::numeric_limits<double>::max();
     750          634 :     MSTransportableRouter& router = MSNet::getInstance()->getIntermodalRouter(0, routingMode);
     751          873 :     for (SUMOVehicleParameter* vehPar : pars) {
     752              :         std::vector<TraCIStage> resultCand;
     753              :         SUMOVehicle* vehicle = nullptr;
     754          556 :         if (vehPar != nullptr) {
     755          315 :             MSVehicleType* type = MSNet::getInstance()->getVehicleControl().getVType(vehPar->vtypeid);
     756          315 :             const bool isTaxi = type != nullptr && type->getID() == DEFAULT_TAXITYPE_ID && vehPar->line == "taxi";
     757              :             if (type == nullptr) {
     758            0 :                 throw TraCIException("Unknown vehicle type '" + vehPar->vtypeid + "'.");
     759              :             }
     760          315 :             if (type->getVehicleClass() != SVC_IGNORING && (fromEdge->getPermissions() & type->getVehicleClass()) == 0 && !isTaxi) {
     761           30 :                 WRITE_WARNINGF(TL("Ignoring vehicle type '%' when performing intermodal routing because it is not allowed on the start edge '%'."), type->getID(), from);
     762              :             } else {
     763          305 :                 ConstMSRoutePtr const routeDummy = std::make_shared<MSRoute>(vehPar->id, ConstMSEdgeVector({ fromEdge }), false, nullptr, StopParVector());
     764          305 :                 vehicle = vehControl.buildVehicle(vehPar, routeDummy, type, !MSGlobals::gCheckRoutes);
     765              :                 // we need to fix the speed factor here for deterministic results
     766          305 :                 vehicle->setChosenSpeedFactor(type->getSpeedFactor().getParameter(0));
     767              :             }
     768              :         }
     769              :         std::vector<MSTransportableRouter::TripItem> items;
     770         1112 :         if (router.compute(fromEdge, toEdge, departPos, "", arrivalPos, destStop,
     771              :                            speed * walkFactor, vehicle, pedType->getParameter(), modeSet, departStep, items, externalFactor)) {
     772              :             double cost = 0;
     773         1859 :             for (std::vector<MSTransportableRouter::TripItem>::iterator it = items.begin(); it != items.end(); ++it) {
     774         1303 :                 if (!it->edges.empty()) {
     775         3227 :                     resultCand.push_back(TraCIStage((it->line == "" ? STAGE_WALKING : STAGE_DRIVING), it->vType, it->line, it->destStop));
     776         3811 :                     for (const MSEdge* e : it->edges) {
     777         2508 :                         resultCand.back().edges.push_back(e->getID());
     778              :                     }
     779         1303 :                     resultCand.back().travelTime = it->traveltime;
     780         1303 :                     resultCand.back().cost = it->cost;
     781         1303 :                     resultCand.back().length = it->length;
     782         1303 :                     resultCand.back().intended = it->intended;
     783         1303 :                     resultCand.back().depart = it->depart;
     784         1303 :                     resultCand.back().departPos = it->departPos;
     785         1303 :                     resultCand.back().arrivalPos = it->arrivalPos;
     786         1303 :                     resultCand.back().description = it->description;
     787              :                 }
     788         1303 :                 cost += it->cost;
     789              :             }
     790          556 :             if (cost < minCost) {
     791              :                 minCost = cost;
     792          341 :                 result = resultCand;
     793              :             }
     794              :         }
     795          556 :         if (vehicle != nullptr) {
     796          305 :             vehControl.deleteVehicle(vehicle, true);
     797              :             vehControl.discountRoutingVehicle();
     798              :         }
     799          556 :     }
     800          317 :     return result;
     801          332 : }
     802              : 
     803              : 
     804              : std::string
     805         2730 : Simulation::getParameter(const std::string& objectID, const std::string& key) {
     806         5460 :     if (StringUtils::startsWith(key, "chargingStation.")) {
     807           30 :         const std::string attrName = key.substr(16);
     808           30 :         MSChargingStation* cs = static_cast<MSChargingStation*>(MSNet::getInstance()->getStoppingPlace(objectID, SUMO_TAG_CHARGING_STATION));
     809           30 :         if (cs == nullptr) {
     810           10 :             throw TraCIException("Invalid chargingStation '" + objectID + "'");
     811              :         }
     812           25 :         if (attrName == toString(SUMO_ATTR_TOTALENERGYCHARGED)) {
     813            5 :             return toString(cs->getTotalCharged());
     814           20 :         } else if (attrName == toString(SUMO_ATTR_NAME)) {
     815            5 :             return toString(cs->getMyName());
     816           15 :         } else if (attrName == "lane") {
     817            5 :             return cs->getLane().getID();
     818           10 :         } else if (cs->hasParameter(attrName)) {
     819           20 :             return cs->getParameter(attrName);
     820              :         } else {
     821           10 :             throw TraCIException("Invalid chargingStation parameter '" + attrName + "'");
     822              :         }
     823         5400 :     } else if (StringUtils::startsWith(key, "overheadWire.")) {
     824            0 :         const std::string attrName = key.substr(16);
     825            0 :         MSOverheadWire* cs = static_cast<MSOverheadWire*>(MSNet::getInstance()->getStoppingPlace(objectID, SUMO_TAG_OVERHEAD_WIRE_SEGMENT));
     826            0 :         if (cs == 0) {
     827            0 :             throw TraCIException("Invalid overhead wire '" + objectID + "'");
     828              :         }
     829            0 :         if (attrName == toString(SUMO_ATTR_TOTALENERGYCHARGED)) {
     830            0 :             return toString(cs->getTotalCharged());
     831            0 :         } else if (attrName == toString(SUMO_ATTR_NAME)) {
     832            0 :             return toString(cs->getMyName());
     833              :         } else {
     834            0 :             throw TraCIException("Invalid overhead wire parameter '" + attrName + "'");
     835              :         }
     836         5400 :     } else if (StringUtils::startsWith(key, "net.")) {
     837            0 :         const std::string attrName = key.substr(4);
     838            0 :         if (attrName == toString(SUMO_ATTR_NET_OFFSET)) {
     839            0 :             return toString(GeoConvHelper::getFinal().getOffsetBase());
     840              :         } else {
     841            0 :             throw TraCIException("Invalid net parameter '" + attrName + "'");
     842              :         }
     843         5400 :     } else if (StringUtils::startsWith(key, "stats.")) {
     844           85 :         if (objectID != "") {
     845            0 :             throw TraCIException("Simulation parameter '" + key + "' is not supported for object id '" + objectID + "'. Use empty id for stats");
     846              :         }
     847           85 :         const std::string attrName = key.substr(6);
     848           85 :         const MSVehicleControl& vc = MSNet::getInstance()->getVehicleControl();
     849           85 :         const MSTransportableControl* pc = MSNet::getInstance()->hasPersons() ? &MSNet::getInstance()->getPersonControl() : nullptr;
     850           85 :         if (attrName == "vehicles.loaded") {
     851            5 :             return toString(vc.getLoadedVehicleNo());
     852           80 :         } else if (attrName == "vehicles.inserted") {
     853            5 :             return toString(vc.getDepartedVehicleNo());
     854           75 :         } else if (attrName == "vehicles.running") {
     855            5 :             return toString(vc.getRunningVehicleNo());
     856           70 :         } else if (attrName == "vehicles.waiting") {
     857            5 :             return toString(MSNet::getInstance()->getInsertionControl().getWaitingVehicleNo());
     858           65 :         } else if (attrName == "teleports.total") {
     859            5 :             return toString(vc.getTeleportCount());
     860           60 :         } else if (attrName == "teleports.jam") {
     861            5 :             return toString(vc.getTeleportsJam());
     862           55 :         } else if (attrName == "teleports.yield") {
     863            5 :             return toString(vc.getTeleportsYield());
     864           50 :         } else if (attrName == "teleports.wrongLane") {
     865            5 :             return toString(vc.getTeleportsWrongLane());
     866           45 :         } else if (attrName == "safety.collisions") {
     867            5 :             return toString(vc.getCollisionCount());
     868           40 :         } else if (attrName == "safety.emergencyStops") {
     869            5 :             return toString(vc.getEmergencyStops());
     870           35 :         } else if (attrName == "safety.emergencyBraking") {
     871            5 :             return toString(vc.getEmergencyBrakingCount());
     872           30 :         } else if (attrName == "persons.loaded") {
     873           10 :             return toString(pc != nullptr ? pc->getLoadedNumber() : 0);
     874           25 :         } else if (attrName == "persons.running") {
     875           10 :             return toString(pc != nullptr ? pc->getRunningNumber() : 0);
     876           20 :         } else if (attrName == "persons.jammed") {
     877           10 :             return toString(pc != nullptr ? pc->getJammedNumber() : 0);
     878           15 :         } else if (attrName == "personTeleports.total") {
     879           10 :             return toString(pc != nullptr ? pc->getTeleportCount() : 0);
     880           10 :         } else if (attrName == "personTeleports.abortWait") {
     881           10 :             return toString(pc != nullptr ? pc->getTeleportsAbortWait() : 0);
     882            5 :         } else if (attrName == "personTeleports.wrongDest") {
     883           10 :             return toString(pc != nullptr ? pc->getTeleportsWrongDest() : 0);
     884              :         } else {
     885            0 :             throw TraCIException("Invalid stats parameter '" + attrName + "'");
     886              :         }
     887         5230 :     } else if (StringUtils::startsWith(key, "parkingArea.")) {
     888           26 :         const std::string attrName = key.substr(12);
     889           26 :         MSParkingArea* pa = static_cast<MSParkingArea*>(MSNet::getInstance()->getStoppingPlace(objectID, SUMO_TAG_PARKING_AREA));
     890           26 :         if (pa == nullptr) {
     891            0 :             throw TraCIException("Invalid parkingArea '" + objectID + "'");
     892              :         }
     893           26 :         if (attrName == "capacity") {
     894            6 :             return toString(pa->getCapacity());
     895           20 :         } else if (attrName == "occupancy") {
     896            5 :             return toString(pa->getOccupancyIncludingBlocked());
     897           15 :         } else if (attrName == toString(SUMO_ATTR_NAME)) {
     898            5 :             return toString(pa->getMyName());
     899           10 :         } else if (attrName == "lane") {
     900            5 :             return pa->getLane().getID();
     901            5 :         } else if (pa->hasParameter(attrName)) {
     902           10 :             return pa->getParameter(attrName);
     903              :         } else {
     904            0 :             throw TraCIException("Invalid parkingArea parameter '" + attrName + "'");
     905              :         }
     906         5178 :     } else if (StringUtils::startsWith(key, "busStop.")) {
     907           15 :         const std::string attrName = key.substr(8);
     908           15 :         MSStoppingPlace* bs = static_cast<MSStoppingPlace*>(MSNet::getInstance()->getStoppingPlace(objectID, SUMO_TAG_BUS_STOP));
     909           15 :         if (bs == nullptr) {
     910            0 :             throw TraCIException("Invalid busStop '" + objectID + "'");
     911              :         }
     912           15 :         if (attrName == toString(SUMO_ATTR_NAME)) {
     913            5 :             return toString(bs->getMyName());
     914           10 :         } else if (attrName == "lane") {
     915            5 :             return bs->getLane().getID();
     916            5 :         } else if (bs->hasParameter(attrName)) {
     917           10 :             return bs->getParameter(attrName);
     918              :         } else {
     919            0 :             throw TraCIException("Invalid busStop parameter '" + attrName + "'");
     920              :         }
     921         5148 :     } else if (StringUtils::startsWith(key, "device.tripinfo.")) {
     922         2548 :         if (objectID != "") {
     923            0 :             throw TraCIException("Simulation parameter '" + key + "' is not supported for object id '" + objectID
     924            0 :                                  + "'. Use empty id for global device parameers or vehicle domain for vehicle specific parameters");
     925              :         }
     926         2548 :         const std::string attrName = key.substr(16);
     927         2548 :         return MSDevice_Tripinfo::getGlobalParameter(attrName);
     928           26 :     } else if (objectID == "") {
     929           42 :         return MSNet::getInstance()->getParameter(key, "");
     930              :     } else {
     931           10 :         throw TraCIException("Simulation parameter '" + key + "' is not supported for object id '" + objectID + "'. Use empty id for generic network parameters");
     932              :     }
     933              : }
     934              : 
     935           16 : LIBSUMO_GET_PARAMETER_WITH_KEY_IMPLEMENTATION(Simulation)
     936              : 
     937              : void
     938           10 : Simulation::setParameter(const std::string& objectID, const std::string& key, const std::string& value) {
     939           10 :     if (objectID == "") {
     940            5 :         MSNet::getInstance()->setParameter(key, value);
     941              :     } else {
     942           10 :         throw TraCIException("Setting simulation parameter '" + key + "' is not supported for object id '" + objectID + "'. Use empty id for generic network parameters");
     943              :     }
     944            5 : }
     945              : 
     946              : void
     947            5 : Simulation::setScale(double value) {
     948            5 :     MSNet::getInstance()->getVehicleControl().setScale(value);
     949            5 : }
     950              : 
     951              : void
     952            6 : Simulation::clearPending(const std::string& routeID) {
     953            6 :     MSNet::getInstance()->getInsertionControl().clearPendingVehicles(routeID);
     954            6 : }
     955              : 
     956              : 
     957              : void
     958           81 : Simulation::saveState(const std::string& fileName) {
     959           81 :     MSStateHandler::saveState(fileName, MSNet::getInstance()->getCurrentTimeStep());
     960           81 : }
     961              : 
     962              : double
     963          196 : Simulation::loadState(const std::string& fileName) {
     964          588 :     long before = PROGRESS_BEGIN_TIME_MESSAGE("Loading state from '" + fileName + "'");
     965              :     try {
     966          196 :         const SUMOTime newTime = MSNet::getInstance()->loadState(fileName, false);
     967          186 :         Helper::clearStateChanges();
     968          186 :         Helper::clearSubscriptions();
     969          186 :         PROGRESS_TIME_MESSAGE(before);
     970          186 :         return STEPS2TIME(newTime);
     971           10 :     } catch (const IOError& e) {
     972           10 :         throw TraCIException("Loading state from '" + fileName + "' failed. " + e.what());
     973           10 :     } catch (const ProcessError& e) {
     974           10 :         throw TraCIException("Loading state from '" + fileName + "' failed, check whether SUMO versions match. " + e.what());
     975            5 :     }
     976              : }
     977              : 
     978              : void
     979            6 : Simulation::writeMessage(const std::string& msg) {
     980            6 :     WRITE_MESSAGE(msg);
     981            6 : }
     982              : 
     983              : 
     984              : void
     985         2290 : Simulation::storeShape(PositionVector& shape) {
     986         4580 :     shape = GeoConvHelper::getFinal().getConvBoundary().getShape(true);
     987         2290 : }
     988              : 
     989              : 
     990              : std::shared_ptr<VariableWrapper>
     991          271 : Simulation::makeWrapper() {
     992          271 :     return std::make_shared<Helper::SubscriptionWrapper>(handleVariable, mySubscriptionResults, myContextSubscriptionResults);
     993              : }
     994              : 
     995              : 
     996              : bool
     997      7822207 : Simulation::handleVariable(const std::string& objID, const int variable, VariableWrapper* wrapper, tcpip::Storage* paramData) {
     998      7822207 :     switch (variable) {
     999       178694 :         case VAR_TIME:
    1000       178694 :             return wrapper->wrapDouble(objID, variable, getTime());
    1001           14 :         case VAR_TIME_STEP:
    1002           14 :             return wrapper->wrapInt(objID, variable, (int)getCurrentTime());
    1003           12 :         case VAR_END:
    1004           12 :             return wrapper->wrapDouble(objID, variable, getEndTime());
    1005            2 :         case VAR_LOADED_VEHICLES_NUMBER:
    1006            2 :             return wrapper->wrapInt(objID, variable, getLoadedNumber());
    1007           42 :         case VAR_LOADED_VEHICLES_IDS:
    1008           42 :             return wrapper->wrapStringList(objID, variable, getLoadedIDList());
    1009            2 :         case VAR_DEPARTED_VEHICLES_NUMBER:
    1010            2 :             return wrapper->wrapInt(objID, variable, getDepartedNumber());
    1011           64 :         case VAR_DEPARTED_VEHICLES_IDS:
    1012           64 :             return wrapper->wrapStringList(objID, variable, getDepartedIDList());
    1013            2 :         case VAR_TELEPORT_STARTING_VEHICLES_NUMBER:
    1014            2 :             return wrapper->wrapInt(objID, variable, getStartingTeleportNumber());
    1015            2 :         case VAR_TELEPORT_STARTING_VEHICLES_IDS:
    1016            2 :             return wrapper->wrapStringList(objID, variable, getStartingTeleportIDList());
    1017            2 :         case VAR_TELEPORT_ENDING_VEHICLES_NUMBER:
    1018            2 :             return wrapper->wrapInt(objID, variable, getEndingTeleportNumber());
    1019            2 :         case VAR_TELEPORT_ENDING_VEHICLES_IDS:
    1020            2 :             return wrapper->wrapStringList(objID, variable, getEndingTeleportIDList());
    1021            2 :         case VAR_ARRIVED_VEHICLES_NUMBER:
    1022            2 :             return wrapper->wrapInt(objID, variable, getArrivedNumber());
    1023            2 :         case VAR_ARRIVED_VEHICLES_IDS:
    1024            2 :             return wrapper->wrapStringList(objID, variable, getArrivedIDList());
    1025            2 :         case VAR_PARKING_STARTING_VEHICLES_NUMBER:
    1026            2 :             return wrapper->wrapInt(objID, variable, getParkingStartingVehiclesNumber());
    1027            2 :         case VAR_PARKING_STARTING_VEHICLES_IDS:
    1028            2 :             return wrapper->wrapStringList(objID, variable, getParkingStartingVehiclesIDList());
    1029            2 :         case VAR_PARKING_ENDING_VEHICLES_NUMBER:
    1030            2 :             return wrapper->wrapInt(objID, variable, getParkingEndingVehiclesNumber());
    1031            2 :         case VAR_PARKING_ENDING_VEHICLES_IDS:
    1032            2 :             return wrapper->wrapStringList(objID, variable, getParkingEndingVehiclesIDList());
    1033            2 :         case VAR_STOP_STARTING_VEHICLES_NUMBER:
    1034            2 :             return wrapper->wrapInt(objID, variable, getStopStartingVehiclesNumber());
    1035            2 :         case VAR_STOP_STARTING_VEHICLES_IDS:
    1036            2 :             return wrapper->wrapStringList(objID, variable, getStopStartingVehiclesIDList());
    1037            2 :         case VAR_STOP_ENDING_VEHICLES_NUMBER:
    1038            2 :             return wrapper->wrapInt(objID, variable, getStopEndingVehiclesNumber());
    1039            2 :         case VAR_STOP_ENDING_VEHICLES_IDS:
    1040            2 :             return wrapper->wrapStringList(objID, variable, getStopEndingVehiclesIDList());
    1041            3 :         case VAR_COLLIDING_VEHICLES_NUMBER:
    1042            3 :             return wrapper->wrapInt(objID, variable, getCollidingVehiclesNumber());
    1043            2 :         case VAR_COLLIDING_VEHICLES_IDS:
    1044            2 :             return wrapper->wrapStringList(objID, variable, getCollidingVehiclesIDList());
    1045            2 :         case VAR_EMERGENCYSTOPPING_VEHICLES_NUMBER:
    1046            2 :             return wrapper->wrapInt(objID, variable, getEmergencyStoppingVehiclesNumber());
    1047            2 :         case VAR_EMERGENCYSTOPPING_VEHICLES_IDS:
    1048            2 :             return wrapper->wrapStringList(objID, variable, getEmergencyStoppingVehiclesIDList());
    1049            2 :         case VAR_DEPARTED_PERSONS_NUMBER:
    1050            2 :             return wrapper->wrapInt(objID, variable, getDepartedPersonNumber());
    1051            2 :         case VAR_DEPARTED_PERSONS_IDS:
    1052            2 :             return wrapper->wrapStringList(objID, variable, getDepartedPersonIDList());
    1053            2 :         case VAR_ARRIVED_PERSONS_NUMBER:
    1054            2 :             return wrapper->wrapInt(objID, variable, getArrivedPersonNumber());
    1055            2 :         case VAR_ARRIVED_PERSONS_IDS:
    1056            2 :             return wrapper->wrapStringList(objID, variable, getArrivedPersonIDList());
    1057           11 :         case VAR_SCALE:
    1058           11 :             return wrapper->wrapDouble(objID, variable, getScale());
    1059           86 :         case VAR_DELTA_T:
    1060           86 :             return wrapper->wrapDouble(objID, variable, getDeltaT());
    1061           12 :         case VAR_OPTION:
    1062           24 :             return wrapper->wrapString(objID, variable, getOption(objID));
    1063      7641176 :         case VAR_MIN_EXPECTED_VEHICLES:
    1064      7641176 :             return wrapper->wrapInt(objID, variable, getMinExpectedNumber());
    1065           11 :         case VAR_BUS_STOP_ID_LIST:
    1066           11 :             return wrapper->wrapStringList(objID, variable, getBusStopIDList());
    1067           11 :         case VAR_BUS_STOP_WAITING:
    1068           11 :             return wrapper->wrapInt(objID, variable, getBusStopWaiting(objID));
    1069           98 :         case VAR_BUS_STOP_WAITING_IDS:
    1070           98 :             return wrapper->wrapStringList(objID, variable, getBusStopWaitingIDList(objID));
    1071           26 :         case VAR_PENDING_VEHICLES:
    1072           26 :             return wrapper->wrapStringList(objID, variable, getPendingVehicles());
    1073         1876 :         case VAR_PARAMETER:
    1074         3743 :             return wrapper->wrapString(objID, variable, getParameter(objID, StoHelp::readTypedString(*paramData)));
    1075            8 :         case VAR_PARAMETER_WITH_KEY:
    1076           16 :             return wrapper->wrapStringPair(objID, variable, getParameterWithKey(objID, StoHelp::readTypedString(*paramData)));
    1077              :         default:
    1078              :             return false;
    1079              :     }
    1080              : }
    1081              : }
    1082              : 
    1083              : 
    1084              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1