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