LCOV - code coverage report
Current view: top level - src/microsim/devices - MSDevice_Tripinfo.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 95.4 % 504 481
Test Date: 2024-11-22 15:46:21 Functions: 93.2 % 44 41

            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_Tripinfo.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/MSVehicle.h>
      30              : #include <microsim/transportables/MSTransportableControl.h>
      31              : #include <mesosim/MEVehicle.h>
      32              : #include <utils/options/OptionsCont.h>
      33              : #include <utils/iodevices/OutputDevice.h>
      34              : #include <utils/xml/SUMOSAXAttributes.h>
      35              : #include "MSDevice_Vehroutes.h"
      36              : #include "MSDevice_Tripinfo.h"
      37              : 
      38              : #define NOT_ARRIVED TIME2STEPS(-1)
      39              : #define STATE_EMPTY_ARRIVALLANE "NONE"
      40              : 
      41              : 
      42              : // ===========================================================================
      43              : // static members
      44              : // ===========================================================================
      45              : std::set<const MSDevice_Tripinfo*, ComparatorNumericalIdLess> MSDevice_Tripinfo::myPendingOutput;
      46              : 
      47              : int MSDevice_Tripinfo::myVehicleCount(0);
      48              : int MSDevice_Tripinfo::myUndepartedVehicleCount(0);
      49              : double MSDevice_Tripinfo::myTotalRouteLength(0);
      50              : double MSDevice_Tripinfo::myTotalSpeed(0);
      51              : SUMOTime MSDevice_Tripinfo::myTotalDuration(0);
      52              : SUMOTime MSDevice_Tripinfo::myTotalWaitingTime(0);
      53              : SUMOTime MSDevice_Tripinfo::myTotalTimeLoss(0);
      54              : SUMOTime MSDevice_Tripinfo::myTotalDepartDelay(0);
      55              : SUMOTime MSDevice_Tripinfo::myWaitingDepartDelay(-1);
      56              : 
      57              : int MSDevice_Tripinfo::myBikeCount(0);
      58              : double MSDevice_Tripinfo::myTotalBikeRouteLength(0);
      59              : double MSDevice_Tripinfo::myTotalBikeSpeed(0);
      60              : SUMOTime MSDevice_Tripinfo::myTotalBikeDuration(0);
      61              : SUMOTime MSDevice_Tripinfo::myTotalBikeWaitingTime(0);
      62              : SUMOTime MSDevice_Tripinfo::myTotalBikeTimeLoss(0);
      63              : 
      64              : int MSDevice_Tripinfo::myWalkCount(0);
      65              : double MSDevice_Tripinfo::myTotalWalkRouteLength(0);
      66              : SUMOTime MSDevice_Tripinfo::myTotalWalkDuration(0);
      67              : SUMOTime MSDevice_Tripinfo::myTotalWalkTimeLoss(0);
      68              : std::vector<int> MSDevice_Tripinfo::myRideCount({0, 0});
      69              : std::vector<int> MSDevice_Tripinfo::myRideBusCount({0, 0});
      70              : std::vector<int> MSDevice_Tripinfo::myRideRailCount({0, 0});
      71              : std::vector<int> MSDevice_Tripinfo::myRideTaxiCount({0, 0});
      72              : std::vector<int> MSDevice_Tripinfo::myRideBikeCount({0, 0});
      73              : std::vector<int> MSDevice_Tripinfo::myRideAbortCount({0, 0});
      74              : std::vector<SUMOTime> MSDevice_Tripinfo::myTotalRideWaitingTime({0, 0});
      75              : std::vector<double> MSDevice_Tripinfo::myTotalRideRouteLength({0., 0.});
      76              : std::vector<SUMOTime> MSDevice_Tripinfo::myTotalRideDuration({0, 0});
      77              : 
      78              : // ===========================================================================
      79              : // method definitions
      80              : // ===========================================================================
      81              : // ---------------------------------------------------------------------------
      82              : // static initialisation methods
      83              : // ---------------------------------------------------------------------------
      84              : void
      85        43644 : MSDevice_Tripinfo::insertOptions(OptionsCont& oc) {
      86        43644 :     oc.addOptionSubTopic("Tripinfo Device");
      87        87288 :     insertDefaultAssignmentOptions("tripinfo", "Tripinfo Device", oc);
      88        43644 : }
      89              : 
      90              : 
      91              : void
      92      5104379 : MSDevice_Tripinfo::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into) {
      93      5104379 :     OptionsCont& oc = OptionsCont::getOptions();
      94      9959641 :     const bool enableByOutputOption = oc.isSet("tripinfo-output") || oc.getBool("duration-log.statistics");
      95     10208758 :     if (equippedByDefaultAssignmentOptions(oc, "tripinfo", v, enableByOutputOption)) {
      96      2034678 :         MSDevice_Tripinfo* device = new MSDevice_Tripinfo(v, "tripinfo_" + v.getID());
      97      2034678 :         into.push_back(device);
      98              :         myPendingOutput.insert(device);
      99              :     }
     100      5104379 : }
     101              : 
     102              : 
     103              : // ---------------------------------------------------------------------------
     104              : // MSDevice_Tripinfo-methods
     105              : // ---------------------------------------------------------------------------
     106      2034678 : MSDevice_Tripinfo::MSDevice_Tripinfo(SUMOVehicle& holder, const std::string& id) :
     107              :     MSVehicleDevice(holder, id),
     108            0 :     myDepartLane(""),
     109      2034678 :     myDepartSpeed(-1),
     110      2034678 :     myDepartPosLat(0),
     111      2034678 :     myWaitingTime(0),
     112      2034678 :     myAmWaiting(false),
     113      2034678 :     myWaitingCount(0),
     114      2034678 :     myStoppingTime(0),
     115      2034678 :     myParkingStarted(-1),
     116      2034678 :     myArrivalTime(NOT_ARRIVED),
     117      2034678 :     myArrivalLane(""),
     118      2034678 :     myArrivalPos(-1),
     119      2034678 :     myArrivalPosLat(0.),
     120      2034678 :     myArrivalSpeed(-1),
     121      2034678 :     myArrivalReason(MSMoveReminder::NOTIFICATION_ARRIVED),
     122      2034678 :     myMesoTimeLoss(0),
     123      2034678 :     myRouteLength(0.) {
     124      2034678 : }
     125              : 
     126              : 
     127      4069306 : MSDevice_Tripinfo::~MSDevice_Tripinfo() {
     128              :     // ensure clean up for vaporized vehicles which do not generate output
     129      2034653 :     myPendingOutput.erase(this);
     130      4069306 : }
     131              : 
     132              : void
     133        40275 : MSDevice_Tripinfo::cleanup() {
     134        40275 :     myVehicleCount = 0;
     135        40275 :     myTotalRouteLength = 0;
     136        40275 :     myTotalSpeed = 0;
     137        40275 :     myTotalDuration = 0;
     138        40275 :     myTotalWaitingTime = 0;
     139        40275 :     myTotalTimeLoss = 0;
     140        40275 :     myTotalDepartDelay = 0;
     141        40275 :     myWaitingDepartDelay = -1;
     142              : 
     143        40275 :     myBikeCount = 0;
     144        40275 :     myTotalBikeRouteLength = 0;
     145        40275 :     myTotalBikeSpeed = 0;
     146        40275 :     myTotalBikeDuration = 0;
     147        40275 :     myTotalBikeWaitingTime = 0;
     148        40275 :     myTotalBikeTimeLoss = 0;
     149              : 
     150        40275 :     myWalkCount = 0;
     151        40275 :     myTotalWalkRouteLength = 0;
     152        40275 :     myTotalWalkDuration = 0;
     153        40275 :     myTotalWalkTimeLoss = 0;
     154              : 
     155        40275 :     myRideCount = {0, 0};
     156        40275 :     myRideBusCount = {0, 0};
     157        40275 :     myRideRailCount = {0, 0};
     158        40275 :     myRideTaxiCount = {0, 0};
     159        40275 :     myRideBikeCount = {0, 0};
     160        40275 :     myRideAbortCount = {0, 0};
     161        40275 :     myTotalRideWaitingTime = {0, 0};
     162        40275 :     myTotalRideRouteLength = {0., 0.};
     163        40275 :     myTotalRideDuration = {0, 0};
     164        40275 : }
     165              : 
     166              : bool
     167         3432 : MSDevice_Tripinfo::notifyIdle(SUMOTrafficObject& veh) {
     168         3432 :     if (veh.isVehicle()) {
     169         3432 :         myWaitingTime += DELTA_T;
     170         3432 :         if (!myAmWaiting) {
     171          132 :             myWaitingCount++;
     172          132 :             myAmWaiting = true;
     173              :         }
     174              :     }
     175         3432 :     return true;
     176              : }
     177              : 
     178              : 
     179              : bool
     180    321865107 : MSDevice_Tripinfo::notifyMove(SUMOTrafficObject& veh, double /*oldPos*/,
     181              :                               double /*newPos*/, double newSpeed) {
     182    321865107 :     if (veh.isStopped()) {
     183      1677459 :         if (newSpeed <= SUMO_const_haltingSpeed) {
     184      1677275 :             myStoppingTime += DELTA_T;
     185              :         }
     186    320187648 :     } else if (newSpeed <= SUMO_const_haltingSpeed && lowAcceleration(veh)) {
     187     48716913 :         myWaitingTime += DELTA_T;
     188     48716913 :         if (!myAmWaiting) {
     189      2470081 :             myWaitingCount++;
     190      2470081 :             myAmWaiting = true;
     191              :         }
     192              :     } else {
     193    271470735 :         myAmWaiting = false;
     194              :     }
     195    321865107 :     return true;
     196              : }
     197              : 
     198              : 
     199              : bool
     200     48717597 : MSDevice_Tripinfo::lowAcceleration(const SUMOTrafficObject& veh) {
     201     48717597 :     if (MSGlobals::gUseMesoSim) {
     202              :         // acceleration is not modelled
     203              :         return false;
     204              :     } else {
     205     48717597 :         const MSVehicle& v = dynamic_cast<const MSVehicle&>(veh);
     206     48717597 :         return v.getAcceleration() <= v.accelThresholdForWaiting();
     207              :     }
     208              : }
     209              : 
     210              : 
     211              : void
     212     13055004 : MSDevice_Tripinfo::notifyMoveInternal(const SUMOTrafficObject& veh,
     213              :                                       const double /* frontOnLane */,
     214              :                                       const double timeOnLane,
     215              :                                       const double /* meanSpeedFrontOnLane */,
     216              :                                       const double meanSpeedVehicleOnLane,
     217              :                                       const double /* travelledDistanceFrontOnLane */,
     218              :                                       const double /* travelledDistanceVehicleOnLane */,
     219              :                                       const double /* meanLengthOnLane */) {
     220              : 
     221              :     // called by meso
     222     13055004 :     const double vmax = veh.getEdge()->getVehicleMaxSpeed(&veh);
     223     13055004 :     if (vmax > 0) {
     224     15859560 :         myMesoTimeLoss += TIME2STEPS(timeOnLane * (vmax - meanSpeedVehicleOnLane) / vmax);
     225              :     }
     226     13055004 :     myWaitingTime += veh.getWaitingTime();
     227     13055004 : }
     228              : 
     229              : 
     230              : void
     231      1515006 : MSDevice_Tripinfo::updateParkingStopTime() {
     232      1515006 :     if (myParkingStarted >= 0) {
     233         3447 :         myStoppingTime += (MSNet::getInstance()->getCurrentTimeStep() - myParkingStarted);
     234         3447 :         myParkingStarted = -1;
     235              :     }
     236      1515006 : }
     237              : 
     238              : bool
     239     26178024 : MSDevice_Tripinfo::notifyEnter(SUMOTrafficObject& veh, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
     240     26178024 :     if (reason == MSMoveReminder::NOTIFICATION_DEPARTED) {
     241      1544568 :         if (!MSGlobals::gUseMesoSim) {
     242      1195392 :             myDepartLane = static_cast<MSVehicle&>(veh).getLane()->getID();
     243      1195392 :             myDepartPosLat = static_cast<MSVehicle&>(veh).getLateralPositionOnLane();
     244              :         } else {
     245       349176 :             myDepartLane = veh.getEdge()->getFirstAllowed(veh.getVClass(), true)->getID();
     246              :         }
     247      1544568 :         myDepartSpeed = veh.getSpeed();
     248      1544568 :         myRouteLength = -veh.getPositionOnLane();
     249     24633456 :     } else if (reason == MSMoveReminder::NOTIFICATION_PARKING) {
     250              :         // notifyMove is not called while parking
     251              :         // @note insertion delay when resuming after parking is included
     252         2943 :         updateParkingStopTime();
     253              :     }
     254     26178024 :     return true;
     255              : }
     256              : 
     257              : 
     258              : bool
     259     26109189 : MSDevice_Tripinfo::notifyLeave(SUMOTrafficObject& veh, double /*lastPos*/,
     260              :                                MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
     261     26109189 :     if (reason >= MSMoveReminder::NOTIFICATION_ARRIVED) {
     262      1480081 :         myArrivalTime = MSNet::getInstance()->getCurrentTimeStep();
     263      1480081 :         myArrivalReason = reason;
     264      1480081 :         if (!MSGlobals::gUseMesoSim) {
     265      1136399 :             myArrivalLane = static_cast<MSVehicle&>(veh).getLane()->getID();
     266      1136399 :             myArrivalPosLat = static_cast<MSVehicle&>(veh).getLateralPositionOnLane();
     267              :         } else {
     268       343682 :             myArrivalLane = veh.getEdge()->getFirstAllowed(veh.getVClass(), true)->getID();
     269              :         }
     270              :         // @note vehicle may have moved past its arrivalPos during the last step
     271              :         // due to non-zero arrivalspeed but we consider it as arrived at the desired position
     272              :         // However, vaporization may happen anywhere (via TraCI)
     273      1480081 :         if (reason > MSMoveReminder::NOTIFICATION_TELEPORT_ARRIVED) {
     274              :             // vaporized
     275          545 :             myArrivalPos = veh.getPositionOnLane();
     276              :         } else {
     277      1479536 :             myArrivalPos = myHolder.getArrivalPos();
     278              :         }
     279      1480081 :         myArrivalSpeed = veh.getSpeed();
     280      1480081 :         updateParkingStopTime();
     281     24629108 :     } else if (reason == MSMoveReminder::NOTIFICATION_PARKING) {
     282         3527 :         myParkingStarted = MSNet::getInstance()->getCurrentTimeStep();
     283     24625581 :     } else if (reason == NOTIFICATION_JUNCTION
     284     24625581 :                || reason == NOTIFICATION_TELEPORT
     285     12140776 :                || reason == NOTIFICATION_TELEPORT_CONTINUATION) {
     286     12490070 :         if (MSGlobals::gUseMesoSim) {
     287      1283850 :             myRouteLength += myHolder.getEdge()->getLength();
     288              :         } else {
     289     11206220 :             const MSLane* lane = static_cast<MSVehicle&>(veh).getLane();
     290     11206220 :             if (lane != nullptr) {
     291     11206196 :                 myRouteLength += lane->getLength();
     292              :             }
     293              :         }
     294              :     }
     295     26109189 :     return true;
     296              : }
     297              : 
     298              : 
     299              : void
     300      1511885 : MSDevice_Tripinfo::generateOutput(OutputDevice* tripinfoOut) const {
     301      1511885 :     const SUMOTime timeLoss = MSGlobals::gUseMesoSim ? myMesoTimeLoss : static_cast<MSVehicle&>(myHolder).getTimeLoss();
     302      1511885 :     const double routeLength = myRouteLength + (myArrivalTime == NOT_ARRIVED ? myHolder.getPositionOnLane() : myArrivalPos);
     303              :     SUMOTime duration = 0;
     304      1511885 :     if (myHolder.hasDeparted()) {
     305      1543415 :         duration = (myArrivalTime == NOT_ARRIVED ? SIMSTEP : myArrivalTime) - myHolder.getDeparture();
     306      1511641 :         if (myHolder.getVClass() == SVC_BICYCLE) {
     307        24866 :             myBikeCount++;
     308        24866 :             myTotalBikeRouteLength += routeLength;
     309        24866 :             myTotalBikeSpeed += routeLength / STEPS2TIME(duration);
     310        24866 :             myTotalBikeDuration += duration;
     311        24866 :             myTotalBikeWaitingTime += myWaitingTime;
     312        24866 :             myTotalBikeTimeLoss += timeLoss;
     313              :         } else {
     314      1486775 :             myVehicleCount++;
     315      1486775 :             myTotalRouteLength += routeLength;
     316      1486775 :             myTotalSpeed += routeLength / STEPS2TIME(duration);
     317      1486775 :             myTotalDuration += duration;
     318      1486775 :             myTotalWaitingTime += myWaitingTime;
     319      1486775 :             myTotalTimeLoss += timeLoss;
     320              :         }
     321      1511641 :         myTotalDepartDelay += myHolder.getDepartDelay();
     322              :     }
     323              : 
     324      1511885 :     myPendingOutput.erase(this);
     325      1511885 :     if (tripinfoOut == nullptr) {
     326      1280476 :         return;
     327              :     }
     328              :     // write
     329              :     OutputDevice& os = *tripinfoOut;
     330       462818 :     os.openTag("tripinfo").writeAttr("id", myHolder.getID());
     331       462818 :     os.writeAttr("depart", myHolder.hasDeparted() ? time2string(myHolder.getDeparture()) : "-1");
     332       231409 :     os.writeAttr("departLane", myDepartLane);
     333       231409 :     os.writeAttr("departPos", myHolder.getDepartPos());
     334       231409 :     if (MSGlobals::gLateralResolution > 0) {
     335        48980 :         os.writeAttr("departPosLat", myDepartPosLat);
     336              :     }
     337       231409 :     os.writeAttr("departSpeed", myDepartSpeed);
     338       231409 :     SUMOTime departDelay = myHolder.getDepartDelay();
     339       231409 :     const SUMOVehicleParameter& param = myHolder.getParameter();
     340       231409 :     if (!myHolder.hasDeparted()) {
     341              :         assert(param.depart <= SIMSTEP || param.departProcedure != DepartDefinition::GIVEN);
     342          244 :         departDelay = SIMSTEP - param.depart;
     343              :     }
     344       462818 :     os.writeAttr("departDelay", time2string(departDelay));
     345       462818 :     os.writeAttr("arrival", time2string(myArrivalTime));
     346       231409 :     os.writeAttr("arrivalLane", myArrivalLane);
     347       231409 :     os.writeAttr("arrivalPos", myArrivalPos);
     348       231409 :     if (MSGlobals::gLateralResolution > 0) {
     349        48980 :         os.writeAttr("arrivalPosLat", myArrivalPosLat);
     350              :     }
     351       231409 :     os.writeAttr("arrivalSpeed", myArrivalSpeed);
     352       462818 :     os.writeAttr("duration", time2string(duration));
     353       231409 :     os.writeAttr("routeLength", routeLength);
     354       231409 :     os.writeAttr(SUMO_ATTR_WAITINGTIME, time2string(myWaitingTime));
     355       231409 :     os.writeAttr(SUMO_ATTR_WAITINGCOUNT, myWaitingCount);
     356       231409 :     os.writeAttr(SUMO_ATTR_STOPTIME, time2string(myStoppingTime));
     357       231409 :     os.writeAttr(SUMO_ATTR_TIMELOSS, time2string(timeLoss));
     358       231409 :     os.writeAttr("rerouteNo", myHolder.getNumberReroutes());
     359       694227 :     os.writeAttr("devices", toString(myHolder.getDevices()));
     360       231409 :     os.writeAttr("vType", myHolder.getVehicleType().getID());
     361       462818 :     os.writeAttr("speedFactor", myHolder.getChosenSpeedFactor());
     362              :     std::string vaporized;
     363       231409 :     switch (myArrivalReason) {
     364              :         case MSMoveReminder::NOTIFICATION_VAPORIZED_CALIBRATOR:
     365              :             vaporized = "calibrator";
     366              :             break;
     367              :         case MSMoveReminder::NOTIFICATION_VAPORIZED_GUI:
     368              :             vaporized = "gui";
     369              :             break;
     370              :         case MSMoveReminder::NOTIFICATION_VAPORIZED_COLLISION:
     371              :             vaporized = "collision";
     372              :             break;
     373              :         case MSMoveReminder::NOTIFICATION_VAPORIZED_VAPORIZER:
     374              :             vaporized = "vaporizer";
     375              :             break;
     376              :         case MSMoveReminder::NOTIFICATION_VAPORIZED_TRACI:
     377              :             vaporized = "traci";
     378              :             break;
     379              :         case MSMoveReminder::NOTIFICATION_TELEPORT_ARRIVED:
     380              :             vaporized = "teleport";
     381              :             break;
     382       231019 :         default:
     383       231019 :             if (myHolder.getEdge() == myHolder.getRoute().getLastEdge() ||
     384         1484 :                     (param.arrivalEdge >= 0 && myHolder.getRoutePosition() >= param.arrivalEdge)) {
     385              :                 vaporized = "";
     386              :             } else {
     387              :                 vaporized = "end";
     388              :             }
     389              :             break;
     390              :     }
     391       462818 :     os.writeAttr("vaporized", vaporized);
     392              :     // cannot close tag because emission device output might follow
     393              : }
     394              : 
     395              : 
     396              : void
     397          828 : MSDevice_Tripinfo::generateOutputForUnfinished() {
     398          828 :     MSNet* net = MSNet::getInstance();
     399          828 :     OutputDevice* tripinfoOut = (OptionsCont::getOptions().isSet("tripinfo-output") ?
     400         1409 :                                  &OutputDevice::getDeviceByOption("tripinfo-output") : nullptr);
     401          828 :     myWaitingDepartDelay = 0;
     402          828 :     myUndepartedVehicleCount = 0;
     403         1656 :     const bool writeUndeparted = OptionsCont::getOptions().getBool("tripinfo-output.write-undeparted");
     404              :     const SUMOTime t = net->getCurrentTimeStep();
     405        63333 :     while (myPendingOutput.size() > 0) {
     406        62505 :         const MSDevice_Tripinfo* d = *myPendingOutput.begin();
     407        62505 :         const bool departed = d->myHolder.hasDeparted();
     408        62505 :         const bool departDelayed = d->myHolder.getParameter().depart <= t;
     409        62505 :         if (!departed && departDelayed) {
     410        30755 :             myUndepartedVehicleCount++;
     411        30755 :             myWaitingDepartDelay += (t - d->myHolder.getParameter().depart);
     412              :         }
     413        62505 :         if (departed || (writeUndeparted && departDelayed)) {
     414        31982 :             const_cast<MSDevice_Tripinfo*>(d)->updateParkingStopTime();
     415        31982 :             d->generateOutput(tripinfoOut);
     416        31982 :             if (tripinfoOut != nullptr) {
     417         6169 :                 for (MSVehicleDevice* const dev : d->myHolder.getDevices()) {
     418         4268 :                     if (typeid(*dev) == typeid(MSDevice_Tripinfo) || typeid(*dev) == typeid(MSDevice_Vehroutes)) {
     419              :                         // tripinfo is special and vehroute has its own write-unfinished option
     420         2296 :                         continue;
     421              :                     }
     422         1972 :                     dev->generateOutput(tripinfoOut);
     423              :                 }
     424         3802 :                 OutputDevice::getDeviceByOption("tripinfo-output").closeTag();
     425              :             }
     426              :         } else {
     427              :             myPendingOutput.erase(d);
     428              :         }
     429              :     }
     430              :     // unfinished persons
     431          828 :     if (net->hasPersons()) {
     432          475 :         MSTransportableControl& pc = net->getPersonControl();
     433          499 :         while (pc.loadedBegin() != pc.loadedEnd()) {
     434           24 :             pc.erase(pc.loadedBegin()->second);
     435              :         }
     436              :     }
     437              : 
     438          828 : }
     439              : 
     440              : 
     441              : void
     442        54478 : MSDevice_Tripinfo::addPedestrianData(double walkLength, SUMOTime walkDuration, SUMOTime walkTimeLoss) {
     443        54478 :     myWalkCount++;
     444        54478 :     myTotalWalkRouteLength += walkLength;
     445        54478 :     myTotalWalkDuration += walkDuration;
     446        54478 :     myTotalWalkTimeLoss += walkTimeLoss;
     447        54478 : }
     448              : 
     449              : 
     450              : void
     451         6346 : MSDevice_Tripinfo::addRideTransportData(const bool isPerson, const double distance, const SUMOTime duration,
     452              :                                         const SUMOVehicleClass vClass, const std::string& line, const SUMOTime waitingTime) {
     453         6346 :     const int index = isPerson ? 0 : 1;
     454         6346 :     myRideCount[index]++;
     455         6346 :     if (duration > 0) {
     456         6079 :         myTotalRideWaitingTime[index] += waitingTime;
     457         6079 :         myTotalRideRouteLength[index] += distance;
     458         6079 :         myTotalRideDuration[index] += duration;
     459         6079 :         if (vClass == SVC_BICYCLE) {
     460           13 :             myRideBikeCount[index]++;
     461         6066 :         } else if (!line.empty()) {
     462         4975 :             if (isRailway(vClass)) {
     463          778 :                 myRideRailCount[index]++;
     464         4197 :             } else if (vClass == SVC_TAXI) {
     465         1253 :                 myRideTaxiCount[index]++;
     466              :             } else {
     467              :                 // some kind of road vehicle
     468         2944 :                 myRideBusCount[index]++;
     469              :             }
     470              :         }
     471              :     } else {
     472          267 :         myRideAbortCount[index]++;
     473              :     }
     474         6346 : }
     475              : 
     476              : 
     477              : std::string
     478         2658 : MSDevice_Tripinfo::printStatistics() {
     479         2658 :     std::ostringstream msg;
     480              :     msg.setf(msg.fixed);
     481         2658 :     msg.precision(gPrecision);
     482         2658 :     if (myBikeCount == 0 || myVehicleCount > 0) {
     483         2596 :         msg << "Statistics (avg of " << myVehicleCount << "):\n";
     484         2596 :         msg << " RouteLength: " << getAvgRouteLength() << "\n"
     485         2596 :             << " Speed: " << getAvgTripSpeed() << "\n"
     486         2596 :             << " Duration: " << getAvgDuration() << "\n"
     487         2596 :             << " WaitingTime: " << getAvgWaitingTime() << "\n"
     488         5192 :             << " TimeLoss: " << getAvgTimeLoss() << "\n";
     489              :     }
     490         2658 :     if (myBikeCount > 0) {
     491              :         msg << "Bike Statistics (avg of " << myBikeCount << "):\n"
     492          282 :             << " RouteLength: " << getAvgBikeRouteLength() << "\n"
     493          141 :             << " Speed: " << getAvgBikeTripSpeed() << "\n"
     494          141 :             << " Duration: " << getAvgBikeDuration() << "\n"
     495          141 :             << " WaitingTime: " << getAvgBikeWaitingTime() << "\n"
     496          282 :             << " TimeLoss: " << getAvgBikeTimeLoss() << "\n";
     497          141 :         if (myVehicleCount > 0) {
     498           79 :             msg << "Statistics (avg of " << (myVehicleCount + myBikeCount) << "):\n";
     499              :         }
     500              :     }
     501         5316 :     msg << " DepartDelay: " << getAvgDepartDelay() << "\n";
     502         2658 :     if (myWaitingDepartDelay >= 0) {
     503          654 :         msg << " DepartDelayWaiting: " << getAvgDepartDelayWaiting() << "\n";
     504              :     }
     505         2658 :     if (myWalkCount > 0) {
     506              :         msg << "Pedestrian Statistics (avg of " << myWalkCount << " walks):\n"
     507          540 :             << " RouteLength: " << getAvgWalkRouteLength() << "\n"
     508          270 :             << " Duration: " << getAvgWalkDuration() << "\n"
     509          540 :             << " TimeLoss: " << getAvgWalkTimeLoss() << "\n";
     510              :     }
     511         5316 :     printRideStatistics(msg, "Ride", "rides", 0);
     512         5316 :     printRideStatistics(msg, "Transport", "transports", 1);
     513         2658 :     return msg.str();
     514         2658 : }
     515              : 
     516              : void
     517         5316 : MSDevice_Tripinfo::printRideStatistics(std::ostringstream& msg, const std::string& category, const std::string& modeName, const int index) {
     518         5316 :     if (myRideCount[index] > 0) {
     519          336 :         msg << category << " Statistics (avg of " << myRideCount[index] << " " << modeName << "):\n";
     520          112 :         msg << " WaitingTime: " << STEPS2TIME(myTotalRideWaitingTime[index] / myRideCount[index]) << "\n";
     521          112 :         msg << " RouteLength: " << myTotalRideRouteLength[index] / myRideCount[index] << "\n";
     522          112 :         msg << " Duration: " << STEPS2TIME(myTotalRideDuration[index] / myRideCount[index]) << "\n";
     523          112 :         if (myRideBusCount[index] > 0) {
     524           15 :             msg << " Bus: " << myRideBusCount[index] << "\n";
     525              :         }
     526          112 :         if (myRideRailCount[index] > 0) {
     527            9 :             msg << " Train: " << myRideRailCount[index] << "\n";
     528              :         }
     529          112 :         if (myRideTaxiCount[index] > 0) {
     530           66 :             msg << " Taxi: " << myRideTaxiCount[index] << "\n";
     531              :         }
     532          112 :         if (myRideBikeCount[index] > 0) {
     533           13 :             msg << " Bike: " << myRideBikeCount[index] << "\n";
     534              :         }
     535          112 :         if (myRideAbortCount[index] > 0) {
     536           11 :             msg << " Aborted: " << myRideAbortCount[index] << "\n";
     537              :         }
     538              :     }
     539              : 
     540         5316 : }
     541              : 
     542              : 
     543              : void
     544          262 : MSDevice_Tripinfo::writeStatistics(OutputDevice& od) {
     545          262 :     od.setPrecision(gPrecision);
     546          262 :     od.openTag("vehicleTripStatistics");
     547          262 :     od.writeAttr("count", myVehicleCount);
     548          262 :     od.writeAttr("routeLength", getAvgRouteLength());
     549          262 :     od.writeAttr("speed", getAvgTripSpeed());
     550          262 :     od.writeAttr("duration", getAvgDuration());
     551          262 :     od.writeAttr("waitingTime", getAvgWaitingTime());
     552          262 :     od.writeAttr("timeLoss", getAvgTimeLoss());
     553          262 :     od.writeAttr("departDelay", getAvgDepartDelay());
     554          262 :     od.writeAttr("departDelayWaiting", getAvgDepartDelayWaiting());
     555          524 :     od.writeAttr("totalTravelTime", time2string(myTotalDuration));
     556          524 :     od.writeAttr("totalDepartDelay", time2string(TIME2STEPS(getTotalDepartDelay())));
     557          262 :     od.closeTag();
     558          262 :     if (myBikeCount > 0) {
     559            4 :         od.openTag("bikeTripStatistics");
     560            4 :         od.writeAttr("count", myBikeCount);
     561            4 :         od.writeAttr("routeLength", getAvgBikeRouteLength());
     562            4 :         od.writeAttr("speed", getAvgBikeTripSpeed());
     563            4 :         od.writeAttr("duration", getAvgBikeDuration());
     564            4 :         od.writeAttr("waitingTime", getAvgBikeWaitingTime());
     565            4 :         od.writeAttr("timeLoss", getAvgBikeTimeLoss());
     566            8 :         od.writeAttr("totalTravelTime", time2string(myTotalBikeDuration));
     567            8 :         od.closeTag();
     568              :     }
     569          262 :     od.openTag("pedestrianStatistics");
     570          262 :     od.writeAttr("number", myWalkCount);
     571          262 :     od.writeAttr("routeLength", getAvgWalkRouteLength());
     572          262 :     od.writeAttr("duration", getAvgWalkDuration());
     573          262 :     od.writeAttr("timeLoss", getAvgWalkTimeLoss());
     574          262 :     od.closeTag();
     575          262 :     writeRideStatistics(od, "rideStatistics", 0);
     576          262 :     writeRideStatistics(od, "transportStatistics", 1);
     577          262 : }
     578              : 
     579              : void
     580          524 : MSDevice_Tripinfo::writeRideStatistics(OutputDevice& od, const std::string& category, const int index) {
     581          524 :     od.openTag(category);
     582         1048 :     od.writeAttr("number", myRideCount[index]);
     583          524 :     if (myRideCount[index] > 0) {
     584            0 :         od.writeAttr("waitingTime", STEPS2TIME(myTotalRideWaitingTime[index] / myRideCount[index]));
     585            0 :         od.writeAttr("routeLength", myTotalRideRouteLength[index] / myRideCount[index]);
     586            0 :         od.writeAttr("duration", STEPS2TIME(myTotalRideDuration[index] / myRideCount[index]));
     587            0 :         od.writeAttr("bus", myRideBusCount[index]);
     588            0 :         od.writeAttr("train", myRideRailCount[index]);
     589            0 :         od.writeAttr("taxi", myRideTaxiCount[index]);
     590            0 :         od.writeAttr("bike", myRideBikeCount[index]);
     591            0 :         od.writeAttr("aborted", myRideAbortCount[index]);
     592              :     }
     593          524 :     od.closeTag();
     594          524 : }
     595              : 
     596              : 
     597              : double
     598         2982 : MSDevice_Tripinfo::getAvgRouteLength() {
     599         2982 :     if (myVehicleCount > 0) {
     600         2760 :         return myTotalRouteLength / myVehicleCount;
     601              :     } else {
     602              :         return 0;
     603              :     }
     604              : }
     605              : 
     606              : double
     607         2982 : MSDevice_Tripinfo::getAvgTripSpeed() {
     608         2982 :     if (myVehicleCount > 0) {
     609         2760 :         return myTotalSpeed / myVehicleCount;
     610              :     } else {
     611              :         return 0;
     612              :     }
     613              : }
     614              : 
     615              : double
     616         2982 : MSDevice_Tripinfo::getAvgDuration() {
     617         2982 :     if (myVehicleCount > 0) {
     618         2760 :         return STEPS2TIME(myTotalDuration / myVehicleCount);
     619              :     } else {
     620              :         return 0;
     621              :     }
     622              : }
     623              : 
     624              : double
     625         2982 : MSDevice_Tripinfo::getAvgWaitingTime() {
     626         2982 :     if (myVehicleCount > 0) {
     627         2760 :         return STEPS2TIME(myTotalWaitingTime / myVehicleCount);
     628              :     } else {
     629              :         return 0;
     630              :     }
     631              : }
     632              : 
     633              : 
     634              : double
     635         2982 : MSDevice_Tripinfo::getAvgTimeLoss() {
     636         2982 :     if (myVehicleCount > 0) {
     637         2760 :         return STEPS2TIME(myTotalTimeLoss / myVehicleCount);
     638              :     } else {
     639              :         return 0;
     640              :     }
     641              : }
     642              : 
     643              : 
     644              : double
     645         3044 : MSDevice_Tripinfo::getAvgDepartDelay() {
     646         3044 :     if (myVehicleCount > 0) {
     647         2760 :         return STEPS2TIME(myTotalDepartDelay / myVehicleCount);
     648              :     } else {
     649              :         return 0;
     650              :     }
     651              : }
     652              : 
     653              : double
     654          713 : MSDevice_Tripinfo::getAvgDepartDelayWaiting() {
     655          713 :     if (myWaitingDepartDelay >= 0) {
     656          339 :         return STEPS2TIME(myWaitingDepartDelay / MAX2(1, myUndepartedVehicleCount));
     657              :     } else {
     658              :         return -1;
     659              :     }
     660              : }
     661              : 
     662              : 
     663              : double
     664          648 : MSDevice_Tripinfo::getTotalDepartDelay() {
     665          648 :     return STEPS2TIME(myTotalDepartDelay + MAX2((SUMOTime)0, myWaitingDepartDelay));
     666              : }
     667              : 
     668              : double
     669          207 : MSDevice_Tripinfo::getAvgBikeRouteLength() {
     670          207 :     if (myBikeCount > 0) {
     671          145 :         return myTotalBikeRouteLength / myBikeCount;
     672              :     } else {
     673              :         return 0;
     674              :     }
     675              : }
     676              : 
     677              : double
     678          207 : MSDevice_Tripinfo::getAvgBikeTripSpeed() {
     679          207 :     if (myBikeCount > 0) {
     680          145 :         return myTotalBikeSpeed / myBikeCount;
     681              :     } else {
     682              :         return 0;
     683              :     }
     684              : }
     685              : 
     686              : double
     687          207 : MSDevice_Tripinfo::getAvgBikeDuration() {
     688          207 :     if (myBikeCount > 0) {
     689          145 :         return STEPS2TIME(myTotalBikeDuration / myBikeCount);
     690              :     } else {
     691              :         return 0;
     692              :     }
     693              : }
     694              : 
     695              : double
     696          207 : MSDevice_Tripinfo::getAvgBikeWaitingTime() {
     697          207 :     if (myBikeCount > 0) {
     698          145 :         return STEPS2TIME(myTotalBikeWaitingTime / myBikeCount);
     699              :     } else {
     700              :         return 0;
     701              :     }
     702              : }
     703              : 
     704              : 
     705              : double
     706          207 : MSDevice_Tripinfo::getAvgBikeTimeLoss() {
     707          207 :     if (myBikeCount > 0) {
     708          145 :         return STEPS2TIME(myTotalBikeTimeLoss / myBikeCount);
     709              :     } else {
     710              :         return 0;
     711              :     }
     712              : }
     713              : 
     714              : 
     715              : 
     716              : double
     717          594 : MSDevice_Tripinfo::getAvgWalkRouteLength() {
     718          594 :     if (myWalkCount > 0) {
     719          274 :         return myTotalWalkRouteLength / myWalkCount;
     720              :     } else {
     721              :         return 0;
     722              :     }
     723              : }
     724              : 
     725              : double
     726          594 : MSDevice_Tripinfo::getAvgWalkDuration() {
     727          594 :     if (myWalkCount > 0) {
     728          274 :         return STEPS2TIME(myTotalWalkDuration / myWalkCount);
     729              :     } else {
     730              :         return 0;
     731              :     }
     732              : }
     733              : 
     734              : 
     735              : double
     736          594 : MSDevice_Tripinfo::getAvgWalkTimeLoss() {
     737          594 :     if (myWalkCount > 0) {
     738          274 :         return STEPS2TIME(myTotalWalkTimeLoss / myWalkCount);
     739              :     } else {
     740              :         return 0;
     741              :     }
     742              : }
     743              : 
     744              : 
     745              : double
     746            0 : MSDevice_Tripinfo::getAvgRideDuration() {
     747            0 :     if (myRideCount[0] > 0) {
     748            0 :         return STEPS2TIME(myTotalRideDuration[0] / myRideCount[0]);
     749              :     } else {
     750              :         return 0;
     751              :     }
     752              : }
     753              : 
     754              : double
     755            0 : MSDevice_Tripinfo::getAvgRideWaitingTime() {
     756            0 :     if (myRideCount[0] > 0) {
     757            0 :         return STEPS2TIME(myTotalRideWaitingTime[0] / myRideCount[0]);
     758              :     } else {
     759              :         return 0;
     760              :     }
     761              : }
     762              : 
     763              : double
     764            0 : MSDevice_Tripinfo::getAvgRideRouteLength() {
     765            0 :     if (myRideCount[0] > 0) {
     766            0 :         return myTotalRideRouteLength[0] / myRideCount[0];
     767              :     } else {
     768              :         return 0;
     769              :     }
     770              : }
     771              : 
     772              : 
     773              : std::string
     774          281 : MSDevice_Tripinfo::getParameter(const std::string& key) const {
     775          281 :     if (key == toString(SUMO_ATTR_WAITINGTIME)) {
     776           52 :         return toString(STEPS2TIME(myWaitingTime));
     777          229 :     } else if (key == toString(SUMO_ATTR_WAITINGCOUNT)) {
     778           52 :         return toString(myWaitingCount);
     779          177 :     } else if (key == toString(SUMO_ATTR_STOPTIME)) {
     780           52 :         return toString(STEPS2TIME(myStoppingTime));
     781          125 :     } else if (key == toString(SUMO_ATTR_ARRIVALTIME)) {
     782           25 :         return toString(STEPS2TIME(myArrivalTime));
     783          100 :     } else if (key == toString(SUMO_ATTR_ARRIVALLANE)) {
     784           25 :         return toString(myArrivalLane);
     785           75 :     } else if (key == toString(SUMO_ATTR_ARRIVALPOS)) {
     786           25 :         return toString(myArrivalPos);
     787           50 :     } else if (key == toString(SUMO_ATTR_ARRIVALPOS_LAT)) {
     788           25 :         return toString(myArrivalPosLat);
     789           25 :     } else if (key == toString(SUMO_ATTR_ARRIVALSPEED)) {
     790           25 :         return toString(myArrivalSpeed);
     791              :     }
     792            0 :     throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
     793              : }
     794              : 
     795              : 
     796              : std::string
     797         3224 : MSDevice_Tripinfo::getGlobalParameter(const std::string& prefixedKey) {
     798              :     std::string key = prefixedKey; // by default, assume vehicleTripStatistics;
     799         3224 :     const std::string err = "Parameter '" + prefixedKey + "' is not supported for device of type 'tripinfo'";
     800         6448 :     if (StringUtils::startsWith(key, "vehicleTripStatistics.")) {
     801         1240 :         key = prefixedKey.substr(22);
     802         5208 :     } else if (StringUtils::startsWith(key, "bikeTripStatistics.")) {
     803          434 :         key = prefixedKey.substr(19);
     804          434 :         if (key == toString(SUMO_ATTR_COUNT)) {
     805           62 :             return toString(myBikeCount);
     806          372 :         } else if (key == "routeLength") {
     807           62 :             return toString(getAvgBikeRouteLength());
     808          310 :         } else if (key == toString(SUMO_ATTR_SPEED)) {
     809           62 :             return toString(getAvgBikeTripSpeed());
     810          248 :         } else if (key == toString(SUMO_ATTR_DURATION)) {
     811           62 :             return toString(getAvgBikeDuration());
     812          186 :         } else if (key == toString(SUMO_ATTR_WAITINGTIME)) {
     813           62 :             return toString(getAvgBikeWaitingTime());
     814          124 :         } else if (key == toString(SUMO_ATTR_TIMELOSS)) {
     815           62 :             return toString(getAvgBikeTimeLoss());
     816           62 :         } else if (key == "totalTravelTime") {
     817              :             // avoid human readable output
     818           62 :             return toString(STEPS2TIME((myTotalBikeDuration)));
     819              :         }
     820            0 :         throw InvalidArgument(err);
     821              : 
     822         4340 :     } else if (StringUtils::startsWith(key, "pedestrianStatistics.")) {
     823          310 :         key = prefixedKey.substr(21);
     824          558 :         if (key == toString(SUMO_ATTR_NUMBER) || key == toString(SUMO_ATTR_COUNT)) {
     825          124 :             return toString(myWalkCount);
     826          186 :         } else if (key == "routeLength") {
     827           62 :             return toString(getAvgWalkRouteLength());
     828          124 :         } else if (key == toString(SUMO_ATTR_DURATION)) {
     829           62 :             return toString(getAvgWalkDuration());
     830           62 :         } else if (key == toString(SUMO_ATTR_TIMELOSS)) {
     831           62 :             return toString(getAvgWalkTimeLoss());
     832              :         }
     833            0 :         throw InvalidArgument(err);
     834              : 
     835         3720 :     } else if (StringUtils::startsWith(key, "rideStatistics.") ||
     836         3100 :                StringUtils::startsWith(key, "transportStatistics.")) {
     837              :         int index = 0;
     838         2480 :         if (StringUtils::startsWith(key, "rideStatistics.")) {
     839         1240 :             key = prefixedKey.substr(15);
     840              :         } else {
     841              :             index = 1;
     842         1240 :             key = prefixedKey.substr(20);
     843              :         }
     844         2356 :         if (key == toString(SUMO_ATTR_NUMBER) || key == toString(SUMO_ATTR_COUNT)) {
     845          248 :             return toString(myRideCount[index]);
     846          992 :         } else if (key == toString(SUMO_ATTR_WAITINGTIME)) {
     847          124 :             return toString(STEPS2TIME(myTotalRideWaitingTime[index] / MAX2(1, myRideCount[index])));
     848          868 :         } else if (key == "routeLength") {
     849          124 :             return toString(myTotalRideRouteLength[index] / MAX2(1, myRideCount[index]));
     850          744 :         } else if (key == toString(SUMO_ATTR_DURATION)) {
     851          124 :             return toString(myTotalRideRouteLength[index] / MAX2(1, myRideCount[index]));
     852          620 :         } else if (key == "bus") {
     853          124 :             return toString(myRideBusCount[index]);
     854          496 :         } else if (key == "train") {
     855          124 :             return toString(myRideRailCount[index]);
     856          372 :         } else if (key == "taxi") {
     857          124 :             return toString(myRideTaxiCount[index]);
     858          248 :         } else if (key == "bike") {
     859          124 :             return toString(myRideBikeCount[index]);
     860          124 :         } else if (key == "aborted") {
     861          124 :             return toString(myRideAbortCount[index]);
     862              :         }
     863            0 :         throw InvalidArgument(err);
     864              :     }
     865              :     // vehicleTripStatistics
     866         1240 :     if (key == toString(SUMO_ATTR_COUNT)) {
     867          124 :         return toString(myVehicleCount);
     868         1116 :     } else if (key == "routeLength") {
     869          124 :         return toString(getAvgRouteLength());
     870          992 :     } else if (key == toString(SUMO_ATTR_SPEED)) {
     871          124 :         return toString(getAvgTripSpeed());
     872          868 :     } else if (key == toString(SUMO_ATTR_DURATION)) {
     873          124 :         return toString(getAvgDuration());
     874          744 :     } else if (key == toString(SUMO_ATTR_WAITINGTIME)) {
     875          124 :         return toString(getAvgWaitingTime());
     876          620 :     } else if (key == toString(SUMO_ATTR_TIMELOSS)) {
     877          124 :         return toString(getAvgTimeLoss());
     878          496 :     } else if (key == "departDelay") {
     879          124 :         return toString(getAvgDepartDelay());
     880          372 :     } else if (key == "departDelayWaiting") {
     881          124 :         return toString(getAvgDepartDelayWaiting());
     882          248 :     } else if (key == "totalTravelTime") {
     883              :         // avoid human readable output
     884          124 :         return toString(STEPS2TIME((myTotalDuration)));
     885          124 :     } else if (key == "totalDepartDelay") {
     886          124 :         return toString(getTotalDepartDelay());
     887              :     }
     888            0 :     throw InvalidArgument(err);
     889              : }
     890              : 
     891              : 
     892              : void
     893          152 : MSDevice_Tripinfo::saveState(OutputDevice& out) const {
     894          152 :     if (myHolder.hasDeparted()) {
     895           81 :         out.openTag(SUMO_TAG_DEVICE);
     896              :         out.writeAttr(SUMO_ATTR_ID, getID());
     897           81 :         std::ostringstream internals;
     898           81 :         internals << myDepartLane << " ";
     899           81 :         if (!MSGlobals::gUseMesoSim) {
     900           61 :             internals << myDepartPosLat << " ";
     901              :         }
     902           81 :         std::string state_arrivalLane = myArrivalLane == "" ? STATE_EMPTY_ARRIVALLANE : myArrivalLane;
     903          405 :         internals << myDepartSpeed << " " << myRouteLength << " " << myWaitingTime << " " << myAmWaiting << " " << myWaitingCount << " ";
     904          162 :         internals << myStoppingTime << " " << myParkingStarted << " ";
     905          324 :         internals << myArrivalTime << " " << state_arrivalLane << " " << myArrivalPos << " " << myArrivalPosLat << " " << myArrivalSpeed;
     906           81 :         out.writeAttr(SUMO_ATTR_STATE, internals.str());
     907          162 :         out.closeTag();
     908           81 :     }
     909          152 : }
     910              : 
     911              : 
     912              : void
     913           70 : MSDevice_Tripinfo::loadState(const SUMOSAXAttributes& attrs) {
     914           70 :     std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
     915           70 :     bis >> myDepartLane;
     916           70 :     if (!MSGlobals::gUseMesoSim) {
     917           52 :         bis >> myDepartPosLat;
     918              :     }
     919           70 :     bis >> myDepartSpeed >> myRouteLength >> myWaitingTime >> myAmWaiting >> myWaitingCount;
     920           70 :     bis >> myStoppingTime >> myParkingStarted;
     921           70 :     bis >> myArrivalTime >> myArrivalLane >> myArrivalPos >> myArrivalPosLat >> myArrivalSpeed;
     922           70 :     if (myArrivalLane == STATE_EMPTY_ARRIVALLANE) {
     923              :         myArrivalLane = "";
     924              :     }
     925           70 : }
     926              : 
     927              : 
     928              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1