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-02 16:00:03 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_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         1128 : 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         1128 :     if (GUI::start(cmd)) {
      92          532 :         return getVersion();
      93              :     }
      94              : #endif
      95          596 :     load(std::vector<std::string>(cmd.begin() + 1, cmd.end()));
      96          596 :     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            2 : Simulation::setOrder(int /* order */) {
     120            4 :     throw TraCIException("Multi client support (including connection switching) is not implemented in libsumo.");
     121              : }
     122              : 
     123              : 
     124              : void
     125          603 : Simulation::load(const std::vector<std::string>& args) {
     126              : #ifdef HAVE_LIBSUMOGUI
     127          603 :     if (GUI::load(args)) {
     128              :         return;
     129              :     }
     130              : #endif
     131          601 :     close("Libsumo issued load command.");
     132              :     try {
     133         1202 :         OptionsCont::getOptions().setApplicationName("libsumo", "Eclipse SUMO libsumo " VERSION_STRING);
     134          601 :         gSimulation = true;
     135          601 :         XMLSubSys::init();
     136          601 :         OptionsIO::setArgs(args);
     137          601 :         if (NLBuilder::init(true) != nullptr) {
     138          599 :             const SUMOTime begin = string2time(OptionsCont::getOptions().getString("begin"));
     139          599 :             MSNet::getInstance()->setCurrentTimeStep(begin); // needed for state loading
     140         1198 :             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       188237 : Simulation::step(const double time) {
     166              : #ifdef HAVE_FOX
     167              :     FXMutexLock lock(myStepMutex);
     168              : #endif
     169       188237 :     Helper::clearStateChanges();
     170       188237 :     const SUMOTime t = TIME2STEPS(time);
     171              : #ifdef HAVE_LIBSUMOGUI
     172       188237 :     if (!GUI::step(t)) {
     173              : #endif
     174       104098 :         if (t == 0) {
     175       103931 :             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       188237 :     Helper::handleSubscriptions(SIMSTEP);
     185       188237 : }
     186              : 
     187              : 
     188              : void
     189            4 : Simulation::executeMove() {
     190            4 :     MSNet::getInstance()->simulationStep(true);
     191            4 : }
     192              : 
     193              : 
     194              : void
     195         1707 : Simulation::close(const std::string& reason) {
     196         1707 :     Helper::clearSubscriptions();
     197            0 :     if (
     198              : #ifdef HAVE_LIBSUMOGUI
     199         1707 :         !GUI::close(reason) &&
     200              : #endif
     201              :         MSNet::hasInstance()) {
     202          598 :         MSNet::getInstance()->closeSimulation(0, reason);
     203          598 :         delete MSNet::getInstance();
     204          598 :         SystemFrame::close();
     205              :     }
     206         1705 : }
     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         1130 : Simulation::getVersion() {
     226         1130 :     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       296217 : Simulation::getTime() {
     248       296217 :     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         6021 : Simulation::getDepartedIDList() {
     277         6021 :     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         6001 : Simulation::getArrivedIDList() {
     289         6001 :     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            0 :     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            0 :     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            0 :     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            0 :     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          151 : Simulation::getDeltaT() {
     481          151 :     return TS;
     482              : }
     483              : 
     484              : 
     485              : TraCIPositionVector
     486           11 : Simulation::getNetBoundary() {
     487           11 :     Boundary b = GeoConvHelper::getFinal().getConvBoundary();
     488            0 :     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      8673600 : Simulation::getMinExpectedNumber() {
     505      8673600 :     MSNet* net = MSNet::getInstance();
     506              :     return (net->getVehicleControl().getActiveVehicleCount()
     507      8673599 :             + net->getInsertionControl().getPendingFlowCount()
     508      8673599 :             + (net->hasPersons() ? net->getPersonControl().getActiveCount() : 0)
     509      8673599 :             + (net->hasContainers() ? net->getContainerControl().getActiveCount() : 0)
     510      8673599 :             + (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           80 : Simulation::getDistanceRoad(const std::string& edgeID1, double pos1, const std::string& edgeID2, double pos2, bool isDriving) {
     589           80 :     std::pair<const MSLane*, double> roadPos1 = std::make_pair(libsumo::Helper::getLaneChecking(edgeID1, 0, pos1), pos1);
     590           80 :     std::pair<const MSLane*, double> roadPos2 = std::make_pair(libsumo::Helper::getLaneChecking(edgeID2, 0, pos2), pos2);
     591           80 :     if (isDriving) {
     592           10 :         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            0 :     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            0 :     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            0 :     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            0 :         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            0 :         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         2745 : Simulation::getParameter(const std::string& objectID, const std::string& key) {
     806         5490 :     if (StringUtils::startsWith(key, "chargingStation.")) {
     807           30 :         WRITE_WARNING("Retrieving chargingStation parameters via the simulation API is deprecated, please use traci.chargingstation.");
     808           30 :         const std::string attrName = key.substr(16);
     809           30 :         MSChargingStation* cs = static_cast<MSChargingStation*>(MSNet::getInstance()->getStoppingPlace(objectID, SUMO_TAG_CHARGING_STATION));
     810           30 :         if (cs == nullptr) {
     811           10 :             throw TraCIException("Invalid chargingStation '" + objectID + "'");
     812              :         }
     813           25 :         if (attrName == toString(SUMO_ATTR_TOTALENERGYCHARGED)) {
     814            5 :             return toString(cs->getTotalCharged());
     815           20 :         } else if (attrName == toString(SUMO_ATTR_NAME)) {
     816            5 :             return toString(cs->getMyName());
     817           15 :         } else if (attrName == "lane") {
     818            5 :             return cs->getLane().getID();
     819           10 :         } else if (cs->hasParameter(attrName)) {
     820           20 :             return cs->getParameter(attrName);
     821              :         } else {
     822           10 :             throw TraCIException("Invalid chargingStation parameter '" + attrName + "'");
     823              :         }
     824         5430 :     } else if (StringUtils::startsWith(key, "overheadWire.")) {
     825            0 :         WRITE_WARNING("Retrieving overheadWire parameters via the simulation API is deprecated, please use traci.overheadwire.");
     826            0 :         const std::string attrName = key.substr(16);
     827            0 :         MSOverheadWire* cs = static_cast<MSOverheadWire*>(MSNet::getInstance()->getStoppingPlace(objectID, SUMO_TAG_OVERHEAD_WIRE_SEGMENT));
     828            0 :         if (cs == 0) {
     829            0 :             throw TraCIException("Invalid overhead wire '" + objectID + "'");
     830              :         }
     831            0 :         if (attrName == toString(SUMO_ATTR_TOTALENERGYCHARGED)) {
     832            0 :             return toString(cs->getTotalCharged());
     833            0 :         } else if (attrName == toString(SUMO_ATTR_NAME)) {
     834            0 :             return toString(cs->getMyName());
     835              :         } else {
     836            0 :             throw TraCIException("Invalid overhead wire parameter '" + attrName + "'");
     837              :         }
     838         5430 :     } else if (StringUtils::startsWith(key, "net.")) {
     839            0 :         const std::string attrName = key.substr(4);
     840            0 :         if (attrName == toString(SUMO_ATTR_NET_OFFSET)) {
     841            0 :             return toString(GeoConvHelper::getFinal().getOffsetBase());
     842              :         } else {
     843            0 :             throw TraCIException("Invalid net parameter '" + attrName + "'");
     844              :         }
     845         5430 :     } else if (StringUtils::startsWith(key, "stats.")) {
     846           85 :         if (objectID != "") {
     847            0 :             throw TraCIException("Simulation parameter '" + key + "' is not supported for object id '" + objectID + "'. Use empty id for stats");
     848              :         }
     849           85 :         const std::string attrName = key.substr(6);
     850           85 :         const MSVehicleControl& vc = MSNet::getInstance()->getVehicleControl();
     851           85 :         const MSTransportableControl* pc = MSNet::getInstance()->hasPersons() ? &MSNet::getInstance()->getPersonControl() : nullptr;
     852           85 :         if (attrName == "vehicles.loaded") {
     853            5 :             return toString(vc.getLoadedVehicleNo());
     854           80 :         } else if (attrName == "vehicles.inserted") {
     855            5 :             return toString(vc.getDepartedVehicleNo());
     856           75 :         } else if (attrName == "vehicles.running") {
     857            5 :             return toString(vc.getRunningVehicleNo());
     858           70 :         } else if (attrName == "vehicles.waiting") {
     859            5 :             return toString(MSNet::getInstance()->getInsertionControl().getWaitingVehicleNo());
     860           65 :         } else if (attrName == "teleports.total") {
     861            5 :             return toString(vc.getTeleportCount());
     862           60 :         } else if (attrName == "teleports.jam") {
     863            5 :             return toString(vc.getTeleportsJam());
     864           55 :         } else if (attrName == "teleports.yield") {
     865            5 :             return toString(vc.getTeleportsYield());
     866           50 :         } else if (attrName == "teleports.wrongLane") {
     867            5 :             return toString(vc.getTeleportsWrongLane());
     868           45 :         } else if (attrName == "safety.collisions") {
     869            5 :             return toString(vc.getCollisionCount());
     870           40 :         } else if (attrName == "safety.emergencyStops") {
     871            5 :             return toString(vc.getEmergencyStops());
     872           35 :         } else if (attrName == "safety.emergencyBraking") {
     873            5 :             return toString(vc.getEmergencyBrakingCount());
     874           30 :         } else if (attrName == "persons.loaded") {
     875           10 :             return toString(pc != nullptr ? pc->getLoadedNumber() : 0);
     876           25 :         } else if (attrName == "persons.running") {
     877           10 :             return toString(pc != nullptr ? pc->getRunningNumber() : 0);
     878           20 :         } else if (attrName == "persons.jammed") {
     879           10 :             return toString(pc != nullptr ? pc->getJammedNumber() : 0);
     880           15 :         } else if (attrName == "personTeleports.total") {
     881           10 :             return toString(pc != nullptr ? pc->getTeleportCount() : 0);
     882           10 :         } else if (attrName == "personTeleports.abortWait") {
     883           10 :             return toString(pc != nullptr ? pc->getTeleportsAbortWait() : 0);
     884            5 :         } else if (attrName == "personTeleports.wrongDest") {
     885           10 :             return toString(pc != nullptr ? pc->getTeleportsWrongDest() : 0);
     886              :         } else {
     887            0 :             throw TraCIException("Invalid stats parameter '" + attrName + "'");
     888              :         }
     889         5260 :     } else if (StringUtils::startsWith(key, "parkingArea.")) {
     890           26 :         WRITE_WARNING("Retrieving parkingArea parameters via the simulation API is deprecated, please use traci.parkingarea.");
     891           26 :         const std::string attrName = key.substr(12);
     892           26 :         MSParkingArea* pa = static_cast<MSParkingArea*>(MSNet::getInstance()->getStoppingPlace(objectID, SUMO_TAG_PARKING_AREA));
     893           26 :         if (pa == nullptr) {
     894            0 :             throw TraCIException("Invalid parkingArea '" + objectID + "'");
     895              :         }
     896           26 :         if (attrName == "capacity") {
     897            6 :             return toString(pa->getCapacity());
     898           20 :         } else if (attrName == "occupancy") {
     899            5 :             return toString(pa->getOccupancyIncludingBlocked());
     900           15 :         } else if (attrName == toString(SUMO_ATTR_NAME)) {
     901            5 :             return toString(pa->getMyName());
     902           10 :         } else if (attrName == "lane") {
     903            5 :             return pa->getLane().getID();
     904            5 :         } else if (pa->hasParameter(attrName)) {
     905           10 :             return pa->getParameter(attrName);
     906              :         } else {
     907            0 :             throw TraCIException("Invalid parkingArea parameter '" + attrName + "'");
     908              :         }
     909         5208 :     } else if (StringUtils::startsWith(key, "busStop.")) {
     910           15 :         WRITE_WARNING("Retrieving busStop parameters via the simulation API is deprecated, please use traci.busstop.");
     911           15 :         const std::string attrName = key.substr(8);
     912           15 :         MSStoppingPlace* bs = static_cast<MSStoppingPlace*>(MSNet::getInstance()->getStoppingPlace(objectID, SUMO_TAG_BUS_STOP));
     913           15 :         if (bs == nullptr) {
     914            0 :             throw TraCIException("Invalid busStop '" + objectID + "'");
     915              :         }
     916           15 :         if (attrName == toString(SUMO_ATTR_NAME)) {
     917            5 :             return toString(bs->getMyName());
     918           10 :         } else if (attrName == "lane") {
     919            5 :             return bs->getLane().getID();
     920            5 :         } else if (bs->hasParameter(attrName)) {
     921           10 :             return bs->getParameter(attrName);
     922              :         } else {
     923            0 :             throw TraCIException("Invalid busStop parameter '" + attrName + "'");
     924              :         }
     925         5178 :     } else if (StringUtils::startsWith(key, "device.tripinfo.")) {
     926         2548 :         if (objectID != "") {
     927            0 :             throw TraCIException("Simulation parameter '" + key + "' is not supported for object id '" + objectID
     928            0 :                                  + "'. Use empty id for global device parameters or vehicle domain for vehicle specific parameters");
     929              :         }
     930         2548 :         const std::string attrName = key.substr(16);
     931         2548 :         return MSDevice_Tripinfo::getGlobalParameter(attrName);
     932           82 :     } else if (StringUtils::startsWith(key, "buildConfig.")) {
     933           15 :         if (objectID != "") {
     934            0 :             throw TraCIException("Simulation parameter '" + key + "' is not supported for object id '" + objectID
     935            0 :                                  + "'. Use an empty id for buildConfig parameters");
     936              :         }
     937           15 :         if (key == "buildConfig.ARROW_SO_VERSION") {
     938              : #ifdef ARROW_SO_VERSION
     939            5 :             return ARROW_SO_VERSION;
     940              : #else
     941              :             return "";
     942              : #endif
     943           10 :         } else if (key == "buildConfig.JPS_VERSION") {
     944              : #ifdef JPS_VERSION
     945              :             return toString(JPS_VERSION);
     946              : #else
     947            5 :             return "";
     948              : #endif
     949            5 :         } else if (key == "buildConfig.ENABLED") {
     950            5 :             return HAVE_ENABLED;
     951              :         }
     952            0 :         throw TraCIException("Unknown parameter '" + key + "'");
     953           26 :     } else if (objectID == "") {
     954           42 :         return MSNet::getInstance()->getParameter(key, "");
     955              :     } else {
     956           10 :         throw TraCIException("Simulation parameter '" + key + "' is not supported for object id '" + objectID + "'. Use empty id for generic network parameters");
     957              :     }
     958              : }
     959              : 
     960           16 : LIBSUMO_GET_PARAMETER_WITH_KEY_IMPLEMENTATION(Simulation)
     961              : 
     962              : void
     963           10 : Simulation::setParameter(const std::string& objectID, const std::string& key, const std::string& value) {
     964           10 :     if (objectID == "") {
     965            5 :         MSNet::getInstance()->setParameter(key, value);
     966              :     } else {
     967           10 :         throw TraCIException("Setting simulation parameter '" + key + "' is not supported for object id '" + objectID + "'. Use empty id for generic network parameters");
     968              :     }
     969            5 : }
     970              : 
     971              : void
     972            5 : Simulation::setScale(double value) {
     973            5 :     MSNet::getInstance()->getVehicleControl().setScale(value);
     974            5 : }
     975              : 
     976              : void
     977            6 : Simulation::clearPending(const std::string& routeID) {
     978            6 :     MSNet::getInstance()->getInsertionControl().clearPendingVehicles(routeID);
     979            6 : }
     980              : 
     981              : 
     982              : void
     983           80 : Simulation::saveState(const std::string& fileName) {
     984           80 :     MSStateHandler::saveState(fileName, MSNet::getInstance()->getCurrentTimeStep());
     985           80 : }
     986              : 
     987              : double
     988          196 : Simulation::loadState(const std::string& fileName) {
     989          588 :     long before = PROGRESS_BEGIN_TIME_MESSAGE("Loading state from '" + fileName + "'");
     990              :     try {
     991          196 :         const SUMOTime newTime = MSNet::getInstance()->loadState(fileName, false);
     992          186 :         Helper::clearStateChanges();
     993          186 :         Helper::clearSubscriptions();
     994          186 :         PROGRESS_TIME_MESSAGE(before);
     995          186 :         return STEPS2TIME(newTime);
     996           10 :     } catch (const IOError& e) {
     997           10 :         throw TraCIException("Loading state from '" + fileName + "' failed. " + e.what());
     998           10 :     } catch (const ProcessError& e) {
     999           10 :         throw TraCIException("Loading state from '" + fileName + "' failed, check whether SUMO versions match. " + e.what());
    1000            5 :     }
    1001              : }
    1002              : 
    1003              : void
    1004            6 : Simulation::writeMessage(const std::string& msg) {
    1005            6 :     WRITE_MESSAGE(msg);
    1006            6 : }
    1007              : 
    1008              : 
    1009              : void
    1010         2290 : Simulation::storeShape(PositionVector& shape) {
    1011         4580 :     shape = GeoConvHelper::getFinal().getConvBoundary().getShape(true);
    1012         2290 : }
    1013              : 
    1014              : 
    1015              : std::shared_ptr<VariableWrapper>
    1016          271 : Simulation::makeWrapper() {
    1017          271 :     return std::make_shared<Helper::SubscriptionWrapper>(handleVariable, mySubscriptionResults, myContextSubscriptionResults);
    1018              : }
    1019              : 
    1020              : 
    1021              : bool
    1022      8763243 : Simulation::handleVariable(const std::string& objID, const int variable, VariableWrapper* wrapper, tcpip::Storage* paramData) {
    1023      8763243 :     switch (variable) {
    1024       180133 :         case VAR_TIME:
    1025       180133 :             return wrapper->wrapDouble(objID, variable, getTime());
    1026           14 :         case VAR_TIME_STEP:
    1027           14 :             return wrapper->wrapInt(objID, variable, (int)getCurrentTime());
    1028           12 :         case VAR_END:
    1029           12 :             return wrapper->wrapDouble(objID, variable, getEndTime());
    1030            2 :         case VAR_LOADED_VEHICLES_NUMBER:
    1031            2 :             return wrapper->wrapInt(objID, variable, getLoadedNumber());
    1032           42 :         case VAR_LOADED_VEHICLES_IDS:
    1033           42 :             return wrapper->wrapStringList(objID, variable, getLoadedIDList());
    1034            2 :         case VAR_DEPARTED_VEHICLES_NUMBER:
    1035            2 :             return wrapper->wrapInt(objID, variable, getDepartedNumber());
    1036           64 :         case VAR_DEPARTED_VEHICLES_IDS:
    1037           64 :             return wrapper->wrapStringList(objID, variable, getDepartedIDList());
    1038            2 :         case VAR_TELEPORT_STARTING_VEHICLES_NUMBER:
    1039            2 :             return wrapper->wrapInt(objID, variable, getStartingTeleportNumber());
    1040            2 :         case VAR_TELEPORT_STARTING_VEHICLES_IDS:
    1041            2 :             return wrapper->wrapStringList(objID, variable, getStartingTeleportIDList());
    1042            2 :         case VAR_TELEPORT_ENDING_VEHICLES_NUMBER:
    1043            2 :             return wrapper->wrapInt(objID, variable, getEndingTeleportNumber());
    1044            2 :         case VAR_TELEPORT_ENDING_VEHICLES_IDS:
    1045            2 :             return wrapper->wrapStringList(objID, variable, getEndingTeleportIDList());
    1046            2 :         case VAR_ARRIVED_VEHICLES_NUMBER:
    1047            2 :             return wrapper->wrapInt(objID, variable, getArrivedNumber());
    1048            2 :         case VAR_ARRIVED_VEHICLES_IDS:
    1049            2 :             return wrapper->wrapStringList(objID, variable, getArrivedIDList());
    1050            2 :         case VAR_PARKING_STARTING_VEHICLES_NUMBER:
    1051            2 :             return wrapper->wrapInt(objID, variable, getParkingStartingVehiclesNumber());
    1052            2 :         case VAR_PARKING_STARTING_VEHICLES_IDS:
    1053            2 :             return wrapper->wrapStringList(objID, variable, getParkingStartingVehiclesIDList());
    1054            2 :         case VAR_PARKING_ENDING_VEHICLES_NUMBER:
    1055            2 :             return wrapper->wrapInt(objID, variable, getParkingEndingVehiclesNumber());
    1056            2 :         case VAR_PARKING_ENDING_VEHICLES_IDS:
    1057            2 :             return wrapper->wrapStringList(objID, variable, getParkingEndingVehiclesIDList());
    1058            2 :         case VAR_STOP_STARTING_VEHICLES_NUMBER:
    1059            2 :             return wrapper->wrapInt(objID, variable, getStopStartingVehiclesNumber());
    1060            2 :         case VAR_STOP_STARTING_VEHICLES_IDS:
    1061            2 :             return wrapper->wrapStringList(objID, variable, getStopStartingVehiclesIDList());
    1062            2 :         case VAR_STOP_ENDING_VEHICLES_NUMBER:
    1063            2 :             return wrapper->wrapInt(objID, variable, getStopEndingVehiclesNumber());
    1064            2 :         case VAR_STOP_ENDING_VEHICLES_IDS:
    1065            2 :             return wrapper->wrapStringList(objID, variable, getStopEndingVehiclesIDList());
    1066            3 :         case VAR_COLLIDING_VEHICLES_NUMBER:
    1067            3 :             return wrapper->wrapInt(objID, variable, getCollidingVehiclesNumber());
    1068            2 :         case VAR_COLLIDING_VEHICLES_IDS:
    1069            2 :             return wrapper->wrapStringList(objID, variable, getCollidingVehiclesIDList());
    1070            2 :         case VAR_EMERGENCYSTOPPING_VEHICLES_NUMBER:
    1071            2 :             return wrapper->wrapInt(objID, variable, getEmergencyStoppingVehiclesNumber());
    1072            2 :         case VAR_EMERGENCYSTOPPING_VEHICLES_IDS:
    1073            2 :             return wrapper->wrapStringList(objID, variable, getEmergencyStoppingVehiclesIDList());
    1074            2 :         case VAR_DEPARTED_PERSONS_NUMBER:
    1075            2 :             return wrapper->wrapInt(objID, variable, getDepartedPersonNumber());
    1076            2 :         case VAR_DEPARTED_PERSONS_IDS:
    1077            2 :             return wrapper->wrapStringList(objID, variable, getDepartedPersonIDList());
    1078            2 :         case VAR_ARRIVED_PERSONS_NUMBER:
    1079            2 :             return wrapper->wrapInt(objID, variable, getArrivedPersonNumber());
    1080            2 :         case VAR_ARRIVED_PERSONS_IDS:
    1081            2 :             return wrapper->wrapStringList(objID, variable, getArrivedPersonIDList());
    1082           11 :         case VAR_SCALE:
    1083           11 :             return wrapper->wrapDouble(objID, variable, getScale());
    1084           86 :         case VAR_DELTA_T:
    1085           86 :             return wrapper->wrapDouble(objID, variable, getDeltaT());
    1086           12 :         case VAR_OPTION:
    1087           24 :             return wrapper->wrapString(objID, variable, getOption(objID));
    1088      8580764 :         case VAR_MIN_EXPECTED_VEHICLES:
    1089      8580764 :             return wrapper->wrapInt(objID, variable, getMinExpectedNumber());
    1090           11 :         case VAR_BUS_STOP_ID_LIST:
    1091           11 :             return wrapper->wrapStringList(objID, variable, getBusStopIDList());
    1092           11 :         case VAR_BUS_STOP_WAITING:
    1093           11 :             return wrapper->wrapInt(objID, variable, getBusStopWaiting(objID));
    1094           98 :         case VAR_BUS_STOP_WAITING_IDS:
    1095           98 :             return wrapper->wrapStringList(objID, variable, getBusStopWaitingIDList(objID));
    1096           26 :         case VAR_PENDING_VEHICLES:
    1097           26 :             return wrapper->wrapStringList(objID, variable, getPendingVehicles());
    1098         1885 :         case VAR_PARAMETER:
    1099         3761 :             return wrapper->wrapString(objID, variable, getParameter(objID, StoHelp::readTypedString(*paramData)));
    1100            8 :         case VAR_PARAMETER_WITH_KEY:
    1101           16 :             return wrapper->wrapStringPair(objID, variable, getParameterWithKey(objID, StoHelp::readTypedString(*paramData)));
    1102              :         default:
    1103              :             return false;
    1104              :     }
    1105              : }
    1106              : }
    1107              : 
    1108              : 
    1109              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1