SUMO - Simulation of Urban MObility

MSE2Collector.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // An areal (along a single lane) detector
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 <algorithm>
00031 #include "MSE2Collector.h"
00032 #include <microsim/MSLane.h>
00033 #include <microsim/MSVehicleType.h>
00034 
00035 #ifdef CHECK_MEMORY_LEAKS
00036 #include <foreign/nvwa/debug_new.h>
00037 #endif // CHECK_MEMORY_LEAKS
00038 
00039 
00040 // ===========================================================================
00041 // method definitions
00042 // ===========================================================================
00043 MSE2Collector::MSE2Collector(const std::string& id, DetectorUsage usage,
00044                              MSLane* const lane, SUMOReal startPos, SUMOReal detLength,
00045                              SUMOTime haltingTimeThreshold,
00046                              SUMOReal haltingSpeedThreshold,
00047                              SUMOReal jamDistThreshold) throw()
00048     : MSMoveReminder(lane), MSDetectorFileOutput(id),
00049       myJamHaltingSpeedThreshold(haltingSpeedThreshold),
00050       myJamHaltingTimeThreshold(haltingTimeThreshold),
00051       myJamDistanceThreshold(jamDistThreshold),
00052       myStartPos(startPos), myEndPos(startPos + detLength),
00053       myUsage(usage),
00054       myCurrentOccupancy(0), myCurrentMeanSpeed(-1), myCurrentJamNo(0),
00055       myCurrentMaxJamLengthInMeters(0), myCurrentMaxJamLengthInVehicles(0),
00056       myCurrentJamLengthInMeters(0), myCurrentJamLengthInVehicles(0), myCurrentStartedHalts(0)
00057 
00058 {
00059     assert(myLane != 0);
00060     assert(myStartPos >= 0 && myStartPos < myLane->getLength());
00061     assert(myEndPos - myStartPos > 0 && myEndPos <= myLane->getLength());
00062     reset();
00063 }
00064 
00065 
00066 MSE2Collector::~MSE2Collector() throw() {
00067     myKnownVehicles.clear();
00068 }
00069 
00070 
00071 bool
00072 MSE2Collector::notifyMove(SUMOVehicle& veh, SUMOReal oldPos,
00073                           SUMOReal newPos, SUMOReal) throw() {
00074     if (newPos < myStartPos) {
00075         // detector not yet reached
00076         return true;
00077     }
00078     if (newPos >= myStartPos && oldPos < myStartPos) {
00079         if (find(myKnownVehicles.begin(), myKnownVehicles.end(), &veh)==myKnownVehicles.end()) {
00080             myKnownVehicles.push_back(&veh);
00081         }
00082     }
00083     if (newPos - veh.getVehicleType().getLengthWithGap() > myEndPos) {
00084         std::list<SUMOVehicle*>::iterator i = find(myKnownVehicles.begin(), myKnownVehicles.end(), &veh);
00085         if (i!=myKnownVehicles.end()) {
00086             myKnownVehicles.erase(i);
00087         }
00088         return false;
00089     }
00090     return true;
00091 }
00092 
00093 
00094 bool
00095 MSE2Collector::notifyLeave(SUMOVehicle& veh, SUMOReal lastPos, MSMoveReminder::Notification reason) throw() {
00096     if (reason != MSMoveReminder::NOTIFICATION_JUNCTION || (lastPos >= myStartPos && lastPos - veh.getVehicleType().getLengthWithGap() < myEndPos)) {
00097         std::list<SUMOVehicle*>::iterator i = find(myKnownVehicles.begin(), myKnownVehicles.end(), &veh);
00098         if (i!=myKnownVehicles.end()) {
00099             myKnownVehicles.erase(i);
00100         }
00101         return false;
00102     }
00103     return true;
00104 }
00105 
00106 
00107 bool
00108 MSE2Collector::notifyEnter(SUMOVehicle& veh, MSMoveReminder::Notification) throw() {
00109     if (veh.getPositionOnLane() >= myStartPos && veh.getPositionOnLane() - veh.getVehicleType().getLengthWithGap() < myEndPos) {
00110         // vehicle is on detector
00111         myKnownVehicles.push_back(&veh);
00112         return true;
00113     }
00114     if (veh.getPositionOnLane() - veh.getVehicleType().getLengthWithGap() > myEndPos) {
00115         // vehicle is beyond detector
00116         return false;
00117     }
00118     // vehicle is in front of detector
00119     return true;
00120 }
00121 
00122 
00123 void
00124 MSE2Collector::reset() throw() {
00125     mySpeedSum = 0;
00126     myStartedHalts = 0;
00127     myJamLengthInMetersSum = 0;
00128     myJamLengthInVehiclesSum = 0;
00129     myVehicleSamples = 0;
00130     myOccupancySum = 0;
00131     myMaxOccupancy = 0;
00132     myMeanMaxJamInVehicles = 0;
00133     myMeanMaxJamInMeters = 0;
00134     myMaxJamInVehicles = 0;
00135     myMaxJamInMeters = 0;
00136     myTimeSamples = 0;
00137     myMeanVehicleNumber = 0;
00138     myMaxVehicleNumber = 0;
00139     for (std::map<SUMOVehicle*, SUMOTime>::iterator i=myIntervalHaltingVehicleDurations.begin(); i!=myIntervalHaltingVehicleDurations.end(); ++i) {
00140         (*i).second = 0;
00141     }
00142     myPastStandingDurations.clear();
00143     myPastIntervalStandingDurations.clear();
00144 }
00145 
00146 
00147 
00148 void
00149 MSE2Collector::detectorUpdate(const SUMOTime step) throw() {
00150     JamInfo* currentJam = 0;
00151     std::map<SUMOVehicle*, SUMOTime> haltingVehicles;
00152     std::map<SUMOVehicle*, SUMOTime> intervalHaltingVehicles;
00153     std::vector<JamInfo*> jams;
00154 
00155     SUMOReal lengthSum = 0;
00156     myCurrentMeanSpeed = 0;
00157     myCurrentMeanLength = 0;
00158     myCurrentStartedHalts = 0;
00159 
00160     // go through the (sorted) list of vehicles positioned on the detector
00161     //  sum up values and prepare the list of jams
00162     myKnownVehicles.sort(by_vehicle_position_sorter(getLane()));
00163     for (std::list<SUMOVehicle*>::const_iterator i=myKnownVehicles.begin(); i!=myKnownVehicles.end(); ++i) {
00164         MSVehicle* veh = static_cast<MSVehicle*>(*i);
00165 
00166         SUMOReal length = veh->getVehicleType().getLengthWithGap();
00167         if (veh->getLane()==getLane()) {
00168             if (veh->getPositionOnLane() - veh->getVehicleType().getLengthWithGap() < myStartPos) {
00169                 // vehicle entered detector partially
00170                 length -= (veh->getVehicleType().getLengthWithGap() - (veh->getPositionOnLane()-myStartPos));
00171             }
00172             if (veh->getPositionOnLane()>myEndPos && veh->getPositionOnLane()-veh->getVehicleType().getLengthWithGap()<=myEndPos) {
00173                 // vehicle left detector partially
00174                 length -= (veh->getPositionOnLane()-myEndPos);
00175             }
00176         } else {
00177             // ok, the vehicle is only partially still on the detector, has already moved to the
00178             //  next lane; still, we do not know how far away it is
00179             assert(veh==myLane->getPartialOccupator());
00180             length = myEndPos - myLane->getPartialOccupatorEnd();
00181         }
00182         assert(length>=0);
00183 
00184         mySpeedSum += veh->getSpeed();
00185         myCurrentMeanSpeed += veh->getSpeed();
00186         lengthSum += length;
00187         myCurrentMeanLength += length;
00188 
00189         // jam-checking begins
00190         bool isInJam = false;
00191         // first, check whether the vehicle is slow enough to be states as halting
00192         if (veh->getSpeed()<myJamHaltingSpeedThreshold) {
00193             // we have to track the time it was halting;
00194             //  so let's look up whether it was halting before and compute the overall halting time
00195             bool wasHalting = myHaltingVehicleDurations.find(veh)!=myHaltingVehicleDurations.end();
00196             if (wasHalting) {
00197                 haltingVehicles[veh] = myHaltingVehicleDurations[veh] + DELTA_T;
00198                 intervalHaltingVehicles[veh] = myIntervalHaltingVehicleDurations[veh] + DELTA_T;
00199             } else {
00200                 haltingVehicles[veh] = DELTA_T;
00201                 intervalHaltingVehicles[veh] = DELTA_T;
00202                 myCurrentStartedHalts++;
00203                 myStartedHalts++;
00204             }
00205             // we now check whether the halting time is large enough
00206             if (haltingVehicles[veh]>myJamHaltingTimeThreshold) {
00207                 // yep --> the vehicle is a part of a jam
00208                 isInJam = true;
00209             }
00210         } else {
00211             // is not standing anymore; keep duration information
00212             std::map<SUMOVehicle*, SUMOTime>::iterator v = myHaltingVehicleDurations.find(veh);
00213             if (v!=myHaltingVehicleDurations.end()) {
00214                 myPastStandingDurations.push_back((*v).second);
00215                 myHaltingVehicleDurations.erase(v);
00216             }
00217             v = myIntervalHaltingVehicleDurations.find(veh);
00218             if (v!=myIntervalHaltingVehicleDurations.end()) {
00219                 myPastIntervalStandingDurations.push_back((*v).second);
00220                 myIntervalHaltingVehicleDurations.erase(v);
00221             }
00222         }
00223 
00224         // jam-building
00225         if (isInJam) {
00226             // the vehicle is in a jam;
00227             //  it may be a new one or already an existing one
00228             if (currentJam==0) {
00229                 // the vehicle is the first vehicle in a jam
00230                 currentJam = new JamInfo;
00231                 currentJam->firstStandingVehicle = i;
00232             } else {
00233                 // ok, we have a jam already. But - maybe it is too far away
00234                 //  ... honestly, I can hardly find a reason for doing this,
00235                 //  but jams were defined this way in an earlier version...
00236                 if (veh->getPositionOnLane()-(*currentJam->lastStandingVehicle)->getPositionOnLane()>myJamDistanceThreshold) {
00237                     // yep, yep, yep - it's a new one...
00238                     //  close the frist, build a new
00239                     jams.push_back(currentJam);
00240                     currentJam = new JamInfo;
00241                     currentJam->firstStandingVehicle = i;
00242                 }
00243             }
00244             currentJam->lastStandingVehicle = i;
00245         } else {
00246             // the vehicle is not part of a jam...
00247             //  maybe we have to close an already computed jam
00248             if (currentJam!=0) {
00249                 jams.push_back(currentJam);
00250                 currentJam = 0;
00251             }
00252         }
00253     }
00254     if (currentJam!=0) {
00255         jams.push_back(currentJam);
00256         currentJam = 0;
00257     }
00258 
00259     myCurrentMaxJamLengthInMeters = 0;
00260     myCurrentMaxJamLengthInVehicles = 0;
00261     myCurrentJamLengthInMeters = 0;
00262     myCurrentJamLengthInVehicles = 0;
00263     // process jam information
00264     for (std::vector<JamInfo*>::iterator i=jams.begin(); i!=jams.end(); ++i) {
00265         // compute current jam's values
00266         SUMOReal jamLengthInMeters =
00267             (*(*i)->firstStandingVehicle)->getPositionOnLane()
00268             - (*(*i)->lastStandingVehicle)->getPositionOnLane()
00269             + (*(*i)->lastStandingVehicle)->getVehicleType().getLengthWithGap();
00270         const MSVehicle* const occ = myLane->getPartialOccupator();
00271         if (occ && occ == *(*i)->firstStandingVehicle && occ != *(*i)->lastStandingVehicle) {
00272             jamLengthInMeters = myLane->getPartialOccupatorEnd() +occ->getVehicleType().getLengthWithGap()
00273                                 - (*(*i)->lastStandingVehicle)->getPositionOnLane()
00274                                 + (*(*i)->lastStandingVehicle)->getVehicleType().getLengthWithGap();
00275         }
00276         unsigned jamLengthInVehicles = (unsigned) distance((*i)->firstStandingVehicle, (*i)->lastStandingVehicle) + 1;
00277         // apply them to the statistics
00278         myCurrentMaxJamLengthInMeters = MAX2(myCurrentMaxJamLengthInMeters, jamLengthInMeters);
00279         myCurrentMaxJamLengthInVehicles = MAX2(myCurrentMaxJamLengthInVehicles, jamLengthInVehicles);
00280         myJamLengthInMetersSum += jamLengthInMeters;
00281         myJamLengthInVehiclesSum += jamLengthInVehicles;
00282         myCurrentJamLengthInMeters += jamLengthInMeters;
00283         myCurrentJamLengthInVehicles += jamLengthInVehicles;
00284     }
00285     myCurrentJamNo = (unsigned) jams.size();
00286 
00287     unsigned noVehicles = (unsigned) myKnownVehicles.size();
00288     myVehicleSamples += noVehicles;
00289     myTimeSamples += 1;
00290     // compute occupancy values
00291     SUMOReal currentOccupancy = lengthSum / (myEndPos-myStartPos) * (SUMOReal) 100.;
00292     myCurrentOccupancy = currentOccupancy;
00293     myOccupancySum += currentOccupancy;
00294     myMaxOccupancy = MAX2(myMaxOccupancy, currentOccupancy);
00295     // compute jam values
00296     myMeanMaxJamInVehicles += myCurrentMaxJamLengthInVehicles;
00297     myMeanMaxJamInMeters += myCurrentMaxJamLengthInMeters;
00298     myMaxJamInVehicles = MAX2(myMaxJamInVehicles, myCurrentMaxJamLengthInVehicles);
00299     myMaxJamInMeters = MAX2(myMaxJamInMeters, myCurrentMaxJamLengthInMeters);
00300     // save information about halting vehicles
00301     myHaltingVehicleDurations = haltingVehicles;
00302     myIntervalHaltingVehicleDurations = intervalHaltingVehicles;
00303     // compute information about vehicle numbers
00304     myMeanVehicleNumber += (unsigned) myKnownVehicles.size();
00305     myMaxVehicleNumber = MAX2((unsigned) myKnownVehicles.size(), myMaxVehicleNumber);
00306     // norm current values
00307     myCurrentMeanSpeed = noVehicles!=0 ? myCurrentMeanSpeed / (SUMOReal) noVehicles : -1;
00308     myCurrentMeanLength = noVehicles!=0 ? myCurrentMeanLength / (SUMOReal) noVehicles : -1;
00309 
00310     // clean up
00311     for (std::vector<JamInfo*>::iterator i=jams.begin(); i!=jams.end(); ++i) {
00312         delete *i;
00313     }
00314     jams.clear();
00315 }
00316 
00317 
00318 
00319 void
00320 MSE2Collector::writeXMLOutput(OutputDevice& dev, SUMOTime startTime, SUMOTime stopTime) throw(IOError) {
00321     dev<<"   <interval begin=\""<<time2string(startTime)<<"\" end=\""<< time2string(stopTime)<<"\" "<<"id=\""<<getID()<<"\" ";
00322 
00323     const SUMOReal meanSpeed = myVehicleSamples!=0 ? mySpeedSum / (SUMOReal) myVehicleSamples : -1;
00324     const SUMOReal meanOccupancy = myTimeSamples!=0 ? myOccupancySum / (SUMOReal) myTimeSamples : 0;
00325     const SUMOReal meanJamLengthInMeters = myTimeSamples!=0 ? myMeanMaxJamInMeters / (SUMOReal) myTimeSamples : 0;
00326     const SUMOReal meanJamLengthInVehicles = myTimeSamples!=0 ? myMeanMaxJamInVehicles / (SUMOReal) myTimeSamples : 0;
00327     const SUMOReal meanVehicleNumber = myTimeSamples!=0 ? (SUMOReal) myMeanVehicleNumber / (SUMOReal) myTimeSamples : 0;
00328 
00329     SUMOTime haltingDurationSum = 0;
00330     SUMOTime maxHaltingDuration = 0;
00331     unsigned haltingNo = 0;
00332     for (std::vector<SUMOTime>::iterator i=myPastStandingDurations.begin(); i!=myPastStandingDurations.end(); ++i) {
00333         haltingDurationSum += (*i);
00334         maxHaltingDuration = MAX2(maxHaltingDuration, (*i));
00335         haltingNo++;
00336     }
00337     for (std::map<SUMOVehicle*, SUMOTime> ::iterator i=myHaltingVehicleDurations.begin(); i!=myHaltingVehicleDurations.end(); ++i) {
00338         haltingDurationSum += (*i).second;
00339         maxHaltingDuration = MAX2(maxHaltingDuration, (*i).second);
00340         haltingNo++;
00341     }
00342     const SUMOTime meanHaltingDuration = haltingNo!=0 ? haltingDurationSum / haltingNo : 0;
00343 
00344     SUMOTime intervalHaltingDurationSum = 0;
00345     SUMOTime intervalMaxHaltingDuration = 0;
00346     unsigned intervalHaltingNo = 0;
00347     for (std::vector<SUMOTime>::iterator i=myPastIntervalStandingDurations.begin(); i!=myPastIntervalStandingDurations.end(); ++i) {
00348         intervalHaltingDurationSum += (*i);
00349         intervalMaxHaltingDuration = MAX2(intervalMaxHaltingDuration, (*i));
00350         intervalHaltingNo++;
00351     }
00352     for (std::map<SUMOVehicle*, SUMOTime> ::iterator i=myIntervalHaltingVehicleDurations.begin(); i!=myIntervalHaltingVehicleDurations.end(); ++i) {
00353         intervalHaltingDurationSum += (*i).second;
00354         intervalMaxHaltingDuration = MAX2(intervalMaxHaltingDuration, (*i).second);
00355         intervalHaltingNo++;
00356     }
00357     const SUMOTime intervalMeanHaltingDuration = intervalHaltingNo!=0 ? intervalHaltingDurationSum / intervalHaltingNo : 0;
00358 
00359     dev << "nSamples=\"" << myVehicleSamples << "\" "
00360         << "meanSpeed=\"" << meanSpeed << "\" "
00361         << "meanOccupancy=\"" << meanOccupancy << "\" "
00362         << "maxOccupancy=\"" << myMaxOccupancy << "\" "
00363         << "meanMaxJamLengthInVehicles=\"" << meanJamLengthInVehicles << "\" "
00364         << "meanMaxJamLengthInMeters=\"" << meanJamLengthInMeters << "\" "
00365         << "maxJamLengthInVehicles=\"" << myMaxJamInVehicles << "\" "
00366         << "maxJamLengthInMeters=\"" << myMaxJamInMeters << "\" "
00367         << "jamLengthInVehiclesSum=\"" << myJamLengthInVehiclesSum << "\" "
00368         << "jamLengthInMetersSum=\"" << myJamLengthInMetersSum << "\" "
00369         << "meanHaltingDuration=\"" << STEPS2TIME(meanHaltingDuration) << "\" "
00370         << "maxHaltingDuration=\"" << STEPS2TIME(maxHaltingDuration) << "\" "
00371         << "haltingDurationSum=\"" << STEPS2TIME(haltingDurationSum) << "\" "
00372         << "meanIntervalHaltingDuration=\"" << STEPS2TIME(intervalMeanHaltingDuration) << "\" "
00373         << "maxIntervalHaltingDuration=\"" << STEPS2TIME(intervalMaxHaltingDuration) << "\" "
00374         << "intervalHaltingDurationSum=\"" << STEPS2TIME(intervalHaltingDurationSum) << "\" "
00375         << "startedHalts=\"" << myStartedHalts << "\" "
00376         << "meanVehicleNumber=\"" << meanVehicleNumber << "\" "
00377         << "maxVehicleNumber=\"" << myMaxVehicleNumber << "\" "
00378         << "/>\n";
00379     reset();
00380 }
00381 
00382 
00383 void
00384 MSE2Collector::writeXMLDetectorProlog(OutputDevice& dev) const throw(IOError) {
00385     dev.writeXMLHeader("detector");
00386 }
00387 
00388 
00389 unsigned
00390 MSE2Collector::getCurrentVehicleNumber() const throw() {
00391     return (unsigned) myKnownVehicles.size();
00392 }
00393 
00394 
00395 SUMOReal
00396 MSE2Collector::getCurrentOccupancy() const throw() {
00397     return myCurrentOccupancy *(SUMOReal) 100.;
00398 }
00399 
00400 
00401 SUMOReal
00402 MSE2Collector::getCurrentMeanSpeed() const throw() {
00403     return myCurrentMeanSpeed;
00404 }
00405 
00406 
00407 SUMOReal
00408 MSE2Collector::getCurrentMeanLength() const throw() {
00409     return myCurrentMeanLength;
00410 }
00411 
00412 
00413 unsigned
00414 MSE2Collector::getCurrentJamNumber() const throw() {
00415     return myCurrentJamNo;
00416 }
00417 
00418 
00419 unsigned
00420 MSE2Collector::getCurrentMaxJamLengthInVehicles() const throw() {
00421     return myCurrentMaxJamLengthInVehicles;
00422 }
00423 
00424 
00425 SUMOReal
00426 MSE2Collector::getCurrentMaxJamLengthInMeters() const throw() {
00427     return myCurrentMaxJamLengthInMeters;
00428 }
00429 
00430 
00431 unsigned
00432 MSE2Collector::getCurrentJamLengthInVehicles() const throw() {
00433     return myCurrentJamLengthInVehicles;
00434 }
00435 
00436 
00437 SUMOReal
00438 MSE2Collector::getCurrentJamLengthInMeters() const throw() {
00439     return myCurrentJamLengthInMeters;
00440 }
00441 
00442 
00443 unsigned
00444 MSE2Collector::getCurrentStartedHalts() const throw() {
00445     return myCurrentStartedHalts;
00446 }
00447 
00448 
00449 /****************************************************************************/
00450 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines