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