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

            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      9019860 : MSMeanData::MeanDataValues::MeanDataValues(
      61              :     MSLane* const lane, const double length, const bool doAdd,
      62      9019860 :     const MSMeanData* const parent) :
      63      9019860 :     MSMoveReminder("meandata_" + (lane == nullptr ? "NULL" :  lane->getID()), lane, doAdd),
      64      9019860 :     myParent(parent),
      65      9019860 :     myLaneLength(length),
      66      9019860 :     sampleSeconds(0),
      67     27059580 :     travelledDistance(0) {}
      68              : 
      69              : 
      70      8946510 : MSMeanData::MeanDataValues::~MeanDataValues() {
      71      8946510 : }
      72              : 
      73              : 
      74              : bool
      75       610597 : 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       610597 :     return myParent == nullptr || myParent->vehicleApplies(veh);
      83              : }
      84              : 
      85              : 
      86              : bool
      87    441609540 : 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    441609540 :     const double oldSpeed = veh.getPreviousSpeed();
      91    441609540 :     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    441609540 :     double timeOnLane = TS;
      96    441609540 :     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    441609540 :     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    441609540 :     if (oldPos < 0 && newPos >= 0) {
     107              :         // Vehicle was not on this lane in the last time step
     108      9785196 :         timeBeforeEnter = MSCFModel::passingTime(oldPos, 0, newPos, oldSpeed, newSpeed);
     109      9785196 :         timeOnLane = TS - timeBeforeEnter;
     110              :         frontOnLane = timeOnLane;
     111      9785196 :         enterSpeed = MSCFModel::speedAfterTime(timeBeforeEnter, oldSpeed, newPos - oldPos);
     112              :     }
     113              : 
     114    441609540 :     const double oldBackPos = oldPos - veh.getVehicleType().getLength();
     115    441609540 :     const double newBackPos = newPos - veh.getVehicleType().getLength();
     116              : 
     117              :     // Determine the time before the vehicle back enters
     118    441609540 :     if (oldBackPos < 0. && newBackPos > 0.) {
     119     10038053 :         timeBeforeEnterBack = MSCFModel::passingTime(oldBackPos, 0., newBackPos, oldSpeed, newSpeed);
     120    431571487 :     } else if (newBackPos <= 0) {
     121      6500853 :         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    441609540 :     if (newBackPos > myLaneLength // vehicle's back has left the lane
     128     11185281 :             && 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     11185281 :         timeBeforeLeave = MSCFModel::passingTime(oldBackPos, myLaneLength, newBackPos, oldSpeed, newSpeed);
     132     11185281 :         const double timeAfterLeave = TS - timeBeforeLeave;
     133     11185281 :         timeOnLane -= timeAfterLeave;
     134     11185281 :         leaveSpeed = MSCFModel::speedAfterTime(timeBeforeLeave, oldSpeed, newPos - oldPos);
     135              :         // XXX: Do we really need this? Why would this "reduce rounding errors"? (Leo) Refs. #2579
     136     11185281 :         if (fabs(timeOnLane) < NUMERICAL_EPS) { // reduce rounding errors
     137              :             timeOnLane = 0.;
     138              :         }
     139     11185281 :         ret = veh.hasArrived();
     140              :     }
     141              : 
     142              :     // Treat the case that the vehicle's front left the lane in the last step
     143    441609540 :     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     12145360 :         timeBeforeLeaveFront = MSCFModel::passingTime(oldPos, myLaneLength, newPos, oldSpeed, newSpeed);
     147     12145360 :         const double timeAfterLeave = TS - timeBeforeLeaveFront;
     148     12145360 :         frontOnLane -= timeAfterLeave;
     149              :         // XXX: Do we really need this? Why would this "reduce rounding errors"? (Leo) Refs. #2579
     150     12145360 :         if (fabs(frontOnLane) < NUMERICAL_EPS) { // reduce rounding errors
     151              :             frontOnLane = 0.;
     152              :         }
     153     12145360 :         leaveSpeedFront = MSCFModel::speedAfterTime(timeBeforeLeaveFront, oldSpeed, newPos - oldPos);
     154              :     }
     155              : 
     156              :     assert(frontOnLane <= TS);
     157              :     assert(timeOnLane <= TS);
     158              : 
     159    441609540 :     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    441609540 :     if (timeOnLane == 0) {
     164        20688 :         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    441588852 :     double vehLength = veh.getVehicleType().getLength();
     192              :     // occupied lane length at timeBeforeEnter (resp. stepStart if already on lane)
     193    441588852 :     double lengthOnLaneAtStepStart = MAX2(0., MIN4(myLaneLength, vehLength, vehLength - (oldPos - myLaneLength), oldPos));
     194              :     // occupied lane length at timeBeforeLeave (resp. stepEnd if still on lane)
     195    441588852 :     double lengthOnLaneAtStepEnd = MAX2(0., MIN4(myLaneLength, vehLength, vehLength - (newPos - myLaneLength), newPos));
     196              :     double integratedLengthOnLane = 0.;
     197    441588852 :     if (timeBeforeEnterBack < timeBeforeLeaveFront) {
     198              :         // => timeBeforeLeaveFront>0, myLaneLength>vehLength
     199              :         // vehicle length on detector at timeBeforeEnterBack
     200    429060177 :         double lengthOnLaneAtBackEnter = MIN2(veh.getVehicleType().getLength(), newPos);
     201              :         // linear quadrature of occupancy between timeBeforeEnter and timeBeforeEnterBack
     202    429060177 :         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    429060177 :         integratedLengthOnLane += (timeBeforeLeaveFront - timeBeforeEnterBack) * vehLength;
     206              :         // and until vehicle leaves/stepEnd
     207    429060177 :         integratedLengthOnLane += (timeBeforeLeave - timeBeforeLeaveFront) * (vehLength + lengthOnLaneAtStepEnd) * 0.5;
     208     12528675 :     } else if (timeBeforeEnterBack >= timeBeforeLeaveFront) {
     209              :         // => myLaneLength <= vehLength or (timeBeforeLeaveFront == timeBeforeEnterBack == 0)
     210              :         // vehicle length on detector at timeBeforeLeaveFront
     211              :         double lengthOnLaneAtLeaveFront;
     212     12528675 :         if (timeBeforeLeaveFront == timeBeforeEnter) {
     213              :             // for the case that front already left
     214              :             lengthOnLaneAtLeaveFront = lengthOnLaneAtStepStart;
     215      6525418 :         } 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     12528675 :         integratedLengthOnLane += (timeBeforeLeaveFront - timeBeforeEnter) * (lengthOnLaneAtLeaveFront + lengthOnLaneAtStepStart) * 0.5;
     226              :         // linear quadrature of occupancy between timeBeforeLeaveFront and timeBeforeEnterBack
     227     12528675 :         integratedLengthOnLane += (timeBeforeEnterBack - timeBeforeLeaveFront) * lengthOnLaneAtLeaveFront;
     228              :         // and until vehicle leaves/stepEnd
     229     12528675 :         integratedLengthOnLane += (timeBeforeLeave - timeBeforeEnterBack) * (lengthOnLaneAtLeaveFront + lengthOnLaneAtStepEnd) * 0.5;
     230              :     }
     231              : 
     232    441588852 :     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    441588852 :     const double travelledDistanceFrontOnLane = MSGlobals::gSemiImplicitEulerUpdate ? frontOnLane * newSpeed
     244    161481306 :             : MAX2(0., MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.));
     245    522329505 :     const double travelledDistanceVehicleOnLane = MSGlobals::gSemiImplicitEulerUpdate ? timeOnLane * newSpeed
     246    161481306 :             : 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    441588852 :     ScopedLocker<> lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
     253              : #endif
     254    441588852 :     notifyMoveInternal(veh, frontOnLane, timeOnLane, (enterSpeed + leaveSpeedFront) / 2., (enterSpeed + leaveSpeed) / 2., travelledDistanceFrontOnLane, travelledDistanceVehicleOnLane, meanLengthOnLane);
     255              :     return ret;
     256              : }
     257              : 
     258              : 
     259              : bool
     260      1097982 : MSMeanData::MeanDataValues::notifyLeave(SUMOTrafficObject& /*veh*/, double /*lastPos*/, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
     261      1097982 :     if (MSGlobals::gUseMesoSim) {
     262              :         return false; // reminder is re-added on every segment (@recheck for performance)
     263              :     }
     264       994776 :     return reason == MSMoveReminder::NOTIFICATION_JUNCTION;
     265              : }
     266              : 
     267              : 
     268              : bool
     269      2951676 : MSMeanData::MeanDataValues::isEmpty() const {
     270      2951676 :     return sampleSeconds == 0;
     271              : }
     272              : 
     273              : 
     274              : void
     275            0 : MSMeanData::MeanDataValues::update() {
     276            0 : }
     277              : 
     278              : 
     279              : double
     280       978558 : MSMeanData::MeanDataValues::getSamples() const {
     281       978558 :     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        20726 : 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        20726 :                        bool aggregate) :
     425              :     MSDetectorFileOutput(id, vTypes, "", detectPersons),
     426        20726 :     myMinSamples(minSamples),
     427        20726 :     myMaxTravelTime(maxTravelTime),
     428        20726 :     myDumpEmpty(withEmpty),
     429        20726 :     myAmEdgeBased(!useLanes),
     430        20726 :     myDumpBegin(dumpBegin),
     431        20726 :     myDumpEnd(dumpEnd),
     432        20726 :     myInitTime(SUMOTime_MAX),
     433        20726 :     myEdges(edges),
     434        20726 :     myPrintDefaults(printDefaults),
     435        20726 :     myDumpInternal(withInternal),
     436        20726 :     myTrackVehicles(trackVehicles),
     437        20726 :     myWrittenAttributes(initWrittenAttributes(writeAttributes, id)),
     438        62178 :     myAggregate(aggregate)
     439        20726 : { }
     440              : 
     441              : 
     442              : void
     443        19772 : MSMeanData::init() {
     444        19772 :     myInitTime = MSNet::getInstance()->getCurrentTimeStep();
     445        19772 :     if (myEdges.empty()) {
     446              :         // use all edges by default
     447       697571 :         for (MSEdge* const edge : MSNet::getInstance()->getEdgeControl().getEdges()) {
     448       677856 :             if ((myDumpInternal || !edge->isInternal()) &&
     449       452819 :                     ((detectPersons() && myDumpInternal) || (!edge->isCrossing() && !edge->isWalkingArea()))) {
     450       310303 :                 myEdges.push_back(edge);
     451              :             }
     452              :         }
     453              :     }
     454              :     int index = 0;
     455       330172 :     for (MSEdge* edge : myEdges) {
     456       310400 :         myMeasures.push_back(std::vector<MeanDataValues*>());
     457       310400 :         myEdgeIndex[edge] = index++;
     458       310400 :         const std::vector<MSLane*>& lanes = edge->getLanes();
     459       310400 :         if (MSGlobals::gUseMesoSim) {
     460              :             MeanDataValues* data;
     461        29293 :             if (!myAmEdgeBased) {
     462           85 :                 for (MSLane* const lane : lanes) {
     463           52 :                     data = createValues(lane, lanes[0]->getLength(), false);
     464           52 :                     myMeasures.back().push_back(data);
     465           52 :                     MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
     466          310 :                     while (s != nullptr) {
     467          258 :                         s->addDetector(data, lane->getIndex());
     468          258 :                         s->prepareDetectorForWriting(*data, lane->getIndex());
     469              :                         s = s->getNextSegment();
     470              :                     }
     471           52 :                     data->reset();
     472           52 :                     data->reset(true);
     473              :                 }
     474              :             } else {
     475        29260 :                 if (myTrackVehicles) {
     476          880 :                     data = new MeanDataValueTracker(nullptr, lanes[0]->getLength(), this);
     477              :                 } else {
     478        28380 :                     data = createValues(nullptr, lanes[0]->getLength(), false);
     479              :                 }
     480        58520 :                 data->setDescription("meandata_" + edge->getID());
     481        29260 :                 myMeasures.back().push_back(data);
     482        29260 :                 MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
     483       147042 :                 while (s != nullptr) {
     484       117782 :                     s->addDetector(data);
     485       117782 :                     s->prepareDetectorForWriting(*data);
     486              :                     s = s->getNextSegment();
     487              :                 }
     488        29260 :                 data->reset();
     489        29260 :                 data->reset(true);
     490              :             }
     491              :             continue;
     492        29293 :         }
     493       281107 :         if (myAmEdgeBased && myTrackVehicles) {
     494          912 :             myMeasures.back().push_back(new MeanDataValueTracker(nullptr, lanes[0]->getLength(), this));
     495              :         }
     496       730098 :         for (MSLane* const lane : lanes) {
     497       448991 :             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       447071 :                 myMeasures.back().push_back(createValues(lane, lane->getLength(), true));
     505              :             }
     506              :         }
     507              :     }
     508        19772 : }
     509              : 
     510              : 
     511        20597 : MSMeanData::~MSMeanData() {
     512       329368 :     for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
     513       783885 :         for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
     514       475114 :             delete *j;
     515              :         }
     516              :     }
     517        20597 : }
     518              : 
     519              : 
     520              : void
     521        12233 : MSMeanData::resetOnly(SUMOTime stopTime) {
     522              :     UNUSED_PARAMETER(stopTime);
     523        12233 :     if (MSGlobals::gUseMesoSim) {
     524              :         MSEdgeVector::iterator edge = myEdges.begin();
     525       117278 :         for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i, ++edge) {
     526       113696 :             MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(**edge);
     527       227392 :             for (MeanDataValues* data : *i) {
     528       602142 :                 while (s != nullptr) {
     529       488446 :                     s->prepareDetectorForWriting(*data);
     530              :                     s = s->getNextSegment();
     531              :                 }
     532       113696 :                 data->reset();
     533              :             }
     534              :         }
     535              :         return;
     536              :     }
     537       252010 :     for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
     538       515422 :         for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
     539       272063 :             (*j)->reset();
     540              :         }
     541              :     }
     542              : }
     543              : 
     544              : 
     545              : std::string
     546      9801319 : MSMeanData::getEdgeID(const MSEdge* const edge) {
     547      9801319 :     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->getNumDrivingLanes();
     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     17830578 : MSMeanData::writeEdge(OutputDevice& dev,
     597              :                       const std::vector<MeanDataValues*>& edgeValues,
     598              :                       const MSEdge* const edge, SUMOTime startTime, SUMOTime stopTime) {
     599     17830578 :     if (MSGlobals::gUseMesoSim) {
     600              :         int idx = 0;
     601      2723261 :         for (MeanDataValues* const data : edgeValues) {
     602      1361654 :             MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
     603      6992278 :             while (s != nullptr) {
     604      5630966 :                 s->prepareDetectorForWriting(*data, myAmEdgeBased ? -1 : idx);
     605              :                 s = s->getNextSegment();
     606              :             }
     607      1361654 :             idx++;
     608              :         }
     609      1361607 :         if (myAmEdgeBased) {
     610      1361560 :             MeanDataValues* data = edgeValues.front();
     611      2723120 :             if (writePrefix(dev, *data, SUMO_TAG_EDGE, getEdgeID(edge))) {
     612        60438 :                 data->write(dev, myWrittenAttributes, stopTime - startTime,
     613              :                             edge->getNumDrivingLanes(),
     614              :                             edge->getSpeedLimit(),
     615        60438 :                             myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
     616              :             }
     617      1361560 :             if (!MSNet::getInstance()->skipFinalReset()) {
     618      1361560 :                 data->reset(true);
     619              :             }
     620              :             return;
     621              :         }
     622              :     }
     623              :     std::vector<MeanDataValues*>::const_iterator lane;
     624     16469018 :     if (!myAmEdgeBased) {
     625      8003819 :         bool writeCheck = myDumpEmpty;
     626      8003819 :         if (!writeCheck) {
     627     15610324 :             for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
     628      7912215 :                 if (!(*lane)->isEmpty()) {
     629              :                     writeCheck = true;
     630              :                     break;
     631              :                 }
     632              :             }
     633              :         }
     634      7901044 :         if (writeCheck) {
     635       611420 :             dev.openTag(SUMO_TAG_EDGE).writeAttr(SUMO_ATTR_ID, edge->getID());
     636              :         }
     637     16104776 :         for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
     638      8100957 :             MeanDataValues& meanData = **lane;
     639     24302871 :             if (writePrefix(dev, meanData, SUMO_TAG_LANE, meanData.getLane()->getID())) {
     640       391611 :                 meanData.write(dev, myWrittenAttributes, stopTime - startTime, 1, meanData.getLane()->getSpeedLimit(),
     641       391611 :                                myPrintDefaults ? meanData.getLane()->getLength() / meanData.getLane()->getSpeedLimit() : -1.);
     642              :             }
     643      8100957 :             if (!MSNet::getInstance()->skipFinalReset()) {
     644      8100957 :                 meanData.reset(true);
     645              :             }
     646              :         }
     647      8003819 :         if (writeCheck) {
     648       611420 :             dev.closeTag();
     649              :         }
     650              :     } else {
     651      8465199 :         if (myTrackVehicles) {
     652        22416 :             MeanDataValues& meanData = **edgeValues.begin();
     653        67248 :             if (writePrefix(dev, meanData, SUMO_TAG_EDGE, edge->getID())) {
     654          136 :                 meanData.write(dev, myWrittenAttributes, stopTime - startTime, edge->getNumDrivingLanes(), 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      8442783 :             MeanDataValues* sumData = createValues(nullptr, edge->getLength(), false);
     662     17028126 :             for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
     663      8585343 :                 MeanDataValues& meanData = **lane;
     664      8585343 :                 meanData.addTo(*sumData);
     665      8585343 :                 if (!MSNet::getInstance()->skipFinalReset()) {
     666      8585343 :                     meanData.reset();
     667              :                 }
     668              :             }
     669     16885566 :             if (writePrefix(dev, *sumData, SUMO_TAG_EDGE, getEdgeID(edge))) {
     670       486456 :                 sumData->write(dev, myWrittenAttributes, stopTime - startTime, edge->getNumDrivingLanes(), edge->getSpeedLimit(),
     671       486456 :                                myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
     672              :             }
     673      8442782 :             delete sumData;
     674              :         }
     675              :     }
     676              : }
     677              : 
     678              : 
     679              : void
     680       430937 : MSMeanData::openInterval(OutputDevice& dev, const SUMOTime startTime, const SUMOTime stopTime) {
     681      1292811 :     dev.openTag(SUMO_TAG_INTERVAL).writeAttr(SUMO_ATTR_BEGIN, time2string(startTime)).writeAttr(SUMO_ATTR_END, time2string(stopTime));
     682       430937 :     dev.writeAttr(SUMO_ATTR_ID, myID);
     683       430937 : }
     684              : 
     685              : 
     686              : bool
     687     17924728 : MSMeanData::writePrefix(OutputDevice& dev, const MeanDataValues& values, const SumoXMLTag tag, const std::string id) const {
     688     17924728 :     if (myDumpEmpty || !values.isEmpty()) {
     689       935957 :         dev.openTag(tag);
     690              :         dev.writeAttr(SUMO_ATTR_ID, id);
     691       935957 :         dev.writeOptionalAttr(SUMO_ATTR_SAMPLEDSECONDS, values.getSamples(), myWrittenAttributes);
     692       935957 :         return true;
     693              :     }
     694              :     return false;
     695              : }
     696              : 
     697              : 
     698              : void
     699       441838 : MSMeanData::writeXMLOutput(OutputDevice& dev,
     700              :                            SUMOTime startTime, SUMOTime stopTime) {
     701              :     // check whether this dump shall be written for the current time
     702       441838 :     int numReady = myDumpBegin < stopTime && myDumpEnd - DELTA_T >= startTime ? 1 : 0;
     703       441838 :     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       441838 :     const bool partialInterval = startTime < myInitTime;
     719       441838 :     if (numReady == 0 || myTrackVehicles || partialInterval) {
     720        12233 :         resetOnly(stopTime);
     721              :     }
     722       441838 :     if (partialInterval) {
     723              :         return;
     724              :     }
     725       873018 :     while (numReady-- > 0) {
     726       431189 :         if (!myPendingIntervals.empty()) {
     727         1584 :             startTime = myPendingIntervals.front().first;
     728         1584 :             stopTime = myPendingIntervals.front().second;
     729         1584 :             myPendingIntervals.pop_front();
     730              :         }
     731       431189 :         openInterval(dev, startTime, stopTime);
     732       431189 :         if (myAggregate) {
     733           36 :             writeAggregated(dev, startTime, stopTime);
     734              :         } else {
     735              :             MSEdgeVector::const_iterator edge = myEdges.begin();
     736     18261730 :             for (const std::vector<MeanDataValues*>& measures : myMeasures) {
     737     17830578 :                 writeEdge(dev, measures, *edge, startTime, stopTime);
     738              :                 ++edge;
     739              :             }
     740              :         }
     741       862376 :         dev.closeTag();
     742              :     }
     743              :     dev.flush();
     744              : }
     745              : 
     746              : 
     747              : void
     748        19750 : MSMeanData::writeXMLDetectorProlog(OutputDevice& dev) const {
     749        39500 :     dev.writeXMLHeader("meandata", "meandata_file.xsd");
     750        19750 : }
     751              : 
     752              : 
     753              : void
     754     60883576 : MSMeanData::detectorUpdate(const SUMOTime step) {
     755     60883576 :     if (step + DELTA_T == myDumpBegin) {
     756          639 :         init();
     757              :     }
     758     60883576 : }
     759              : 
     760              : 
     761              : long long int
     762        20726 : MSMeanData::initWrittenAttributes(const std::string writeAttributes, const std::string& id) {
     763              :     long long int result = 0;
     764        41602 :     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        20726 :     }
     773        20726 :     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 2.0-1