LCOV - code coverage report
Current view: top level - src/microsim/devices - MSDevice_Tripinfo.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 472 486 97.1 %
Date: 2024-04-30 15:40:33 Functions: 41 44 93.2 %

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

Generated by: LCOV version 1.14