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

Generated on Wed May 5 00:06:31 2010 for Sumo - Simulation of Urban MObility by  doxygen 1.5.6