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