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