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.dev/sumo
3 // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
22 // Data collector for edges/lanes
23 /****************************************************************************/
24 #include <config.h>
25 
26 #include <limits>
27 #ifdef HAVE_FOX
29 #endif
30 #include <utils/common/SUMOTime.h>
31 #include <utils/common/ToString.h>
34 #include <microsim/MSEdgeControl.h>
35 #include <microsim/MSEdge.h>
36 #include <microsim/MSLane.h>
37 #include <microsim/MSVehicle.h>
39 #include <microsim/MSNet.h>
40 #include "MSMeanData_Amitran.h"
41 #include "MSMeanData.h"
42 
43 #include <microsim/MSGlobals.h>
44 #include <mesosim/MESegment.h>
45 #include <mesosim/MELoop.h>
46 
47 
48 // ===========================================================================
49 // debug constants
50 // ===========================================================================
51 //#define DEBUG_NOTIFY_MOVE
52 //#define DEBUG_NOTIFY_ENTER
53 
54 // ===========================================================================
55 // method definitions
56 // ===========================================================================
57 // ---------------------------------------------------------------------------
58 // MSMeanData::MeanDataValues - methods
59 // ---------------------------------------------------------------------------
61  MSLane* const lane, const double length, const bool doAdd,
62  const MSMeanData* const parent) :
63  MSMoveReminder("meandata_" + (lane == nullptr ? "NULL" : lane->getID()), lane, doAdd),
64  myParent(parent),
65  myLaneLength(length),
66  sampleSeconds(0),
67  travelledDistance(0) {}
68 
69 
71 }
72 
73 
74 bool
76 #ifdef DEBUG_NOTIFY_ENTER
77  std::cout << "\n" << SIMTIME << " MSMeanData_Net::MSLaneMeanDataValues: veh '" << veh.getID() << "' enters lane '" << enteredLane->getID() << "'" << std::endl;
78 #else
79  UNUSED_PARAMETER(enteredLane);
80 #endif
81  UNUSED_PARAMETER(reason);
82  return myParent == nullptr || myParent->vehicleApplies(veh);
83 }
84 
85 
86 bool
87 MSMeanData::MeanDataValues::notifyMove(SUMOTrafficObject& veh, double oldPos, double newPos, double newSpeed) {
88  // if the vehicle has arrived, the reminder must be kept so it can be
89  // notified of the arrival subsequently
90  const double oldSpeed = veh.getPreviousSpeed();
91  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
92  double leaveSpeed = newSpeed, leaveSpeedFront = newSpeed;
93 
94  // These values will be further decreased below
95  double timeOnLane = TS;
96  double frontOnLane = oldPos > myLaneLength ? 0. : TS;
97  bool ret = true;
98 
99  // entry and exit times (will be modified below)
100  double timeBeforeEnter = 0.;
101  double timeBeforeEnterBack = 0.;
102  double timeBeforeLeaveFront = newPos <= myLaneLength ? TS : 0.;
103  double timeBeforeLeave = TS;
104 
105  // Treat the case that the vehicle entered the lane in the last step
106  if (oldPos < 0 && newPos >= 0) {
107  // Vehicle was not on this lane in the last time step
108  timeBeforeEnter = MSCFModel::passingTime(oldPos, 0, newPos, oldSpeed, newSpeed);
109  timeOnLane = TS - timeBeforeEnter;
110  frontOnLane = timeOnLane;
111  enterSpeed = MSCFModel::speedAfterTime(timeBeforeEnter, oldSpeed, newPos - oldPos);
112  }
113 
114  const double oldBackPos = oldPos - veh.getVehicleType().getLength();
115  const double newBackPos = newPos - veh.getVehicleType().getLength();
116 
117  // Determine the time before the vehicle back enters
118  if (oldBackPos < 0. && newBackPos > 0.) {
119  timeBeforeEnterBack = MSCFModel::passingTime(oldBackPos, 0., newBackPos, oldSpeed, newSpeed);
120  } else if (newBackPos <= 0) {
121  timeBeforeEnterBack = TS;
122  } else {
123  timeBeforeEnterBack = 0.;
124  }
125 
126  // Treat the case that the vehicle's back left the lane in the last step
127  if (newBackPos > myLaneLength // vehicle's back has left the lane
128  && oldBackPos <= myLaneLength) { // and hasn't left the lane before
129  assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the lane boundary otherwise
130  // (Leo) vehicle left this lane (it can also have skipped over it in one time step -> therefore we use "timeOnLane -= ..." and ( ... - timeOnLane) below)
131  timeBeforeLeave = MSCFModel::passingTime(oldBackPos, myLaneLength, newBackPos, oldSpeed, newSpeed);
132  const double timeAfterLeave = TS - timeBeforeLeave;
133  timeOnLane -= timeAfterLeave;
134  leaveSpeed = MSCFModel::speedAfterTime(timeBeforeLeave, oldSpeed, newPos - oldPos);
135  // XXX: Do we really need this? Why would this "reduce rounding errors"? (Leo) Refs. #2579
136  if (fabs(timeOnLane) < NUMERICAL_EPS) { // reduce rounding errors
137  timeOnLane = 0.;
138  }
139  ret = veh.hasArrived();
140  }
141 
142  // Treat the case that the vehicle's front left the lane in the last step
143  if (newPos > myLaneLength && oldPos <= myLaneLength) {
144  // vehicle's front has left the lane and has not left before
145  assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0);
146  timeBeforeLeaveFront = MSCFModel::passingTime(oldPos, myLaneLength, newPos, oldSpeed, newSpeed);
147  const double timeAfterLeave = TS - timeBeforeLeaveFront;
148  frontOnLane -= timeAfterLeave;
149  // XXX: Do we really need this? Why would this "reduce rounding errors"? (Leo) Refs. #2579
150  if (fabs(frontOnLane) < NUMERICAL_EPS) { // reduce rounding errors
151  frontOnLane = 0.;
152  }
153  leaveSpeedFront = MSCFModel::speedAfterTime(timeBeforeLeaveFront, oldSpeed, newPos - oldPos);
154  }
155 
156  assert(frontOnLane <= TS);
157  assert(timeOnLane <= TS);
158 
159  if (timeOnLane < 0) {
160  WRITE_ERRORF(TL("Negative vehicle step fraction for '%' on lane '%'."), veh.getID(), getLane()->getID());
161  return veh.hasArrived();
162  }
163  if (timeOnLane == 0) {
164  return veh.hasArrived();
165  }
166 
167 #ifdef DEBUG_NOTIFY_MOVE
168  std::stringstream ss;
169  ss << "\n"
170  << "lane length: " << myLaneLength
171  << "\noldPos: " << oldPos
172  << "\nnewPos: " << newPos
173  << "\noldPosBack: " << oldBackPos
174  << "\nnewPosBack: " << newBackPos
175  << "\ntimeBeforeEnter: " << timeBeforeEnter
176  << "\ntimeBeforeEnterBack: " << timeBeforeEnterBack
177  << "\ntimeBeforeLeaveFront: " << timeBeforeLeaveFront
178  << "\ntimeBeforeLeave: " << timeBeforeLeave;
179  if (!(timeBeforeLeave >= MAX2(timeBeforeEnterBack, timeBeforeLeaveFront))
180  || !(timeBeforeEnter <= MIN2(timeBeforeEnterBack, timeBeforeLeaveFront))) {
181  WRITE_ERROR(ss.str());
182  } else {
183  std::cout << ss.str() << std::endl;
184  }
185 
186 #endif
187 
188  assert(timeBeforeEnter <= MIN2(timeBeforeEnterBack, timeBeforeLeaveFront));
189  assert(timeBeforeLeave >= MAX2(timeBeforeEnterBack, timeBeforeLeaveFront));
190  // compute average vehicle length on lane in last step
191  double vehLength = veh.getVehicleType().getLength();
192  // occupied lane length at timeBeforeEnter (resp. stepStart if already on lane)
193  double lengthOnLaneAtStepStart = MAX2(0., MIN4(myLaneLength, vehLength, vehLength - (oldPos - myLaneLength), oldPos));
194  // occupied lane length at timeBeforeLeave (resp. stepEnd if still on lane)
195  double lengthOnLaneAtStepEnd = MAX2(0., MIN4(myLaneLength, vehLength, vehLength - (newPos - myLaneLength), newPos));
196  double integratedLengthOnLane = 0.;
197  if (timeBeforeEnterBack < timeBeforeLeaveFront) {
198  // => timeBeforeLeaveFront>0, myLaneLength>vehLength
199  // vehicle length on detector at timeBeforeEnterBack
200  double lengthOnLaneAtBackEnter = MIN2(veh.getVehicleType().getLength(), newPos);
201  // linear quadrature of occupancy between timeBeforeEnter and timeBeforeEnterBack
202  integratedLengthOnLane += (timeBeforeEnterBack - timeBeforeEnter) * (lengthOnLaneAtBackEnter + lengthOnLaneAtStepStart) * 0.5;
203  // linear quadrature of occupancy between timeBeforeEnterBack and timeBeforeLeaveFront
204  // (vehicle is completely on the edge in between)
205  integratedLengthOnLane += (timeBeforeLeaveFront - timeBeforeEnterBack) * vehLength;
206  // and until vehicle leaves/stepEnd
207  integratedLengthOnLane += (timeBeforeLeave - timeBeforeLeaveFront) * (vehLength + lengthOnLaneAtStepEnd) * 0.5;
208  } else if (timeBeforeEnterBack >= timeBeforeLeaveFront) {
209  // => myLaneLength <= vehLength or (timeBeforeLeaveFront == timeBeforeEnterBack == 0)
210  // vehicle length on detector at timeBeforeLeaveFront
211  double lengthOnLaneAtLeaveFront;
212  if (timeBeforeLeaveFront == timeBeforeEnter) {
213  // for the case that front already left
214  lengthOnLaneAtLeaveFront = lengthOnLaneAtStepStart;
215  } else if (timeBeforeLeaveFront == timeBeforeLeave) {
216  // for the case that front doesn't leave in this step
217  lengthOnLaneAtLeaveFront = lengthOnLaneAtStepEnd;
218  } else {
219  lengthOnLaneAtLeaveFront = myLaneLength;
220  }
221 #ifdef DEBUG_NOTIFY_MOVE
222  std::cout << "lengthOnLaneAtLeaveFront=" << lengthOnLaneAtLeaveFront << std::endl;
223 #endif
224  // linear quadrature of occupancy between timeBeforeEnter and timeBeforeLeaveFront
225  integratedLengthOnLane += (timeBeforeLeaveFront - timeBeforeEnter) * (lengthOnLaneAtLeaveFront + lengthOnLaneAtStepStart) * 0.5;
226  // linear quadrature of occupancy between timeBeforeLeaveFront and timeBeforeEnterBack
227  integratedLengthOnLane += (timeBeforeEnterBack - timeBeforeLeaveFront) * lengthOnLaneAtLeaveFront;
228  // and until vehicle leaves/stepEnd
229  integratedLengthOnLane += (timeBeforeLeave - timeBeforeEnterBack) * (lengthOnLaneAtLeaveFront + lengthOnLaneAtStepEnd) * 0.5;
230  }
231 
232  double meanLengthOnLane = integratedLengthOnLane / TS;
233 #ifdef DEBUG_NOTIFY_MOVE
234  std::cout << "Calculated mean length on lane '" << myLane->getID() << "' in last step as " << meanLengthOnLane
235  << "\nlengthOnLaneAtStepStart=" << lengthOnLaneAtStepStart << ", lengthOnLaneAtStepEnd=" << lengthOnLaneAtStepEnd << ", integratedLengthOnLane=" << integratedLengthOnLane
236  << std::endl;
237 #endif
238 
239 // // XXX: use this, when #2556 is fixed! Refs. #2575
240 // const double travelledDistanceFrontOnLane = MAX2(0., MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.));
241 // const double travelledDistanceVehicleOnLane = MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.) + MIN2(MAX2(0., newPos - myLaneLength), veh.getVehicleType().getLength());
242 // // XXX: #2556 fixed for ballistic update
243  const double travelledDistanceFrontOnLane = MSGlobals::gSemiImplicitEulerUpdate ? frontOnLane * newSpeed
244  : MAX2(0., MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.));
245  const double travelledDistanceVehicleOnLane = MSGlobals::gSemiImplicitEulerUpdate ? timeOnLane * newSpeed
246  : MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.) + MIN2(MAX2(0., newPos - myLaneLength), veh.getVehicleType().getLength());
247 // // XXX: no fix
248 // const double travelledDistanceFrontOnLane = frontOnLane*newSpeed;
249 // const double travelledDistanceVehicleOnLane = timeOnLane*newSpeed;
250 
251 #ifdef HAVE_FOX
252  ScopedLocker<> lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
253 #endif
254  notifyMoveInternal(veh, frontOnLane, timeOnLane, (enterSpeed + leaveSpeedFront) / 2., (enterSpeed + leaveSpeed) / 2., travelledDistanceFrontOnLane, travelledDistanceVehicleOnLane, meanLengthOnLane);
255  return ret;
256 }
257 
258 
259 bool
260 MSMeanData::MeanDataValues::notifyLeave(SUMOTrafficObject& /*veh*/, double /*lastPos*/, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
262  return false; // reminder is re-added on every segment (@recheck for performance)
263  }
264  return reason == MSMoveReminder::NOTIFICATION_JUNCTION;
265 }
266 
267 
268 bool
270  return sampleSeconds == 0;
271 }
272 
273 
274 void
276 }
277 
278 
279 double
281  return sampleSeconds;
282 }
283 
284 
285 // ---------------------------------------------------------------------------
286 // MSMeanData::MeanDataValueTracker - methods
287 // ---------------------------------------------------------------------------
289  const double length,
290  const MSMeanData* const parent)
291  : MSMeanData::MeanDataValues(lane, length, true, parent) {
292  myCurrentData.push_back(new TrackerEntry(parent->createValues(lane, length, false)));
293 }
294 
295 
297  std::list<TrackerEntry*>::iterator i;
298  for (i = myCurrentData.begin(); i != myCurrentData.end(); i++) {
299  delete *i;
300  }
301 
302  // FIXME: myTrackedData may still hold some undeleted TrackerEntries. When to delete those? (Leo), refers to #2251
303  // code below fails
304 
305 // std::map<SUMOTrafficObject*, TrackerEntry*>::iterator j;
306 // for(j=myTrackedData.begin(); j!=myTrackedData.end();j++){
307 // delete j->second;
308 // }
309 }
310 
311 
312 void
314  if (afterWrite) {
315  if (myCurrentData.begin() != myCurrentData.end()) {
316  // delete myCurrentData.front();
317  myCurrentData.pop_front();
318  }
319  } else {
320  myCurrentData.push_back(new TrackerEntry(myParent->createValues(myLane, myLaneLength, false)));
321  }
322 }
323 
324 
325 void
327  myCurrentData.front()->myValues->addTo(val);
328 }
329 
330 
331 void
332 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) {
333  myTrackedData[&veh]->myValues->notifyMoveInternal(veh, frontOnLane, timeOnLane, meanSpeedFrontOnLane, meanSpeedVehicleOnLane, travelledDistanceFrontOnLane, travelledDistanceVehicleOnLane, meanLengthOnLane);
334 }
335 
336 
337 bool
339  if (myParent == nullptr || reason != MSMoveReminder::NOTIFICATION_SEGMENT) {
340  myTrackedData[&veh]->myNumVehicleLeft++;
341  }
342  return myTrackedData[&veh]->myValues->notifyLeave(veh, lastPos, reason);
343 }
344 
345 
346 bool
348 #ifdef DEBUG_NOTIFY_ENTER
349  std::cout << "\n" << SIMTIME << " MSMeanData::MeanDataValueTracker: veh '" << veh.getID() << "' enters lane '" << enteredLane->getID() << "'" << std::endl;
350 #else
351  UNUSED_PARAMETER(enteredLane);
352 #endif
353  if (reason == MSMoveReminder::NOTIFICATION_SEGMENT) {
354  return true;
355  }
356  if (myParent->vehicleApplies(veh) && myTrackedData.find(&veh) == myTrackedData.end()) {
357  myTrackedData[&veh] = myCurrentData.back();
358  myTrackedData[&veh]->myNumVehicleEntered++;
359  if (!myTrackedData[&veh]->myValues->notifyEnter(veh, reason)) {
360  myTrackedData[&veh]->myNumVehicleLeft++;
361  myTrackedData.erase(&veh);
362  return false;
363  }
364  return true;
365  }
366  return false;
367 }
368 
369 
370 bool
372  return myCurrentData.front()->myValues->isEmpty();
373 }
374 
375 
376 void
378  long long int attributeMask,
379  const SUMOTime period,
380  const int numLanes,
381  const double speedLimit,
382  const double defaultTravelTime,
383  const int /*numVehicles*/) const {
384  myCurrentData.front()->myValues->write(dev, attributeMask, period, numLanes, speedLimit,
385  defaultTravelTime,
386  myCurrentData.front()->myNumVehicleEntered);
387 }
388 
389 
390 int
392  int result = 0;
393  for (std::list<TrackerEntry*>::const_iterator it = myCurrentData.begin(); it != myCurrentData.end(); ++it) {
394  if ((*it)->myNumVehicleEntered == (*it)->myNumVehicleLeft) {
395  result++;
396  } else {
397  break;
398  }
399  }
400  return result;
401 }
402 
403 
404 double
406  return myCurrentData.front()->myValues->getSamples();
407 }
408 
409 
410 // ---------------------------------------------------------------------------
411 // MSMeanData - methods
412 // ---------------------------------------------------------------------------
413 MSMeanData::MSMeanData(const std::string& id,
414  const SUMOTime dumpBegin, const SUMOTime dumpEnd,
415  const bool useLanes, const bool withEmpty,
416  const bool printDefaults, const bool withInternal,
417  const bool trackVehicles,
418  const int detectPersons,
419  const double maxTravelTime,
420  const double minSamples,
421  const std::string& vTypes,
422  const std::string& writeAttributes,
423  const std::vector<MSEdge*>& edges,
424  bool aggregate) :
425  MSDetectorFileOutput(id, vTypes, "", detectPersons),
426  myMinSamples(minSamples),
427  myMaxTravelTime(maxTravelTime),
428  myDumpEmpty(withEmpty),
429  myAmEdgeBased(!useLanes),
430  myDumpBegin(dumpBegin),
431  myDumpEnd(dumpEnd),
433  myEdges(edges),
434  myPrintDefaults(printDefaults),
435  myDumpInternal(withInternal),
436  myTrackVehicles(trackVehicles),
437  myWrittenAttributes(initWrittenAttributes(writeAttributes, id)),
438  myAggregate(aggregate)
439 { }
440 
441 
442 void
445  if (myEdges.empty()) {
446  // use all edges by default
447  for (MSEdge* const edge : MSNet::getInstance()->getEdgeControl().getEdges()) {
448  if ((myDumpInternal || !edge->isInternal()) &&
449  ((detectPersons() && myDumpInternal) || (!edge->isCrossing() && !edge->isWalkingArea()))) {
450  myEdges.push_back(edge);
451  }
452  }
453  }
454  int index = 0;
455  for (MSEdge* edge : myEdges) {
456  myMeasures.push_back(std::vector<MeanDataValues*>());
457  myEdgeIndex[edge] = index++;
458  const std::vector<MSLane*>& lanes = edge->getLanes();
460  MeanDataValues* data;
461  if (!myAmEdgeBased) {
462  for (MSLane* const lane : lanes) {
463  data = createValues(lane, lanes[0]->getLength(), false);
464  myMeasures.back().push_back(data);
466  while (s != nullptr) {
467  s->addDetector(data, lane->getIndex());
468  s->prepareDetectorForWriting(*data, lane->getIndex());
469  s = s->getNextSegment();
470  }
471  data->reset();
472  data->reset(true);
473  }
474  } else {
475  if (myTrackVehicles) {
476  data = new MeanDataValueTracker(nullptr, lanes[0]->getLength(), this);
477  } else {
478  data = createValues(nullptr, lanes[0]->getLength(), false);
479  }
480  data->setDescription("meandata_" + edge->getID());
481  myMeasures.back().push_back(data);
483  while (s != nullptr) {
484  s->addDetector(data);
485  s->prepareDetectorForWriting(*data);
486  s = s->getNextSegment();
487  }
488  data->reset();
489  data->reset(true);
490  }
491  continue;
492  }
494  myMeasures.back().push_back(new MeanDataValueTracker(nullptr, lanes[0]->getLength(), this));
495  }
496  for (MSLane* const lane : lanes) {
497  if (myTrackVehicles) {
498  if (myAmEdgeBased) {
499  lane->addMoveReminder(myMeasures.back().back());
500  } else {
501  myMeasures.back().push_back(new MeanDataValueTracker(lane, lane->getLength(), this));
502  }
503  } else {
504  myMeasures.back().push_back(createValues(lane, lane->getLength(), true));
505  }
506  }
507  }
508 }
509 
510 
512  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
513  for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
514  delete *j;
515  }
516  }
517 }
518 
519 
520 void
522  UNUSED_PARAMETER(stopTime);
524  MSEdgeVector::iterator edge = myEdges.begin();
525  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i, ++edge) {
527  for (MeanDataValues* data : *i) {
528  while (s != nullptr) {
529  s->prepareDetectorForWriting(*data);
530  s = s->getNextSegment();
531  }
532  data->reset();
533  }
534  }
535  return;
536  }
537  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
538  for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
539  (*j)->reset();
540  }
541  }
542 }
543 
544 
545 std::string
546 MSMeanData::getEdgeID(const MSEdge* const edge) {
547  return edge->getID();
548 }
549 
550 
551 void
553  if (myTrackVehicles) {
554  throw ProcessError(TL("aggregated meanData output not yet implemented for trackVehicles"));
555  }
556 
557  double edgeLengthSum = 0;
558  int laneNumber = 0;
559  double speedSum = 0;
560  double totalTT = 0;
561  for (MSEdge* edge : myEdges) {
562  edgeLengthSum += edge->getLength();
563  laneNumber += edge->getNumLanes();
564  speedSum += edge->getSpeedLimit();
565  totalTT += edge->getLength() / edge->getSpeedLimit();
566  }
567  MeanDataValues* sumData = createValues(nullptr, edgeLengthSum, false);
568  for (const std::vector<MeanDataValues*>& edgeValues : myMeasures) {
569  for (MeanDataValues* meanData : edgeValues) {
570  meanData->addTo(*sumData);
571  if (!MSNet::getInstance()->skipFinalReset()) {
572  meanData->reset();
573  }
574  }
575  }
577  for (MSEdge* edge : myEdges) {
579  while (s != nullptr) {
580  s->prepareDetectorForWriting(*sumData);
581  s = s->getNextSegment();
582  }
583  }
584  }
585 
586  if (writePrefix(dev, *sumData, SUMO_TAG_EDGE, "AGGREGATED")) {
587  dev.writeAttr(SUMO_ATTR_NUMEDGES, myEdges.size());
588  sumData->write(dev, myWrittenAttributes, stopTime - startTime, laneNumber, speedSum / (double)myEdges.size(),
589  myPrintDefaults ? totalTT : -1.);
590  }
591  delete sumData;
592 }
593 
594 
595 void
597  const std::vector<MeanDataValues*>& edgeValues,
598  const MSEdge* const edge, SUMOTime startTime, SUMOTime stopTime) {
600  int idx = 0;
601  for (MeanDataValues* const data : edgeValues) {
603  while (s != nullptr) {
604  s->prepareDetectorForWriting(*data, myAmEdgeBased ? -1 : idx);
605  s = s->getNextSegment();
606  }
607  idx++;
608  }
609  if (myAmEdgeBased) {
610  MeanDataValues* data = edgeValues.front();
611  if (writePrefix(dev, *data, SUMO_TAG_EDGE, getEdgeID(edge))) {
612  data->write(dev, myWrittenAttributes, stopTime - startTime,
613  (int)edge->getLanes().size(),
614  edge->getSpeedLimit(),
615  myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
616  }
617  if (!MSNet::getInstance()->skipFinalReset()) {
618  data->reset(true);
619  }
620  return;
621  }
622  }
623  std::vector<MeanDataValues*>::const_iterator lane;
624  if (!myAmEdgeBased) {
625  bool writeCheck = myDumpEmpty;
626  if (!writeCheck) {
627  for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
628  if (!(*lane)->isEmpty()) {
629  writeCheck = true;
630  break;
631  }
632  }
633  }
634  if (writeCheck) {
636  }
637  for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
638  MeanDataValues& meanData = **lane;
639  if (writePrefix(dev, meanData, SUMO_TAG_LANE, meanData.getLane()->getID())) {
640  meanData.write(dev, myWrittenAttributes, stopTime - startTime, 1, meanData.getLane()->getSpeedLimit(),
641  myPrintDefaults ? meanData.getLane()->getLength() / meanData.getLane()->getSpeedLimit() : -1.);
642  }
643  if (!MSNet::getInstance()->skipFinalReset()) {
644  meanData.reset(true);
645  }
646  }
647  if (writeCheck) {
648  dev.closeTag();
649  }
650  } else {
651  if (myTrackVehicles) {
652  MeanDataValues& meanData = **edgeValues.begin();
653  if (writePrefix(dev, meanData, SUMO_TAG_EDGE, edge->getID())) {
654  meanData.write(dev, myWrittenAttributes, stopTime - startTime, (int)edge->getLanes().size(), edge->getSpeedLimit(),
655  myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
656  }
657  if (!MSNet::getInstance()->skipFinalReset()) {
658  meanData.reset(true);
659  }
660  } else {
661  MeanDataValues* sumData = createValues(nullptr, edge->getLength(), false);
662  for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
663  MeanDataValues& meanData = **lane;
664  meanData.addTo(*sumData);
665  if (!MSNet::getInstance()->skipFinalReset()) {
666  meanData.reset();
667  }
668  }
669  if (writePrefix(dev, *sumData, SUMO_TAG_EDGE, getEdgeID(edge))) {
670  sumData->write(dev, myWrittenAttributes, stopTime - startTime, (int)edge->getLanes().size(), edge->getSpeedLimit(),
671  myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
672  }
673  delete sumData;
674  }
675  }
676 }
677 
678 
679 void
680 MSMeanData::openInterval(OutputDevice& dev, const SUMOTime startTime, const SUMOTime stopTime) {
683 }
684 
685 
686 bool
687 MSMeanData::writePrefix(OutputDevice& dev, const MeanDataValues& values, const SumoXMLTag tag, const std::string id) const {
688  if (myDumpEmpty || !values.isEmpty()) {
689  dev.openTag(tag);
690  dev.writeAttr(SUMO_ATTR_ID, id);
692  return true;
693  }
694  return false;
695 }
696 
697 
698 void
700  SUMOTime startTime, SUMOTime stopTime) {
701  // check whether this dump shall be written for the current time
702  int numReady = myDumpBegin < stopTime && myDumpEnd - DELTA_T >= startTime ? 1 : 0;
703  if (myTrackVehicles && myDumpBegin < stopTime) {
704  myPendingIntervals.push_back(std::make_pair(startTime, stopTime));
705  numReady = (int)myPendingIntervals.size();
706  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
707  for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
708  numReady = MIN2(numReady, ((MeanDataValueTracker*)*j)->getNumReady());
709  if (numReady == 0) {
710  break;
711  }
712  }
713  if (numReady == 0) {
714  break;
715  }
716  }
717  }
718  const bool partialInterval = startTime < myInitTime;
719  if (numReady == 0 || myTrackVehicles || partialInterval) {
720  resetOnly(stopTime);
721  }
722  if (partialInterval) {
723  return;
724  }
725  while (numReady-- > 0) {
726  if (!myPendingIntervals.empty()) {
727  startTime = myPendingIntervals.front().first;
728  stopTime = myPendingIntervals.front().second;
729  myPendingIntervals.pop_front();
730  }
731  openInterval(dev, startTime, stopTime);
732  if (myAggregate) {
733  writeAggregated(dev, startTime, stopTime);
734  } else {
735  MSEdgeVector::const_iterator edge = myEdges.begin();
736  for (const std::vector<MeanDataValues*>& measures : myMeasures) {
737  writeEdge(dev, measures, *edge, startTime, stopTime);
738  ++edge;
739  }
740  }
741  dev.closeTag();
742  }
743  dev.flush();
744 }
745 
746 
747 void
749  dev.writeXMLHeader("meandata", "meandata_file.xsd");
750 }
751 
752 
753 void
755  if (step + DELTA_T == myDumpBegin) {
756  init();
757  }
758 }
759 
760 
761 long long int
762 MSMeanData::initWrittenAttributes(const std::string writeAttributes, const std::string& id) {
763  long long int result = 0;
764  for (std::string attrName : StringTokenizer(writeAttributes).getVector()) {
765  if (!SUMOXMLDefinitions::Attrs.hasString(attrName)) {
766  WRITE_ERRORF(TL("Unknown attribute '%' to write in meanData '%'."), attrName, id);
767  continue;
768  }
769  int attr = SUMOXMLDefinitions::Attrs.get(attrName);
770  assert(attr < 63);
771  result |= ((long long int)1 << attr);
772  }
773  return result;
774 }
775 
776 const std::vector<MSMeanData::MeanDataValues*>*
777 MSMeanData::getEdgeValues(const MSEdge* edge) const {
778  auto it = myEdgeIndex.find(edge);
779  if (it != myEdgeIndex.end()) {
780  return &myMeasures[it->second];
781  } else {
782  return nullptr;
783  }
784 }
785 
786 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#define WRITE_ERRORF(...)
Definition: MsgHandler.h:305
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:304
#define TL(string)
Definition: MsgHandler.h:315
SUMOTime DELTA_T
Definition: SUMOTime.cpp:38
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition: SUMOTime.cpp:69
#define SUMOTime_MAX
Definition: SUMOTime.h:34
#define TS
Definition: SUMOTime.h:42
#define SIMTIME
Definition: SUMOTime.h:62
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_INTERVAL
an aggreagated-output interval
@ SUMO_TAG_LANE
begin/end of the description of a single lane
@ SUMO_TAG_EDGE
begin/end of the description of an edge
@ SUMO_ATTR_NUMEDGES
@ SUMO_ATTR_BEGIN
weights: time range begin
@ SUMO_ATTR_END
weights: time range end
@ SUMO_ATTR_SAMPLEDSECONDS
MSMeanData_Net.
@ SUMO_ATTR_ID
T MIN4(T a, T b, T c, T d)
Definition: StdDefs.h:103
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:76
T MAX2(T a, T b)
Definition: StdDefs.h:82
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition: MELoop.cpp:325
A single mesoscopic segment (cell)
Definition: MESegment.h:49
void addDetector(MSMoveReminder *data, int queueIndex=-1)
Adds a data collector for a detector to this segment.
Definition: MESegment.cpp:250
MESegment * getNextSegment() const
Returns the following segment on the same edge (0 if it is the last).
Definition: MESegment.h:234
void prepareDetectorForWriting(MSMoveReminder &data, int queueIndex=-1)
Removes a data collector for a detector from this segment.
Definition: MESegment.cpp:279
static double speedAfterTime(const double t, const double oldSpeed, const double dist)
Calculates the speed after a time t \in [0,TS] given the initial speed and the distance traveled in a...
Definition: MSCFModel.cpp:736
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:658
Base of value-generating classes (detectors)
A road/street connecting two junctions.
Definition: MSEdge.h:77
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:168
double getSpeedLimit() const
Returns the speed limit of the edge @caution The speed limit of the first lane is retured; should pro...
Definition: MSEdge.cpp:1094
double getLength() const
return the length of the edge
Definition: MSEdge.h:662
static bool gUseMesoSim
Definition: MSGlobals.h:103
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition: MSGlobals.h:109
static bool gSemiImplicitEulerUpdate
Definition: MSGlobals.h:53
static int gNumSimThreads
how many threads to use for simulation
Definition: MSGlobals.h:143
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition: MSLane.h:584
double getLength() const
Returns the lane's length.
Definition: MSLane.h:598
Definition: MSMeanData.h:276
Data structure for mean (aggregated) edge/lane values for tracked vehicles.
Definition: MSMeanData.h:202
double getSamples() const
Returns the number of collected sample seconds.
Definition: MSMeanData.cpp:405
MeanDataValueTracker(MSLane *const lane, const double length, const MSMeanData *const parent)
Constructor.
Definition: MSMeanData.cpp:288
bool notifyLeave(SUMOTrafficObject &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Called if the vehicle leaves the reminder's lane.
Definition: MSMeanData.cpp:338
void addTo(MSMeanData::MeanDataValues &val) const
Add the values of this to the given one and store them there.
Definition: MSMeanData.cpp:326
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:332
virtual ~MeanDataValueTracker()
Destructor.
Definition: MSMeanData.cpp:296
void write(OutputDevice &dev, long long int attributeMask, const SUMOTime period, const int numLanes, const double speedLimit, const double defaultTravelTime, const int numVehicles=-1) const
Writes output values into the given stream.
Definition: MSMeanData.cpp:377
bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Computes current values and adds them to their sums.
Definition: MSMeanData.cpp:347
std::list< TrackerEntry * > myCurrentData
The currently active meandata "intervals".
Definition: MSMeanData.h:301
bool isEmpty() const
Returns whether any data was collected.
Definition: MSMeanData.cpp:371
void reset(bool afterWrite)
Resets values so they may be used for the next interval.
Definition: MSMeanData.cpp:313
Data structure for mean (aggregated) edge/lane values.
Definition: MSMeanData.h:66
virtual void addTo(MeanDataValues &val) const =0
Add the values of this to the given one and store them there.
virtual bool notifyLeave(SUMOTrafficObject &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Called if the vehicle leaves the reminder's lane.
Definition: MSMeanData.cpp:260
MeanDataValues(MSLane *const lane, const double length, const bool doAdd, const MSMeanData *const parent)
Constructor.
Definition: MSMeanData.cpp:60
virtual void update()
Called if a per timestep update is needed. Default does nothing.
Definition: MSMeanData.cpp:275
virtual bool isEmpty() const
Returns whether any data was collected.
Definition: MSMeanData.cpp:269
virtual void write(OutputDevice &dev, long long int attributeMask, const SUMOTime period, const int numLanes, const double speedLimit, const double defaultTravelTime, const int numVehicles=-1) const =0
Writes output values into the given stream.
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:87
virtual ~MeanDataValues()
Destructor.
Definition: MSMeanData.cpp:70
virtual void reset(bool afterWrite=false)=0
Resets values so they may be used for the next interval.
virtual bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Called if the vehicle enters the reminder's lane.
Definition: MSMeanData.cpp:75
virtual double getSamples() const
Returns the number of collected sample seconds.
Definition: MSMeanData.cpp:280
Data collector for edges/lanes.
Definition: MSMeanData.h:57
const bool myAggregate
whether the data for all edges shall be aggregated
Definition: MSMeanData.h:518
void writeXMLOutput(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Writes collected values into the given stream.
Definition: MSMeanData.cpp:699
const bool myDumpInternal
Whether internal lanes/edges shall be written.
Definition: MSMeanData.h:509
const SUMOTime myDumpBegin
The first and the last time step to write information (-1 indicates always)
Definition: MSMeanData.h:494
virtual void detectorUpdate(const SUMOTime step)
Updates the detector.
Definition: MSMeanData.cpp:754
virtual ~MSMeanData()
Destructor.
Definition: MSMeanData.cpp:511
virtual MSMeanData::MeanDataValues * createValues(MSLane *const lane, const double length, const bool doAdd) const =0
Create an instance of MeanDataValues.
void writeAggregated(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Writes aggregate of all edge values into the given stream.
Definition: MSMeanData.cpp:552
void init()
Adds the value collectors to all relevant edges.
Definition: MSMeanData.cpp:443
const double myMinSamples
the minimum sample seconds
Definition: MSMeanData.h:476
void resetOnly(SUMOTime stopTime)
Resets network value in order to allow processing of the next interval.
Definition: MSMeanData.cpp:521
const long long int myWrittenAttributes
bit mask for checking attributes to be written
Definition: MSMeanData.h:515
const bool myPrintDefaults
Whether empty lanes/edges shall be written.
Definition: MSMeanData.h:506
std::map< const MSEdge *, int > myEdgeIndex
The index in myEdges / myMeasures.
Definition: MSMeanData.h:503
const bool myAmEdgeBased
Information whether the output shall be edge-based (not lane-based)
Definition: MSMeanData.h:488
SUMOTime myInitTime
time at which init was called();
Definition: MSMeanData.h:497
const double myMaxTravelTime
the maximum travel time to write
Definition: MSMeanData.h:479
const SUMOTime myDumpEnd
Definition: MSMeanData.h:494
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:521
const std::vector< MeanDataValues * > * getEdgeValues(const MSEdge *edge) const
Definition: MSMeanData.cpp:777
void writeEdge(OutputDevice &dev, const std::vector< MeanDataValues * > &edgeValues, const MSEdge *const edge, SUMOTime startTime, SUMOTime stopTime)
Writes edge values into the given stream.
Definition: MSMeanData.cpp:596
virtual std::string getEdgeID(const MSEdge *const edge)
Return the relevant edge id.
Definition: MSMeanData.cpp:546
static long long int initWrittenAttributes(const std::string writeAttributes, const std::string &id)
Definition: MSMeanData.cpp:762
virtual void writeXMLDetectorProlog(OutputDevice &dev) const
Opens the XML-output using "netstats" as root element.
Definition: MSMeanData.cpp:748
const bool myDumpEmpty
Whether empty lanes/edges shall be written.
Definition: MSMeanData.h:485
MSEdgeVector myEdges
The corresponding first edges.
Definition: MSMeanData.h:500
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, const std::string &writeAttributes, const std::vector< MSEdge * > &edges, bool aggregate)
Constructor.
Definition: MSMeanData.cpp:413
virtual void openInterval(OutputDevice &dev, const SUMOTime startTime, const SUMOTime stopTime)
Writes the interval opener.
Definition: MSMeanData.cpp:680
std::vector< std::vector< MeanDataValues * > > myMeasures
Value collectors; sorted by edge, then by lane.
Definition: MSMeanData.h:482
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:687
const bool myTrackVehicles
Whether vehicles are tracked.
Definition: MSMeanData.h:512
Something on a lane to be noticed about vehicle movement.
const MSLane * getLane() const
Returns the lane the reminder works on.
void setDescription(const std::string &description)
Notification
Definition of a vehicle state.
@ NOTIFICATION_SEGMENT
The vehicle changes the segment (meso only)
@ NOTIFICATION_JUNCTION
The vehicle arrived at a junction.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:182
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
double getLength() const
Get vehicle's length [m].
std::string myID
The name of the object.
Definition: Named.h:125
const std::string & getID() const
Returns the id.
Definition: Named.h:74
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeOptionalAttr(const SumoXMLAttr attr, const T &val, long long int attributeMask)
writes a named attribute unless filtered
Definition: OutputDevice.h:271
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >(), bool includeConfig=true)
Writes an XML header with optional configuration.
Representation of a vehicle, person, or container.
virtual double getPreviousSpeed() const =0
Returns the object's previous speed.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual bool hasArrived() const =0
Returns whether this object has arrived.
static StringBijection< int > Attrs
The names of SUMO-XML attributes for use in netbuild.
A scoped lock which only triggers on condition.
Definition: ScopedLocker.h:40
T get(const std::string &str) const