SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MSMeanData.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // Data collector for edges/lanes
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
13 // Copyright (C) 2001-2013 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #include <microsim/MSEdgeControl.h>
35 #include <microsim/MSEdge.h>
36 #include <microsim/MSLane.h>
37 #include <microsim/MSVehicle.h>
38 #include <microsim/MSNet.h>
39 #include <utils/common/SUMOTime.h>
40 #include <utils/common/ToString.h>
42 #include "MSMeanData.h"
43 #include <limits>
44 
45 #ifdef HAVE_INTERNAL
46 #include <microsim/MSGlobals.h>
47 #include <mesosim/MELoop.h>
48 #include <mesosim/MESegment.h>
49 #endif
50 
51 #ifdef CHECK_MEMORY_LEAKS
52 #include <foreign/nvwa/debug_new.h>
53 #endif // CHECK_MEMORY_LEAKS
54 
55 
56 // ===========================================================================
57 // method definitions
58 // ===========================================================================
59 // ---------------------------------------------------------------------------
60 // MSMeanData::MeanDataValues - methods
61 // ---------------------------------------------------------------------------
63  MSLane* const lane, const SUMOReal length, const bool doAdd,
64  const std::set<std::string>* const vTypes) :
65  MSMoveReminder(lane, doAdd),
66  myLaneLength(length),
67  sampleSeconds(0),
68  travelledDistance(0),
69  myVehicleTypes(vTypes) {}
70 
71 
73 }
74 
75 
76 bool
78  UNUSED_PARAMETER(reason);
79  return vehicleApplies(veh);
80 }
81 
82 
83 bool
85  // if the vehicle has arrived, the reminder must be kept so it can be
86  // notified of the arrival subsequently
87  SUMOReal timeOnLane = TS;
88  bool ret = true;
89  if (oldPos < 0 && newSpeed != 0) {
90  timeOnLane = newPos / newSpeed;
91  }
92  if (newPos - veh.getVehicleType().getLength() > myLaneLength && newSpeed != 0) {
93  timeOnLane -= (newPos - veh.getVehicleType().getLength() - myLaneLength) / newSpeed;
94  if (fabs(timeOnLane) < 0.001) { // reduce rounding errors
95  timeOnLane = 0.;
96  }
97  ret = veh.hasArrived();
98  }
99  if (timeOnLane < 0) {
100  WRITE_ERROR("Negative vehicle step fraction for '" + veh.getID() + "' on lane '" + getLane()->getID() + "'.");
101  return veh.hasArrived();
102  }
103  if (timeOnLane == 0) {
104  return veh.hasArrived();
105  }
106  notifyMoveInternal(veh, timeOnLane, newSpeed);
107  return ret;
108 }
109 
110 
111 bool
113  return reason == MSMoveReminder::NOTIFICATION_JUNCTION;
114 }
115 
116 
117 bool
119  return myVehicleTypes == 0 || myVehicleTypes->empty() ||
120  myVehicleTypes->find(veh.getVehicleType().getID()) != myVehicleTypes->end();
121 }
122 
123 
124 bool
126  return sampleSeconds == 0;
127 }
128 
129 
130 void
132 }
133 
134 
135 SUMOReal
137  return sampleSeconds;
138 }
139 
140 
141 // ---------------------------------------------------------------------------
142 // MSMeanData::MeanDataValueTracker - methods
143 // ---------------------------------------------------------------------------
145  const SUMOReal length,
146  const std::set<std::string>* const vTypes,
147  const MSMeanData* const parent)
148  : MSMeanData::MeanDataValues(lane, length, true, vTypes), myParent(parent) {
149  myCurrentData.push_back(new TrackerEntry(parent->createValues(lane, length, false)));
150 }
151 
152 
154 }
155 
156 
157 void
159  if (afterWrite) {
160  myCurrentData.pop_front();
161  } else {
162  myCurrentData.push_back(new TrackerEntry(myParent->createValues(myLane, myLaneLength, false)));
163  }
164 }
165 
166 
167 void
169  myCurrentData.front()->myValues->addTo(val);
170 }
171 
172 
173 void
175  myTrackedData[&veh]->myValues->notifyMoveInternal(veh, timeOnLane, speed);
176 }
177 
178 
179 bool
181  if (myParent == 0 || reason != MSMoveReminder::NOTIFICATION_SEGMENT) {
182  myTrackedData[&veh]->myNumVehicleLeft++;
183  }
184  return myTrackedData[&veh]->myValues->notifyLeave(veh, lastPos, reason);
185 }
186 
187 
188 bool
190  if (reason == MSMoveReminder::NOTIFICATION_SEGMENT) {
191  return true;
192  }
193  if (vehicleApplies(veh) && myTrackedData.find(&veh) == myTrackedData.end()) {
194  myTrackedData[&veh] = myCurrentData.back();
195  myTrackedData[&veh]->myNumVehicleEntered++;
196  if (!myTrackedData[&veh]->myValues->notifyEnter(veh, reason)) {
197  myTrackedData[&veh]->myNumVehicleLeft++;
198  myTrackedData.erase(&veh);
199  return false;
200  }
201  return true;
202  }
203  return false;
204 }
205 
206 
207 bool
209  return myCurrentData.front()->myValues->isEmpty();
210 }
211 
212 
213 void
215  const SUMOTime period,
216  const SUMOReal numLanes,
217  const SUMOReal defaultTravelTime,
218  const int /*numVehicles*/) const {
219  myCurrentData.front()->myValues->write(dev, period, numLanes,
220  defaultTravelTime,
221  myCurrentData.front()->myNumVehicleEntered);
222 }
223 
224 
225 size_t
227  size_t result = 0;
228  for (std::list<TrackerEntry*>::const_iterator it = myCurrentData.begin(); it != myCurrentData.end(); ++it) {
229  if ((*it)->myNumVehicleEntered == (*it)->myNumVehicleLeft) {
230  result++;
231  } else {
232  break;
233  }
234  }
235  return result;
236 }
237 
238 
239 SUMOReal
241  return myCurrentData.front()->myValues->getSamples();
242 }
243 
244 
245 // ---------------------------------------------------------------------------
246 // MSMeanData - methods
247 // ---------------------------------------------------------------------------
248 MSMeanData::MSMeanData(const std::string& id,
249  const SUMOTime dumpBegin, const SUMOTime dumpEnd,
250  const bool useLanes, const bool withEmpty,
251  const bool printDefaults, const bool withInternal, const bool trackVehicles,
252  const SUMOReal maxTravelTime,
253  const SUMOReal minSamples,
254  const std::set<std::string> vTypes) :
256  myMinSamples(minSamples),
257  myMaxTravelTime(maxTravelTime),
258  myVehicleTypes(vTypes),
259  myAmEdgeBased(!useLanes),
260  myDumpBegin(dumpBegin),
261  myDumpEnd(dumpEnd),
262  myDumpEmpty(withEmpty),
263  myPrintDefaults(printDefaults),
264  myDumpInternal(withInternal),
265  myTrackVehicles(trackVehicles) {
266 }
267 
268 
269 void
271  const std::vector<MSEdge*>& edges = MSNet::getInstance()->getEdgeControl().getEdges();
272  for (std::vector<MSEdge*>::const_iterator e = edges.begin(); e != edges.end(); ++e) {
273  if (myDumpInternal || (*e)->getPurpose() != MSEdge::EDGEFUNCTION_INTERNAL) {
274  myEdges.push_back(*e);
275  myMeasures.push_back(std::vector<MeanDataValues*>());
276  const std::vector<MSLane*>& lanes = (*e)->getLanes();
277 #ifdef HAVE_INTERNAL
279  MeanDataValues* data;
280  if (myTrackVehicles) {
281  data = new MeanDataValueTracker(0, lanes[0]->getLength(), &myVehicleTypes, this);
282  } else {
283  data = createValues(0, lanes[0]->getLength(), false);
284  }
285  myMeasures.back().push_back(data);
286  MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(**e);
287  while (s != 0) {
288  s->addDetector(data);
289  s->prepareDetectorForWriting(*data);
290  s = s->getNextSegment();
291  }
292  data->reset();
293  data->reset(true);
294  continue;
295  }
296 #endif
298  myMeasures.back().push_back(new MeanDataValueTracker(0, lanes[0]->getLength(), &myVehicleTypes, this));
299  }
300  for (std::vector<MSLane*>::const_iterator lane = lanes.begin(); lane != lanes.end(); ++lane) {
301  if (myTrackVehicles) {
302  if (myAmEdgeBased) {
303  (*lane)->addMoveReminder(myMeasures.back().back());
304  } else {
305  myMeasures.back().push_back(new MeanDataValueTracker(*lane, (*lane)->getLength(), &myVehicleTypes, this));
306  }
307  } else {
308  myMeasures.back().push_back(createValues(*lane, (*lane)->getLength(), true));
309  }
310  }
311  }
312  }
313 }
314 
315 
317  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
318  for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
319  delete *j;
320  }
321  }
322 }
323 
324 
325 void
327  UNUSED_PARAMETER(stopTime);
328 #ifdef HAVE_INTERNAL
330  std::vector<MSEdge*>::iterator edge = myEdges.begin();
331  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i, ++edge) {
332  MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(**edge);
333  MeanDataValues* data = i->front();
334  while (s != 0) {
335  s->prepareDetectorForWriting(*data);
336  s = s->getNextSegment();
337  }
338  data->reset();
339  }
340  return;
341  }
342 #endif
343  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
344  for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
345  (*j)->reset();
346  }
347  }
348 }
349 
350 
351 void
353  const std::vector<MeanDataValues*>& edgeValues,
354  MSEdge* edge, SUMOTime startTime, SUMOTime stopTime) {
355 #ifdef HAVE_INTERNAL
357  MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
358  MeanDataValues* data = edgeValues.front();
359  while (s != 0) {
360  s->prepareDetectorForWriting(*data);
361  s = s->getNextSegment();
362  }
363  if (writePrefix(dev, *data, SUMO_TAG_EDGE, edge->getID())) {
364  data->write(dev, stopTime - startTime,
365  (SUMOReal)edge->getLanes().size(),
366  myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
367  }
368  data->reset(true);
369  return;
370  }
371 #endif
372  std::vector<MeanDataValues*>::const_iterator lane;
373  if (!myAmEdgeBased) {
374  bool writeCheck = myDumpEmpty;
375  if (!writeCheck) {
376  for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
377  if (!(*lane)->isEmpty()) {
378  writeCheck = true;
379  break;
380  }
381  }
382  }
383  if (writeCheck) {
385  }
386  for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
387  MeanDataValues& meanData = **lane;
388  if (writePrefix(dev, meanData, SUMO_TAG_LANE, meanData.getLane()->getID())) {
389  meanData.write(dev, stopTime - startTime, 1.f, myPrintDefaults ? meanData.getLane()->getLength() / meanData.getLane()->getSpeedLimit() : -1.);
390  }
391  meanData.reset(true);
392  }
393  if (writeCheck) {
394  dev.closeTag();
395  }
396  } else {
397  if (myTrackVehicles) {
398  MeanDataValues& meanData = **edgeValues.begin();
399  if (writePrefix(dev, meanData, SUMO_TAG_EDGE, edge->getID())) {
400  meanData.write(dev, stopTime - startTime, (SUMOReal)edge->getLanes().size(), myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
401  }
402  meanData.reset(true);
403  } else {
404  MeanDataValues* sumData = createValues(0, edge->getLength(), false);
405  for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
406  MeanDataValues& meanData = **lane;
407  meanData.addTo(*sumData);
408  meanData.reset();
409  }
410  if (writePrefix(dev, *sumData, SUMO_TAG_EDGE, edge->getID())) {
411  sumData->write(dev, stopTime - startTime, (SUMOReal)edge->getLanes().size(), myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
412  }
413  delete sumData;
414  }
415  }
416 }
417 
418 
419 bool
420 MSMeanData::writePrefix(OutputDevice& dev, const MeanDataValues& values, const SumoXMLTag tag, const std::string id) const {
421  if (myDumpEmpty || !values.isEmpty()) {
422  dev.openTag(tag).writeAttr(SUMO_ATTR_ID, id) << " sampledSeconds=\"" << values.getSamples();
423  return true;
424  }
425  return false;
426 }
427 
428 
429 void
431  SUMOTime startTime, SUMOTime stopTime) {
432  // check whether this dump shall be written for the current time
433  size_t numReady = myDumpBegin < stopTime && myDumpEnd - DELTA_T >= startTime;
434  if (myTrackVehicles && myDumpBegin < stopTime) {
435  myPendingIntervals.push_back(std::make_pair(startTime, stopTime));
436  numReady = myPendingIntervals.size();
437  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
438  for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
439  numReady = MIN2(numReady, ((MeanDataValueTracker*)*j)->getNumReady());
440  if (numReady == 0) {
441  break;
442  }
443  }
444  if (numReady == 0) {
445  break;
446  }
447  }
448  }
449  if (numReady == 0 || myTrackVehicles) {
450  resetOnly(stopTime);
451  }
452  while (numReady-- > 0) {
453  if (!myPendingIntervals.empty()) {
454  startTime = myPendingIntervals.front().first;
455  stopTime = myPendingIntervals.front().second;
456  myPendingIntervals.pop_front();
457  }
460  std::vector<MSEdge*>::iterator edge = myEdges.begin();
461  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i, ++edge) {
462  writeEdge(dev, (*i), *edge, startTime, stopTime);
463  }
464  dev.closeTag();
465  }
466 }
467 
468 
469 void
471  dev.writeXMLHeader("meandata", "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.sf.net/xsd/meandata_file.xsd\"");
472 }
473 
474 
475 void
477  if (step + DELTA_T == myDumpBegin) {
478  init();
479  }
480 }
481 
482 
483 /****************************************************************************/
484