SUMO - Simulation of Urban MObility

MSE3Collector.cpp

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