Eclipse SUMO - Simulation of Urban MObility
MSMeanData.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
19 // Data collector for edges/lanes
20 /****************************************************************************/
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #include <config.h>
27 
28 #include <limits>
29 #include <microsim/MSEdgeControl.h>
30 #include <microsim/MSEdge.h>
31 #include <microsim/MSLane.h>
32 #include <microsim/MSVehicle.h>
34 #include <microsim/MSNet.h>
35 #include <utils/common/SUMOTime.h>
36 #include <utils/common/ToString.h>
38 #include "MSMeanData_Amitran.h"
39 #include "MSMeanData.h"
40 
41 #include <microsim/MSGlobals.h>
42 #include <mesosim/MESegment.h>
43 #include <mesosim/MELoop.h>
44 
45 
46 // ===========================================================================
47 // debug constants
48 // ===========================================================================
49 //#define DEBUG_NOTIFY_MOVE
50 //#define DEBUG_NOTIFY_ENTER
51 
52 // ===========================================================================
53 // method definitions
54 // ===========================================================================
55 // ---------------------------------------------------------------------------
56 // MSMeanData::MeanDataValues - methods
57 // ---------------------------------------------------------------------------
59  MSLane* const lane, const double length, const bool doAdd,
60  const MSMeanData* const parent) :
61  MSMoveReminder("meandata_" + (lane == nullptr ? "NULL" : lane->getID()), lane, doAdd),
62  myParent(parent),
63  myLaneLength(length),
64  sampleSeconds(0),
65  travelledDistance(0) {}
66 
67 
69 }
70 
71 
72 bool
74 #ifdef DEBUG_NOTIFY_ENTER
75  std::cout << "\n" << SIMTIME << " MSMeanData_Net::MSLaneMeanDataValues: veh '" << veh.getID() << "' enters lane '" << enteredLane->getID() << "'" << std::endl;
76 #else
77  UNUSED_PARAMETER(enteredLane);
78 #endif
79  UNUSED_PARAMETER(reason);
80  return myParent == nullptr || myParent->vehicleApplies(veh);
81 }
82 
83 
84 bool
85 MSMeanData::MeanDataValues::notifyMove(SUMOTrafficObject& veh, double oldPos, double newPos, double newSpeed) {
86  // if the vehicle has arrived, the reminder must be kept so it can be
87  // notified of the arrival subsequently
88  const double oldSpeed = veh.getPreviousSpeed();
89  double enterSpeed = MSGlobals::gSemiImplicitEulerUpdate ? newSpeed : oldSpeed; // NOTE: For the euler update, the vehicle is assumed to travel at constant speed for the whole time step
90  double leaveSpeed = newSpeed, leaveSpeedFront = newSpeed;
91 
92  // These values will be further decreased below
93  double timeOnLane = TS;
94  double frontOnLane = oldPos > myLaneLength ? 0. : TS;
95  bool ret = true;
96 
97  // entry and exit times (will be modified below)
98  double timeBeforeEnter = 0.;
99  double timeBeforeEnterBack = 0.;
100  double timeBeforeLeaveFront = newPos < myLaneLength ? TS : 0.;
101  double timeBeforeLeave = TS;
102 
103  // Treat the case that the vehicle entered the lane in the last step
104  if (oldPos < 0 && newPos >= 0) {
105  // Vehicle was not on this lane in the last time step
106  timeBeforeEnter = MSCFModel::passingTime(oldPos, 0, newPos, oldSpeed, newSpeed);
107  timeOnLane = TS - timeBeforeEnter;
108  frontOnLane = timeOnLane;
109  enterSpeed = MSCFModel::speedAfterTime(timeBeforeEnter, oldSpeed, newPos - oldPos);
110  }
111 
112  const double oldBackPos = oldPos - veh.getVehicleType().getLength();
113  const double newBackPos = newPos - veh.getVehicleType().getLength();
114 
115  // Determine the time before the vehicle back enters
116  if (oldBackPos < 0. && newBackPos > 0.) {
117  timeBeforeEnterBack = MSCFModel::passingTime(oldBackPos, 0., newBackPos, oldSpeed, newSpeed);
118  } else if (newBackPos <= 0) {
119  timeBeforeEnterBack = TS;
120  } else {
121  timeBeforeEnterBack = 0.;
122  }
123 
124  // Treat the case that the vehicle's back left the lane in the last step
125  if (newBackPos > myLaneLength // vehicle's back has left the lane
126  && oldBackPos <= myLaneLength) { // and hasn't left the lane before
127  assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the lane boundary otherwise
128  // (Leo) vehicle left this lane (it can also have skipped over it in one time step -> therefore we use "timeOnLane -= ..." and ( ... - timeOnLane) below)
129  timeBeforeLeave = MSCFModel::passingTime(oldBackPos, myLaneLength, newBackPos, oldSpeed, newSpeed);
130  const double timeAfterLeave = TS - timeBeforeLeave;
131  timeOnLane -= timeAfterLeave;
132  leaveSpeed = MSCFModel::speedAfterTime(timeBeforeLeave, oldSpeed, newPos - oldPos);
133  // XXX: Do we really need this? Why would this "reduce rounding errors"? (Leo) Refs. #2579
134  if (fabs(timeOnLane) < NUMERICAL_EPS) { // reduce rounding errors
135  timeOnLane = 0.;
136  }
137  ret = veh.hasArrived();
138  }
139 
140  // Treat the case that the vehicle's front left the lane in the last step
141  if (newPos > myLaneLength && oldPos <= myLaneLength) {
142  // vehicle's front has left the lane and has not left before
143  assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0);
144  timeBeforeLeaveFront = MSCFModel::passingTime(oldPos, myLaneLength, newPos, oldSpeed, newSpeed);
145  const double timeAfterLeave = TS - timeBeforeLeaveFront;
146  frontOnLane -= timeAfterLeave;
147  // XXX: Do we really need this? Why would this "reduce rounding errors"? (Leo) Refs. #2579
148  if (fabs(frontOnLane) < NUMERICAL_EPS) { // reduce rounding errors
149  frontOnLane = 0.;
150  }
151  leaveSpeedFront = MSCFModel::speedAfterTime(timeBeforeLeaveFront, oldSpeed, newPos - oldPos);
152  }
153 
154  assert(frontOnLane <= TS);
155  assert(timeOnLane <= TS);
156 
157  if (timeOnLane < 0) {
158  WRITE_ERROR("Negative vehicle step fraction for '" + veh.getID() + "' on lane '" + getLane()->getID() + "'.");
159  return veh.hasArrived();
160  }
161  if (timeOnLane == 0) {
162  return veh.hasArrived();
163  }
164 
165 #ifdef DEBUG_NOTIFY_MOVE
166  std::stringstream ss;
167  ss << "\n"
168  << "lane length: " << myLaneLength
169  << "\noldPos: " << oldPos
170  << "\nnewPos: " << newPos
171  << "\noldPosBack: " << oldBackPos
172  << "\nnewPosBack: " << newBackPos
173  << "\ntimeBeforeEnter: " << timeBeforeEnter
174  << "\ntimeBeforeEnterBack: " << timeBeforeEnterBack
175  << "\ntimeBeforeLeaveFront: " << timeBeforeLeaveFront
176  << "\ntimeBeforeLeave: " << timeBeforeLeave;
177  if (!(timeBeforeLeave >= MAX2(timeBeforeEnterBack, timeBeforeLeaveFront))
178  || !(timeBeforeEnter <= MIN2(timeBeforeEnterBack, timeBeforeLeaveFront))) {
179  WRITE_ERROR(ss.str());
180  } else {
181  std::cout << ss.str() << std::endl;
182  }
183 
184 #endif
185 
186  assert(timeBeforeEnter <= MIN2(timeBeforeEnterBack, timeBeforeLeaveFront));
187  assert(timeBeforeLeave >= MAX2(timeBeforeEnterBack, timeBeforeLeaveFront));
188  // compute average vehicle length on lane in last step
189  double vehLength = veh.getVehicleType().getLength();
190  // occupied lane length at timeBeforeEnter (resp. stepStart if already on lane)
191  double lengthOnLaneAtStepStart = MAX2(0., MIN4(myLaneLength, vehLength, vehLength - (oldPos - myLaneLength), oldPos));
192  // occupied lane length at timeBeforeLeave (resp. stepEnd if still on lane)
193  double lengthOnLaneAtStepEnd = MAX2(0., MIN4(myLaneLength, vehLength, vehLength - (newPos - myLaneLength), newPos));
194  double integratedLengthOnLane = 0.;
195  if (timeBeforeEnterBack < timeBeforeLeaveFront) {
196  // => timeBeforeLeaveFront>0, myLaneLength>vehLength
197  // vehicle length on detector at timeBeforeEnterBack
198  double lengthOnLaneAtBackEnter = MIN2(veh.getVehicleType().getLength(), newPos);
199  // linear quadrature of occupancy between timeBeforeEnter and timeBeforeEnterBack
200  integratedLengthOnLane += (timeBeforeEnterBack - timeBeforeEnter) * (lengthOnLaneAtBackEnter + lengthOnLaneAtStepStart) * 0.5;
201  // linear quadrature of occupancy between timeBeforeEnterBack and timeBeforeLeaveFront
202  // (vehicle is completely on the edge in between)
203  integratedLengthOnLane += (timeBeforeLeaveFront - timeBeforeEnterBack) * vehLength;
204  // and until vehicle leaves/stepEnd
205  integratedLengthOnLane += (timeBeforeLeave - timeBeforeLeaveFront) * (vehLength + lengthOnLaneAtStepEnd) * 0.5;
206  } else if (timeBeforeEnterBack >= timeBeforeLeaveFront) {
207  // => myLaneLength <= vehLength or (timeBeforeLeaveFront == timeBeforeEnterBack == 0)
208  // vehicle length on detector at timeBeforeLeaveFront
209  double lengthOnLaneAtLeaveFront;
210  if (timeBeforeLeaveFront == timeBeforeEnter) {
211  // for the case that front already left
212  lengthOnLaneAtLeaveFront = lengthOnLaneAtStepStart;
213  } else if (timeBeforeLeaveFront == timeBeforeLeave) {
214  // for the case that front doesn't leave in this step
215  lengthOnLaneAtLeaveFront = lengthOnLaneAtStepEnd;
216  } else {
217  lengthOnLaneAtLeaveFront = myLaneLength;
218  }
219 #ifdef DEBUG_NOTIFY_MOVE
220  std::cout << "lengthOnLaneAtLeaveFront=" << lengthOnLaneAtLeaveFront << std::endl;
221 #endif
222  // linear quadrature of occupancy between timeBeforeEnter and timeBeforeLeaveFront
223  integratedLengthOnLane += (timeBeforeLeaveFront - timeBeforeEnter) * (lengthOnLaneAtLeaveFront + lengthOnLaneAtStepStart) * 0.5;
224  // linear quadrature of occupancy between timeBeforeLeaveFront and timeBeforeEnterBack
225  integratedLengthOnLane += (timeBeforeEnterBack - timeBeforeLeaveFront) * lengthOnLaneAtLeaveFront;
226  // and until vehicle leaves/stepEnd
227  integratedLengthOnLane += (timeBeforeLeave - timeBeforeEnterBack) * (lengthOnLaneAtLeaveFront + lengthOnLaneAtStepEnd) * 0.5;
228  }
229 
230  double meanLengthOnLane = integratedLengthOnLane / TS;
231 #ifdef DEBUG_NOTIFY_MOVE
232  std::cout << "Calculated mean length on lane '" << myLane->getID() << "' in last step as " << meanLengthOnLane
233  << "\nlengthOnLaneAtStepStart=" << lengthOnLaneAtStepStart << ", lengthOnLaneAtStepEnd=" << lengthOnLaneAtStepEnd << ", integratedLengthOnLane=" << integratedLengthOnLane
234  << std::endl;
235 #endif
236 
237 // // XXX: use this, when #2556 is fixed! Refs. #2575
238 // const double travelledDistanceFrontOnLane = MAX2(0., MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.));
239 // const double travelledDistanceVehicleOnLane = MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.) + MIN2(MAX2(0., newPos - myLaneLength), veh.getVehicleType().getLength());
240 // // XXX: #2556 fixed for ballistic update
241  const double travelledDistanceFrontOnLane = MSGlobals::gSemiImplicitEulerUpdate ? frontOnLane * newSpeed
242  : MAX2(0., MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.));
243  const double travelledDistanceVehicleOnLane = MSGlobals::gSemiImplicitEulerUpdate ? timeOnLane * newSpeed
244  : MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.) + MIN2(MAX2(0., newPos - myLaneLength), veh.getVehicleType().getLength());
245 // // XXX: no fix
246 // const double travelledDistanceFrontOnLane = frontOnLane*newSpeed;
247 // const double travelledDistanceVehicleOnLane = timeOnLane*newSpeed;
248 
249  notifyMoveInternal(veh, frontOnLane, timeOnLane, (enterSpeed + leaveSpeedFront) / 2., (enterSpeed + leaveSpeed) / 2., travelledDistanceFrontOnLane, travelledDistanceVehicleOnLane, meanLengthOnLane);
250  return ret;
251 }
252 
253 
254 bool
255 MSMeanData::MeanDataValues::notifyLeave(SUMOTrafficObject& /*veh*/, double /*lastPos*/, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
257  return false; // reminder is re-added on every segment (@recheck for performance)
258  }
259  return reason == MSMoveReminder::NOTIFICATION_JUNCTION;
260 }
261 
262 
263 bool
265  return sampleSeconds == 0;
266 }
267 
268 
269 void
271 }
272 
273 
274 double
276  return sampleSeconds;
277 }
278 
279 
280 // ---------------------------------------------------------------------------
281 // MSMeanData::MeanDataValueTracker - methods
282 // ---------------------------------------------------------------------------
284  const double length,
285  const MSMeanData* const parent)
286  : MSMeanData::MeanDataValues(lane, length, true, parent) {
287  myCurrentData.push_back(new TrackerEntry(parent->createValues(lane, length, false)));
288 }
289 
290 
292  std::list<TrackerEntry*>::iterator i;
293  for (i = myCurrentData.begin(); i != myCurrentData.end(); i++) {
294  delete *i;
295  }
296 
297  // FIXME: myTrackedData may still hold some undeleted TrackerEntries. When to delete those? (Leo), refers to #2251
298  // code below fails
299 
300 // std::map<SUMOTrafficObject*, TrackerEntry*>::iterator j;
301 // for(j=myTrackedData.begin(); j!=myTrackedData.end();j++){
302 // delete j->second;
303 // }
304 }
305 
306 
307 void
309  if (afterWrite) {
310  if (myCurrentData.begin() != myCurrentData.end()) {
311  myCurrentData.pop_front();
312  }
313  } else {
315  }
316 }
317 
318 
319 void
321  myCurrentData.front()->myValues->addTo(val);
322 }
323 
324 
325 void
326 MSMeanData::MeanDataValueTracker::notifyMoveInternal(const SUMOTrafficObject& veh, const double frontOnLane, const double timeOnLane, const double meanSpeedFrontOnLane, const double meanSpeedVehicleOnLane, const double travelledDistanceFrontOnLane, const double travelledDistanceVehicleOnLane, const double meanLengthOnLane) {
327  myTrackedData[&veh]->myValues->notifyMoveInternal(veh, frontOnLane, timeOnLane, meanSpeedFrontOnLane, meanSpeedVehicleOnLane, travelledDistanceFrontOnLane, travelledDistanceVehicleOnLane, meanLengthOnLane);
328 }
329 
330 
331 bool
333  if (myParent == nullptr || reason != MSMoveReminder::NOTIFICATION_SEGMENT) {
334  myTrackedData[&veh]->myNumVehicleLeft++;
335  }
336  return myTrackedData[&veh]->myValues->notifyLeave(veh, lastPos, reason);
337 }
338 
339 
340 bool
342 #ifdef DEBUG_NOTIFY_ENTER
343  std::cout << "\n" << SIMTIME << " MSMeanData::MeanDataValueTracker: veh '" << veh.getID() << "' enters lane '" << enteredLane->getID() << "'" << std::endl;
344 #else
345  UNUSED_PARAMETER(enteredLane);
346 #endif
347  if (reason == MSMoveReminder::NOTIFICATION_SEGMENT) {
348  return true;
349  }
350  if (myParent->vehicleApplies(veh) && myTrackedData.find(&veh) == myTrackedData.end()) {
351  myTrackedData[&veh] = myCurrentData.back();
352  myTrackedData[&veh]->myNumVehicleEntered++;
353  if (!myTrackedData[&veh]->myValues->notifyEnter(veh, reason)) {
354  myTrackedData[&veh]->myNumVehicleLeft++;
355  myTrackedData.erase(&veh);
356  return false;
357  }
358  return true;
359  }
360  return false;
361 }
362 
363 
364 bool
366  return myCurrentData.front()->myValues->isEmpty();
367 }
368 
369 
370 void
372  const SUMOTime period,
373  const double numLanes,
374  const double defaultTravelTime,
375  const int /*numVehicles*/) const {
376  myCurrentData.front()->myValues->write(dev, period, numLanes,
377  defaultTravelTime,
378  myCurrentData.front()->myNumVehicleEntered);
379 }
380 
381 
382 int
384  int result = 0;
385  for (std::list<TrackerEntry*>::const_iterator it = myCurrentData.begin(); it != myCurrentData.end(); ++it) {
386  if ((*it)->myNumVehicleEntered == (*it)->myNumVehicleLeft) {
387  result++;
388  } else {
389  break;
390  }
391  }
392  return result;
393 }
394 
395 
396 double
398  return myCurrentData.front()->myValues->getSamples();
399 }
400 
401 
402 // ---------------------------------------------------------------------------
403 // MSMeanData - methods
404 // ---------------------------------------------------------------------------
405 MSMeanData::MSMeanData(const std::string& id,
406  const SUMOTime dumpBegin, const SUMOTime dumpEnd,
407  const bool useLanes, const bool withEmpty,
408  const bool printDefaults, const bool withInternal,
409  const bool trackVehicles,
410  const int detectPersons,
411  const double maxTravelTime,
412  const double minSamples,
413  const std::string& vTypes) :
414  MSDetectorFileOutput(id, vTypes, detectPersons),
415  myMinSamples(minSamples),
416  myMaxTravelTime(maxTravelTime),
417  myDumpEmpty(withEmpty),
418  myAmEdgeBased(!useLanes),
419  myDumpBegin(dumpBegin),
420  myDumpEnd(dumpEnd),
421  myPrintDefaults(printDefaults),
422  myDumpInternal(withInternal),
423  myTrackVehicles(trackVehicles) {
424 }
425 
426 
427 void
430  for (MSEdgeVector::const_iterator e = edges.begin(); e != edges.end(); ++e) {
431  if ((myDumpInternal || !(*e)->isInternal()) &&
432  ((detectPersons() && myDumpInternal) || (!(*e)->isCrossing() && !(*e)->isWalkingArea()))) {
433  myEdges.push_back(*e);
434  myMeasures.push_back(std::vector<MeanDataValues*>());
435  const std::vector<MSLane*>& lanes = (*e)->getLanes();
437  MeanDataValues* data;
438  if (myTrackVehicles) {
439  data = new MeanDataValueTracker(nullptr, lanes[0]->getLength(), this);
440  } else {
441  data = createValues(nullptr, lanes[0]->getLength(), false);
442  }
443  data->setDescription("meandata_" + (*e)->getID());
444  myMeasures.back().push_back(data);
446  while (s != nullptr) {
447  s->addDetector(data);
448  s->prepareDetectorForWriting(*data);
449  s = s->getNextSegment();
450  }
451  data->reset();
452  data->reset(true);
453  continue;
454  }
456  myMeasures.back().push_back(new MeanDataValueTracker(nullptr, lanes[0]->getLength(), this));
457  }
458  for (std::vector<MSLane*>::const_iterator lane = lanes.begin(); lane != lanes.end(); ++lane) {
459  if (myTrackVehicles) {
460  if (myAmEdgeBased) {
461  (*lane)->addMoveReminder(myMeasures.back().back());
462  } else {
463  myMeasures.back().push_back(new MeanDataValueTracker(*lane, (*lane)->getLength(), this));
464  }
465  } else {
466  myMeasures.back().push_back(createValues(*lane, (*lane)->getLength(), true));
467  }
468  }
469  }
470  }
471 }
472 
473 
475  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
476  for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
477  delete *j;
478  }
479  }
480 }
481 
482 
483 void
485  UNUSED_PARAMETER(stopTime);
487  MSEdgeVector::iterator edge = myEdges.begin();
488  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i, ++edge) {
490  MeanDataValues* data = i->front();
491  while (s != nullptr) {
492  s->prepareDetectorForWriting(*data);
493  s = s->getNextSegment();
494  }
495  data->reset();
496  }
497  return;
498  }
499  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
500  for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
501  (*j)->reset();
502  }
503  }
504 }
505 
506 
507 std::string
508 MSMeanData::getEdgeID(const MSEdge* const edge) {
509  return edge->getID();
510 }
511 
512 
513 void
515  const std::vector<MeanDataValues*>& edgeValues,
516  MSEdge* edge, SUMOTime startTime, SUMOTime stopTime) {
519  MeanDataValues* data = edgeValues.front();
520  while (s != nullptr) {
521  s->prepareDetectorForWriting(*data);
522  s = s->getNextSegment();
523  }
524  if (writePrefix(dev, *data, SUMO_TAG_EDGE, getEdgeID(edge))) {
525  data->write(dev, stopTime - startTime,
526  (double)edge->getLanes().size(),
527  myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
528  }
529  data->reset(true);
530  return;
531  }
532  std::vector<MeanDataValues*>::const_iterator lane;
533  if (!myAmEdgeBased) {
534  bool writeCheck = myDumpEmpty;
535  if (!writeCheck) {
536  for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
537  if (!(*lane)->isEmpty()) {
538  writeCheck = true;
539  break;
540  }
541  }
542  }
543  if (writeCheck) {
545  }
546  for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
547  MeanDataValues& meanData = **lane;
548  if (writePrefix(dev, meanData, SUMO_TAG_LANE, meanData.getLane()->getID())) {
549  meanData.write(dev, stopTime - startTime, 1.f, myPrintDefaults ? meanData.getLane()->getLength() / meanData.getLane()->getSpeedLimit() : -1.);
550  }
551  meanData.reset(true);
552  }
553  if (writeCheck) {
554  dev.closeTag();
555  }
556  } else {
557  if (myTrackVehicles) {
558  MeanDataValues& meanData = **edgeValues.begin();
559  if (writePrefix(dev, meanData, SUMO_TAG_EDGE, edge->getID())) {
560  meanData.write(dev, stopTime - startTime, (double)edge->getLanes().size(), myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
561  }
562  meanData.reset(true);
563  } else {
564  MeanDataValues* sumData = createValues(nullptr, edge->getLength(), false);
565  for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
566  MeanDataValues& meanData = **lane;
567  meanData.addTo(*sumData);
568  meanData.reset();
569  }
570  if (writePrefix(dev, *sumData, SUMO_TAG_EDGE, getEdgeID(edge))) {
571  sumData->write(dev, stopTime - startTime, (double)edge->getLanes().size(), myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
572  }
573  delete sumData;
574  }
575  }
576 }
577 
578 
579 void
580 MSMeanData::openInterval(OutputDevice& dev, const SUMOTime startTime, const SUMOTime stopTime) {
583 }
584 
585 
586 bool
587 MSMeanData::writePrefix(OutputDevice& dev, const MeanDataValues& values, const SumoXMLTag tag, const std::string id) const {
588  if (myDumpEmpty || !values.isEmpty()) {
589  dev.openTag(tag).writeAttr(SUMO_ATTR_ID, id).writeAttr("sampledSeconds", values.getSamples());
590  return true;
591  }
592  return false;
593 }
594 
595 
596 void
598  SUMOTime startTime, SUMOTime stopTime) {
599  // check whether this dump shall be written for the current time
600  int numReady = myDumpBegin < stopTime && myDumpEnd - DELTA_T >= startTime ? 1 : 0;
601  if (myTrackVehicles && myDumpBegin < stopTime) {
602  myPendingIntervals.push_back(std::make_pair(startTime, stopTime));
603  numReady = (int)myPendingIntervals.size();
604  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
605  for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
606  numReady = MIN2(numReady, ((MeanDataValueTracker*)*j)->getNumReady());
607  if (numReady == 0) {
608  break;
609  }
610  }
611  if (numReady == 0) {
612  break;
613  }
614  }
615  }
616  if (numReady == 0 || myTrackVehicles) {
617  resetOnly(stopTime);
618  }
619  while (numReady-- > 0) {
620  if (!myPendingIntervals.empty()) {
621  startTime = myPendingIntervals.front().first;
622  stopTime = myPendingIntervals.front().second;
623  myPendingIntervals.pop_front();
624  }
625  openInterval(dev, startTime, stopTime);
626  MSEdgeVector::iterator edge = myEdges.begin();
627  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i, ++edge) {
628  writeEdge(dev, (*i), *edge, startTime, stopTime);
629  }
630  dev.closeTag();
631  }
632  dev.flush();
633 }
634 
635 
636 void
638  dev.writeXMLHeader("meandata", "meandata_file.xsd");
639 }
640 
641 
642 void
644  if (step + DELTA_T == myDumpBegin) {
645  init();
646  }
647 }
648 
649 
650 /****************************************************************************/
651 
static double speedAfterTime(const double t, const double oldSpeed, const double dist)
Calculates the speed after a time t [0,TS] given the initial speed and the distance traveled in an i...
Definition: MSCFModel.cpp:674
MESegment * getNextSegment() const
Returns the following segment on the same edge (0 if it is the last).
Definition: MESegment.h:152
Data collector for edges/lanes.
Definition: MSMeanData.h:60
virtual ~MeanDataValueTracker()
Destructor.
Definition: MSMeanData.cpp:291
const MSLane * getLane() const
Returns the lane the reminder works on.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:256
SumoXMLTag
Numbers representing SUMO-XML - element names.
bool vehicleApplies(const SUMOTrafficObject &veh) const
Checks whether the detector measures vehicles of the given type.
long long int SUMOTime
Definition: SUMOTime.h:35
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition: MELoop.cpp:293
std::vector< std::vector< MeanDataValues * > > myMeasures
Value collectors; sorted by edge, then by lane.
Definition: MSMeanData.h:430
virtual const MSVehicleType & getVehicleType() const =0
Returns the vehicle&#39;s type.
begin/end of the description of a single lane
virtual const std::string & getID() const =0
Get the vehicle&#39;s ID.
const bool myDumpInternal
Whether internal lanes/edges shall be written.
Definition: MSMeanData.h:449
MeanDataValueTracker(MSLane *const lane, const double length, const MSMeanData *const parent)
Constructor.
Definition: MSMeanData.cpp:283
bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Computes current values and adds them to their sums.
Definition: MSMeanData.cpp:341
double getSamples() const
Returns the number of collected sample seconds.
Definition: MSMeanData.cpp:397
const SUMOTime myDumpEnd
Definition: MSMeanData.h:440
const double myMaxTravelTime
the maximum travel time to write
Definition: MSMeanData.h:427
The vehicle arrived at a junction.
T MIN4(T a, T b, T c, T d)
Definition: StdDefs.h:101
virtual bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Called if the vehicle enters the reminder&#39;s lane.
Definition: MSMeanData.cpp:73
MSLane *const myLane
Lane on which the reminder works.
bool isEmpty() const
Returns whether any data was collected.
Definition: MSMeanData.cpp:365
Notification
Definition of a vehicle state.
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:65
virtual void write(OutputDevice &dev, const SUMOTime period, const double numLanes, const double defaultTravelTime, const int numVehicles=-1) const =0
Writes output values into the given stream.
weights: time range begin
const std::vector< MSLane * > & getLanes() const
Returns this edge&#39;s lanes.
Definition: MSEdge.h:165
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:168
T MAX2(T a, T b)
Definition: StdDefs.h:80
virtual bool isEmpty() const
Returns whether any data was collected.
Definition: MSMeanData.cpp:264
SUMOTime DELTA_T
Definition: SUMOTime.cpp:35
double getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:541
The vehicle changes the segment (meso only)
const std::string & getID() const
Returns the id.
Definition: Named.h:77
#define TS
Definition: SUMOTime.h:44
double getLength() const
return the length of the edge
Definition: MSEdge.h:582
void notifyMoveInternal(const SUMOTrafficObject &veh, const double frontOnLane, const double timeOnLane, const double meanSpeedFrontOnLane, const double meanSpeedVehicleOnLane, const double travelledDistanceFrontOnLane, const double travelledDistanceVehicleOnLane, const double meanLengthOnLane)
Internal notification about the vehicle moves.
Definition: MSMeanData.cpp:326
double getSpeedLimit() const
Returns the speed limit of the edge The speed limit of the first lane is retured; should probably be...
Definition: MSEdge.cpp:916
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:32
virtual void notifyMoveInternal(const SUMOTrafficObject &veh, const double frontOnLane, const double timeOnLane, const double meanSpeedFrontOnLane, const double meanSpeedVehicleOnLane, const double travelledDistanceFrontOnLane, const double travelledDistanceVehicleOnLane, const double meanLengthOnLane)
Internal notification about the vehicle moves.
#define SIMTIME
Definition: SUMOTime.h:64
std::list< TrackerEntry * > myCurrentData
The currently active meandata "intervals".
Definition: MSMeanData.h:285
virtual MSMeanData::MeanDataValues * createValues(MSLane *const lane, const double length, const bool doAdd) const =0
Create an instance of MeanDataValues.
void addTo(MSMeanData::MeanDataValues &val) const
Add the values of this to the given one and store them there.
Definition: MSMeanData.cpp:320
A road/street connecting two junctions.
Definition: MSEdge.h:76
const bool myPrintDefaults
Whether empty lanes/edges shall be written.
Definition: MSMeanData.h:446
bool notifyMove(SUMOTrafficObject &veh, double oldPos, double newPos, double newSpeed)
Checks whether the reminder still has to be notified about the vehicle moves.
Definition: MSMeanData.cpp:85
bool notifyLeave(SUMOTrafficObject &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Called if the vehicle leaves the reminder&#39;s lane.
Definition: MSMeanData.cpp:332
Data structure for mean (aggregated) edge/lane values.
Definition: MSMeanData.h:69
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >())
Writes an XML header with optional configuration.
Definition: MSMeanData.h:260
MSEdgeVector myEdges
The corresponding first edges.
Definition: MSMeanData.h:443
const bool myAmEdgeBased
Information whether the output shall be edge-based (not lane-based)
Definition: MSMeanData.h:437
double getSpeedLimit() const
Returns the lane&#39;s maximum allowed speed.
Definition: MSLane.h:533
T MIN2(T a, T b)
Definition: StdDefs.h:74
void addDetector(MSMoveReminder *data)
Adds a data collector for a detector to this segment.
Definition: MESegment.cpp:212
Something on a lane to be noticed about vehicle movement.
const SUMOTime myDumpBegin
The first and the last time step to write information (-1 indicates always)
Definition: MSMeanData.h:440
const double myLaneLength
The length of the lane / edge the data collector is on.
Definition: MSMeanData.h:168
virtual ~MSMeanData()
Destructor.
Definition: MSMeanData.cpp:474
const double myMinSamples
the minimum sample seconds
Definition: MSMeanData.h:424
virtual bool notifyLeave(SUMOTrafficObject &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Called if the vehicle leaves the reminder&#39;s lane.
Definition: MSMeanData.cpp:255
virtual void addTo(MeanDataValues &val) const =0
Add the values of this to the given one and store them there.
begin/end of the description of an edge
virtual void openInterval(OutputDevice &dev, const SUMOTime startTime, const SUMOTime stopTime)
Writes the interval opener.
Definition: MSMeanData.cpp:580
virtual double getPreviousSpeed() const =0
Returns the vehicle&#39;s previous speed.
void setDescription(const std::string &description)
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:245
static double passingTime(const double lastPos, const double passedPos, const double currentPos, const double lastSpeed, const double currentSpeed)
Calculates the time at which the position passedPosition has been passed In case of a ballistic updat...
Definition: MSCFModel.cpp:597
virtual ~MeanDataValues()
Destructor.
Definition: MSMeanData.cpp:68
std::string myID
The name of the object.
Definition: Named.h:134
const MSMeanData *const myParent
The meandata parent.
Definition: MSMeanData.h:165
void writeXMLOutput(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Writes collected values into the given stream.
Definition: MSMeanData.cpp:597
Representation of a vehicle or person.
virtual void reset(bool afterWrite=false)=0
Resets values so they may be used for the next interval.
std::list< std::pair< SUMOTime, SUMOTime > > myPendingIntervals
The intervals for which output still has to be generated (only in the tracking case) ...
Definition: MSMeanData.h:455
virtual void writeXMLDetectorProlog(OutputDevice &dev) const
Opens the XML-output using "netstats" as root element.
Definition: MSMeanData.cpp:637
weights: time range end
A single mesoscopic segment (cell)
Definition: MESegment.h:50
virtual void update()
Called if a per timestep update is needed. Default does nothing.
Definition: MSMeanData.cpp:270
virtual bool hasArrived() const =0
Returns whether this vehicle has arrived.
virtual bool writePrefix(OutputDevice &dev, const MeanDataValues &values, const SumoXMLTag tag, const std::string id) const
Checks for emptiness and writes prefix into the given stream.
Definition: MSMeanData.cpp:587
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition: MSGlobals.h:106
double getLength() const
Get vehicle&#39;s length [m].
const MSEdgeVector & getEdges() const
Returns loaded edges.
virtual void detectorUpdate(const SUMOTime step)
Updates the detector.
Definition: MSMeanData.cpp:643
MSMeanData(const std::string &id, const SUMOTime dumpBegin, const SUMOTime dumpEnd, const bool useLanes, const bool withEmpty, const bool printDefaults, const bool withInternal, const bool trackVehicles, const int detectPersons, const double minSamples, const double maxTravelTime, const std::string &vTypes)
Constructor.
Definition: MSMeanData.cpp:405
an aggreagated-output interval
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:64
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
virtual double getSamples() const
Returns the number of collected sample seconds.
Definition: MSMeanData.cpp:275
static bool gSemiImplicitEulerUpdate
Definition: MSGlobals.h:56
MSEdgeControl & getEdgeControl()
Returns the edge control.
Definition: MSNet.h:380
#define NUMERICAL_EPS
Definition: config.h:145
void prepareDetectorForWriting(MSMoveReminder &data)
Updates data of a detector for all vehicle queues.
Definition: MESegment.cpp:238
std::vector< MSEdge * > MSEdgeVector
Definition: MSEdge.h:72
void resetOnly(SUMOTime stopTime)
Resets network value in order to allow processing of the next interval.
Definition: MSMeanData.cpp:484
const bool myDumpEmpty
Whether empty lanes/edges shall be written.
Definition: MSMeanData.h:433
MeanDataValues(MSLane *const lane, const double length, const bool doAdd, const MSMeanData *const parent)
Constructor.
Definition: MSMeanData.cpp:58
void write(OutputDevice &dev, const SUMOTime period, const double numLanes, const double defaultTravelTime, const int numVehicles=-1) const
Writes output values into the given stream.
Definition: MSMeanData.cpp:371
Data structure for mean (aggregated) edge/lane values for tracked vehicles.
Definition: MSMeanData.h:186
const bool myTrackVehicles
Whether vehicles are tracked.
Definition: MSMeanData.h:452
static bool gUseMesoSim
Definition: MSGlobals.h:91
Representation of a lane in the micro simulation.
Definition: MSLane.h:83
void writeEdge(OutputDevice &dev, const std::vector< MeanDataValues *> &edgeValues, MSEdge *edge, SUMOTime startTime, SUMOTime stopTime)
Writes edge values into the given stream.
Definition: MSMeanData.cpp:514
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
virtual std::string getEdgeID(const MSEdge *const edge)
Return the relevant edge id.
Definition: MSMeanData.cpp:508
Base of value-generating classes (detectors)
std::map< const SUMOTrafficObject *, TrackerEntry * > myTrackedData
The map of vehicles to data entries.
Definition: MSMeanData.h:282
void init()
Adds the value collectors to all relevant edges.
Definition: MSMeanData.cpp:428
void reset(bool afterWrite)
Resets values so they may be used for the next interval.
Definition: MSMeanData.cpp:308