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

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