SUMO - Simulation of Urban MObility

MSMeanData.cpp

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