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

Generated by: LCOV version 2.0-1