LCOV - code coverage report
Current view: top level - src/microsim/output - MSMeanData.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 308 323 95.4 %
Date: 2024-05-06 15:32:35 Functions: 31 36 86.1 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2001-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    MSMeanData.cpp
      15             : /// @author  Daniel Krajzewicz
      16             : /// @author  Jakob Erdmann
      17             : /// @author  Michael Behrisch
      18             : /// @author  Laura Bieker
      19             : /// @author  Leonhard Luecken
      20             : /// @date    Mon, 10.05.2004
      21             : ///
      22             : // Data collector for edges/lanes
      23             : /****************************************************************************/
      24             : #include <config.h>
      25             : 
      26             : #include <limits>
      27             : #ifdef HAVE_FOX
      28             : #include <utils/common/ScopedLocker.h>
      29             : #endif
      30             : #include <utils/common/SUMOTime.h>
      31             : #include <utils/common/ToString.h>
      32             : #include <utils/common/StringTokenizer.h>
      33             : #include <utils/iodevices/OutputDevice.h>
      34             : #include <microsim/MSEdgeControl.h>
      35             : #include <microsim/MSEdge.h>
      36             : #include <microsim/MSLane.h>
      37             : #include <microsim/MSVehicle.h>
      38             : #include <microsim/cfmodels/MSCFModel.h>
      39             : #include <microsim/MSNet.h>
      40             : #include "MSMeanData_Amitran.h"
      41             : #include "MSMeanData.h"
      42             : 
      43             : #include <microsim/MSGlobals.h>
      44             : #include <mesosim/MESegment.h>
      45             : #include <mesosim/MELoop.h>
      46             : 
      47             : 
      48             : // ===========================================================================
      49             : // debug constants
      50             : // ===========================================================================
      51             : //#define DEBUG_NOTIFY_MOVE
      52             : //#define DEBUG_NOTIFY_ENTER
      53             : 
      54             : // ===========================================================================
      55             : // method definitions
      56             : // ===========================================================================
      57             : // ---------------------------------------------------------------------------
      58             : // MSMeanData::MeanDataValues - methods
      59             : // ---------------------------------------------------------------------------
      60    15302307 : MSMeanData::MeanDataValues::MeanDataValues(
      61             :     MSLane* const lane, const double length, const bool doAdd,
      62    15302307 :     const MSMeanData* const parent) :
      63    30604614 :     MSMoveReminder("meandata_" + (lane == nullptr ? "NULL" :  lane->getID()), lane, doAdd),
      64    15302307 :     myParent(parent),
      65    15302307 :     myLaneLength(length),
      66    15302307 :     sampleSeconds(0),
      67    45906921 :     travelledDistance(0) {}
      68             : 
      69             : 
      70    15232012 : MSMeanData::MeanDataValues::~MeanDataValues() {
      71    15232012 : }
      72             : 
      73             : 
      74             : bool
      75     1179183 : MSMeanData::MeanDataValues::notifyEnter(SUMOTrafficObject& veh, MSMoveReminder::Notification reason, const MSLane* enteredLane) {
      76             : #ifdef DEBUG_NOTIFY_ENTER
      77             :     std::cout << "\n" << SIMTIME << " MSMeanData_Net::MSLaneMeanDataValues: veh '" << veh.getID() << "' enters lane '" << enteredLane->getID() << "'" << std::endl;
      78             : #else
      79             :     UNUSED_PARAMETER(enteredLane);
      80             : #endif
      81             :     UNUSED_PARAMETER(reason);
      82     1179183 :     return myParent == nullptr || myParent->vehicleApplies(veh);
      83             : }
      84             : 
      85             : 
      86             : bool
      87   559592845 : MSMeanData::MeanDataValues::notifyMove(SUMOTrafficObject& veh, double oldPos, double newPos, double newSpeed) {
      88             :     // if the vehicle has arrived, the reminder must be kept so it can be
      89             :     // notified of the arrival subsequently
      90   559592845 :     const double oldSpeed = veh.getPreviousSpeed();
      91   559592845 :     double enterSpeed = MSGlobals::gSemiImplicitEulerUpdate ? newSpeed : oldSpeed; // NOTE: For the euler update, the vehicle is assumed to travel at constant speed for the whole time step
      92             :     double leaveSpeed = newSpeed, leaveSpeedFront = newSpeed;
      93             : 
      94             :     // These values will be further decreased below
      95   559592845 :     double timeOnLane = TS;
      96   559592845 :     double frontOnLane = oldPos > myLaneLength ? 0. : TS;
      97             :     bool ret = true;
      98             : 
      99             :     // entry and exit times (will be modified below)
     100             :     double timeBeforeEnter = 0.;
     101             :     double timeBeforeEnterBack = 0.;
     102   559592845 :     double timeBeforeLeaveFront = newPos <= myLaneLength ? TS : 0.;
     103             :     double timeBeforeLeave = TS;
     104             : 
     105             :     // Treat the case that the vehicle entered the lane in the last step
     106   559592845 :     if (oldPos < 0 && newPos >= 0) {
     107             :         // Vehicle was not on this lane in the last time step
     108     6758082 :         timeBeforeEnter = MSCFModel::passingTime(oldPos, 0, newPos, oldSpeed, newSpeed);
     109     6758082 :         timeOnLane = TS - timeBeforeEnter;
     110             :         frontOnLane = timeOnLane;
     111     6758082 :         enterSpeed = MSCFModel::speedAfterTime(timeBeforeEnter, oldSpeed, newPos - oldPos);
     112             :     }
     113             : 
     114   559592845 :     const double oldBackPos = oldPos - veh.getVehicleType().getLength();
     115   559592845 :     const double newBackPos = newPos - veh.getVehicleType().getLength();
     116             : 
     117             :     // Determine the time before the vehicle back enters
     118   559592845 :     if (oldBackPos < 0. && newBackPos > 0.) {
     119     6964292 :         timeBeforeEnterBack = MSCFModel::passingTime(oldBackPos, 0., newBackPos, oldSpeed, newSpeed);
     120   552628553 :     } else if (newBackPos <= 0) {
     121     3994890 :         timeBeforeEnterBack = TS;
     122             :     } else {
     123             :         timeBeforeEnterBack = 0.;
     124             :     }
     125             : 
     126             :     // Treat the case that the vehicle's back left the lane in the last step
     127   559592845 :     if (newBackPos > myLaneLength // vehicle's back has left the lane
     128     7445858 :             && oldBackPos <= myLaneLength) { // and hasn't left the lane before
     129             :         assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the lane boundary otherwise
     130             :         // (Leo) vehicle left this lane (it can also have skipped over it in one time step -> therefore we use "timeOnLane -= ..." and ( ... - timeOnLane) below)
     131     7445858 :         timeBeforeLeave = MSCFModel::passingTime(oldBackPos, myLaneLength, newBackPos, oldSpeed, newSpeed);
     132     7445858 :         const double timeAfterLeave = TS - timeBeforeLeave;
     133     7445858 :         timeOnLane -= timeAfterLeave;
     134     7445858 :         leaveSpeed = MSCFModel::speedAfterTime(timeBeforeLeave, oldSpeed, newPos - oldPos);
     135             :         // XXX: Do we really need this? Why would this "reduce rounding errors"? (Leo) Refs. #2579
     136     7445858 :         if (fabs(timeOnLane) < NUMERICAL_EPS) { // reduce rounding errors
     137             :             timeOnLane = 0.;
     138             :         }
     139     7445858 :         ret = veh.hasArrived();
     140             :     }
     141             : 
     142             :     // Treat the case that the vehicle's front left the lane in the last step
     143   559592845 :     if (newPos > myLaneLength && oldPos <= myLaneLength) {
     144             :         // vehicle's front has left the lane and has not left before
     145             :         assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0);
     146     7970444 :         timeBeforeLeaveFront = MSCFModel::passingTime(oldPos, myLaneLength, newPos, oldSpeed, newSpeed);
     147     7970444 :         const double timeAfterLeave = TS - timeBeforeLeaveFront;
     148     7970444 :         frontOnLane -= timeAfterLeave;
     149             :         // XXX: Do we really need this? Why would this "reduce rounding errors"? (Leo) Refs. #2579
     150     7970444 :         if (fabs(frontOnLane) < NUMERICAL_EPS) { // reduce rounding errors
     151             :             frontOnLane = 0.;
     152             :         }
     153     7970444 :         leaveSpeedFront = MSCFModel::speedAfterTime(timeBeforeLeaveFront, oldSpeed, newPos - oldPos);
     154             :     }
     155             : 
     156             :     assert(frontOnLane <= TS);
     157             :     assert(timeOnLane <= TS);
     158             : 
     159   559592845 :     if (timeOnLane < 0) {
     160           0 :         WRITE_ERRORF(TL("Negative vehicle step fraction for '%' on lane '%'."), veh.getID(), getLane()->getID());
     161           0 :         return veh.hasArrived();
     162             :     }
     163   559592845 :     if (timeOnLane == 0) {
     164       27086 :         return veh.hasArrived();
     165             :     }
     166             : 
     167             : #ifdef DEBUG_NOTIFY_MOVE
     168             :     std::stringstream ss;
     169             :     ss << "\n"
     170             :        << "lane length: " << myLaneLength
     171             :        << "\noldPos: " << oldPos
     172             :        << "\nnewPos: " << newPos
     173             :        << "\noldPosBack: " << oldBackPos
     174             :        << "\nnewPosBack: " << newBackPos
     175             :        << "\ntimeBeforeEnter: " << timeBeforeEnter
     176             :        << "\ntimeBeforeEnterBack: " << timeBeforeEnterBack
     177             :        << "\ntimeBeforeLeaveFront: " << timeBeforeLeaveFront
     178             :        << "\ntimeBeforeLeave: " << timeBeforeLeave;
     179             :     if (!(timeBeforeLeave >= MAX2(timeBeforeEnterBack, timeBeforeLeaveFront))
     180             :             || !(timeBeforeEnter <= MIN2(timeBeforeEnterBack, timeBeforeLeaveFront))) {
     181             :         WRITE_ERROR(ss.str());
     182             :     } else {
     183             :         std::cout << ss.str() << std::endl;
     184             :     }
     185             : 
     186             : #endif
     187             : 
     188             :     assert(timeBeforeEnter <= MIN2(timeBeforeEnterBack, timeBeforeLeaveFront));
     189             :     assert(timeBeforeLeave >= MAX2(timeBeforeEnterBack, timeBeforeLeaveFront));
     190             :     // compute average vehicle length on lane in last step
     191   559565759 :     double vehLength = veh.getVehicleType().getLength();
     192             :     // occupied lane length at timeBeforeEnter (resp. stepStart if already on lane)
     193   559565759 :     double lengthOnLaneAtStepStart = MAX2(0., MIN4(myLaneLength, vehLength, vehLength - (oldPos - myLaneLength), oldPos));
     194             :     // occupied lane length at timeBeforeLeave (resp. stepEnd if still on lane)
     195   559565759 :     double lengthOnLaneAtStepEnd = MAX2(0., MIN4(myLaneLength, vehLength, vehLength - (newPos - myLaneLength), newPos));
     196             :     double integratedLengthOnLane = 0.;
     197   559565759 :     if (timeBeforeEnterBack < timeBeforeLeaveFront) {
     198             :         // => timeBeforeLeaveFront>0, myLaneLength>vehLength
     199             :         // vehicle length on detector at timeBeforeEnterBack
     200   551512207 :         double lengthOnLaneAtBackEnter = MIN2(veh.getVehicleType().getLength(), newPos);
     201             :         // linear quadrature of occupancy between timeBeforeEnter and timeBeforeEnterBack
     202   551512207 :         integratedLengthOnLane += (timeBeforeEnterBack - timeBeforeEnter) * (lengthOnLaneAtBackEnter + lengthOnLaneAtStepStart) * 0.5;
     203             :         // linear quadrature of occupancy between timeBeforeEnterBack and timeBeforeLeaveFront
     204             :         // (vehicle is completely on the edge in between)
     205   551512207 :         integratedLengthOnLane += (timeBeforeLeaveFront - timeBeforeEnterBack) * vehLength;
     206             :         // and until vehicle leaves/stepEnd
     207   551512207 :         integratedLengthOnLane += (timeBeforeLeave - timeBeforeLeaveFront) * (vehLength + lengthOnLaneAtStepEnd) * 0.5;
     208     8053552 :     } else if (timeBeforeEnterBack >= timeBeforeLeaveFront) {
     209             :         // => myLaneLength <= vehLength or (timeBeforeLeaveFront == timeBeforeEnterBack == 0)
     210             :         // vehicle length on detector at timeBeforeLeaveFront
     211             :         double lengthOnLaneAtLeaveFront;
     212     8053552 :         if (timeBeforeLeaveFront == timeBeforeEnter) {
     213             :             // for the case that front already left
     214             :             lengthOnLaneAtLeaveFront = lengthOnLaneAtStepStart;
     215     4034783 :         } else if (timeBeforeLeaveFront == timeBeforeLeave) {
     216             :             // for the case that front doesn't leave in this step
     217             :             lengthOnLaneAtLeaveFront = lengthOnLaneAtStepEnd;
     218             :         } else {
     219             :             lengthOnLaneAtLeaveFront = myLaneLength;
     220             :         }
     221             : #ifdef DEBUG_NOTIFY_MOVE
     222             :         std::cout << "lengthOnLaneAtLeaveFront=" << lengthOnLaneAtLeaveFront << std::endl;
     223             : #endif
     224             :         // linear quadrature of occupancy between timeBeforeEnter and timeBeforeLeaveFront
     225     8053552 :         integratedLengthOnLane += (timeBeforeLeaveFront - timeBeforeEnter) * (lengthOnLaneAtLeaveFront + lengthOnLaneAtStepStart) * 0.5;
     226             :         // linear quadrature of occupancy between timeBeforeLeaveFront and timeBeforeEnterBack
     227     8053552 :         integratedLengthOnLane += (timeBeforeEnterBack - timeBeforeLeaveFront) * lengthOnLaneAtLeaveFront;
     228             :         // and until vehicle leaves/stepEnd
     229     8053552 :         integratedLengthOnLane += (timeBeforeLeave - timeBeforeEnterBack) * (lengthOnLaneAtLeaveFront + lengthOnLaneAtStepEnd) * 0.5;
     230             :     }
     231             : 
     232   559565759 :     double meanLengthOnLane = integratedLengthOnLane / TS;
     233             : #ifdef DEBUG_NOTIFY_MOVE
     234             :     std::cout << "Calculated mean length on lane '" << myLane->getID() << "' in last step as " << meanLengthOnLane
     235             :               << "\nlengthOnLaneAtStepStart=" << lengthOnLaneAtStepStart << ", lengthOnLaneAtStepEnd=" << lengthOnLaneAtStepEnd << ", integratedLengthOnLane=" << integratedLengthOnLane
     236             :               << std::endl;
     237             : #endif
     238             : 
     239             : //    // XXX: use this, when #2556 is fixed! Refs. #2575
     240             : //    const double travelledDistanceFrontOnLane = MAX2(0., MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.));
     241             : //    const double travelledDistanceVehicleOnLane = MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.) + MIN2(MAX2(0., newPos - myLaneLength), veh.getVehicleType().getLength());
     242             : //    // XXX: #2556 fixed for ballistic update
     243   559565759 :     const double travelledDistanceFrontOnLane = MSGlobals::gSemiImplicitEulerUpdate ? frontOnLane * newSpeed
     244   161137220 :             : MAX2(0., MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.));
     245   640134369 :     const double travelledDistanceVehicleOnLane = MSGlobals::gSemiImplicitEulerUpdate ? timeOnLane * newSpeed
     246   161137220 :             : MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.) + MIN2(MAX2(0., newPos - myLaneLength), veh.getVehicleType().getLength());
     247             : //    // XXX: no fix
     248             : //    const double travelledDistanceFrontOnLane = frontOnLane*newSpeed;
     249             : //    const double travelledDistanceVehicleOnLane = timeOnLane*newSpeed;
     250             : 
     251             : #ifdef HAVE_FOX
     252   559565759 :     ScopedLocker<> lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
     253             : #endif
     254   559565759 :     notifyMoveInternal(veh, frontOnLane, timeOnLane, (enterSpeed + leaveSpeedFront) / 2., (enterSpeed + leaveSpeed) / 2., travelledDistanceFrontOnLane, travelledDistanceVehicleOnLane, meanLengthOnLane);
     255             :     return ret;
     256             : }
     257             : 
     258             : 
     259             : bool
     260     2018735 : MSMeanData::MeanDataValues::notifyLeave(SUMOTrafficObject& /*veh*/, double /*lastPos*/, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
     261     2018735 :     if (MSGlobals::gUseMesoSim) {
     262             :         return false; // reminder is re-added on every segment (@recheck for performance)
     263             :     }
     264     1918729 :     return reason == MSMoveReminder::NOTIFICATION_JUNCTION;
     265             : }
     266             : 
     267             : 
     268             : bool
     269     2959979 : MSMeanData::MeanDataValues::isEmpty() const {
     270     2959979 :     return sampleSeconds == 0;
     271             : }
     272             : 
     273             : 
     274             : void
     275           0 : MSMeanData::MeanDataValues::update() {
     276           0 : }
     277             : 
     278             : 
     279             : double
     280     1036149 : MSMeanData::MeanDataValues::getSamples() const {
     281     1036149 :     return sampleSeconds;
     282             : }
     283             : 
     284             : 
     285             : // ---------------------------------------------------------------------------
     286             : // MSMeanData::MeanDataValueTracker - methods
     287             : // ---------------------------------------------------------------------------
     288        2672 : MSMeanData::MeanDataValueTracker::MeanDataValueTracker(MSLane* const lane,
     289             :         const double length,
     290        2672 :         const MSMeanData* const parent)
     291        2672 :     : MSMeanData::MeanDataValues(lane, length, true, parent) {
     292        2672 :     myCurrentData.push_back(new TrackerEntry(parent->createValues(lane, length, false)));
     293        2672 : }
     294             : 
     295             : 
     296        5344 : MSMeanData::MeanDataValueTracker::~MeanDataValueTracker() {
     297             :     std::list<TrackerEntry*>::iterator i;
     298       28928 :     for (i = myCurrentData.begin(); i != myCurrentData.end(); i++) {
     299       26256 :         delete *i;
     300             :     }
     301             : 
     302             :     // FIXME: myTrackedData may still hold some undeleted TrackerEntries. When to delete those? (Leo), refers to #2251
     303             :     // code below fails
     304             : 
     305             : //      std::map<SUMOTrafficObject*, TrackerEntry*>::iterator j;
     306             : //      for(j=myTrackedData.begin(); j!=myTrackedData.end();j++){
     307             : //              delete j->second;
     308             : //      }
     309        5344 : }
     310             : 
     311             : 
     312             : void
     313      164160 : MSMeanData::MeanDataValueTracker::reset(bool afterWrite) {
     314      164160 :     if (afterWrite) {
     315       70288 :         if (myCurrentData.begin() != myCurrentData.end()) {
     316             :             // delete myCurrentData.front();
     317       70288 :             myCurrentData.pop_front();
     318             :         }
     319             :     } else {
     320       93872 :         myCurrentData.push_back(new TrackerEntry(myParent->createValues(myLane, myLaneLength, false)));
     321             :     }
     322      164160 : }
     323             : 
     324             : 
     325             : void
     326           0 : MSMeanData::MeanDataValueTracker::addTo(MSMeanData::MeanDataValues& val) const {
     327           0 :     myCurrentData.front()->myValues->addTo(val);
     328           0 : }
     329             : 
     330             : 
     331             : void
     332       14872 : MSMeanData::MeanDataValueTracker::notifyMoveInternal(const SUMOTrafficObject& veh, const double frontOnLane, const double timeOnLane, const double meanSpeedFrontOnLane, const double meanSpeedVehicleOnLane, const double travelledDistanceFrontOnLane, const double travelledDistanceVehicleOnLane, const double meanLengthOnLane) {
     333       14872 :     myTrackedData[&veh]->myValues->notifyMoveInternal(veh, frontOnLane, timeOnLane, meanSpeedFrontOnLane, meanSpeedVehicleOnLane, travelledDistanceFrontOnLane, travelledDistanceVehicleOnLane, meanLengthOnLane);
     334       14872 : }
     335             : 
     336             : 
     337             : bool
     338         760 : MSMeanData::MeanDataValueTracker::notifyLeave(SUMOTrafficObject& veh, double lastPos, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
     339         760 :     if (myParent == nullptr || reason != MSMoveReminder::NOTIFICATION_SEGMENT) {
     340         360 :         myTrackedData[&veh]->myNumVehicleLeft++;
     341             :     }
     342         760 :     return myTrackedData[&veh]->myValues->notifyLeave(veh, lastPos, reason);
     343             : }
     344             : 
     345             : 
     346             : bool
     347        1220 : MSMeanData::MeanDataValueTracker::notifyEnter(SUMOTrafficObject& veh, MSMoveReminder::Notification reason, const MSLane* enteredLane) {
     348             : #ifdef DEBUG_NOTIFY_ENTER
     349             :     std::cout << "\n" << SIMTIME << " MSMeanData::MeanDataValueTracker: veh '" << veh.getID() << "' enters lane '" << enteredLane->getID() << "'" << std::endl;
     350             : #else
     351             :     UNUSED_PARAMETER(enteredLane);
     352             : #endif
     353        1220 :     if (reason == MSMoveReminder::NOTIFICATION_SEGMENT) {
     354             :         return true;
     355             :     }
     356        1420 :     if (myParent->vehicleApplies(veh) && myTrackedData.find(&veh) == myTrackedData.end()) {
     357         480 :         myTrackedData[&veh] = myCurrentData.back();
     358         480 :         myTrackedData[&veh]->myNumVehicleEntered++;
     359         480 :         if (!myTrackedData[&veh]->myValues->notifyEnter(veh, reason)) {
     360           0 :             myTrackedData[&veh]->myNumVehicleLeft++;
     361           0 :             myTrackedData.erase(&veh);
     362           0 :             return false;
     363             :         }
     364             :         return true;
     365             :     }
     366             :     return false;
     367             : }
     368             : 
     369             : 
     370             : bool
     371       91696 : MSMeanData::MeanDataValueTracker::isEmpty() const {
     372       91696 :     return myCurrentData.front()->myValues->isEmpty();
     373             : }
     374             : 
     375             : 
     376             : void
     377         296 : MSMeanData::MeanDataValueTracker::write(OutputDevice& dev,
     378             :                                         long long int attributeMask,
     379             :                                         const SUMOTime period,
     380             :                                         const int numLanes,
     381             :                                         const double speedLimit,
     382             :                                         const double defaultTravelTime,
     383             :                                         const int /*numVehicles*/) const {
     384         296 :     myCurrentData.front()->myValues->write(dev, attributeMask, period, numLanes, speedLimit,
     385             :                                            defaultTravelTime,
     386             :                                            myCurrentData.front()->myNumVehicleEntered);
     387         296 : }
     388             : 
     389             : 
     390             : int
     391       63044 : MSMeanData::MeanDataValueTracker::getNumReady() const {
     392             :     int result = 0;
     393     1444912 :     for (std::list<TrackerEntry*>::const_iterator it = myCurrentData.begin(); it != myCurrentData.end(); ++it) {
     394     1384520 :         if ((*it)->myNumVehicleEntered == (*it)->myNumVehicleLeft) {
     395     1381868 :             result++;
     396             :         } else {
     397             :             break;
     398             :         }
     399             :     }
     400       63044 :     return result;
     401             : }
     402             : 
     403             : 
     404             : double
     405         296 : MSMeanData::MeanDataValueTracker::getSamples() const {
     406         296 :     return myCurrentData.front()->myValues->getSamples();
     407             : }
     408             : 
     409             : 
     410             : // ---------------------------------------------------------------------------
     411             : // MSMeanData - methods
     412             : // ---------------------------------------------------------------------------
     413        5903 : MSMeanData::MSMeanData(const std::string& id,
     414             :                        const SUMOTime dumpBegin, const SUMOTime dumpEnd,
     415             :                        const bool useLanes, const bool withEmpty,
     416             :                        const bool printDefaults, const bool withInternal,
     417             :                        const bool trackVehicles,
     418             :                        const int detectPersons,
     419             :                        const double maxTravelTime,
     420             :                        const double minSamples,
     421             :                        const std::string& vTypes,
     422             :                        const std::string& writeAttributes,
     423             :                        const std::vector<MSEdge*>& edges,
     424        5903 :                        bool aggregate) :
     425             :     MSDetectorFileOutput(id, vTypes, "", detectPersons),
     426        5903 :     myMinSamples(minSamples),
     427        5903 :     myMaxTravelTime(maxTravelTime),
     428        5903 :     myDumpEmpty(withEmpty),
     429        5903 :     myAmEdgeBased(!useLanes),
     430        5903 :     myDumpBegin(dumpBegin),
     431        5903 :     myDumpEnd(dumpEnd),
     432        5903 :     myInitTime(SUMOTime_MAX),
     433        5903 :     myEdges(edges),
     434        5903 :     myPrintDefaults(printDefaults),
     435        5903 :     myDumpInternal(withInternal),
     436        5903 :     myTrackVehicles(trackVehicles),
     437        5903 :     myWrittenAttributes(initWrittenAttributes(writeAttributes, id)),
     438       17709 :     myAggregate(aggregate)
     439        5903 : { }
     440             : 
     441             : 
     442             : void
     443        5426 : MSMeanData::init() {
     444        5426 :     myInitTime = MSNet::getInstance()->getCurrentTimeStep();
     445        5426 :     if (myEdges.empty()) {
     446             :         // use all edges by default
     447      194154 :         for (MSEdge* const edge : MSNet::getInstance()->getEdgeControl().getEdges()) {
     448      188777 :             if ((myDumpInternal || !edge->isInternal()) &&
     449      161124 :                     ((detectPersons() && myDumpInternal) || (!edge->isCrossing() && !edge->isWalkingArea()))) {
     450      160552 :                 myEdges.push_back(edge);
     451             :             }
     452             :         }
     453             :     }
     454             :     int index = 0;
     455      166067 :     for (MSEdge* edge : myEdges) {
     456      160641 :         myMeasures.push_back(std::vector<MeanDataValues*>());
     457      160641 :         myEdgeIndex[edge] = index++;
     458      160641 :         const std::vector<MSLane*>& lanes = edge->getLanes();
     459      160641 :         if (MSGlobals::gUseMesoSim) {
     460             :             MeanDataValues* data;
     461       29149 :             if (!myAmEdgeBased) {
     462          77 :                 for (MSLane* const lane : lanes) {
     463          46 :                     data = createValues(lane, lanes[0]->getLength(), false);
     464          46 :                     myMeasures.back().push_back(data);
     465          46 :                     MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
     466         292 :                     while (s != nullptr) {
     467         246 :                         s->addDetector(data, lane->getIndex());
     468         246 :                         s->prepareDetectorForWriting(*data, lane->getIndex());
     469             :                         s = s->getNextSegment();
     470             :                     }
     471          46 :                     data->reset();
     472          46 :                     data->reset(true);
     473             :                 }
     474             :             } else {
     475       29118 :                 if (myTrackVehicles) {
     476         880 :                     data = new MeanDataValueTracker(nullptr, lanes[0]->getLength(), this);
     477             :                 } else {
     478       28238 :                     data = createValues(nullptr, lanes[0]->getLength(), false);
     479             :                 }
     480       58236 :                 data->setDescription("meandata_" + edge->getID());
     481       29118 :                 myMeasures.back().push_back(data);
     482       29118 :                 MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
     483      146490 :                 while (s != nullptr) {
     484      117372 :                     s->addDetector(data);
     485      117372 :                     s->prepareDetectorForWriting(*data);
     486             :                     s = s->getNextSegment();
     487             :                 }
     488       29118 :                 data->reset();
     489       29118 :                 data->reset(true);
     490             :             }
     491             :             continue;
     492       29149 :         }
     493      131492 :         if (myAmEdgeBased && myTrackVehicles) {
     494         912 :             myMeasures.back().push_back(new MeanDataValueTracker(nullptr, lanes[0]->getLength(), this));
     495             :         }
     496      273256 :         for (MSLane* const lane : lanes) {
     497      141764 :             if (myTrackVehicles) {
     498        1920 :                 if (myAmEdgeBased) {
     499        1040 :                     lane->addMoveReminder(myMeasures.back().back());
     500             :                 } else {
     501         880 :                     myMeasures.back().push_back(new MeanDataValueTracker(lane, lane->getLength(), this));
     502             :                 }
     503             :             } else {
     504      139844 :                 myMeasures.back().push_back(createValues(lane, lane->getLength(), true));
     505             :             }
     506             :         }
     507             :     }
     508        5426 : }
     509             : 
     510             : 
     511        5902 : MSMeanData::~MSMeanData() {
     512      166538 :     for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
     513      331431 :         for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
     514      170795 :             delete *j;
     515             :         }
     516             :     }
     517        5902 : }
     518             : 
     519             : 
     520             : void
     521       11148 : MSMeanData::resetOnly(SUMOTime stopTime) {
     522             :     UNUSED_PARAMETER(stopTime);
     523       11148 :     if (MSGlobals::gUseMesoSim) {
     524             :         MSEdgeVector::iterator edge = myEdges.begin();
     525      116756 :         for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i, ++edge) {
     526      113232 :             MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(**edge);
     527      226464 :             for (MeanDataValues* data : *i) {
     528      601214 :                 while (s != nullptr) {
     529      487982 :                     s->prepareDetectorForWriting(*data);
     530             :                     s = s->getNextSegment();
     531             :                 }
     532      113232 :                 data->reset();
     533             :             }
     534             :         }
     535             :         return;
     536             :     }
     537      239193 :     for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
     538      477258 :         for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
     539      245689 :             (*j)->reset();
     540             :         }
     541             :     }
     542             : }
     543             : 
     544             : 
     545             : std::string
     546    16391872 : MSMeanData::getEdgeID(const MSEdge* const edge) {
     547    16391872 :     return edge->getID();
     548             : }
     549             : 
     550             : 
     551             : void
     552          36 : MSMeanData::writeAggregated(OutputDevice& dev, SUMOTime startTime, SUMOTime stopTime) {
     553          36 :     if (myTrackVehicles) {
     554           0 :         throw ProcessError(TL("aggregated meanData output not yet implemented for trackVehicles"));
     555             :     }
     556             : 
     557             :     double edgeLengthSum = 0;
     558             :     int laneNumber = 0;
     559             :     double speedSum = 0;
     560             :     double totalTT = 0;
     561        1620 :     for (MSEdge* edge : myEdges) {
     562        1584 :         edgeLengthSum += edge->getLength();
     563        1584 :         laneNumber += edge->getNumLanes();
     564        1584 :         speedSum += edge->getSpeedLimit();
     565        1584 :         totalTT += edge->getLength() / edge->getSpeedLimit();
     566             :     }
     567          36 :     MeanDataValues* sumData = createValues(nullptr, edgeLengthSum, false);
     568        1620 :     for (const std::vector<MeanDataValues*>& edgeValues : myMeasures) {
     569        3168 :         for (MeanDataValues* meanData : edgeValues) {
     570        1584 :             meanData->addTo(*sumData);
     571        1584 :             if (!MSNet::getInstance()->skipFinalReset()) {
     572        1584 :                 meanData->reset();
     573             :             }
     574             :         }
     575             :     }
     576          36 :     if (MSGlobals::gUseMesoSim) {
     577         540 :         for (MSEdge* edge : myEdges) {
     578         528 :             MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
     579        2640 :             while (s != nullptr) {
     580        2112 :                 s->prepareDetectorForWriting(*sumData);
     581             :                 s = s->getNextSegment();
     582             :             }
     583             :         }
     584             :     }
     585             : 
     586          72 :     if (writePrefix(dev, *sumData, SUMO_TAG_EDGE, "AGGREGATED")) {
     587          36 :         dev.writeAttr(SUMO_ATTR_NUMEDGES, myEdges.size());
     588          36 :         sumData->write(dev, myWrittenAttributes, stopTime - startTime, laneNumber, speedSum / (double)myEdges.size(),
     589          36 :                        myPrintDefaults ? totalTT : -1.);
     590             :     }
     591          36 :     delete sumData;
     592          36 : }
     593             : 
     594             : 
     595             : void
     596    31025959 : MSMeanData::writeEdge(OutputDevice& dev,
     597             :                       const std::vector<MeanDataValues*>& edgeValues,
     598             :                       const MSEdge* const edge, SUMOTime startTime, SUMOTime stopTime) {
     599    31025959 :     if (MSGlobals::gUseMesoSim) {
     600             :         int idx = 0;
     601     2722789 :         for (MeanDataValues* const data : edgeValues) {
     602     1361402 :             MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
     603     6991444 :             while (s != nullptr) {
     604     5630288 :                 s->prepareDetectorForWriting(*data, myAmEdgeBased ? -1 : idx);
     605             :                 s = s->getNextSegment();
     606             :             }
     607     1361402 :             idx++;
     608             :         }
     609     1361387 :         if (myAmEdgeBased) {
     610     1361356 :             MeanDataValues* data = edgeValues.front();
     611     2722712 :             if (writePrefix(dev, *data, SUMO_TAG_EDGE, getEdgeID(edge))) {
     612       60304 :                 data->write(dev, myWrittenAttributes, stopTime - startTime,
     613             :                             (int)edge->getLanes().size(),
     614             :                             edge->getSpeedLimit(),
     615       60304 :                             myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
     616             :             }
     617     1361356 :             if (!MSNet::getInstance()->skipFinalReset()) {
     618     1361356 :                 data->reset(true);
     619             :             }
     620             :             return;
     621             :         }
     622             :     }
     623             :     std::vector<MeanDataValues*>::const_iterator lane;
     624    29664603 :     if (!myAmEdgeBased) {
     625    14608647 :         bool writeCheck = myDumpEmpty;
     626    14608647 :         if (!writeCheck) {
     627    28829504 :             for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
     628    14608534 :                 if (!(*lane)->isEmpty()) {
     629             :                     writeCheck = true;
     630             :                     break;
     631             :                 }
     632             :             }
     633             :         }
     634    14608647 :         if (writeCheck) {
     635      775354 :             dev.openTag(SUMO_TAG_EDGE).writeAttr(SUMO_ATTR_ID, edge->getID());
     636             :         }
     637    29230689 :         for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
     638    14622042 :             MeanDataValues& meanData = **lane;
     639    29244084 :             if (writePrefix(dev, meanData, SUMO_TAG_LANE, meanData.getLane()->getID())) {
     640      389857 :                 meanData.write(dev, myWrittenAttributes, stopTime - startTime, 1, meanData.getLane()->getSpeedLimit(),
     641      389857 :                                myPrintDefaults ? meanData.getLane()->getLength() / meanData.getLane()->getSpeedLimit() : -1.);
     642             :             }
     643    14622042 :             if (!MSNet::getInstance()->skipFinalReset()) {
     644    14622042 :                 meanData.reset(true);
     645             :             }
     646             :         }
     647    14608647 :         if (writeCheck) {
     648      775354 :             dev.closeTag();
     649             :         }
     650             :     } else {
     651    15055956 :         if (myTrackVehicles) {
     652       22416 :             MeanDataValues& meanData = **edgeValues.begin();
     653       44832 :             if (writePrefix(dev, meanData, SUMO_TAG_EDGE, edge->getID())) {
     654         136 :                 meanData.write(dev, myWrittenAttributes, stopTime - startTime, (int)edge->getLanes().size(), edge->getSpeedLimit(),
     655         136 :                                myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
     656             :             }
     657       22416 :             if (!MSNet::getInstance()->skipFinalReset()) {
     658       22416 :                 meanData.reset(true);
     659             :             }
     660             :         } else {
     661    15033540 :             MeanDataValues* sumData = createValues(nullptr, edge->getLength(), false);
     662    30131633 :             for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
     663    15098093 :                 MeanDataValues& meanData = **lane;
     664    15098093 :                 meanData.addTo(*sumData);
     665    15098093 :                 if (!MSNet::getInstance()->skipFinalReset()) {
     666    15098093 :                     meanData.reset();
     667             :                 }
     668             :             }
     669    30067080 :             if (writePrefix(dev, *sumData, SUMO_TAG_EDGE, getEdgeID(edge))) {
     670      545937 :                 sumData->write(dev, myWrittenAttributes, stopTime - startTime, (int)edge->getLanes().size(), edge->getSpeedLimit(),
     671      545937 :                                myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
     672             :             }
     673    15033538 :             delete sumData;
     674             :         }
     675             :     }
     676             : }
     677             : 
     678             : 
     679             : void
     680      719735 : MSMeanData::openInterval(OutputDevice& dev, const SUMOTime startTime, const SUMOTime stopTime) {
     681     2159205 :     dev.openTag(SUMO_TAG_INTERVAL).writeAttr(SUMO_ATTR_BEGIN, time2string(startTime)).writeAttr(SUMO_ATTR_END, time2string(stopTime));
     682      719735 :     dev.writeAttr(SUMO_ATTR_ID, myID);
     683      719735 : }
     684             : 
     685             : 
     686             : bool
     687    31036366 : MSMeanData::writePrefix(OutputDevice& dev, const MeanDataValues& values, const SumoXMLTag tag, const std::string id) const {
     688    31036366 :     if (myDumpEmpty || !values.isEmpty()) {
     689      993550 :         dev.openTag(tag);
     690             :         dev.writeAttr(SUMO_ATTR_ID, id);
     691      993550 :         dev.writeOptionalAttr(SUMO_ATTR_SAMPLEDSECONDS, values.getSamples(), myWrittenAttributes);
     692      993550 :         return true;
     693             :     }
     694             :     return false;
     695             : }
     696             : 
     697             : 
     698             : void
     699      729551 : MSMeanData::writeXMLOutput(OutputDevice& dev,
     700             :                            SUMOTime startTime, SUMOTime stopTime) {
     701             :     // check whether this dump shall be written for the current time
     702      729551 :     int numReady = myDumpBegin < stopTime && myDumpEnd - DELTA_T >= startTime ? 1 : 0;
     703      729551 :     if (myTrackVehicles && myDumpBegin < stopTime) {
     704        2120 :         myPendingIntervals.push_back(std::make_pair(startTime, stopTime));
     705        2120 :         numReady = (int)myPendingIntervals.size();
     706       63260 :         for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
     707      124184 :             for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
     708       63044 :                 numReady = MIN2(numReady, ((MeanDataValueTracker*)*j)->getNumReady());
     709       63044 :                 if (numReady == 0) {
     710             :                     break;
     711             :                 }
     712             :             }
     713       63044 :             if (numReady == 0) {
     714             :                 break;
     715             :             }
     716             :         }
     717             :     }
     718      729551 :     const bool partialInterval = startTime < myInitTime;
     719      729551 :     if (numReady == 0 || myTrackVehicles || partialInterval) {
     720       11148 :         resetOnly(stopTime);
     721             :     }
     722      729551 :     if (partialInterval) {
     723             :         return;
     724             :     }
     725     1449530 :     while (numReady-- > 0) {
     726      719987 :         if (!myPendingIntervals.empty()) {
     727        1584 :             startTime = myPendingIntervals.front().first;
     728        1584 :             stopTime = myPendingIntervals.front().second;
     729        1584 :             myPendingIntervals.pop_front();
     730             :         }
     731      719987 :         openInterval(dev, startTime, stopTime);
     732      719987 :         if (myAggregate) {
     733          36 :             writeAggregated(dev, startTime, stopTime);
     734             :         } else {
     735             :             MSEdgeVector::const_iterator edge = myEdges.begin();
     736    31745908 :             for (const std::vector<MeanDataValues*>& measures : myMeasures) {
     737    31025959 :                 writeEdge(dev, measures, *edge, startTime, stopTime);
     738             :                 ++edge;
     739             :             }
     740             :         }
     741     1439970 :         dev.closeTag();
     742             :     }
     743             :     dev.flush();
     744             : }
     745             : 
     746             : 
     747             : void
     748        5402 : MSMeanData::writeXMLDetectorProlog(OutputDevice& dev) const {
     749       16206 :     dev.writeXMLHeader("meandata", "meandata_file.xsd");
     750        5402 : }
     751             : 
     752             : 
     753             : void
     754     8622907 : MSMeanData::detectorUpdate(const SUMOTime step) {
     755     8622907 :     if (step + DELTA_T == myDumpBegin) {
     756         619 :         init();
     757             :     }
     758     8622907 : }
     759             : 
     760             : 
     761             : long long int
     762        5903 : MSMeanData::initWrittenAttributes(const std::string writeAttributes, const std::string& id) {
     763             :     long long int result = 0;
     764        6085 :     for (std::string attrName : StringTokenizer(writeAttributes).getVector()) {
     765         150 :         if (!SUMOXMLDefinitions::Attrs.hasString(attrName)) {
     766           0 :             WRITE_ERRORF(TL("Unknown attribute '%' to write in meanData '%'."), attrName, id);
     767             :             continue;
     768             :         }
     769         150 :         int attr = SUMOXMLDefinitions::Attrs.get(attrName);
     770             :         assert(attr < 63);
     771         150 :         result |= ((long long int)1 << attr);
     772        5903 :     }
     773        5903 :     return result;
     774             : }
     775             : 
     776             : const std::vector<MSMeanData::MeanDataValues*>*
     777           0 : MSMeanData::getEdgeValues(const MSEdge* edge) const {
     778             :     auto it = myEdgeIndex.find(edge);
     779           0 :     if (it != myEdgeIndex.end()) {
     780           0 :         return &myMeasures[it->second];
     781             :     } else {
     782             :         return nullptr;
     783             :     }
     784             : }
     785             : 
     786             : /****************************************************************************/

Generated by: LCOV version 1.14