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