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-2022 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_ERROR("Negative vehicle step fraction for '" + veh.getID() + "' on lane '" + 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  myCurrentData.pop_front();
317  }
318  } else {
319  myCurrentData.push_back(new TrackerEntry(myParent->createValues(myLane, myLaneLength, false)));
320  }
321 }
322 
323 
324 void
326  myCurrentData.front()->myValues->addTo(val);
327 }
328 
329 
330 void
331 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) {
332  myTrackedData[&veh]->myValues->notifyMoveInternal(veh, frontOnLane, timeOnLane, meanSpeedFrontOnLane, meanSpeedVehicleOnLane, travelledDistanceFrontOnLane, travelledDistanceVehicleOnLane, meanLengthOnLane);
333 }
334 
335 
336 bool
338  if (myParent == nullptr || reason != MSMoveReminder::NOTIFICATION_SEGMENT) {
339  myTrackedData[&veh]->myNumVehicleLeft++;
340  }
341  return myTrackedData[&veh]->myValues->notifyLeave(veh, lastPos, reason);
342 }
343 
344 
345 bool
347 #ifdef DEBUG_NOTIFY_ENTER
348  std::cout << "\n" << SIMTIME << " MSMeanData::MeanDataValueTracker: veh '" << veh.getID() << "' enters lane '" << enteredLane->getID() << "'" << std::endl;
349 #else
350  UNUSED_PARAMETER(enteredLane);
351 #endif
352  if (reason == MSMoveReminder::NOTIFICATION_SEGMENT) {
353  return true;
354  }
355  if (myParent->vehicleApplies(veh) && myTrackedData.find(&veh) == myTrackedData.end()) {
356  myTrackedData[&veh] = myCurrentData.back();
357  myTrackedData[&veh]->myNumVehicleEntered++;
358  if (!myTrackedData[&veh]->myValues->notifyEnter(veh, reason)) {
359  myTrackedData[&veh]->myNumVehicleLeft++;
360  myTrackedData.erase(&veh);
361  return false;
362  }
363  return true;
364  }
365  return false;
366 }
367 
368 
369 bool
371  return myCurrentData.front()->myValues->isEmpty();
372 }
373 
374 
375 void
377  long long int attributeMask,
378  const SUMOTime period,
379  const double numLanes,
380  const double speedLimit,
381  const double defaultTravelTime,
382  const int /*numVehicles*/) const {
383  myCurrentData.front()->myValues->write(dev, attributeMask, period, numLanes, speedLimit,
384  defaultTravelTime,
385  myCurrentData.front()->myNumVehicleEntered);
386 }
387 
388 
389 int
391  int result = 0;
392  for (std::list<TrackerEntry*>::const_iterator it = myCurrentData.begin(); it != myCurrentData.end(); ++it) {
393  if ((*it)->myNumVehicleEntered == (*it)->myNumVehicleLeft) {
394  result++;
395  } else {
396  break;
397  }
398  }
399  return result;
400 }
401 
402 
403 double
405  return myCurrentData.front()->myValues->getSamples();
406 }
407 
408 
409 // ---------------------------------------------------------------------------
410 // MSMeanData - methods
411 // ---------------------------------------------------------------------------
412 MSMeanData::MSMeanData(const std::string& id,
413  const SUMOTime dumpBegin, const SUMOTime dumpEnd,
414  const bool useLanes, const bool withEmpty,
415  const bool printDefaults, const bool withInternal,
416  const bool trackVehicles,
417  const int detectPersons,
418  const double maxTravelTime,
419  const double minSamples,
420  const std::string& vTypes,
421  const std::string& writeAttributes) :
422  MSDetectorFileOutput(id, vTypes, detectPersons),
423  myMinSamples(minSamples),
424  myMaxTravelTime(maxTravelTime),
425  myDumpEmpty(withEmpty),
426  myAmEdgeBased(!useLanes),
427  myDumpBegin(dumpBegin),
428  myDumpEnd(dumpEnd),
430  myPrintDefaults(printDefaults),
431  myDumpInternal(withInternal),
432  myTrackVehicles(trackVehicles),
433  myWrittenAttributes(initWrittenAttributes(writeAttributes, id))
434 { }
435 
436 
437 void
440  for (MSEdge* const edge : MSNet::getInstance()->getEdgeControl().getEdges()) {
441  if ((myDumpInternal || !edge->isInternal()) &&
442  ((detectPersons() && myDumpInternal) || (!edge->isCrossing() && !edge->isWalkingArea()))) {
443  myEdges.push_back(edge);
444  myMeasures.push_back(std::vector<MeanDataValues*>());
445  const std::vector<MSLane*>& lanes = edge->getLanes();
447  MeanDataValues* data;
448  if (myTrackVehicles) {
449  data = new MeanDataValueTracker(nullptr, lanes[0]->getLength(), this);
450  } else {
451  data = createValues(nullptr, lanes[0]->getLength(), false);
452  }
453  data->setDescription("meandata_" + edge->getID());
454  myMeasures.back().push_back(data);
456  while (s != nullptr) {
457  s->addDetector(data);
458  s->prepareDetectorForWriting(*data);
459  s = s->getNextSegment();
460  }
461  data->reset();
462  data->reset(true);
463  continue;
464  }
466  myMeasures.back().push_back(new MeanDataValueTracker(nullptr, lanes[0]->getLength(), this));
467  }
468  for (MSLane* const lane : lanes) {
469  if (myTrackVehicles) {
470  if (myAmEdgeBased) {
471  lane->addMoveReminder(myMeasures.back().back());
472  } else {
473  myMeasures.back().push_back(new MeanDataValueTracker(lane, lane->getLength(), this));
474  }
475  } else {
476  myMeasures.back().push_back(createValues(lane, lane->getLength(), true));
477  }
478  }
479  }
480  }
481 }
482 
483 
485  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
486  for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
487  delete *j;
488  }
489  }
490 }
491 
492 
493 void
495  UNUSED_PARAMETER(stopTime);
497  MSEdgeVector::iterator edge = myEdges.begin();
498  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i, ++edge) {
500  MeanDataValues* data = i->front();
501  while (s != nullptr) {
502  s->prepareDetectorForWriting(*data);
503  s = s->getNextSegment();
504  }
505  data->reset();
506  }
507  return;
508  }
509  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
510  for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
511  (*j)->reset();
512  }
513  }
514 }
515 
516 
517 std::string
518 MSMeanData::getEdgeID(const MSEdge* const edge) {
519  return edge->getID();
520 }
521 
522 
523 void
525  const std::vector<MeanDataValues*>& edgeValues,
526  MSEdge* edge, SUMOTime startTime, SUMOTime stopTime) {
529  MeanDataValues* data = edgeValues.front();
530  while (s != nullptr) {
531  s->prepareDetectorForWriting(*data);
532  s = s->getNextSegment();
533  }
534  if (writePrefix(dev, *data, SUMO_TAG_EDGE, getEdgeID(edge))) {
535  data->write(dev, myWrittenAttributes, stopTime - startTime,
536  (double)edge->getLanes().size(),
537  edge->getSpeedLimit(),
538  myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
539  }
540  data->reset(true);
541  return;
542  }
543  std::vector<MeanDataValues*>::const_iterator lane;
544  if (!myAmEdgeBased) {
545  bool writeCheck = myDumpEmpty;
546  if (!writeCheck) {
547  for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
548  if (!(*lane)->isEmpty()) {
549  writeCheck = true;
550  break;
551  }
552  }
553  }
554  if (writeCheck) {
556  }
557  for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
558  MeanDataValues& meanData = **lane;
559  if (writePrefix(dev, meanData, SUMO_TAG_LANE, meanData.getLane()->getID())) {
560  meanData.write(dev, myWrittenAttributes, stopTime - startTime, 1.f, meanData.getLane()->getSpeedLimit(),
561  myPrintDefaults ? meanData.getLane()->getLength() / meanData.getLane()->getSpeedLimit() : -1.);
562  }
563  meanData.reset(true);
564  }
565  if (writeCheck) {
566  dev.closeTag();
567  }
568  } else {
569  if (myTrackVehicles) {
570  MeanDataValues& meanData = **edgeValues.begin();
571  if (writePrefix(dev, meanData, SUMO_TAG_EDGE, edge->getID())) {
572  meanData.write(dev, myWrittenAttributes, stopTime - startTime, (double)edge->getLanes().size(), edge->getSpeedLimit(),
573  myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
574  }
575  meanData.reset(true);
576  } else {
577  MeanDataValues* sumData = createValues(nullptr, edge->getLength(), false);
578  for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
579  MeanDataValues& meanData = **lane;
580  meanData.addTo(*sumData);
581  meanData.reset();
582  }
583  if (writePrefix(dev, *sumData, SUMO_TAG_EDGE, getEdgeID(edge))) {
584  sumData->write(dev, myWrittenAttributes, stopTime - startTime, (double)edge->getLanes().size(), edge->getSpeedLimit(),
585  myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
586  }
587  delete sumData;
588  }
589  }
590 }
591 
592 
593 void
594 MSMeanData::openInterval(OutputDevice& dev, const SUMOTime startTime, const SUMOTime stopTime) {
597 }
598 
599 
600 bool
601 MSMeanData::writePrefix(OutputDevice& dev, const MeanDataValues& values, const SumoXMLTag tag, const std::string id) const {
602  if (myDumpEmpty || !values.isEmpty()) {
603  dev.openTag(tag);
604  dev.writeAttr(SUMO_ATTR_ID, id);
606  return true;
607  }
608  return false;
609 }
610 
611 
612 void
614  SUMOTime startTime, SUMOTime stopTime) {
615  // check whether this dump shall be written for the current time
616  int numReady = myDumpBegin < stopTime && myDumpEnd - DELTA_T >= startTime ? 1 : 0;
617  if (myTrackVehicles && myDumpBegin < stopTime) {
618  myPendingIntervals.push_back(std::make_pair(startTime, stopTime));
619  numReady = (int)myPendingIntervals.size();
620  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
621  for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
622  numReady = MIN2(numReady, ((MeanDataValueTracker*)*j)->getNumReady());
623  if (numReady == 0) {
624  break;
625  }
626  }
627  if (numReady == 0) {
628  break;
629  }
630  }
631  }
632  const bool partialInterval = startTime < myInitTime;
633  if (numReady == 0 || myTrackVehicles || partialInterval) {
634  resetOnly(stopTime);
635  }
636  if (partialInterval) {
637  return;
638  }
639  while (numReady-- > 0) {
640  if (!myPendingIntervals.empty()) {
641  startTime = myPendingIntervals.front().first;
642  stopTime = myPendingIntervals.front().second;
643  myPendingIntervals.pop_front();
644  }
645  openInterval(dev, startTime, stopTime);
646  MSEdgeVector::iterator edge = myEdges.begin();
647  for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i, ++edge) {
648  writeEdge(dev, (*i), *edge, startTime, stopTime);
649  }
650  dev.closeTag();
651  }
652  dev.flush();
653 }
654 
655 
656 void
658  dev.writeXMLHeader("meandata", "meandata_file.xsd");
659 }
660 
661 
662 void
664  if (step + DELTA_T == myDumpBegin) {
665  init();
666  }
667 }
668 
669 
670 long long int
671 MSMeanData::initWrittenAttributes(const std::string writeAttributes, const std::string& id) {
672  long long int result = 0;
673  for (std::string attrName : StringTokenizer(writeAttributes).getVector()) {
674  if (!SUMOXMLDefinitions::Attrs.hasString(attrName)) {
675  WRITE_ERROR("Unknown attribute '" + attrName + "' to write in meanData '" + id + "'.");
676  continue;
677  }
678  int attr = SUMOXMLDefinitions::Attrs.get(attrName);
679  assert(attr < 63);
680  result |= ((long long int)1 << attr);
681  }
682  return result;
683 }
684 
685 
686 /****************************************************************************/
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:288
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
std::string time2string(SUMOTime t)
convert SUMOTime to string
Definition: SUMOTime.cpp:68
#define SUMOTime_MAX
Definition: SUMOTime.h:33
#define TS
Definition: SUMOTime.h:40
#define SIMTIME
Definition: SUMOTime.h:60
long long int SUMOTime
Definition: SUMOTime.h:32
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:101
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:74
T MAX2(T a, T b)
Definition: StdDefs.h:80
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition: MELoop.cpp:314
A single mesoscopic segment (cell)
Definition: MESegment.h:49
MESegment * getNextSegment() const
Returns the following segment on the same edge (0 if it is the last).
Definition: MESegment.h:227
void prepareDetectorForWriting(MSMoveReminder &data)
Updates data of a detector for all vehicle queues.
Definition: MESegment.cpp:261
void addDetector(MSMoveReminder *data)
Adds a data collector for a detector to this segment.
Definition: MESegment.cpp:236
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:678
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:600
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:990
double getLength() const
return the length of the edge
Definition: MSEdge.h:641
static bool gUseMesoSim
Definition: MSGlobals.h:94
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition: MSGlobals.h:100
static bool gSemiImplicitEulerUpdate
Definition: MSGlobals.h:53
static int gNumSimThreads
how many threads to use for simulation
Definition: MSGlobals.h:133
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:533
double getLength() const
Returns the lane's length.
Definition: MSLane.h:541
Definition: MSMeanData.h:257
Data structure for mean (aggregated) edge/lane values for tracked vehicles.
Definition: MSMeanData.h:183
double getSamples() const
Returns the number of collected sample seconds.
Definition: MSMeanData.cpp:404
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:337
void addTo(MSMeanData::MeanDataValues &val) const
Add the values of this to the given one and store them there.
Definition: MSMeanData.cpp:325
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:331
virtual ~MeanDataValueTracker()
Destructor.
Definition: MSMeanData.cpp:296
bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Computes current values and adds them to their sums.
Definition: MSMeanData.cpp:346
std::list< TrackerEntry * > myCurrentData
The currently active meandata "intervals".
Definition: MSMeanData.h:282
bool isEmpty() const
Returns whether any data was collected.
Definition: MSMeanData.cpp:370
void reset(bool afterWrite)
Resets values so they may be used for the next interval.
Definition: MSMeanData.cpp:313
void write(OutputDevice &dev, long long int attributeMask, const SUMOTime period, const double numLanes, const double speedLimit, const double defaultTravelTime, const int numVehicles=-1) const
Writes output values into the given stream.
Definition: MSMeanData.cpp:376
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 void write(OutputDevice &dev, long long int attributeMask, const SUMOTime period, const double numLanes, const double speedLimit, const double defaultTravelTime, const int numVehicles=-1) const =0
Writes output values into the given stream.
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
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
void writeXMLOutput(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Writes collected values into the given stream.
Definition: MSMeanData.cpp:613
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:524
const bool myDumpInternal
Whether internal lanes/edges shall be written.
Definition: MSMeanData.h:456
const SUMOTime myDumpBegin
The first and the last time step to write information (-1 indicates always)
Definition: MSMeanData.h:444
virtual void detectorUpdate(const SUMOTime step)
Updates the detector.
Definition: MSMeanData.cpp:663
virtual ~MSMeanData()
Destructor.
Definition: MSMeanData.cpp:484
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:438
const double myMinSamples
the minimum sample seconds
Definition: MSMeanData.h:426
void resetOnly(SUMOTime stopTime)
Resets network value in order to allow processing of the next interval.
Definition: MSMeanData.cpp:494
const long long int myWrittenAttributes
bit mask for checking attributes to be written
Definition: MSMeanData.h:462
const bool myPrintDefaults
Whether empty lanes/edges shall be written.
Definition: MSMeanData.h:453
const bool myAmEdgeBased
Information whether the output shall be edge-based (not lane-based)
Definition: MSMeanData.h:441
SUMOTime myInitTime
time at which init was called();
Definition: MSMeanData.h:447
const double myMaxTravelTime
the maximum travel time to write
Definition: MSMeanData.h:429
const SUMOTime myDumpEnd
Definition: MSMeanData.h:444
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:465
virtual std::string getEdgeID(const MSEdge *const edge)
Return the relevant edge id.
Definition: MSMeanData.cpp:518
static long long int initWrittenAttributes(const std::string writeAttributes, const std::string &id)
Definition: MSMeanData.cpp:671
virtual void writeXMLDetectorProlog(OutputDevice &dev) const
Opens the XML-output using "netstats" as root element.
Definition: MSMeanData.cpp:657
const bool myDumpEmpty
Whether empty lanes/edges shall be written.
Definition: MSMeanData.h:435
MSEdgeVector myEdges
The corresponding first edges.
Definition: MSMeanData.h:450
virtual void openInterval(OutputDevice &dev, const SUMOTime startTime, const SUMOTime stopTime)
Writes the interval opener.
Definition: MSMeanData.cpp:594
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:412
std::vector< std::vector< MeanDataValues * > > myMeasures
Value collectors; sorted by edge, then by lane.
Definition: MSMeanData.h:432
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:601
const bool myTrackVehicles
Whether vehicles are tracked.
Definition: MSMeanData.h:459
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:174
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:318
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:265
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:248
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