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