SUMO - Simulation of Urban MObility
MSMeanData.cpp
Go to the documentation of this file.
00001 /****************************************************************************/
00010 // Data collector for edges/lanes
00011 /****************************************************************************/
00012 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00013 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
00014 /****************************************************************************/
00015 //
00016 //   This file is part of SUMO.
00017 //   SUMO is free software: you can redistribute it and/or modify
00018 //   it under the terms of the GNU General Public License as published by
00019 //   the Free Software Foundation, either version 3 of the License, or
00020 //   (at your option) any later version.
00021 //
00022 /****************************************************************************/
00023 
00024 
00025 // ===========================================================================
00026 // included modules
00027 // ===========================================================================
00028 #ifdef _MSC_VER
00029 #include <windows_config.h>
00030 #else
00031 #include <config.h>
00032 #endif
00033 
00034 #include <microsim/MSEdgeControl.h>
00035 #include <microsim/MSEdge.h>
00036 #include <microsim/MSLane.h>
00037 #include <microsim/MSVehicle.h>
00038 #include <microsim/MSNet.h>
00039 #include <utils/common/SUMOTime.h>
00040 #include <utils/common/ToString.h>
00041 #include <utils/iodevices/OutputDevice.h>
00042 #include "MSMeanData.h"
00043 #include <limits>
00044 
00045 #ifdef HAVE_MESOSIM
00046 #include <microsim/MSGlobals.h>
00047 #include <mesosim/MELoop.h>
00048 #include <mesosim/MESegment.h>
00049 #endif
00050 
00051 #ifdef CHECK_MEMORY_LEAKS
00052 #include <foreign/nvwa/debug_new.h>
00053 #endif // CHECK_MEMORY_LEAKS
00054 
00055 
00056 // ===========================================================================
00057 // method definitions
00058 // ===========================================================================
00059 // ---------------------------------------------------------------------------
00060 // MSMeanData::MeanDataValues - methods
00061 // ---------------------------------------------------------------------------
00062 MSMeanData::MeanDataValues::MeanDataValues(
00063     MSLane* const lane, const SUMOReal length, const bool doAdd,
00064     const std::set<std::string>* const vTypes) :
00065     MSMoveReminder(lane, doAdd),
00066     myLaneLength(length),
00067     sampleSeconds(0),
00068     travelledDistance(0),
00069     myVehicleTypes(vTypes) {}
00070 
00071 
00072 MSMeanData::MeanDataValues::~MeanDataValues() {
00073 }
00074 
00075 
00076 bool
00077 MSMeanData::MeanDataValues::notifyEnter(SUMOVehicle& veh, MSMoveReminder::Notification reason) {
00078     UNUSED_PARAMETER(reason);
00079     return vehicleApplies(veh);
00080 }
00081 
00082 
00083 bool
00084 MSMeanData::MeanDataValues::notifyMove(SUMOVehicle& veh, SUMOReal oldPos, SUMOReal newPos, SUMOReal newSpeed) {
00085     SUMOReal timeOnLane = TS;
00086     bool ret = true;
00087     if (oldPos < 0 && newSpeed != 0) {
00088         timeOnLane = newPos / newSpeed;
00089     }
00090     if (newPos-veh.getVehicleType().getLength() > myLaneLength && newSpeed != 0) {
00091         timeOnLane -= (newPos - veh.getVehicleType().getLength() - myLaneLength) / newSpeed;
00092         if (fabs(timeOnLane) < 0.001) { // reduce rounding errors
00093             timeOnLane = 0.;
00094         }
00095         ret = false;
00096     }
00097     if (timeOnLane < 0) {
00098         WRITE_ERROR("Negative vehicle step fraction for '" + veh.getID() + "' on lane '" + getLane()->getID() + "'.");
00099         return false;
00100     }
00101     if (timeOnLane == 0) {
00102         return false;
00103     }
00104     notifyMoveInternal(veh, timeOnLane, newSpeed);
00105     return ret;
00106 }
00107 
00108 
00109 bool
00110 MSMeanData::MeanDataValues::notifyLeave(SUMOVehicle& /*veh*/, SUMOReal /*lastPos*/, MSMoveReminder::Notification reason) {
00111     return reason == MSMoveReminder::NOTIFICATION_JUNCTION;
00112 }
00113 
00114 
00115 bool
00116 MSMeanData::MeanDataValues::vehicleApplies(const SUMOVehicle& veh) const {
00117     return myVehicleTypes == 0 || myVehicleTypes->empty() ||
00118            myVehicleTypes->find(veh.getVehicleType().getID()) != myVehicleTypes->end();
00119 }
00120 
00121 
00122 bool
00123 MSMeanData::MeanDataValues::isEmpty() const {
00124     return sampleSeconds == 0;
00125 }
00126 
00127 
00128 void
00129 MSMeanData::MeanDataValues::update() {
00130 }
00131 
00132 
00133 SUMOReal
00134 MSMeanData::MeanDataValues::getSamples() const {
00135     return sampleSeconds;
00136 }
00137 
00138 
00139 // ---------------------------------------------------------------------------
00140 // MSMeanData::MeanDataValueTracker - methods
00141 // ---------------------------------------------------------------------------
00142 MSMeanData::MeanDataValueTracker::MeanDataValueTracker(MSLane* const lane,
00143         const SUMOReal length,
00144         const std::set<std::string>* const vTypes,
00145         const MSMeanData* const parent)
00146     : MSMeanData::MeanDataValues(lane, length, true, vTypes), myParent(parent) {
00147     myCurrentData.push_back(new TrackerEntry(parent->createValues(lane, length, false)));
00148 }
00149 
00150 
00151 MSMeanData::MeanDataValueTracker::~MeanDataValueTracker() {
00152 }
00153 
00154 
00155 void
00156 MSMeanData::MeanDataValueTracker::reset(bool afterWrite) {
00157     if (afterWrite) {
00158         myCurrentData.pop_front();
00159     } else {
00160         myCurrentData.push_back(new TrackerEntry(myParent->createValues(myLane, myLaneLength, false)));
00161     }
00162 }
00163 
00164 
00165 void
00166 MSMeanData::MeanDataValueTracker::addTo(MSMeanData::MeanDataValues& val) const {
00167     myCurrentData.front()->myValues->addTo(val);
00168 }
00169 
00170 
00171 void
00172 MSMeanData::MeanDataValueTracker::notifyMoveInternal(SUMOVehicle& veh, SUMOReal timeOnLane, SUMOReal speed) {
00173     myTrackedData[&veh]->myValues->notifyMoveInternal(veh, timeOnLane, speed);
00174 }
00175 
00176 
00177 bool
00178 MSMeanData::MeanDataValueTracker::notifyLeave(SUMOVehicle& veh, SUMOReal lastPos, MSMoveReminder::Notification reason) {
00179     if (myParent == 0 || reason != MSMoveReminder::NOTIFICATION_SEGMENT) {
00180         myTrackedData[&veh]->myNumVehicleLeft++;
00181     }
00182     return myTrackedData[&veh]->myValues->notifyLeave(veh, lastPos, reason);
00183 }
00184 
00185 
00186 bool
00187 MSMeanData::MeanDataValueTracker::notifyEnter(SUMOVehicle& veh, MSMoveReminder::Notification reason) {
00188     if (reason == MSMoveReminder::NOTIFICATION_SEGMENT) {
00189         return true;
00190     }
00191     if (vehicleApplies(veh) && myTrackedData.find(&veh) == myTrackedData.end()) {
00192         myTrackedData[&veh] = myCurrentData.back();
00193         myTrackedData[&veh]->myNumVehicleEntered++;
00194         if (!myTrackedData[&veh]->myValues->notifyEnter(veh, reason)) {
00195             myTrackedData[&veh]->myNumVehicleLeft++;
00196             myTrackedData.erase(&veh);
00197             return false;
00198         }
00199         return true;
00200     }
00201     return false;
00202 }
00203 
00204 
00205 bool
00206 MSMeanData::MeanDataValueTracker::isEmpty() const {
00207     return myCurrentData.front()->myValues->isEmpty();
00208 }
00209 
00210 
00211 void
00212 MSMeanData::MeanDataValueTracker::write(OutputDevice& dev,
00213                                         const SUMOTime period,
00214                                         const SUMOReal numLanes,
00215                                         const SUMOReal defaultTravelTime,
00216                                         const int /*numVehicles*/) const {
00217     myCurrentData.front()->myValues->write(dev, period, numLanes,
00218                                            defaultTravelTime,
00219                                            myCurrentData.front()->myNumVehicleEntered);
00220 }
00221 
00222 
00223 size_t
00224 MSMeanData::MeanDataValueTracker::getNumReady() const {
00225     size_t result = 0;
00226     for (std::list<TrackerEntry*>::const_iterator it = myCurrentData.begin(); it != myCurrentData.end(); ++it) {
00227         if ((*it)->myNumVehicleEntered == (*it)->myNumVehicleLeft) {
00228             result++;
00229         } else {
00230             break;
00231         }
00232     }
00233     return result;
00234 }
00235 
00236 
00237 SUMOReal
00238 MSMeanData::MeanDataValueTracker::getSamples() const {
00239     return myCurrentData.front()->myValues->getSamples();
00240 }
00241 
00242 
00243 // ---------------------------------------------------------------------------
00244 // MSMeanData - methods
00245 // ---------------------------------------------------------------------------
00246 MSMeanData::MSMeanData(const std::string& id,
00247                        const SUMOTime dumpBegin, const SUMOTime dumpEnd,
00248                        const bool useLanes, const bool withEmpty,
00249                        const bool printDefaults, const bool withInternal, const bool trackVehicles,
00250                        const SUMOReal maxTravelTime,
00251                        const SUMOReal minSamples,
00252                        const std::set<std::string> vTypes) :
00253     MSDetectorFileOutput(id),
00254     myMinSamples(minSamples),
00255     myMaxTravelTime(maxTravelTime),
00256     myVehicleTypes(vTypes),
00257     myAmEdgeBased(!useLanes),
00258     myDumpBegin(dumpBegin),
00259     myDumpEnd(dumpEnd),
00260     myDumpEmpty(withEmpty),
00261     myPrintDefaults(printDefaults),
00262     myDumpInternal(withInternal),
00263     myTrackVehicles(trackVehicles) {
00264 }
00265 
00266 
00267 void
00268 MSMeanData::init() {
00269     const std::vector<MSEdge*> &edges = MSNet::getInstance()->getEdgeControl().getEdges();
00270     for (std::vector<MSEdge*>::const_iterator e = edges.begin(); e != edges.end(); ++e) {
00271         if (myDumpInternal || (*e)->getPurpose() != MSEdge::EDGEFUNCTION_INTERNAL) {
00272             myEdges.push_back(*e);
00273             myMeasures.push_back(std::vector<MeanDataValues*>());
00274             const std::vector<MSLane*> &lanes = (*e)->getLanes();
00275 #ifdef HAVE_MESOSIM
00276             if (MSGlobals::gUseMesoSim) {
00277                 MeanDataValues* data;
00278                 if (myTrackVehicles) {
00279                     data = new MeanDataValueTracker(0, lanes[0]->getLength(), &myVehicleTypes, this);
00280                 } else {
00281                     data = createValues(0, lanes[0]->getLength(), false);
00282                 }
00283                 myMeasures.back().push_back(data);
00284                 MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(**e);
00285                 while (s != 0) {
00286                     s->addDetector(data);
00287                     s->prepareDetectorForWriting(*data);
00288                     s = s->getNextSegment();
00289                 }
00290                 data->reset();
00291                 data->reset(true);
00292                 continue;
00293             }
00294 #endif
00295             if (myAmEdgeBased && myTrackVehicles) {
00296                 myMeasures.back().push_back(new MeanDataValueTracker(0, lanes[0]->getLength(), &myVehicleTypes, this));
00297             }
00298             for (std::vector<MSLane*>::const_iterator lane = lanes.begin(); lane != lanes.end(); ++lane) {
00299                 if (myTrackVehicles) {
00300                     if (myAmEdgeBased) {
00301                         (*lane)->addMoveReminder(myMeasures.back().back());
00302                     } else {
00303                         myMeasures.back().push_back(new MeanDataValueTracker(*lane, (*lane)->getLength(), &myVehicleTypes, this));
00304                     }
00305                 } else {
00306                     myMeasures.back().push_back(createValues(*lane, (*lane)->getLength(), true));
00307                 }
00308             }
00309         }
00310     }
00311 }
00312 
00313 
00314 MSMeanData::~MSMeanData() {
00315     for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
00316         for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
00317             delete *j;
00318         }
00319     }
00320 }
00321 
00322 
00323 void
00324 MSMeanData::resetOnly(SUMOTime stopTime) {
00325     UNUSED_PARAMETER(stopTime);
00326 #ifdef HAVE_MESOSIM
00327     if (MSGlobals::gUseMesoSim) {
00328         std::vector<MSEdge*>::iterator edge = myEdges.begin();
00329         for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i, ++edge) {
00330             MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(**edge);
00331             MeanDataValues* data = i->front();
00332             while (s != 0) {
00333                 s->prepareDetectorForWriting(*data);
00334                 s = s->getNextSegment();
00335             }
00336             data->reset();
00337         }
00338         return;
00339     }
00340 #endif
00341     for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
00342         for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
00343             (*j)->reset();
00344         }
00345     }
00346 }
00347 
00348 
00349 void
00350 MSMeanData::writeEdge(OutputDevice& dev,
00351                       const std::vector<MeanDataValues*> &edgeValues,
00352                       MSEdge* edge, SUMOTime startTime, SUMOTime stopTime) {
00353 #ifdef HAVE_MESOSIM
00354     if (MSGlobals::gUseMesoSim) {
00355         MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
00356         MeanDataValues* data = edgeValues.front();
00357         while (s != 0) {
00358             s->prepareDetectorForWriting(*data);
00359             s = s->getNextSegment();
00360         }
00361         if (writePrefix(dev, *data, "edge", edge->getID())) {
00362             data->write(dev, stopTime - startTime,
00363                         (SUMOReal)edge->getLanes().size(),
00364                         myPrintDefaults ? edge->getLength() / edge->getMaxSpeed() : -1.);
00365         }
00366         data->reset(true);
00367         return;
00368     }
00369 #endif
00370     std::vector<MeanDataValues*>::const_iterator lane;
00371     if (!myAmEdgeBased) {
00372         bool writeCheck = myDumpEmpty;
00373         if (!writeCheck) {
00374             for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
00375                 if (!(*lane)->isEmpty()) {
00376                     writeCheck = true;
00377                     break;
00378                 }
00379             }
00380         }
00381         if (writeCheck) {
00382             dev.openTag("edge").writeAttr(SUMO_ATTR_ID, edge->getID()).closeOpener();
00383         }
00384         for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
00385             MeanDataValues& meanData = **lane;
00386             if (writePrefix(dev, meanData, "lane", meanData.getLane()->getID())) {
00387                 meanData.write(dev, stopTime - startTime, 1.f,
00388                                myPrintDefaults ? meanData.getLane()->getLength() / meanData.getLane()->getMaxSpeed() : -1.);
00389             }
00390             meanData.reset(true);
00391         }
00392         if (writeCheck) {
00393             dev.closeTag();
00394         }
00395     } else {
00396         if (myTrackVehicles) {
00397             MeanDataValues& meanData = **edgeValues.begin();
00398             if (writePrefix(dev, meanData, "edge", edge->getID())) {
00399                 meanData.write(dev, stopTime - startTime, (SUMOReal)edge->getLanes().size(),
00400                                myPrintDefaults ? edge->getLength() / edge->getMaxSpeed() : -1.);
00401             }
00402             meanData.reset(true);
00403         } else {
00404             MeanDataValues* sumData = createValues(0, edge->getLength(), false);
00405             for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
00406                 MeanDataValues& meanData = **lane;
00407                 meanData.addTo(*sumData);
00408                 meanData.reset();
00409             }
00410             if (writePrefix(dev, *sumData, "edge", edge->getID())) {
00411                 sumData->write(dev, stopTime - startTime, (SUMOReal)edge->getLanes().size(),
00412                                myPrintDefaults ? edge->getLength() / edge->getMaxSpeed() : -1.);
00413             }
00414             delete sumData;
00415         }
00416     }
00417 }
00418 
00419 
00420 bool
00421 MSMeanData::writePrefix(OutputDevice& dev, const MeanDataValues& values, const std::string tag, const std::string id) const {
00422     if (myDumpEmpty || !values.isEmpty()) {
00423         dev.openTag(tag).writeAttr(SUMO_ATTR_ID, id) << " sampledSeconds=\"" << values.getSamples();
00424         return true;
00425     }
00426     return false;
00427 }
00428 
00429 
00430 void
00431 MSMeanData::writeXMLOutput(OutputDevice& dev,
00432                            SUMOTime startTime, SUMOTime stopTime) {
00433     // check whether this dump shall be written for the current time
00434     size_t numReady = myDumpBegin < stopTime && myDumpEnd - DELTA_T >= startTime;
00435     if (myTrackVehicles && myDumpBegin < stopTime) {
00436         myPendingIntervals.push_back(std::make_pair(startTime, stopTime));
00437         numReady = myPendingIntervals.size();
00438         for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
00439             for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
00440                 numReady = MIN2(numReady, ((MeanDataValueTracker*)*j)->getNumReady());
00441                 if (numReady == 0) {
00442                     break;
00443                 }
00444             }
00445             if (numReady == 0) {
00446                 break;
00447             }
00448         }
00449     }
00450     if (numReady == 0 || myTrackVehicles) {
00451         resetOnly(stopTime);
00452     }
00453     while (numReady-- > 0) {
00454         if (!myPendingIntervals.empty()) {
00455             startTime = myPendingIntervals.front().first;
00456             stopTime = myPendingIntervals.front().second;
00457             myPendingIntervals.pop_front();
00458         }
00459         dev.openTag("interval") << " begin=\"" << time2string(startTime) << "\" end=\"" <<
00460                                 time2string(stopTime) << "\" " << "id=\"" << myID << "\">\n";
00461         std::vector<MSEdge*>::iterator edge = myEdges.begin();
00462         for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i, ++edge) {
00463             writeEdge(dev, (*i), *edge, startTime, stopTime);
00464         }
00465         dev.closeTag();
00466     }
00467 }
00468 
00469 
00470 void
00471 MSMeanData::writeXMLDetectorProlog(OutputDevice& dev) const {
00472     dev.writeXMLHeader("netstats");
00473 }
00474 
00475 
00476 void
00477 MSMeanData::detectorUpdate(const SUMOTime step) {
00478     if (step + DELTA_T == myDumpBegin) {
00479         init();
00480     }
00481 }
00482 
00483 
00484 /****************************************************************************/
00485 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines