00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00042
00043
00044
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
00057 return true;
00058 }
00059 if (oldPos > myPosition) {
00060
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
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
00093 return true;
00094 }
00095 if (oldPos > myPosition) {
00096
00097 return false;
00098 }
00099
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
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
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
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
00249 myLeftContainer.clear();
00250
00251
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
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
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
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