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
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
74bool
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
86bool
87MSMeanData::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
259bool
260MSMeanData::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 }
265}
266
267
268bool
270 return sampleSeconds == 0;
271}
272
273
274void
276}
277
278
279double
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
312void
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
325void
327 myCurrentData.front()->myValues->addTo(val);
328}
329
330
331void
332MSMeanData::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
337bool
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
346bool
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
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
370bool
372 return myCurrentData.front()->myValues->isEmpty();
373}
374
375
376void
378 long long int attributeMask,
379 const SUMOTime period,
380 const double 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
390int
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
404double
406 return myCurrentData.front()->myValues->getSamples();
407}
408
409
410// ---------------------------------------------------------------------------
411// MSMeanData - methods
412// ---------------------------------------------------------------------------
413MSMeanData::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
442void
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 (myTrackVehicles) {
462 data = new MeanDataValueTracker(nullptr, lanes[0]->getLength(), this);
463 } else {
464 data = createValues(nullptr, lanes[0]->getLength(), false);
465 }
466 data->setDescription("meandata_" + edge->getID());
467 myMeasures.back().push_back(data);
469 while (s != nullptr) {
470 s->addDetector(data);
472 s = s->getNextSegment();
473 }
474 data->reset();
475 data->reset(true);
476 continue;
477 }
479 myMeasures.back().push_back(new MeanDataValueTracker(nullptr, lanes[0]->getLength(), this));
480 }
481 for (MSLane* const lane : lanes) {
482 if (myTrackVehicles) {
483 if (myAmEdgeBased) {
484 lane->addMoveReminder(myMeasures.back().back());
485 } else {
486 myMeasures.back().push_back(new MeanDataValueTracker(lane, lane->getLength(), this));
487 }
488 } else {
489 myMeasures.back().push_back(createValues(lane, lane->getLength(), true));
490 }
491 }
492 }
493}
494
495
497 for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
498 for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
499 delete *j;
500 }
501 }
502}
503
504
505void
507 UNUSED_PARAMETER(stopTime);
509 MSEdgeVector::iterator edge = myEdges.begin();
510 for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i, ++edge) {
512 MeanDataValues* data = i->front();
513 while (s != nullptr) {
515 s = s->getNextSegment();
516 }
517 data->reset();
518 }
519 return;
520 }
521 for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
522 for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
523 (*j)->reset();
524 }
525 }
526}
527
528
529std::string
530MSMeanData::getEdgeID(const MSEdge* const edge) {
531 return edge->getID();
532}
533
534
535void
537 if (myTrackVehicles) {
538 throw ProcessError("aggregated meanData output not yet implemented for trackVehicles");
539 }
540
541 double edgeLengthSum = 0;
542 int laneNumber = 0;
543 double speedSum = 0;
544 double totalTT = 0;
545 for (MSEdge* edge : myEdges) {
546 edgeLengthSum += edge->getLength();
547 laneNumber += edge->getNumLanes();
548 speedSum += edge->getSpeedLimit();
549 totalTT += edge->getLength() / edge->getSpeedLimit();
550 }
551 MeanDataValues* sumData = createValues(nullptr, edgeLengthSum, false);
552 for (const std::vector<MeanDataValues*>& edgeValues : myMeasures) {
553 for (MeanDataValues* meanData : edgeValues) {
554 meanData->addTo(*sumData);
555 meanData->reset();
556 }
557 }
559 for (MSEdge* edge : myEdges) {
561 while (s != nullptr) {
562 s->prepareDetectorForWriting(*sumData);
563 s = s->getNextSegment();
564 }
565 }
566 }
567
568 if (writePrefix(dev, *sumData, SUMO_TAG_EDGE, "AGGREGATED")) {
570 sumData->write(dev, myWrittenAttributes, stopTime - startTime, (double)laneNumber, speedSum / (double)myEdges.size(),
571 myPrintDefaults ? totalTT : -1.);
572 }
573 delete sumData;
574}
575
576
577void
579 const std::vector<MeanDataValues*>& edgeValues,
580 MSEdge* edge, SUMOTime startTime, SUMOTime stopTime) {
583 MeanDataValues* data = edgeValues.front();
584 while (s != nullptr) {
586 s = s->getNextSegment();
587 }
588 if (writePrefix(dev, *data, SUMO_TAG_EDGE, getEdgeID(edge))) {
589 data->write(dev, myWrittenAttributes, stopTime - startTime,
590 (double)edge->getLanes().size(),
591 edge->getSpeedLimit(),
592 myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
593 }
594 data->reset(true);
595 return;
596 }
597 std::vector<MeanDataValues*>::const_iterator lane;
598 if (!myAmEdgeBased) {
599 bool writeCheck = myDumpEmpty;
600 if (!writeCheck) {
601 for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
602 if (!(*lane)->isEmpty()) {
603 writeCheck = true;
604 break;
605 }
606 }
607 }
608 if (writeCheck) {
610 }
611 for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
612 MeanDataValues& meanData = **lane;
613 if (writePrefix(dev, meanData, SUMO_TAG_LANE, meanData.getLane()->getID())) {
614 meanData.write(dev, myWrittenAttributes, stopTime - startTime, 1.f, meanData.getLane()->getSpeedLimit(),
615 myPrintDefaults ? meanData.getLane()->getLength() / meanData.getLane()->getSpeedLimit() : -1.);
616 }
617 meanData.reset(true);
618 }
619 if (writeCheck) {
620 dev.closeTag();
621 }
622 } else {
623 if (myTrackVehicles) {
624 MeanDataValues& meanData = **edgeValues.begin();
625 if (writePrefix(dev, meanData, SUMO_TAG_EDGE, edge->getID())) {
626 meanData.write(dev, myWrittenAttributes, stopTime - startTime, (double)edge->getLanes().size(), edge->getSpeedLimit(),
627 myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
628 }
629 meanData.reset(true);
630 } else {
631 MeanDataValues* sumData = createValues(nullptr, edge->getLength(), false);
632 for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
633 MeanDataValues& meanData = **lane;
634 meanData.addTo(*sumData);
635 meanData.reset();
636 }
637 if (writePrefix(dev, *sumData, SUMO_TAG_EDGE, getEdgeID(edge))) {
638 sumData->write(dev, myWrittenAttributes, stopTime - startTime, (double)edge->getLanes().size(), edge->getSpeedLimit(),
639 myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
640 }
641 delete sumData;
642 }
643 }
644}
645
646
647void
648MSMeanData::openInterval(OutputDevice& dev, const SUMOTime startTime, const SUMOTime stopTime) {
651}
652
653
654bool
655MSMeanData::writePrefix(OutputDevice& dev, const MeanDataValues& values, const SumoXMLTag tag, const std::string id) const {
656 if (myDumpEmpty || !values.isEmpty()) {
657 dev.openTag(tag);
658 dev.writeAttr(SUMO_ATTR_ID, id);
660 return true;
661 }
662 return false;
663}
664
665
666void
668 SUMOTime startTime, SUMOTime stopTime) {
669 // check whether this dump shall be written for the current time
670 int numReady = myDumpBegin < stopTime && myDumpEnd - DELTA_T >= startTime ? 1 : 0;
671 if (myTrackVehicles && myDumpBegin < stopTime) {
672 myPendingIntervals.push_back(std::make_pair(startTime, stopTime));
673 numReady = (int)myPendingIntervals.size();
674 for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
675 for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
676 numReady = MIN2(numReady, ((MeanDataValueTracker*)*j)->getNumReady());
677 if (numReady == 0) {
678 break;
679 }
680 }
681 if (numReady == 0) {
682 break;
683 }
684 }
685 }
686 const bool partialInterval = startTime < myInitTime;
687 if (numReady == 0 || myTrackVehicles || partialInterval) {
688 resetOnly(stopTime);
689 }
690 if (partialInterval) {
691 return;
692 }
693 while (numReady-- > 0) {
694 if (!myPendingIntervals.empty()) {
695 startTime = myPendingIntervals.front().first;
696 stopTime = myPendingIntervals.front().second;
697 myPendingIntervals.pop_front();
698 }
699 openInterval(dev, startTime, stopTime);
700 if (myAggregate) {
701 writeAggregated(dev, startTime, stopTime);
702 } else {
703 MSEdgeVector::iterator edge = myEdges.begin();
704 for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i, ++edge) {
705 writeEdge(dev, (*i), *edge, startTime, stopTime);
706 }
707 }
708 dev.closeTag();
709 }
710 dev.flush();
711}
712
713
714void
716 dev.writeXMLHeader("meandata", "meandata_file.xsd");
717}
718
719
720void
722 if (step + DELTA_T == myDumpBegin) {
723 init();
724 }
725}
726
727
728long long int
729MSMeanData::initWrittenAttributes(const std::string writeAttributes, const std::string& id) {
730 long long int result = 0;
731 for (std::string attrName : StringTokenizer(writeAttributes).getVector()) {
732 if (!SUMOXMLDefinitions::Attrs.hasString(attrName)) {
733 WRITE_ERROR("Unknown attribute '" + attrName + "' to write in meanData '" + id + "'.");
734 continue;
735 }
736 int attr = SUMOXMLDefinitions::Attrs.get(attrName);
737 assert(attr < 63);
738 result |= ((long long int)1 << attr);
739 }
740 return result;
741}
742
743const std::vector<MSMeanData::MeanDataValues*>*
745 auto it = myEdgeIndex.find(edge);
746 if (it != myEdgeIndex.end()) {
747 return &myMeasures[it->second];
748 } else {
749 return nullptr;
750 }
751}
752
753/****************************************************************************/
long long int SUMOTime
Definition: GUI.h:36
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:274
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:41
#define SIMTIME
Definition: SUMOTime.h:61
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:98
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:71
T MAX2(T a, T b)
Definition: StdDefs.h:77
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
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
MESegment * getNextSegment() const
Returns the following segment on the same edge (0 if it is the last).
Definition: MESegment.h:223
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:714
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:636
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:1056
double getLength() const
return the length of the edge
Definition: MSEdge.h:658
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:142
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:561
double getLength() const
Returns the lane's length.
Definition: MSLane.h:575
Definition: MSMeanData.h:266
Data structure for mean (aggregated) edge/lane values for tracked vehicles.
Definition: MSMeanData.h:192
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
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:291
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
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:377
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
virtual MSMeanData::MeanDataValues * createValues(MSLane *const lane, const double length, const bool doAdd) const =0
Create an instance of MeanDataValues.
const bool myAggregate
whether the data for all edges shall be aggregated
Definition: MSMeanData.h:508
void writeXMLOutput(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Writes collected values into the given stream.
Definition: MSMeanData.cpp:667
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:578
const bool myDumpInternal
Whether internal lanes/edges shall be written.
Definition: MSMeanData.h:499
const SUMOTime myDumpBegin
The first and the last time step to write information (-1 indicates always)
Definition: MSMeanData.h:484
virtual void detectorUpdate(const SUMOTime step)
Updates the detector.
Definition: MSMeanData.cpp:721
virtual ~MSMeanData()
Destructor.
Definition: MSMeanData.cpp:496
void writeAggregated(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Writes aggregate of all edge values into the given stream.
Definition: MSMeanData.cpp:536
void init()
Adds the value collectors to all relevant edges.
Definition: MSMeanData.cpp:443
const double myMinSamples
the minimum sample seconds
Definition: MSMeanData.h:466
void resetOnly(SUMOTime stopTime)
Resets network value in order to allow processing of the next interval.
Definition: MSMeanData.cpp:506
const long long int myWrittenAttributes
bit mask for checking attributes to be written
Definition: MSMeanData.h:505
const bool myPrintDefaults
Whether empty lanes/edges shall be written.
Definition: MSMeanData.h:496
std::map< const MSEdge *, int > myEdgeIndex
The index in myEdges / myMeasures.
Definition: MSMeanData.h:493
const bool myAmEdgeBased
Information whether the output shall be edge-based (not lane-based)
Definition: MSMeanData.h:478
SUMOTime myInitTime
time at which init was called();
Definition: MSMeanData.h:487
const double myMaxTravelTime
the maximum travel time to write
Definition: MSMeanData.h:469
const SUMOTime myDumpEnd
Definition: MSMeanData.h:484
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:511
const std::vector< MeanDataValues * > * getEdgeValues(const MSEdge *edge) const
Definition: MSMeanData.cpp:744
virtual std::string getEdgeID(const MSEdge *const edge)
Return the relevant edge id.
Definition: MSMeanData.cpp:530
static long long int initWrittenAttributes(const std::string writeAttributes, const std::string &id)
Definition: MSMeanData.cpp:729
virtual void writeXMLDetectorProlog(OutputDevice &dev) const
Opens the XML-output using "netstats" as root element.
Definition: MSMeanData.cpp:715
const bool myDumpEmpty
Whether empty lanes/edges shall be written.
Definition: MSMeanData.h:475
MSEdgeVector myEdges
The corresponding first edges.
Definition: MSMeanData.h:490
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:648
std::vector< std::vector< MeanDataValues * > > myMeasures
Value collectors; sorted by edge, then by lane.
Definition: MSMeanData.h:472
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:655
const bool myTrackVehicles
Whether vehicles are tracked.
Definition: MSMeanData.h:502
Something on a lane to be noticed about vehicle movement.
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.
const MSLane * getLane() const
Returns the lane the reminder works on.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:183
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:321
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 & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:251
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
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.
OutputDevice & writeOptionalAttr(const SumoXMLAttr attr, const T &val, long long int attributeMask)
writes a named attribute unless filtered
Definition: OutputDevice.h:268
Representation of a vehicle, person, or container.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual double getPreviousSpeed() const =0
Returns the object's previous speed.
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