SUMO - Simulation of Urban MObility

MSE2Collector.cpp

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