|
SUMO - Simulation of Urban MObility
|
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