LCOV - code coverage report
Current view: top level - src/microsim/devices - MSDevice_Vehroutes.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 97.2 % 322 313
Test Date: 2024-11-22 15:46:21 Functions: 95.0 % 20 19

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2009-2024 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    MSDevice_Vehroutes.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Laura Bieker
      17              : /// @author  Michael Behrisch
      18              : /// @author  Jakob Erdmann
      19              : /// @date    Fri, 30.01.2009
      20              : ///
      21              : // A device which collects info on the vehicle trip
      22              : /****************************************************************************/
      23              : #include <config.h>
      24              : 
      25              : #include <microsim/MSGlobals.h>
      26              : #include <microsim/MSNet.h>
      27              : #include <microsim/MSLane.h>
      28              : #include <microsim/MSEdge.h>
      29              : #include <microsim/MSRoute.h>
      30              : #include <microsim/MSStop.h>
      31              : #include <microsim/MSVehicle.h>
      32              : #include <microsim/MSVehicleType.h>
      33              : #include <microsim/transportables/MSTransportableControl.h>
      34              : #include <utils/vehicle/SUMOVehicle.h>
      35              : #include <utils/options/OptionsCont.h>
      36              : #include <utils/iodevices/OutputDevice_String.h>
      37              : #include <utils/xml/SUMOSAXAttributes.h>
      38              : #include "MSDevice_Vehroutes.h"
      39              : 
      40              : 
      41              : // ===========================================================================
      42              : // static member variables
      43              : // ===========================================================================
      44              : bool MSDevice_Vehroutes::mySaveExits = false;
      45              : bool MSDevice_Vehroutes::myLastRouteOnly = false;
      46              : bool MSDevice_Vehroutes::myDUAStyle = false;
      47              : bool MSDevice_Vehroutes::myWriteCosts = false;
      48              : bool MSDevice_Vehroutes::mySorted = false;
      49              : bool MSDevice_Vehroutes::myIntendedDepart = false;
      50              : bool MSDevice_Vehroutes::myRouteLength = false;
      51              : bool MSDevice_Vehroutes::mySkipPTLines = false;
      52              : bool MSDevice_Vehroutes::myIncludeIncomplete = false;
      53              : bool MSDevice_Vehroutes::myWriteStopPriorEdges = false;
      54              : bool MSDevice_Vehroutes::myWriteInternal = false;
      55              : MSDevice_Vehroutes::StateListener MSDevice_Vehroutes::myStateListener;
      56              : MSDevice_Vehroutes::SortedRouteInfo MSDevice_Vehroutes::myRouteInfos;
      57              : 
      58              : 
      59              : // ===========================================================================
      60              : // method definitions
      61              : // ===========================================================================
      62              : // ---------------------------------------------------------------------------
      63              : // static initialisation methods
      64              : // ---------------------------------------------------------------------------
      65              : void
      66        42572 : MSDevice_Vehroutes::init() {
      67        42572 :     const OptionsCont& oc = OptionsCont::getOptions();
      68        85144 :     if (oc.isSet("vehroute-output")) {
      69        10462 :         OutputDevice::createDeviceByOption("vehroute-output", "routes", "routes_file.xsd");
      70         5222 :         mySaveExits = oc.getBool("vehroute-output.exit-times");
      71         5222 :         myLastRouteOnly = oc.getBool("vehroute-output.last-route");
      72         5222 :         myDUAStyle = oc.getBool("vehroute-output.dua");
      73         5222 :         myWriteCosts = oc.getBool("vehroute-output.cost");
      74         5222 :         mySorted = myDUAStyle || oc.getBool("vehroute-output.sorted");
      75         5222 :         myIntendedDepart = oc.getBool("vehroute-output.intended-depart");
      76         5222 :         myRouteLength = oc.getBool("vehroute-output.route-length");
      77         5222 :         mySkipPTLines = oc.getBool("vehroute-output.skip-ptlines");
      78         5222 :         myIncludeIncomplete = oc.getBool("vehroute-output.incomplete");
      79         5222 :         myWriteStopPriorEdges = oc.getBool("vehroute-output.stop-edges");
      80         5222 :         myWriteInternal = oc.getBool("vehroute-output.internal");
      81         5222 :         MSNet::getInstance()->addVehicleStateListener(&myStateListener);
      82         5222 :         myRouteInfos.routeOut = &OutputDevice::getDeviceByOption("vehroute-output");
      83              :     }
      84        42566 : }
      85              : 
      86              : 
      87              : void
      88        43644 : MSDevice_Vehroutes::insertOptions(OptionsCont& oc) {
      89        43644 :     oc.addOptionSubTopic("Vehroutes Device");
      90        87288 :     insertDefaultAssignmentOptions("vehroute", "Vehroutes Device", oc);
      91        43644 : }
      92              : 
      93              : 
      94              : MSDevice_Vehroutes*
      95      5869396 : MSDevice_Vehroutes::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into, int maxRoutes) {
      96      5869396 :     if (maxRoutes < std::numeric_limits<int>::max()) {
      97      1530034 :         return new MSDevice_Vehroutes(v, "vehroute_" + v.getID(), maxRoutes);
      98              :     }
      99      5104379 :     if (mySkipPTLines && v.getParameter().line != "") {
     100              :         return nullptr;
     101              :     }
     102      5103337 :     OptionsCont& oc = OptionsCont::getOptions();
     103     10206674 :     if (equippedByDefaultAssignmentOptions(oc, "vehroute", v, oc.isSet("vehroute-output"))) {
     104       120360 :         if (myLastRouteOnly) {
     105              :             maxRoutes = 0;
     106              :         }
     107       120360 :         myStateListener.myDevices[&v] = new MSDevice_Vehroutes(v, "vehroute_" + v.getID(), maxRoutes);
     108       120360 :         into.push_back(myStateListener.myDevices[&v]);
     109       120360 :         return myStateListener.myDevices[&v];
     110              :     }
     111              :     return nullptr;
     112              : }
     113              : 
     114              : 
     115              : // ---------------------------------------------------------------------------
     116              : // MSDevice_Vehroutes::StateListener-methods
     117              : // ---------------------------------------------------------------------------
     118              : void
     119       437540 : MSDevice_Vehroutes::StateListener::vehicleStateChanged(const SUMOVehicle* const vehicle, MSNet::VehicleState to, const std::string& info) {
     120       437540 :     if (to == MSNet::VehicleState::NEWROUTE) {
     121              :         const auto& deviceEntry = myDevices.find(vehicle);
     122        69639 :         if (deviceEntry != myDevices.end()) {
     123        68329 :             deviceEntry->second->addRoute(info);
     124              :         }
     125              :     }
     126       437540 : }
     127              : 
     128              : 
     129              : // ---------------------------------------------------------------------------
     130              : // MSDevice_Vehroutes-methods
     131              : // ---------------------------------------------------------------------------
     132       885377 : MSDevice_Vehroutes::MSDevice_Vehroutes(SUMOVehicle& holder, const std::string& id, int maxRoutes) :
     133              :     MSVehicleDevice(holder, id),
     134       885377 :     myCurrentRoute(holder.getRoutePtr()),
     135       885377 :     myMaxRoutes(maxRoutes),
     136       885377 :     myLastSavedAt(nullptr),
     137       885377 :     myLastRouteIndex(-1),
     138       885377 :     myDepartLane(-1),
     139       885377 :     myDepartPos(-1),
     140       885377 :     myDepartSpeed(-1),
     141       885377 :     myDepartPosLat(0),
     142       885377 :     myStopOut(2) {
     143       885377 : }
     144              : 
     145              : 
     146      1770650 : MSDevice_Vehroutes::~MSDevice_Vehroutes() {
     147       885325 :     myStateListener.myDevices.erase(&myHolder);
     148      1770650 : }
     149              : 
     150              : 
     151              : bool
     152     12054702 : MSDevice_Vehroutes::notifyEnter(SUMOTrafficObject& veh, MSMoveReminder::Notification reason, const MSLane* enteredLane) {
     153     12054702 :     if (reason == MSMoveReminder::NOTIFICATION_DEPARTED) {
     154       722796 :         if (mySorted && myStateListener.myDevices[static_cast<SUMOVehicle*>(&veh)] == this) {
     155         4584 :             const SUMOTime departure = myIntendedDepart ? myHolder.getParameter().depart : MSNet::getInstance()->getCurrentTimeStep();
     156         4584 :             myRouteInfos.departureCounts[departure]++;
     157              :         }
     158       722796 :         if (!MSGlobals::gUseMesoSim) {
     159              :             const MSVehicle& vehicle = static_cast<MSVehicle&>(veh);
     160       427111 :             myDepartLane = vehicle.getLane()->getIndex();
     161       427111 :             myDepartPosLat = vehicle.getLateralPositionOnLane();
     162              :         }
     163       722796 :         myDepartSpeed = veh.getSpeed();
     164       722796 :         myDepartPos = veh.getPositionOnLane();
     165              :     }
     166     12054702 :     if (myWriteStopPriorEdges) {
     167           68 :         if (MSGlobals::gUseMesoSim) {
     168           48 :             const MSEdge* e = veh.getEdge();
     169           48 :             if (myPriorEdges.empty() || myPriorEdges.back() != e) {
     170           12 :                 myPriorEdges.push_back(e);
     171              :             }
     172              :         } else {
     173           20 :             myPriorEdges.push_back(&enteredLane->getEdge());
     174              :         }
     175              :     }
     176     12054702 :     myLastRouteIndex = myHolder.getRoutePosition();
     177     12054702 :     return true;
     178              : }
     179              : 
     180              : 
     181              : bool
     182     12021460 : MSDevice_Vehroutes::notifyLeave(SUMOTrafficObject& veh, double /*lastPos*/, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
     183     12021460 :     if (mySaveExits && reason != NOTIFICATION_LANE_CHANGE && reason != NOTIFICATION_PARKING && reason != NOTIFICATION_SEGMENT) {
     184       270493 :         const MSEdge* edge = myWriteInternal ? dynamic_cast<MSBaseVehicle&>(veh).getCurrentEdge() : veh.getEdge();
     185       270493 :         if (myLastSavedAt != edge) {
     186       153035 :             myExits.push_back(MSNet::getInstance()->getCurrentTimeStep());
     187       153035 :             myLastSavedAt = edge;
     188              :         }
     189              :     }
     190     12021460 :     return true;
     191              : }
     192              : 
     193              : 
     194              : void
     195        17777 : MSDevice_Vehroutes::notifyStopEnded() {
     196        17777 :     SUMOVehicleParameter::Stop stop = myHolder.getStops().front().pars;
     197        17777 :     const bool closeLater = myWriteStopPriorEdges || mySaveExits;
     198        17777 :     if (mySaveExits) {
     199              :         // prevent duplicate output
     200         1451 :         stop.parametersSet &=  ~(STOP_STARTED_SET | STOP_ENDED_SET);
     201              :     }
     202        17777 :     stop.write(myStopOut, !closeLater);
     203        17777 :     if (myWriteStopPriorEdges) {
     204              :         // calculate length
     205           16 :         double priorEdgesLength = 0;
     206           40 :         for (int i = 0; i < (int)myPriorEdges.size(); i++) {
     207           24 :             if (i == 0) {
     208           16 :                 priorEdgesLength += myPriorEdges.at(i)->getLength();
     209            8 :             } else if (myPriorEdges.at(i)->getID() != myPriorEdges.at(i - 1)->getID()) {
     210            8 :                 priorEdgesLength += myPriorEdges.at(i)->getLength();
     211              :             }
     212              :         }
     213           32 :         myStopOut.writeAttr("priorEdges", myPriorEdges);
     214              :         myPriorEdges.clear();
     215           32 :         myStopOut.writeAttr("priorEdgesLength", priorEdgesLength);
     216              :     }
     217        17777 :     if (mySaveExits) {
     218         1451 :         myStopOut.writeAttr(SUMO_ATTR_STARTED, time2string(stop.started));
     219         2902 :         myStopOut.writeAttr(SUMO_ATTR_ENDED, stop.ended < 0 ? "-1" : time2string(stop.ended));
     220              :     }
     221        17777 :     if (closeLater) {
     222         2934 :         myStopOut.closeTag();
     223              :     }
     224        17777 : }
     225              : 
     226              : 
     227              : void
     228       142732 : MSDevice_Vehroutes::writeXMLRoute(OutputDevice& os, int index) const {
     229         9294 :     if (index == 0 && !myIncludeIncomplete && myReplacedRoutes[index].route->size() == 2 &&
     230       146351 :             myReplacedRoutes[index].route->getEdges().front()->isTazConnector() &&
     231            0 :             myReplacedRoutes[index].route->getEdges().back()->isTazConnector()) {
     232              :         return;
     233              :     }
     234              :     // check if a previous route shall be written
     235              :     //std::cout << " writeXMLRoute index=" << index << " numReroutes=" << myHolder.getNumberReroutes() << "\n";
     236       142732 :     const int routesToSkip = myHolder.getParameter().wasSet(VEHPARS_FORCE_REROUTE) ? 1 : 0;
     237       142732 :     os.openTag(SUMO_TAG_ROUTE);
     238       142732 :     if (index >= 0) {
     239              :         assert((int)myReplacedRoutes.size() > index);
     240        32574 :         if (myDUAStyle || myWriteCosts) {
     241        25876 :             os.writeAttr(SUMO_ATTR_COST, myReplacedRoutes[index].route->getCosts());
     242              :         }
     243        32574 :         if (myWriteCosts) {
     244        25876 :             os.writeAttr(SUMO_ATTR_SAVINGS, myReplacedRoutes[index].route->getSavings());
     245              :         }
     246              :         // write edge on which the vehicle was when the route was valid
     247        96716 :         os.writeAttr("replacedOnEdge", (myReplacedRoutes[index].edge ?
     248              :                                         myReplacedRoutes[index].edge->getID() : ""));
     249        32574 :         if (myReplacedRoutes[index].lastRouteIndex > 0) {
     250              :             // do not write the default
     251        22831 :             os.writeAttr(SUMO_ATTR_REPLACED_ON_INDEX, myReplacedRoutes[index].lastRouteIndex);
     252              :         }
     253              :         // write the reason for replacement
     254        65148 :         os.writeAttr("reason", myReplacedRoutes[index].info);
     255              : 
     256              :         // write the time at which the route was replaced
     257        65148 :         os.writeAttr(SUMO_ATTR_REPLACED_AT_TIME, time2string(myReplacedRoutes[index].time));
     258              :         os.writeAttr(SUMO_ATTR_PROB, "0");
     259        32574 :         OutputDevice_String edgesD;
     260              :         // always write the part that was actually driven and the rest of the current route that wasn't yet driven
     261              :         int start = 0;
     262       144618 :         for (int i = routesToSkip; i < index; i++) {
     263       112044 :             if (myReplacedRoutes[i].edge != nullptr) {
     264       111937 :                 int end = myReplacedRoutes[i].lastRouteIndex;
     265       111937 :                 myReplacedRoutes[i].route->writeEdgeIDs(edgesD, start, end, myWriteInternal, myHolder.getVClass());
     266              :             }
     267       112044 :             start = myReplacedRoutes[i].newRouteIndex;
     268              :         }
     269        32574 :         myReplacedRoutes[index].route->writeEdgeIDs(edgesD, start, -1, myWriteInternal, myHolder.getVClass());
     270        32574 :         std::string edgesS = edgesD.getString();
     271              :         edgesS.pop_back(); // remove last ' '
     272              :         os.writeAttr(SUMO_ATTR_EDGES, edgesS);
     273        32574 :         if (myRouteLength) {
     274         6301 :             const bool includeInternalLengths = MSGlobals::gUsingInternalLanes && MSNet::getInstance()->hasInternalLinks();
     275              :             ConstMSRoutePtr route = myReplacedRoutes[index].route;
     276         6301 :             const double routeLength = route->getDistanceBetween(myHolder.getDepartPos(), route->getEdges().back()->getLength(),
     277         6301 :                                        route->begin(), route->end(), includeInternalLengths);
     278        12602 :             os.writeAttr("routeLength", routeLength);
     279              :         }
     280        32574 :     } else {
     281       110158 :         if (myDUAStyle || myWriteCosts) {
     282        40326 :             os.writeAttr(SUMO_ATTR_COST, myHolder.getRoute().getCosts());
     283              :         }
     284       110158 :         if (myWriteCosts) {
     285        40314 :             os.writeAttr(SUMO_ATTR_SAVINGS, myHolder.getRoute().getSavings());
     286              :         }
     287       110158 :         OutputDevice_String edgesD;
     288              :         int numWritten = 0;
     289              :         int start = 0;
     290       110158 :         if (myHolder.getNumberReroutes() > 0) {
     291              :             assert((int)myReplacedRoutes.size() <= myHolder.getNumberReroutes());
     292        73860 :             for (int i = routesToSkip; i < (int)myReplacedRoutes.size(); i++) {
     293        31882 :                 if (myReplacedRoutes[i].edge != nullptr) {
     294        31243 :                     int end = myReplacedRoutes[i].lastRouteIndex;
     295        31243 :                     numWritten += myReplacedRoutes[i].route->writeEdgeIDs(edgesD, start, end, myWriteInternal, myHolder.getVClass());
     296              :                 }
     297        31882 :                 start = myReplacedRoutes[i].newRouteIndex;
     298              :             }
     299              :         }
     300       110158 :         numWritten += myCurrentRoute->writeEdgeIDs(edgesD, start, -1, myWriteInternal, myHolder.getVClass());
     301       110158 :         std::string edgesS = edgesD.getString();
     302              :         edgesS.pop_back(); // remove last ' '
     303              :         os.writeAttr(SUMO_ATTR_EDGES, edgesS);
     304              : 
     305       110158 :         if (mySaveExits) {
     306              :             std::vector<std::string> exits;
     307       131796 :             for (SUMOTime t : myExits) {
     308       243506 :                 exits.push_back(time2string(t));
     309              :             }
     310              :             assert(numWritten >= (int)myExits.size());
     311        20086 :             std::vector<std::string> missing(numWritten - (int)myExits.size(), "-1");
     312        10043 :             exits.insert(exits.end(), missing.begin(), missing.end());
     313              :             os.writeAttr(SUMO_ATTR_EXITTIMES, exits);
     314        10043 :         }
     315       110158 :     }
     316       285464 :     os.closeTag();
     317              : }
     318              : 
     319              : 
     320              : void
     321       109146 : MSDevice_Vehroutes::generateOutput(OutputDevice* /*tripinfoOut*/) const {
     322       109146 :     writeOutput(true);
     323       109146 : }
     324              : 
     325              : 
     326              : void
     327       110164 : MSDevice_Vehroutes::writeOutput(const bool hasArrived) const {
     328       110164 :     const OptionsCont& oc = OptionsCont::getOptions();
     329       110164 :     OutputDevice& routeOut = OutputDevice::getDeviceByOption("vehroute-output");
     330       110164 :     OutputDevice_String od(1);
     331       110164 :     SUMOVehicleParameter tmp = myHolder.getParameter();
     332       110164 :     tmp.depart = myIntendedDepart ? myHolder.getParameter().depart : myHolder.getDeparture();
     333       110164 :     if (!MSGlobals::gUseMesoSim) {
     334        79575 :         if (tmp.wasSet(VEHPARS_DEPARTLANE_SET)) {
     335        14400 :             tmp.departLaneProcedure = DepartLaneDefinition::GIVEN;
     336        14400 :             tmp.departLane = myDepartLane;
     337              :         }
     338        79575 :         if (tmp.wasSet(VEHPARS_DEPARTPOSLAT_SET)) {
     339            8 :             tmp.departPosLatProcedure = (tmp.departPosLatProcedure == DepartPosLatDefinition::RANDOM
     340            4 :                                          ? DepartPosLatDefinition::GIVEN_VEHROUTE
     341              :                                          : DepartPosLatDefinition::GIVEN);
     342            4 :             tmp.departPosLat = myDepartPosLat;
     343              :         }
     344              :     }
     345       110164 :     if (tmp.wasSet(VEHPARS_DEPARTPOS_SET)) {
     346        72448 :         tmp.departPosProcedure = ((tmp.departPosProcedure != DepartPosDefinition::GIVEN
     347        36224 :                                    && tmp.departPosProcedure != DepartPosDefinition::STOP)
     348        36224 :                                   ? DepartPosDefinition::GIVEN_VEHROUTE
     349              :                                   : DepartPosDefinition::GIVEN);
     350        36224 :         tmp.departPos = myDepartPos;
     351              :     }
     352       110164 :     if (tmp.wasSet(VEHPARS_DEPARTSPEED_SET)) {
     353        89924 :         tmp.departSpeedProcedure = ((tmp.departSpeedProcedure != DepartSpeedDefinition::GIVEN
     354        44962 :                                      && tmp.departSpeedProcedure != DepartSpeedDefinition::LIMIT)
     355        44962 :                                     ? DepartSpeedDefinition::GIVEN_VEHROUTE
     356              :                                     : DepartSpeedDefinition::GIVEN);
     357        44962 :         tmp.departSpeed = myDepartSpeed;
     358              :     }
     359       328486 :     if (oc.getBool("vehroute-output.speedfactor") ||
     360       389676 :             (oc.isDefault("vehroute-output.speedfactor") && tmp.wasSet(VEHPARS_DEPARTSPEED_SET))) {
     361        46962 :         tmp.parametersSet |= VEHPARS_SPEEDFACTOR_SET;
     362        46962 :         tmp.speedFactor = myHolder.getChosenSpeedFactor();
     363              :     }
     364              : 
     365       110164 :     const std::string typeID = myHolder.getVehicleType().getID() != DEFAULT_VTYPE_ID ? myHolder.getVehicleType().getID() : "";
     366       110164 :     tmp.write(od, oc, SUMO_TAG_VEHICLE, typeID);
     367       110164 :     if (hasArrived) {
     368       218292 :         od.writeAttr("arrival", time2string(MSNet::getInstance()->getCurrentTimeStep()));
     369              :     }
     370       110164 :     if (myRouteLength) {
     371          851 :         const bool includeInternalLengths = MSGlobals::gUsingInternalLanes && MSNet::getInstance()->hasInternalLinks();
     372          851 :         const double finalPos = hasArrived ? myHolder.getArrivalPos() : myHolder.getPositionOnLane();
     373         1702 :         const double routeLength = myHolder.getRoute().getDistanceBetween(myHolder.getDepartPos(), finalPos,
     374          851 :                                    myHolder.getRoute().begin(), myHolder.getCurrentRouteEdge(), includeInternalLengths);
     375         1702 :         od.writeAttr("routeLength", routeLength);
     376              :     }
     377       110164 :     if (myDUAStyle) {
     378           12 :         const RandomDistributor<ConstMSRoutePtr>* const routeDist = MSRoute::distDictionary("!" + myHolder.getID());
     379           12 :         if (routeDist != nullptr) {
     380              :             const std::vector<ConstMSRoutePtr>& routes = routeDist->getVals();
     381            6 :             unsigned index = 0;
     382            6 :             while (index < routes.size() && routes[index] != myCurrentRoute) {
     383            0 :                 ++index;
     384              :             }
     385            6 :             od.openTag(SUMO_TAG_ROUTE_DISTRIBUTION).writeAttr(SUMO_ATTR_LAST, index);
     386              :             const std::vector<double>& probs = routeDist->getProbs();
     387           18 :             for (int i = 0; i < (int)routes.size(); ++i) {
     388           12 :                 od.setPrecision();
     389           12 :                 od.openTag(SUMO_TAG_ROUTE);
     390           12 :                 od.writeAttr(SUMO_ATTR_COST, routes[i]->getCosts());
     391           12 :                 if (myWriteCosts) {
     392            0 :                     od.writeAttr(SUMO_ATTR_SAVINGS, routes[i]->getSavings());
     393              :                 }
     394           12 :                 od.setPrecision(8);
     395              :                 od.writeAttr(SUMO_ATTR_PROB, probs[i]);
     396           12 :                 od.setPrecision();
     397           12 :                 OutputDevice_String edgesD;
     398           12 :                 routes[i]->writeEdgeIDs(edgesD, 0, -1, myWriteInternal, myHolder.getVClass());
     399           12 :                 std::string edgesS = edgesD.getString();
     400              :                 edgesS.pop_back(); // remove last ' '
     401              :                 od.writeAttr(SUMO_ATTR_EDGES, edgesS);
     402           24 :                 od.closeTag();
     403           12 :             }
     404           12 :             od.closeTag();
     405              :         } else {
     406            6 :             writeXMLRoute(od);
     407              :         }
     408              :     } else {
     409              :         std::string dummyMsg;
     410       110152 :         const int routesToSkip = (myHolder.getParameter().wasSet(VEHPARS_FORCE_REROUTE)
     411        34311 :                                   && !myIncludeIncomplete
     412        34191 :                                   && myReplacedRoutes.size() > 0
     413       177264 :                                   && !myHolder.hasValidRoute(dummyMsg, myReplacedRoutes[0].route) ? 1 : 0);
     414       110152 :         if ((int)myReplacedRoutes.size() > routesToSkip) {
     415        19426 :             od.openTag(SUMO_TAG_ROUTE_DISTRIBUTION);
     416        52000 :             for (int i = routesToSkip; i < (int)myReplacedRoutes.size(); ++i) {
     417        32574 :                 writeXMLRoute(od, i);
     418              :             }
     419        19426 :             writeXMLRoute(od);
     420        38852 :             od.closeTag();
     421              :         } else {
     422        90726 :             writeXMLRoute(od);
     423              :         }
     424              :     }
     425       110164 :     od << myStopOut.getString();
     426       110164 :     myHolder.getParameter().writeParams(od);
     427       110164 :     od.closeTag();
     428       110164 :     od.lf();
     429       110164 :     if (mySorted) {
     430              :         // numerical id reflects loading order
     431         8836 :         writeSortedOutput(&myRouteInfos, tmp.depart, toString(myHolder.getNumericalID()), od.getString());
     432              :     } else {
     433       211492 :         routeOut << od.getString();
     434              :     }
     435       110164 : }
     436              : 
     437              : 
     438              : ConstMSRoutePtr
     439            0 : MSDevice_Vehroutes::getRoute(int index) const {
     440            0 :     if (index < (int)myReplacedRoutes.size()) {
     441            0 :         return myReplacedRoutes[index].route;
     442              :     } else {
     443              :         return nullptr;
     444              :     }
     445              : }
     446              : 
     447              : 
     448              : void
     449        68329 : MSDevice_Vehroutes::addRoute(const std::string& info) {
     450        68329 :     if (myMaxRoutes > 0) {
     451              :         //std::cout << SIMTIME << " " << getID() << " departed=" << myHolder.hasDeparted() << " lastIndex=" << myLastRouteIndex << " start=" << myHolder.getRoutePosition() << "\n";
     452       342032 :         myReplacedRoutes.push_back(RouteReplaceInfo(
     453       102757 :                                        myHolder.hasDeparted() ?  myHolder.getEdge() : nullptr,
     454              :                                        MSNet::getInstance()->getCurrentTimeStep(), myCurrentRoute, info,
     455              :                                        myLastRouteIndex,
     456       102757 :                                        myHolder.hasDeparted() ? myHolder.getRoutePosition() : 0));
     457        68259 :         if ((int)myReplacedRoutes.size() > myMaxRoutes) {
     458              :             myReplacedRoutes.erase(myReplacedRoutes.begin());
     459              :         }
     460              :     }
     461        68329 :     myCurrentRoute = myHolder.getRoutePtr();
     462        68329 : }
     463              : 
     464              : 
     465              : void
     466        38573 : MSDevice_Vehroutes::writePendingOutput(const bool includeUnfinished) {
     467        38573 :     MSNet* const net = MSNet::getInstance();
     468              : 
     469        38573 :     if (!includeUnfinished) {
     470        38309 :         if (mySorted) {
     471          113 :             for (const auto& routeInfo : myRouteInfos.routeXML) {
     472           36 :                 for (const auto& rouXML : routeInfo.second) {
     473           20 :                     (*myRouteInfos.routeOut) << rouXML.second;
     474              :                 }
     475              :             }
     476           97 :             if (net->hasPersons()) {
     477           18 :                 const SortedRouteInfo& personRouteInfos = net->getPersonControl().getRouteInfo();
     478           18 :                 if (personRouteInfos.routeOut != myRouteInfos.routeOut) {
     479            0 :                     for (const auto& routeInfo : personRouteInfos.routeXML) {
     480            0 :                         for (const auto& rouXML : routeInfo.second) {
     481            0 :                             (*personRouteInfos.routeOut) << rouXML.second;
     482              :                         }
     483              :                     }
     484              :                 }
     485              :             }
     486              :         }
     487        38309 :         return;
     488              :     }
     489         1282 :     for (const auto& it : myStateListener.myDevices) {
     490         1018 :         if (it.first->hasDeparted()) {
     491         1018 :             if (it.first->isStopped()) {
     492          439 :                 it.second->notifyStopEnded();
     493              :             }
     494         1018 :             it.second->writeOutput(false);
     495              :         }
     496              :     }
     497              :     // unfinished persons
     498          264 :     if (net->hasPersons()) {
     499           98 :         MSTransportableControl& pc = net->getPersonControl();
     500          120 :         while (pc.loadedBegin() != pc.loadedEnd()) {
     501           22 :             pc.erase(pc.loadedBegin()->second);
     502              :         }
     503              :     }
     504              : }
     505              : 
     506              : 
     507              : void
     508          108 : MSDevice_Vehroutes::registerTransportableDepart(SUMOTime depart) {
     509          108 :     myRouteInfos.departureCounts[depart]++;
     510          108 : }
     511              : 
     512              : 
     513              : void
     514         4540 : MSDevice_Vehroutes::writeSortedOutput(MSDevice_Vehroutes::SortedRouteInfo* routeInfo, SUMOTime depart, const std::string& id, const std::string& xmlOutput) {
     515         4540 :     if (routeInfo->routeOut == myRouteInfos.routeOut) {
     516              :         routeInfo = &myRouteInfos;
     517              :     }
     518         4540 :     routeInfo->routeXML[depart][id] = xmlOutput;
     519         4540 :     routeInfo->departureCounts[depart]--;
     520              :     std::map<const SUMOTime, int>::iterator it = routeInfo->departureCounts.begin();
     521         7780 :     while (it != routeInfo->departureCounts.end() && it->second == 0) {
     522         7760 :         for (const auto& rouXML : routeInfo->routeXML[it->first]) {
     523         4520 :             (*routeInfo->routeOut) << rouXML.second;
     524              :         }
     525              :         routeInfo->routeXML.erase(it->first);
     526              :         it = routeInfo->departureCounts.erase(it);
     527              :     }
     528         4540 : }
     529              : 
     530              : 
     531              : void
     532         1666 : MSDevice_Vehroutes::saveState(OutputDevice& out) const {
     533         1666 :     out.openTag(SUMO_TAG_DEVICE);
     534              :     out.writeAttr(SUMO_ATTR_ID, getID());
     535              :     std::vector<std::string> internals;
     536         1666 :     if (!MSGlobals::gUseMesoSim) {
     537         1186 :         internals.push_back(toString(myDepartLane));
     538         2372 :         internals.push_back(toString(myDepartPosLat));
     539              :     }
     540         1666 :     internals.push_back(toString(myDepartSpeed));
     541         1666 :     internals.push_back(toString(myDepartPos));
     542         1666 :     internals.push_back(toString(myReplacedRoutes.size()));
     543         2774 :     for (int i = 0; i < (int)myReplacedRoutes.size(); ++i) {
     544         1108 :         const std::string replacedOnEdge = myReplacedRoutes[i].edge == nullptr ? "!NULL" : myReplacedRoutes[i].edge->getID();
     545         1108 :         internals.push_back(replacedOnEdge);
     546         2216 :         internals.push_back(toString(myReplacedRoutes[i].time));
     547         1108 :         internals.push_back(myReplacedRoutes[i].route->getID());
     548         1108 :         internals.push_back(myReplacedRoutes[i].info);
     549         1108 :         internals.push_back(toString(myReplacedRoutes[i].lastRouteIndex));
     550         2216 :         internals.push_back(toString(myReplacedRoutes[i].newRouteIndex));
     551              :     }
     552         1666 :     out.writeAttr(SUMO_ATTR_STATE, toString(internals));
     553         1666 :     if (mySaveExits && myExits.size() > 0) {
     554            7 :         out.writeAttr(SUMO_ATTR_EXITTIMES, myExits);
     555            7 :         out.writeAttr(SUMO_ATTR_EDGE, myLastSavedAt->getID());
     556              :     }
     557         1666 :     out.closeTag();
     558         1666 : }
     559              : 
     560              : 
     561              : void
     562         1059 : MSDevice_Vehroutes::loadState(const SUMOSAXAttributes& attrs) {
     563         1059 :     std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
     564         1059 :     if (!MSGlobals::gUseMesoSim) {
     565          657 :         bis >> myDepartLane;
     566          657 :         bis >> myDepartPosLat;
     567              :     }
     568         1059 :     bis >> myDepartSpeed;
     569         1059 :     bis >> myDepartPos;
     570              :     int size;
     571         1059 :     bis >> size;
     572         1708 :     for (int i = 0; i < size; ++i) {
     573              :         std::string edgeID;
     574              :         SUMOTime time;
     575              :         std::string routeID;
     576              :         std::string info;
     577              :         int lastIndex;
     578              :         int newIndex;
     579          649 :         bis >> edgeID;
     580              :         bis >> time;
     581          649 :         bis >> routeID;
     582          649 :         bis >> info;
     583          649 :         bis >> lastIndex;
     584          649 :         bis >> newIndex;
     585              : 
     586          649 :         ConstMSRoutePtr route = MSRoute::dictionary(routeID);
     587          649 :         if (route != nullptr) {
     588           45 :             myReplacedRoutes.push_back(RouteReplaceInfo(MSEdge::dictionary(edgeID), time, route, info, lastIndex, newIndex));
     589              :         }
     590              :     }
     591         1059 :     if (mySaveExits && attrs.hasAttribute(SUMO_ATTR_EXITTIMES)) {
     592            7 :         bool ok = true;
     593           16 :         for (const std::string& t : attrs.get<std::vector<std::string> >(SUMO_ATTR_EXITTIMES, nullptr, ok)) {
     594            9 :             myExits.push_back(StringUtils::toLong(t));
     595            7 :         }
     596            7 :         if (attrs.hasAttribute(SUMO_ATTR_EDGE)) {
     597            7 :             myLastSavedAt = MSEdge::dictionary(attrs.getString(SUMO_ATTR_EDGE));
     598              :         }
     599              :     }
     600         1059 : }
     601              : 
     602              : 
     603              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1