SUMO - Simulation of Urban MObility
MSE3Collector.cpp
Go to the documentation of this file.
00001 /****************************************************************************/
00011 // A detector of vehicles passing an area between entry/exit points
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 // included modules
00027 // ===========================================================================
00028 #ifdef _MSC_VER
00029 #include <windows_config.h>
00030 #else
00031 #include <config.h>
00032 #endif
00033 
00034 #include <algorithm>
00035 
00036 #include "MSE3Collector.h"
00037 #include <microsim/MSNet.h>
00038 #include <microsim/MSVehicle.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 /* -------------------------------------------------------------------------
00049  * MSE3Collector::MSE3EntryReminder - definitions
00050  * ----------------------------------------------------------------------- */
00051 MSE3Collector::MSE3EntryReminder::MSE3EntryReminder(
00052     const MSCrossSection& crossSection, MSE3Collector& collector)
00053     : MSMoveReminder(crossSection.myLane),
00054       myCollector(collector), myPosition(crossSection.myPosition) {}
00055 
00056 
00057 bool
00058 MSE3Collector::MSE3EntryReminder::notifyMove(SUMOVehicle& veh, SUMOReal oldPos,
00059         SUMOReal newPos, SUMOReal newSpeed) {
00060     if (newPos < myPosition/* && static_cast<MSVehicle&>(veh).getLane() == myLane*/) {
00061         return true;
00062     }
00063     if (newPos >= myPosition && oldPos <= myPosition/* && static_cast<MSVehicle&>(veh).getLane() == myLane*/) {
00064         SUMOReal entryTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
00065         if (newSpeed != 0) {
00066             if (myPosition > oldPos) {
00067                 entryTime += (myPosition - oldPos) / newSpeed;
00068             }
00069         }
00070         myCollector.enter(veh, entryTime);
00071     }
00072     return myCollector.myEnteredContainer.find(&veh) != myCollector.myEnteredContainer.end();
00073 }
00074 
00075 
00076 bool
00077 MSE3Collector::MSE3EntryReminder::notifyLeave(SUMOVehicle& veh, SUMOReal, MSMoveReminder::Notification reason) {
00078     if (reason == MSMoveReminder::NOTIFICATION_ARRIVED) {
00079         myCollector.myEnteredContainer.erase(&veh);
00080         return false;
00081     }
00082     return myCollector.myEnteredContainer.find(&veh) != myCollector.myEnteredContainer.end();
00083 }
00084 
00085 
00086 /* -------------------------------------------------------------------------
00087  * MSE3Collector::MSE3LeaveReminder - definitions
00088  * ----------------------------------------------------------------------- */
00089 MSE3Collector::MSE3LeaveReminder::MSE3LeaveReminder(
00090     const MSCrossSection& crossSection, MSE3Collector& collector)
00091     : MSMoveReminder(crossSection.myLane),
00092       myCollector(collector), myPosition(crossSection.myPosition) {}
00093 
00094 
00095 bool
00096 MSE3Collector::MSE3LeaveReminder::notifyMove(SUMOVehicle& veh, SUMOReal oldPos,
00097         SUMOReal newPos, SUMOReal newSpeed) {
00098     if (newPos <= myPosition) {
00099         // crossSection not yet reached
00100         return true;
00101     }
00102     if (oldPos > myPosition) {
00103         // crossSection was not passed
00104         return false;
00105     }
00106     // crossSection left
00107     SUMOReal leaveTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
00108     if (myPosition > oldPos) {
00109         leaveTime += (myPosition - oldPos) / newSpeed;
00110     }
00111     myCollector.leave(veh, leaveTime);
00112     return false;
00113 }
00114 
00115 
00116 /* -------------------------------------------------------------------------
00117  * MSE3Collector - definitions
00118  * ----------------------------------------------------------------------- */
00119 MSE3Collector::MSE3Collector(const std::string& id,
00120                              const CrossSectionVector& entries,
00121                              const CrossSectionVector& exits,
00122                              SUMOReal haltingSpeedThreshold,
00123                              SUMOTime haltingTimeThreshold)
00124     : MSDetectorFileOutput(id), myEntries(entries), myExits(exits),
00125       myHaltingTimeThreshold(haltingTimeThreshold), myHaltingSpeedThreshold(haltingSpeedThreshold),
00126       myCurrentMeanSpeed(0), myCurrentHaltingsNumber(0), myCurrentTouchedVehicles(0),
00127       myLastResetTime(-1) {
00128     // Set MoveReminders to entries and exits
00129     for (CrossSectionVectorConstIt crossSec1 = entries.begin(); crossSec1 != entries.end(); ++crossSec1) {
00130         myEntryReminders.push_back(new MSE3EntryReminder(*crossSec1, *this));
00131     }
00132     for (CrossSectionVectorConstIt crossSec2 = exits.begin(); crossSec2 != exits.end(); ++crossSec2) {
00133         myLeaveReminders.push_back(new MSE3LeaveReminder(*crossSec2, *this));
00134     }
00135     reset();
00136 }
00137 
00138 
00139 MSE3Collector::~MSE3Collector() {
00140     for (std::vector<MSE3EntryReminder*>::iterator i = myEntryReminders.begin(); i != myEntryReminders.end(); ++i) {
00141         delete *i;
00142     }
00143     for (std::vector<MSE3LeaveReminder*>::iterator i = myLeaveReminders.begin(); i != myLeaveReminders.end(); ++i) {
00144         delete *i;
00145     }
00146 }
00147 
00148 
00149 void
00150 MSE3Collector::reset() {
00151     myLeftContainer.clear();
00152 }
00153 
00154 
00155 
00156 void
00157 MSE3Collector::enter(SUMOVehicle& veh, SUMOReal entryTimestep) {
00158     if (myEnteredContainer.find(&veh) != myEnteredContainer.end()) {
00159         WRITE_WARNING("Vehicle '" + veh.getID() + "' reentered " + toString(SUMO_TAG_E3DETECTOR) + " '" + getID() + "'.");
00160         return;
00161     }
00162     SUMOReal entryTimestepFraction = ((SUMOReal) DELTA_T - fmod(entryTimestep * 1000., 1000.)) / (SUMOReal) DELTA_T;
00163     SUMOReal speedFraction = (veh.getSpeed() * entryTimestepFraction);
00164     E3Values v;
00165     v.entryTime = entryTimestep;
00166     v.leaveTime = 0;
00167     v.speedSum = speedFraction / (1000. / (SUMOReal) DELTA_T);
00168     v.haltingBegin = veh.getSpeed() < myHaltingSpeedThreshold ? entryTimestep : -1;
00169     v.intervalSpeedSum = speedFraction / (1000. / (SUMOReal) DELTA_T);
00170     v.haltings = 0;
00171     v.intervalHaltings = 0;
00172     if (veh.getSpeed() < myHaltingSpeedThreshold) {
00173         if (1. - entryTimestepFraction > myHaltingTimeThreshold) {
00174             v.haltings++;
00175             v.intervalHaltings++;
00176         }
00177     }
00178     v.hadUpdate = false;
00179     myEnteredContainer[&veh] = v;
00180 }
00181 
00182 
00183 void
00184 MSE3Collector::leave(SUMOVehicle& veh, SUMOReal leaveTimestep) {
00185     if (myEnteredContainer.find(&veh) == myEnteredContainer.end()) {
00186         WRITE_WARNING("Vehicle '" + veh.getID() + "' left " + toString(SUMO_TAG_E3DETECTOR) + " '" + getID() + "' before entering it.");
00187     } else {
00188         E3Values values = myEnteredContainer[&veh];
00189         values.leaveTime = leaveTimestep;
00190         SUMOReal leaveTimestepFraction = leaveTimestep - (SUMOReal)((int) leaveTimestep);
00191         leaveTimestepFraction = fmod(leaveTimestep * 1000., 1000.) / (SUMOReal) DELTA_T;
00192         if (values.hadUpdate) {
00193             SUMOReal speedFraction = (veh.getSpeed() * leaveTimestepFraction);
00194             values.speedSum += speedFraction / (1000. / (SUMOReal) DELTA_T);
00195             values.intervalSpeedSum += speedFraction / (1000. / (SUMOReal) DELTA_T);
00196             if (veh.getSpeed() < myHaltingSpeedThreshold && values.haltingBegin != -1 && leaveTimestep - values.haltingBegin > myHaltingTimeThreshold) {
00197                 values.haltings++;
00198                 values.intervalHaltings++;
00199             }
00200         } else {
00201             SUMOReal speedFraction = (veh.getSpeed() * SUMOReal(1. - leaveTimestepFraction));
00202             values.speedSum -= speedFraction / (1000. / (SUMOReal) DELTA_T);
00203             values.intervalSpeedSum -= speedFraction / (1000. / (SUMOReal) DELTA_T);
00204         }
00205         myEnteredContainer.erase(&veh);
00206         myLeftContainer[&veh] = values;
00207     }
00208 }
00209 
00210 
00211 void
00212 MSE3Collector::writeXMLOutput(OutputDevice& dev,
00213                               SUMOTime startTime, SUMOTime stopTime) {
00214     dev << "   <interval begin=\"" << time2string(startTime) << "\" end=\"" << time2string(stopTime) << "\" " << "id=\"" << myID << "\" ";
00215     // collect values about vehicles that have left the area
00216     unsigned vehicleSum = (unsigned) myLeftContainer.size();
00217     SUMOReal meanTravelTime = 0.;
00218     SUMOReal meanSpeed = 0.;
00219     SUMOReal meanHaltsPerVehicle = 0.;
00220     for (std::map<SUMOVehicle*, E3Values>::iterator i = myLeftContainer.begin(); i != myLeftContainer.end(); ++i) {
00221         meanHaltsPerVehicle += (SUMOReal)(*i).second.haltings;
00222         SUMOReal steps = (*i).second.leaveTime - (*i).second.entryTime;
00223         meanTravelTime += steps;
00224         meanSpeed += ((*i).second.speedSum / steps);
00225     }
00226     meanTravelTime = vehicleSum != 0 ? meanTravelTime / (SUMOReal) vehicleSum : -1;
00227     meanSpeed = vehicleSum != 0 ?  meanSpeed / (SUMOReal) vehicleSum : -1;
00228     meanHaltsPerVehicle = vehicleSum != 0 ? meanHaltsPerVehicle / (SUMOReal) vehicleSum : -1;
00229     // clear container
00230     myLeftContainer.clear();
00231 
00232     // collect values about vehicles within the container
00233     unsigned vehicleSumWithin = (unsigned) myEnteredContainer.size();
00234     SUMOReal meanSpeedWithin = 0.;
00235     SUMOReal meanDurationWithin = 0.;
00236     SUMOReal meanHaltsPerVehicleWithin = 0.;
00237     SUMOReal meanIntervalSpeedWithin = 0.;
00238     SUMOReal meanIntervalHaltsPerVehicleWithin = 0.;
00239     SUMOReal meanIntervalDurationWithin = 0.;
00240     for (std::map<SUMOVehicle*, E3Values>::iterator i = myEnteredContainer.begin(); i != myEnteredContainer.end(); ++i) {
00241         meanHaltsPerVehicleWithin += (SUMOReal)(*i).second.haltings;
00242         meanIntervalHaltsPerVehicleWithin += (SUMOReal)(*i).second.intervalHaltings;
00243         SUMOReal time = (SUMOReal)stopTime / 1000. - (*i).second.entryTime;
00244         SUMOReal intLength = (SUMOReal)(stopTime - startTime) / 1000.;
00245         SUMOReal timeWithin = MIN2(time, intLength);
00246         meanSpeedWithin += ((*i).second.speedSum / time);
00247         meanIntervalSpeedWithin += ((*i).second.intervalSpeedSum / timeWithin);
00248         meanDurationWithin += time;
00249         meanIntervalDurationWithin += timeWithin;
00250         // reset interval values
00251         (*i).second.intervalHaltings = 0;
00252         (*i).second.intervalSpeedSum = 0;
00253     }
00254     myLastResetTime = stopTime;
00255     meanSpeedWithin = vehicleSumWithin != 0 ?  meanSpeedWithin / (SUMOReal) vehicleSumWithin : -1;
00256     meanHaltsPerVehicleWithin = vehicleSumWithin != 0 ? meanHaltsPerVehicleWithin / (SUMOReal) vehicleSumWithin : -1;
00257     meanDurationWithin = vehicleSumWithin != 0 ? meanDurationWithin / (SUMOReal) vehicleSumWithin : -1;
00258     meanIntervalSpeedWithin = vehicleSumWithin != 0 ?  meanIntervalSpeedWithin / (SUMOReal) vehicleSumWithin : -1;
00259     meanIntervalHaltsPerVehicleWithin = vehicleSumWithin != 0 ? meanIntervalHaltsPerVehicleWithin / (SUMOReal) vehicleSumWithin : -1;
00260     meanIntervalDurationWithin = vehicleSumWithin != 0 ? meanIntervalDurationWithin / (SUMOReal) vehicleSumWithin : -1;
00261 
00262     // write values
00263     dev << "meanTravelTime=\"" << meanTravelTime
00264         << "\" meanSpeed=\"" << meanSpeed
00265         << "\" meanHaltsPerVehicle=\"" << meanHaltsPerVehicle
00266         << "\" vehicleSum=\"" << vehicleSum
00267         << "\" meanSpeedWithin=\"" << meanSpeedWithin
00268         << "\" meanHaltsPerVehicleWithin=\"" << meanHaltsPerVehicleWithin
00269         << "\" meanDurationWithin=\"" << meanDurationWithin
00270         << "\" vehicleSumWithin=\"" << vehicleSumWithin
00271         << "\" meanIntervalSpeedWithin=\"" << meanIntervalSpeedWithin
00272         << "\" meanIntervalHaltsPerVehicleWithin=\"" << meanIntervalHaltsPerVehicleWithin
00273         << "\" meanIntervalDurationWithin=\"" << meanIntervalDurationWithin
00274         << "\"/>\n";
00275 }
00276 
00277 
00278 void
00279 MSE3Collector::writeXMLDetectorProlog(OutputDevice& dev) const {
00280     dev.writeXMLHeader("e3Detector");
00281 }
00282 
00283 
00284 void
00285 MSE3Collector::detectorUpdate(const SUMOTime step) {
00286     myCurrentMeanSpeed = 0;
00287     myCurrentHaltingsNumber = 0;
00288     myCurrentTouchedVehicles = 0;
00289     for (std::map<SUMOVehicle*, E3Values>::iterator pair = myEnteredContainer.begin(); pair != myEnteredContainer.end(); ++pair) {
00290         SUMOVehicle* veh = pair->first;
00291         E3Values& values = pair->second;
00292         values.hadUpdate = true;
00293         if (values.entryTime * 1000. >= step) {
00294             // vehicle entered at this time step
00295             SUMOReal fraction = step + 1. - values.entryTime;
00296             myCurrentMeanSpeed += fraction * veh->getSpeed();
00297             myCurrentTouchedVehicles += fraction;
00298             if (values.haltingBegin >= 0) {
00299                 myCurrentHaltingsNumber++;
00300             }
00301             continue;
00302         }
00303         values.speedSum += veh->getSpeed() * TS;
00304         values.intervalSpeedSum += veh->getSpeed() * TS;
00305         myCurrentMeanSpeed += veh->getSpeed();
00306         myCurrentTouchedVehicles += 1;
00307         if (veh->getSpeed() < myHaltingSpeedThreshold) {
00308             if (values.haltingBegin == -1) {
00309                 values.haltingBegin = step;
00310             }
00311             if (step - values.haltingBegin > myHaltingTimeThreshold) {
00312                 values.haltings++;
00313                 values.intervalHaltings++;
00314                 myCurrentHaltingsNumber++;
00315             }
00316         } else {
00317             values.haltingBegin = -1;
00318         }
00319         myCurrentMeanSpeed /= myCurrentTouchedVehicles;
00320     }
00321 }
00322 
00323 
00324 SUMOReal
00325 MSE3Collector::getCurrentMeanSpeed() const {
00326     SUMOReal ret = 0;
00327     if (myEnteredContainer.size() == 0) {
00328         return -1;
00329     }
00330     for (std::map<SUMOVehicle*, E3Values>::const_iterator pair = myEnteredContainer.begin(); pair != myEnteredContainer.end(); ++pair) {
00331         ret += (*pair).first->getSpeed();
00332     }
00333     return ret / SUMOReal(myEnteredContainer.size());
00334 }
00335 
00336 
00337 SUMOReal
00338 MSE3Collector::getCurrentHaltingNumber() const {
00339     return myCurrentHaltingsNumber;
00340 }
00341 
00342 
00343 SUMOReal
00344 MSE3Collector::getVehiclesWithin() const {
00345     return (SUMOReal) myEnteredContainer.size();
00346 }
00347 
00348 
00349 std::vector<std::string>
00350 MSE3Collector::getCurrentVehicleIDs() const {
00351     std::vector<std::string> ret;
00352     for (std::map<SUMOVehicle*, E3Values>::const_iterator pair = myEnteredContainer.begin(); pair != myEnteredContainer.end(); ++pair) {
00353         ret.push_back((*pair).first->getID());
00354     }
00355     std::sort(ret.begin(), ret.end());
00356     return ret;
00357 }
00358 
00359 
00360 /****************************************************************************/
00361 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines