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-sim.org/
13 // Copyright (C) 2001-2014 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 <limits>
35 #include <microsim/MSEdgeControl.h>
36 #include <microsim/MSEdge.h>
37 #include <microsim/MSLane.h>
38 #include <microsim/MSVehicle.h>
39 #include <microsim/MSNet.h>
40 #include <utils/common/SUMOTime.h>
41 #include <utils/common/ToString.h>
43 #include "MSMeanData_Amitran.h"
44 #include "MSMeanData.h"
45 
46 #ifdef HAVE_INTERNAL
47 #include <microsim/MSGlobals.h>
48 #include <mesosim/MELoop.h>
49 #include <mesosim/MESegment.h>
50 #endif
51 
52 #ifdef CHECK_MEMORY_LEAKS
53 #include <foreign/nvwa/debug_new.h>
54 #endif // CHECK_MEMORY_LEAKS
55 
56 
57 // ===========================================================================
58 // method definitions
59 // ===========================================================================
60 // ---------------------------------------------------------------------------
61 // MSMeanData::MeanDataValues - methods
62 // ---------------------------------------------------------------------------
64  MSLane* const lane, const SUMOReal length, const bool doAdd,
65  const std::set<std::string>* const vTypes) :
66  MSMoveReminder("meandata_" + (lane == 0 ? "NULL" : lane->getID()), lane, doAdd),
67  myLaneLength(length),
68  sampleSeconds(0),
69  travelledDistance(0),
70  myVehicleTypes(vTypes) {}
71 
72 
74 }
75 
76 
77 bool
79  UNUSED_PARAMETER(reason);
80  return vehicleApplies(veh);
81 }
82 
83 
84 bool
86  // if the vehicle has arrived, the reminder must be kept so it can be
87  // notified of the arrival subsequently
88  SUMOReal timeOnLane = TS;
89  bool ret = true;
90  if (oldPos < 0 && newSpeed != 0) {
91  timeOnLane = newPos / newSpeed;
92  }
93  if (newPos - veh.getVehicleType().getLength() > myLaneLength && newSpeed != 0) {
94  timeOnLane -= (newPos - veh.getVehicleType().getLength() - myLaneLength) / newSpeed;
95  if (fabs(timeOnLane) < 0.001) { // reduce rounding errors
96  timeOnLane = 0.;
97  }
98  ret = veh.hasArrived();
99  }
100  if (timeOnLane < 0) {
101  WRITE_ERROR("Negative vehicle step fraction for '" + veh.getID() + "' on lane '" + getLane()->getID() + "'.");
102  return veh.hasArrived();
103  }
104  if (timeOnLane == 0) {
105  return veh.hasArrived();
106  }
107  notifyMoveInternal(veh, timeOnLane, newSpeed);
108  return ret;
109 }
110 
111 
112 bool
114  return reason == MSMoveReminder::NOTIFICATION_JUNCTION;
115 }
116 
117 
118 bool
120  return myVehicleTypes == 0 || myVehicleTypes->empty() ||
121  myVehicleTypes->find(veh.getVehicleType().getID()) != myVehicleTypes->end();
122 }
123 
124 
125 bool
127  return sampleSeconds == 0;
128 }
129 
130 
131 void
133 }
134 
135 
136 SUMOReal
138  return sampleSeconds;
139 }
140 
141 
142 // ---------------------------------------------------------------------------
143 // MSMeanData::MeanDataValueTracker - methods
144 // ---------------------------------------------------------------------------
146  const SUMOReal length,
147  const std::set<std::string>* const vTypes,
148  const MSMeanData* const parent)
149  : MSMeanData::MeanDataValues(lane, length, true, vTypes), myParent(parent) {
150  myCurrentData.push_back(new TrackerEntry(parent->createValues(lane, length, false)));
151 }
152 
153 
155 }
156 
157 
158 void
160  if (afterWrite) {
161  myCurrentData.pop_front();
162  } else {
163  myCurrentData.push_back(new TrackerEntry(myParent->createValues(myLane, myLaneLength, false)));
164  }
165 }
166 
167 
168 void
170  myCurrentData.front()->myValues->addTo(val);
171 }
172 
173 
174 void
176  myTrackedData[&veh]->myValues->notifyMoveInternal(veh, timeOnLane, speed);
177 }
178 
179 
180 bool
182  if (myParent == 0 || reason != MSMoveReminder::NOTIFICATION_SEGMENT) {
183  myTrackedData[&veh]->myNumVehicleLeft++;
184  }
185  return myTrackedData[&veh]->myValues->notifyLeave(veh, lastPos, reason);
186 }
187 
188 
189 bool
191  if (reason == MSMoveReminder::NOTIFICATION_SEGMENT) {
192  return true;
193  }
194  if (vehicleApplies(veh) && myTrackedData.find(&veh) == myTrackedData.end()) {
195  myTrackedData[&veh] = myCurrentData.back();
196  myTrackedData[&veh]->myNumVehicleEntered++;
197  if (!myTrackedData[&veh]->myValues->notifyEnter(veh, reason)) {
198  myTrackedData[&veh]->myNumVehicleLeft++;
199  myTrackedData.erase(&veh);
200  return false;
201  }
202  return true;
203  }
204  return false;
205 }
206 
207 
208 bool
210  return myCurrentData.front()->myValues->isEmpty();
211 }
212 
213 
214 void
216  const SUMOTime period,
217  const SUMOReal numLanes,
218  const SUMOReal defaultTravelTime,
219  const int /*numVehicles*/) const {
220  myCurrentData.front()->myValues->write(dev, period, numLanes,
221  defaultTravelTime,
222  myCurrentData.front()->myNumVehicleEntered);
223 }
224 
225 
226 int
228  int result = 0;
229  for (std::list<TrackerEntry*>::const_iterator it = myCurrentData.begin(); it != myCurrentData.end(); ++it) {
230  if ((*it)->myNumVehicleEntered == (*it)->myNumVehicleLeft) {
231  result++;
232  } else {
233  break;
234  }
235  }
236  return result;
237 }
238 
239 
240 SUMOReal
242  return myCurrentData.front()->myValues->getSamples();
243 }
244 
245 
246 // ---------------------------------------------------------------------------
247 // MSMeanData - methods
248 // ---------------------------------------------------------------------------
249 MSMeanData::MSMeanData(const std::string& id,
250  const SUMOTime dumpBegin, const SUMOTime dumpEnd,
251  const bool useLanes, const bool withEmpty,
252  const bool printDefaults, const bool withInternal, const bool trackVehicles,
253  const SUMOReal maxTravelTime,
254  const SUMOReal minSamples,
255  const std::set<std::string> vTypes) :
257  myMinSamples(minSamples),
258  myMaxTravelTime(maxTravelTime),
259  myVehicleTypes(vTypes),
260  myDumpEmpty(withEmpty),
261  myAmEdgeBased(!useLanes),
262  myDumpBegin(dumpBegin),
263  myDumpEnd(dumpEnd),
264  myPrintDefaults(printDefaults),
265  myDumpInternal(withInternal),
266  myTrackVehicles(trackVehicles) {
267 }
268 
269 
270 void
272  const std::vector<MSEdge*>& edges = MSNet::getInstance()->getEdgeControl().getEdges();
273  for (std::vector<MSEdge*>::const_iterator e = edges.begin(); e != edges.end(); ++e) {
274  if (myDumpInternal || (*e)->getPurpose() != MSEdge::EDGEFUNCTION_INTERNAL) {
275  myEdges.push_back(*e);
276  myMeasures.push_back(std::vector<MeanDataValues*>());
277  const std::vector<MSLane*>& lanes = (*e)->getLanes();
278 #ifdef HAVE_INTERNAL
280  MeanDataValues* data;
281  if (myTrackVehicles) {
282  data = new MeanDataValueTracker(0, lanes[0]->getLength(), &myVehicleTypes, this);
283  } else {
284  data = createValues(0, lanes[0]->getLength(), false);
285  }
286  myMeasures.back().push_back(data);
287  MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(**e);
288  while (s != 0) {
289  s->addDetector(data);
290  s->prepareDetectorForWriting(*data);
291  s = s->getNextSegment();
292  }
293  data->reset();
294  data->reset(true);
295  continue;
296  }
297 #endif
299  myMeasures.back().push_back(new MeanDataValueTracker(0, lanes[0]->getLength(), &myVehicleTypes, this));
300  }
301  for (std::vector<MSLane*>::const_iterator lane = lanes.begin(); lane != lanes.end(); ++lane) {
302  if (myTrackVehicles) {
303  if (myAmEdgeBased) {
304  (*lane)->addMoveReminder(myMeasures.back().back());
305  } else {
306  myMeasures.back().push_back(new MeanDataValueTracker(*lane, (*lane)->getLength(), &myVehicleTypes, this));
307  }
308  } else {
309  myMeasures.back().push_back(createValues(*lane, (*lane)->getLength(), true));
310  }
311  }
312  }
313  }
314 }
315 
316 
318  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
319  for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
320  delete *j;
321  }
322  }
323 }
324 
325 
326 void
328  UNUSED_PARAMETER(stopTime);
329 #ifdef HAVE_INTERNAL
331  std::vector<MSEdge*>::iterator edge = myEdges.begin();
332  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i, ++edge) {
333  MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(**edge);
334  MeanDataValues* data = i->front();
335  while (s != 0) {
336  s->prepareDetectorForWriting(*data);
337  s = s->getNextSegment();
338  }
339  data->reset();
340  }
341  return;
342  }
343 #endif
344  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
345  for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
346  (*j)->reset();
347  }
348  }
349 }
350 
351 
352 std::string
353 MSMeanData::getEdgeID(const MSEdge* const edge) {
354  return edge->getID();
355 }
356 
357 
358 void
360  const std::vector<MeanDataValues*>& edgeValues,
361  MSEdge* edge, SUMOTime startTime, SUMOTime stopTime) {
362 #ifdef HAVE_INTERNAL
364  MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
365  MeanDataValues* data = edgeValues.front();
366  while (s != 0) {
367  s->prepareDetectorForWriting(*data);
368  s = s->getNextSegment();
369  }
370  if (writePrefix(dev, *data, SUMO_TAG_EDGE, edge->getID())) {
371  data->write(dev, stopTime - startTime,
372  (SUMOReal)edge->getLanes().size(),
373  myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
374  }
375  data->reset(true);
376  return;
377  }
378 #endif
379  std::vector<MeanDataValues*>::const_iterator lane;
380  if (!myAmEdgeBased) {
381  bool writeCheck = myDumpEmpty;
382  if (!writeCheck) {
383  for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
384  if (!(*lane)->isEmpty()) {
385  writeCheck = true;
386  break;
387  }
388  }
389  }
390  if (writeCheck) {
392  }
393  for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
394  MeanDataValues& meanData = **lane;
395  if (writePrefix(dev, meanData, SUMO_TAG_LANE, meanData.getLane()->getID())) {
396  meanData.write(dev, stopTime - startTime, 1.f, myPrintDefaults ? meanData.getLane()->getLength() / meanData.getLane()->getSpeedLimit() : -1.);
397  }
398  meanData.reset(true);
399  }
400  if (writeCheck) {
401  dev.closeTag();
402  }
403  } else {
404  if (myTrackVehicles) {
405  MeanDataValues& meanData = **edgeValues.begin();
406  if (writePrefix(dev, meanData, SUMO_TAG_EDGE, edge->getID())) {
407  meanData.write(dev, stopTime - startTime, (SUMOReal)edge->getLanes().size(), myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
408  }
409  meanData.reset(true);
410  } else {
411  MeanDataValues* sumData = createValues(0, edge->getLength(), false);
412  for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
413  MeanDataValues& meanData = **lane;
414  meanData.addTo(*sumData);
415  meanData.reset();
416  }
417  if (writePrefix(dev, *sumData, SUMO_TAG_EDGE, getEdgeID(edge))) {
418  sumData->write(dev, stopTime - startTime, (SUMOReal)edge->getLanes().size(), myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
419  }
420  delete sumData;
421  }
422  }
423 }
424 
425 
426 void
427 MSMeanData::openInterval(OutputDevice& dev, const SUMOTime startTime, const SUMOTime stopTime) {
430 }
431 
432 
433 bool
434 MSMeanData::writePrefix(OutputDevice& dev, const MeanDataValues& values, const SumoXMLTag tag, const std::string id) const {
435  if (myDumpEmpty || !values.isEmpty()) {
436  dev.openTag(tag).writeAttr(SUMO_ATTR_ID, id).writeAttr("sampledSeconds", values.getSamples());
437  return true;
438  }
439  return false;
440 }
441 
442 
443 void
445  SUMOTime startTime, SUMOTime stopTime) {
446  // check whether this dump shall be written for the current time
447  int numReady = myDumpBegin < stopTime && myDumpEnd - DELTA_T >= startTime ? 1 : 0;
448  if (myTrackVehicles && myDumpBegin < stopTime) {
449  myPendingIntervals.push_back(std::make_pair(startTime, stopTime));
450  numReady = (int)myPendingIntervals.size();
451  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
452  for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
453  numReady = MIN2(numReady, ((MeanDataValueTracker*)*j)->getNumReady());
454  if (numReady == 0) {
455  break;
456  }
457  }
458  if (numReady == 0) {
459  break;
460  }
461  }
462  }
463  if (numReady == 0 || myTrackVehicles) {
464  resetOnly(stopTime);
465  }
466  while (numReady-- > 0) {
467  if (!myPendingIntervals.empty()) {
468  startTime = myPendingIntervals.front().first;
469  stopTime = myPendingIntervals.front().second;
470  myPendingIntervals.pop_front();
471  }
472  openInterval(dev, startTime, stopTime);
473  std::vector<MSEdge*>::iterator edge = myEdges.begin();
474  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i, ++edge) {
475  writeEdge(dev, (*i), *edge, startTime, stopTime);
476  }
477  dev.closeTag();
478  }
479 }
480 
481 
482 void
484  dev.writeXMLHeader("meandata", "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo-sim.org/xsd/meandata_file.xsd\"");
485 }
486 
487 
488 void
490  if (step + DELTA_T == myDumpBegin) {
491  init();
492  }
493 }
494 
495 
496 /****************************************************************************/
497