|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00007 // Data collector for edges/lanes 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 // =========================================================================== 00022 // included modules 00023 // =========================================================================== 00024 #ifdef _MSC_VER 00025 #include <windows_config.h> 00026 #else 00027 #include <config.h> 00028 #endif 00029 00030 #include <microsim/MSEdgeControl.h> 00031 #include <microsim/MSEdge.h> 00032 #include <microsim/MSLane.h> 00033 #include <microsim/MSVehicle.h> 00034 #include <utils/common/SUMOTime.h> 00035 #include <utils/common/ToString.h> 00036 #include <utils/iodevices/OutputDevice.h> 00037 #include "MSMeanData.h" 00038 #include <limits> 00039 00040 #ifdef HAVE_MESOSIM 00041 #include <microsim/MSGlobals.h> 00042 #include <mesosim/MELoop.h> 00043 #include <mesosim/MESegment.h> 00044 #endif 00045 00046 #ifdef CHECK_MEMORY_LEAKS 00047 #include <foreign/nvwa/debug_new.h> 00048 #endif // CHECK_MEMORY_LEAKS 00049 00050 00051 // =========================================================================== 00052 // method definitions 00053 // =========================================================================== 00054 // --------------------------------------------------------------------------- 00055 // MSMeanData::MeanDataValues - methods 00056 // --------------------------------------------------------------------------- 00057 MSMeanData::MeanDataValues::MeanDataValues( 00058 MSLane* const lane, const SUMOReal length, const bool doAdd, 00059 const std::set<std::string>* const vTypes) throw() : 00060 MSMoveReminder(lane, doAdd), 00061 myLaneLength(length), 00062 sampleSeconds(0), 00063 travelledDistance(0), 00064 myVehicleTypes(vTypes) {} 00065 00066 00067 MSMeanData::MeanDataValues::~MeanDataValues() throw() { 00068 } 00069 00070 00071 bool 00072 MSMeanData::MeanDataValues::notifyEnter(SUMOVehicle& veh, MSMoveReminder::Notification reason) throw() { 00073 UNUSED_PARAMETER(reason); 00074 return vehicleApplies(veh); 00075 } 00076 00077 00078 bool 00079 MSMeanData::MeanDataValues::notifyMove(SUMOVehicle& veh, SUMOReal oldPos, SUMOReal newPos, SUMOReal newSpeed) throw() { 00080 SUMOReal timeOnLane = TS; 00081 bool ret = true; 00082 if (oldPos < 0 && newSpeed != 0) { 00083 timeOnLane = newPos / newSpeed; 00084 } 00085 if (newPos > myLaneLength && newSpeed != 0) { 00086 timeOnLane -= (newPos - myLaneLength) / newSpeed; 00087 if (fabs(timeOnLane) < 0.001) { // reduce rounding errors 00088 timeOnLane = 0.; 00089 } 00090 ret = false; 00091 } 00092 if (timeOnLane<0) { 00093 WRITE_ERROR("Negative vehicle step fraction for '" + veh.getID() + "' on lane '" + getLane()->getID() + "'."); 00094 return false; 00095 } 00096 if (timeOnLane==0) { 00097 return false; 00098 } 00099 notifyMoveInternal(veh, timeOnLane, newSpeed); 00100 return ret; 00101 } 00102 00103 00104 bool 00105 MSMeanData::MeanDataValues::notifyLeave(SUMOVehicle& /*veh*/, SUMOReal /*lastPos*/, MSMoveReminder::Notification reason) throw() { 00106 return reason == MSMoveReminder::NOTIFICATION_JUNCTION; 00107 } 00108 00109 00110 bool 00111 MSMeanData::MeanDataValues::vehicleApplies(const SUMOVehicle& veh) const throw() { 00112 return myVehicleTypes == 0 || myVehicleTypes->empty() || 00113 myVehicleTypes->find(veh.getVehicleType().getID()) != myVehicleTypes->end(); 00114 } 00115 00116 00117 bool 00118 MSMeanData::MeanDataValues::isEmpty() const throw() { 00119 return sampleSeconds == 0; 00120 } 00121 00122 00123 void 00124 MSMeanData::MeanDataValues::update() throw() { 00125 } 00126 00127 00128 SUMOReal 00129 MSMeanData::MeanDataValues::getSamples() const throw() { 00130 return sampleSeconds; 00131 } 00132 00133 00134 // --------------------------------------------------------------------------- 00135 // MSMeanData::MeanDataValueTracker - methods 00136 // --------------------------------------------------------------------------- 00137 MSMeanData::MeanDataValueTracker::MeanDataValueTracker(MSLane* const lane, 00138 const SUMOReal length, 00139 const std::set<std::string>* const vTypes, 00140 const MSMeanData* const parent) throw() 00141 : MSMeanData::MeanDataValues(lane, length, true, vTypes), myParent(parent) { 00142 myCurrentData.push_back(new TrackerEntry(parent->createValues(lane, length, false))); 00143 } 00144 00145 00146 MSMeanData::MeanDataValueTracker::~MeanDataValueTracker() throw() { 00147 } 00148 00149 00150 void 00151 MSMeanData::MeanDataValueTracker::reset(bool afterWrite) throw() { 00152 if (afterWrite) { 00153 myCurrentData.pop_front(); 00154 } else { 00155 myCurrentData.push_back(new TrackerEntry(myParent->createValues(myLane, myLaneLength, false))); 00156 } 00157 } 00158 00159 00160 void 00161 MSMeanData::MeanDataValueTracker::addTo(MSMeanData::MeanDataValues& val) const throw() { 00162 myCurrentData.front()->myValues->addTo(val); 00163 } 00164 00165 00166 void 00167 MSMeanData::MeanDataValueTracker::notifyMoveInternal(SUMOVehicle& veh, SUMOReal timeOnLane, SUMOReal speed) throw() { 00168 myTrackedData[&veh]->myValues->notifyMoveInternal(veh, timeOnLane, speed); 00169 } 00170 00171 00172 bool 00173 MSMeanData::MeanDataValueTracker::notifyLeave(SUMOVehicle& veh, SUMOReal lastPos, MSMoveReminder::Notification reason) throw() { 00174 if (myParent == 0 || reason != MSMoveReminder::NOTIFICATION_SEGMENT) { 00175 myTrackedData[&veh]->myNumVehicleLeft++; 00176 } 00177 return myTrackedData[&veh]->myValues->notifyLeave(veh, lastPos, reason); 00178 } 00179 00180 00181 bool 00182 MSMeanData::MeanDataValueTracker::notifyEnter(SUMOVehicle& veh, MSMoveReminder::Notification reason) throw() { 00183 if (reason == MSMoveReminder::NOTIFICATION_SEGMENT) { 00184 return true; 00185 } 00186 if (vehicleApplies(veh) && myTrackedData.find(&veh) == myTrackedData.end()) { 00187 myTrackedData[&veh] = myCurrentData.back(); 00188 myTrackedData[&veh]->myNumVehicleEntered++; 00189 if (!myTrackedData[&veh]->myValues->notifyEnter(veh, reason)) { 00190 myTrackedData[&veh]->myNumVehicleLeft++; 00191 myTrackedData.erase(&veh); 00192 return false; 00193 } 00194 return true; 00195 } 00196 return false; 00197 } 00198 00199 00200 bool 00201 MSMeanData::MeanDataValueTracker::isEmpty() const throw() { 00202 return myCurrentData.front()->myValues->isEmpty(); 00203 } 00204 00205 00206 void 00207 MSMeanData::MeanDataValueTracker::write(OutputDevice& dev, const SUMOTime period, 00208 const SUMOReal numLanes, const int /*numVehicles*/) const throw(IOError) { 00209 myCurrentData.front()->myValues->write(dev, period, numLanes, myCurrentData.front()->myNumVehicleEntered); 00210 } 00211 00212 00213 size_t 00214 MSMeanData::MeanDataValueTracker::getNumReady() const throw() { 00215 size_t result = 0; 00216 for (std::list<TrackerEntry*>::const_iterator it = myCurrentData.begin(); it != myCurrentData.end(); ++it) { 00217 if ((*it)->myNumVehicleEntered == (*it)->myNumVehicleLeft) { 00218 result++; 00219 } else { 00220 break; 00221 } 00222 } 00223 return result; 00224 } 00225 00226 00227 SUMOReal 00228 MSMeanData::MeanDataValueTracker::getSamples() const throw() { 00229 return myCurrentData.front()->myValues->getSamples(); 00230 } 00231 00232 00233 // --------------------------------------------------------------------------- 00234 // MSMeanData - methods 00235 // --------------------------------------------------------------------------- 00236 MSMeanData::MSMeanData(const std::string& id, 00237 const SUMOTime dumpBegin, const SUMOTime dumpEnd, 00238 const bool useLanes, const bool withEmpty, const bool withInternal, 00239 const bool trackVehicles, 00240 const SUMOReal maxTravelTime, const SUMOReal minSamples, 00241 const std::set<std::string> vTypes) throw() : 00242 MSDetectorFileOutput(id), 00243 myMinSamples(minSamples), 00244 myMaxTravelTime(maxTravelTime), 00245 myVehicleTypes(vTypes), 00246 myAmEdgeBased(!useLanes), 00247 myDumpBegin(dumpBegin), 00248 myDumpEnd(dumpEnd), 00249 myDumpEmpty(withEmpty), 00250 myDumpInternal(withInternal), 00251 myTrackVehicles(trackVehicles) { 00252 } 00253 00254 00255 void 00256 MSMeanData::init() throw() { 00257 const std::vector<MSEdge*> &edges = MSNet::getInstance()->getEdgeControl().getEdges(); 00258 for (std::vector<MSEdge*>::const_iterator e = edges.begin(); e != edges.end(); ++e) { 00259 if (myDumpInternal || (*e)->getPurpose() != MSEdge::EDGEFUNCTION_INTERNAL) { 00260 myEdges.push_back(*e); 00261 myMeasures.push_back(std::vector<MeanDataValues*>()); 00262 const std::vector<MSLane*> &lanes = (*e)->getLanes(); 00263 #ifdef HAVE_MESOSIM 00264 if (MSGlobals::gUseMesoSim) { 00265 MeanDataValues* data; 00266 if (myTrackVehicles) { 00267 data = new MeanDataValueTracker(0, lanes[0]->getLength(), &myVehicleTypes, this); 00268 } else { 00269 data = createValues(0, lanes[0]->getLength(), false); 00270 } 00271 myMeasures.back().push_back(data); 00272 MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(**e); 00273 while (s!=0) { 00274 s->addDetector(data); 00275 s->prepareDetectorForWriting(*data); 00276 s = s->getNextSegment(); 00277 } 00278 data->reset(); 00279 data->reset(true); 00280 continue; 00281 } 00282 #endif 00283 if (myAmEdgeBased && myTrackVehicles) { 00284 myMeasures.back().push_back(new MeanDataValueTracker(0, lanes[0]->getLength(), &myVehicleTypes, this)); 00285 } 00286 for (std::vector<MSLane*>::const_iterator lane = lanes.begin(); lane != lanes.end(); ++lane) { 00287 if (myTrackVehicles) { 00288 if (myAmEdgeBased) { 00289 (*lane)->addMoveReminder(myMeasures.back().back()); 00290 } else { 00291 myMeasures.back().push_back(new MeanDataValueTracker(*lane, (*lane)->getLength(), &myVehicleTypes, this)); 00292 } 00293 } else { 00294 myMeasures.back().push_back(createValues(*lane, (*lane)->getLength(), true)); 00295 } 00296 } 00297 } 00298 } 00299 } 00300 00301 00302 MSMeanData::~MSMeanData() throw() { 00303 for (std::vector<std::vector<MeanDataValues*> >::const_iterator i=myMeasures.begin(); i!=myMeasures.end(); ++i) { 00304 for (std::vector<MeanDataValues*>::const_iterator j=(*i).begin(); j!=(*i).end(); ++j) { 00305 delete *j; 00306 } 00307 } 00308 } 00309 00310 00311 void 00312 MSMeanData::resetOnly(SUMOTime stopTime) throw() { 00313 UNUSED_PARAMETER(stopTime); 00314 #ifdef HAVE_MESOSIM 00315 if (MSGlobals::gUseMesoSim) { 00316 std::vector<MSEdge*>::iterator edge = myEdges.begin(); 00317 for (std::vector<std::vector<MeanDataValues*> >::const_iterator i=myMeasures.begin(); i!=myMeasures.end(); ++i, ++edge) { 00318 MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(**edge); 00319 MeanDataValues* data = i->front(); 00320 while (s!=0) { 00321 s->prepareDetectorForWriting(*data); 00322 s = s->getNextSegment(); 00323 } 00324 data->reset(); 00325 } 00326 return; 00327 } 00328 #endif 00329 for (std::vector<std::vector<MeanDataValues*> >::const_iterator i=myMeasures.begin(); i!=myMeasures.end(); ++i) { 00330 for (std::vector<MeanDataValues*>::const_iterator j=(*i).begin(); j!=(*i).end(); ++j) { 00331 (*j)->reset(); 00332 } 00333 } 00334 } 00335 00336 00337 void 00338 MSMeanData::writeEdge(OutputDevice& dev, 00339 const std::vector<MeanDataValues*> &edgeValues, 00340 MSEdge* edge, SUMOTime startTime, SUMOTime stopTime) throw(IOError) { 00341 #ifdef HAVE_MESOSIM 00342 if (MSGlobals::gUseMesoSim) { 00343 MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge); 00344 MeanDataValues* data = edgeValues.front(); 00345 while (s!=0) { 00346 s->prepareDetectorForWriting(*data); 00347 s = s->getNextSegment(); 00348 } 00349 if (writePrefix(dev, *data, "<edge id=\""+edge->getID())) { 00350 data->write(dev, stopTime - startTime, 00351 (SUMOReal)edge->getLanes().size()); 00352 } 00353 data->reset(true); 00354 return; 00355 } 00356 #endif 00357 std::vector<MeanDataValues*>::const_iterator lane; 00358 if (!myAmEdgeBased) { 00359 bool writeCheck = myDumpEmpty; 00360 if (!writeCheck) { 00361 for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) { 00362 if (!(*lane)->isEmpty()) { 00363 writeCheck = true; 00364 break; 00365 } 00366 } 00367 } 00368 if (writeCheck) { 00369 dev.openTag("edge")<<" id=\""<<edge->getID()<<"\">\n"; 00370 } 00371 for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) { 00372 MeanDataValues& meanData = **lane; 00373 if (writePrefix(dev, meanData, "<lane id=\""+meanData.getLane()->getID())) { 00374 meanData.write(dev, stopTime - startTime, 1.f); 00375 } 00376 meanData.reset(true); 00377 } 00378 if (writeCheck) { 00379 dev.closeTag(); 00380 } 00381 } else { 00382 if (myTrackVehicles) { 00383 MeanDataValues& meanData = **edgeValues.begin(); 00384 if (writePrefix(dev, meanData, "<edge id=\""+edge->getID())) { 00385 meanData.write(dev, stopTime - startTime, (SUMOReal)edge->getLanes().size()); 00386 } 00387 meanData.reset(true); 00388 } else { 00389 MeanDataValues* sumData = createValues(0, edge->getLanes()[0]->getLength(), false); 00390 for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) { 00391 MeanDataValues& meanData = **lane; 00392 meanData.addTo(*sumData); 00393 meanData.reset(); 00394 } 00395 if (writePrefix(dev, *sumData, "<edge id=\""+edge->getID())) { 00396 sumData->write(dev, stopTime - startTime, (SUMOReal)edge->getLanes().size()); 00397 } 00398 delete sumData; 00399 } 00400 } 00401 } 00402 00403 00404 bool 00405 MSMeanData::writePrefix(OutputDevice& dev, const MeanDataValues& values, const std::string prefix) const throw(IOError) { 00406 if (myDumpEmpty || !values.isEmpty()) { 00407 dev.indent() << prefix << "\" sampledSeconds=\"" << values.getSamples(); 00408 return true; 00409 } 00410 return false; 00411 } 00412 00413 00414 void 00415 MSMeanData::writeXMLOutput(OutputDevice& dev, 00416 SUMOTime startTime, SUMOTime stopTime) throw(IOError) { 00417 // check whether this dump shall be written for the current time 00418 size_t numReady = myDumpBegin < stopTime && myDumpEnd-DELTA_T >= startTime; 00419 if (myTrackVehicles && myDumpBegin < stopTime) { 00420 myPendingIntervals.push_back(std::make_pair(startTime, stopTime)); 00421 numReady = myPendingIntervals.size(); 00422 for (std::vector<std::vector<MeanDataValues*> >::const_iterator i=myMeasures.begin(); i!=myMeasures.end(); ++i) { 00423 for (std::vector<MeanDataValues*>::const_iterator j=(*i).begin(); j!=(*i).end(); ++j) { 00424 numReady = MIN2(numReady, ((MeanDataValueTracker*)*j)->getNumReady()); 00425 if (numReady == 0) { 00426 break; 00427 } 00428 } 00429 if (numReady == 0) { 00430 break; 00431 } 00432 } 00433 } 00434 if (numReady == 0 || myTrackVehicles) { 00435 resetOnly(stopTime); 00436 } 00437 while (numReady-- > 0) { 00438 if (!myPendingIntervals.empty()) { 00439 startTime = myPendingIntervals.front().first; 00440 stopTime = myPendingIntervals.front().second; 00441 myPendingIntervals.pop_front(); 00442 } 00443 dev.openTag("interval")<<" begin=\""<<time2string(startTime)<<"\" end=\""<< 00444 time2string(stopTime)<<"\" "<<"id=\""<<myID<<"\">\n"; 00445 std::vector<MSEdge*>::iterator edge = myEdges.begin(); 00446 for (std::vector<std::vector<MeanDataValues*> >::const_iterator i=myMeasures.begin(); i!=myMeasures.end(); ++i, ++edge) { 00447 writeEdge(dev, (*i), *edge, startTime, stopTime); 00448 } 00449 dev.closeTag(); 00450 } 00451 } 00452 00453 00454 void 00455 MSMeanData::writeXMLDetectorProlog(OutputDevice& dev) const throw(IOError) { 00456 dev.writeXMLHeader("netstats"); 00457 } 00458 00459 00460 void 00461 MSMeanData::detectorUpdate(const SUMOTime step) throw() { 00462 if (step + DELTA_T == myDumpBegin) { 00463 init(); 00464 } 00465 } 00466 00467 00468 /****************************************************************************/ 00469