Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2026 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 : /****************************************************************************/
14 : /// @file MSMeanData.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @author Laura Bieker
19 : /// @author Leonhard Luecken
20 : /// @date Mon, 10.05.2004
21 : ///
22 : // Data collector for edges/lanes
23 : /****************************************************************************/
24 : #include <config.h>
25 :
26 : #include <limits>
27 : #ifdef HAVE_FOX
28 : #include <utils/common/ScopedLocker.h>
29 : #endif
30 : #include <utils/common/SUMOTime.h>
31 : #include <utils/common/ToString.h>
32 : #include <utils/common/StringTokenizer.h>
33 : #include <utils/iodevices/OutputDevice.h>
34 : #include <microsim/MSEdgeControl.h>
35 : #include <microsim/MSEdge.h>
36 : #include <microsim/MSLane.h>
37 : #include <microsim/MSVehicle.h>
38 : #include <microsim/cfmodels/MSCFModel.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 : // ---------------------------------------------------------------------------
60 9145610 : MSMeanData::MeanDataValues::MeanDataValues(
61 : MSLane* const lane, const double length, const bool doAdd,
62 9145610 : const MSMeanData* const parent) :
63 18291220 : MSMoveReminder("meandata_" + (parent == nullptr ? "" : parent->getID() + "|") + (lane == nullptr ? "NULL" : lane->getID()), lane, doAdd),
64 9145610 : myParent(parent),
65 9145610 : myLaneLength(length),
66 9145610 : sampleSeconds(0),
67 27436830 : travelledDistance(0) { }
68 :
69 :
70 9144316 : MSMeanData::MeanDataValues::~MeanDataValues() {
71 9144316 : }
72 :
73 :
74 : bool
75 692777 : MSMeanData::MeanDataValues::notifyEnter(SUMOTrafficObject& veh, MSMoveReminder::Notification reason, const MSLane* enteredLane) {
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 692777 : return myParent == nullptr || myParent->vehicleApplies(veh);
83 : }
84 :
85 :
86 : bool
87 482196356 : 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 482196356 : const double oldSpeed = veh.getPreviousSpeed();
91 482196356 : 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 482196356 : double timeOnLane = TS;
96 482196356 : 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 482196356 : 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 482196356 : if (oldPos < 0 && newPos >= 0) {
107 : // Vehicle was not on this lane in the last time step
108 11236838 : timeBeforeEnter = MSCFModel::passingTime(oldPos, 0, newPos, oldSpeed, newSpeed);
109 11236838 : timeOnLane = TS - timeBeforeEnter;
110 : frontOnLane = timeOnLane;
111 11236838 : enterSpeed = MSCFModel::speedAfterTime(timeBeforeEnter, oldSpeed, newPos - oldPos);
112 : }
113 :
114 482196356 : const double oldBackPos = oldPos - veh.getVehicleType().getLength();
115 482196356 : const double newBackPos = newPos - veh.getVehicleType().getLength();
116 :
117 : // Determine the time before the vehicle back enters
118 482196356 : if (oldBackPos < 0. && newBackPos > 0.) {
119 11517687 : timeBeforeEnterBack = MSCFModel::passingTime(oldBackPos, 0., newBackPos, oldSpeed, newSpeed);
120 470678669 : } else if (newBackPos <= 0) {
121 7949967 : 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 482196356 : if (newBackPos > myLaneLength // vehicle's back has left the lane
128 12964893 : && 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 12964683 : timeBeforeLeave = MSCFModel::passingTime(oldBackPos, myLaneLength, newBackPos, oldSpeed, newSpeed);
132 12964683 : const double timeAfterLeave = TS - timeBeforeLeave;
133 12964683 : timeOnLane -= timeAfterLeave;
134 12964683 : leaveSpeed = MSCFModel::speedAfterTime(timeBeforeLeave, oldSpeed, newPos - oldPos);
135 : // XXX: Do we really need this? Why would this "reduce rounding errors"? (Leo) Refs. #2579
136 12964683 : if (fabs(timeOnLane) < NUMERICAL_EPS) { // reduce rounding errors
137 : timeOnLane = 0.;
138 : }
139 12964683 : ret = veh.hasArrived();
140 : }
141 :
142 : // Treat the case that the vehicle's front left the lane in the last step
143 482196356 : 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 14170641 : timeBeforeLeaveFront = MSCFModel::passingTime(oldPos, myLaneLength, newPos, oldSpeed, newSpeed);
147 14170641 : const double timeAfterLeave = TS - timeBeforeLeaveFront;
148 14170641 : frontOnLane -= timeAfterLeave;
149 : // XXX: Do we really need this? Why would this "reduce rounding errors"? (Leo) Refs. #2579
150 14170641 : if (fabs(frontOnLane) < NUMERICAL_EPS) { // reduce rounding errors
151 : frontOnLane = 0.;
152 : }
153 14170641 : leaveSpeedFront = MSCFModel::speedAfterTime(timeBeforeLeaveFront, oldSpeed, newPos - oldPos);
154 : }
155 :
156 : assert(frontOnLane <= TS);
157 : assert(timeOnLane <= TS);
158 :
159 482196356 : if (timeOnLane < 0) {
160 0 : WRITE_ERRORF(TL("Negative vehicle step fraction for '%' on lane '%'."), veh.getID(), getLane()->getID());
161 0 : return veh.hasArrived();
162 : }
163 482196356 : if (timeOnLane == 0) {
164 21963 : 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 482174393 : double vehLength = veh.getVehicleType().getLength();
192 : // occupied lane length at timeBeforeEnter (resp. stepStart if already on lane)
193 482174393 : double lengthOnLaneAtStepStart = MAX2(0., MIN4(myLaneLength, vehLength, vehLength - (oldPos - myLaneLength), oldPos));
194 : // occupied lane length at timeBeforeLeave (resp. stepEnd if still on lane)
195 482174393 : double lengthOnLaneAtStepEnd = MAX2(0., MIN4(myLaneLength, vehLength, vehLength - (newPos - myLaneLength), newPos));
196 : double integratedLengthOnLane = 0.;
197 482174393 : if (timeBeforeEnterBack < timeBeforeLeaveFront) {
198 : // => timeBeforeLeaveFront>0, myLaneLength>vehLength
199 : // vehicle length on detector at timeBeforeEnterBack
200 466271371 : double lengthOnLaneAtBackEnter = MIN2(veh.getVehicleType().getLength(), newPos);
201 : // linear quadrature of occupancy between timeBeforeEnter and timeBeforeEnterBack
202 466271371 : 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 466271371 : integratedLengthOnLane += (timeBeforeLeaveFront - timeBeforeEnterBack) * vehLength;
206 : // and until vehicle leaves/stepEnd
207 466271371 : integratedLengthOnLane += (timeBeforeLeave - timeBeforeLeaveFront) * (vehLength + lengthOnLaneAtStepEnd) * 0.5;
208 15903022 : } else if (timeBeforeEnterBack >= timeBeforeLeaveFront) {
209 : // => myLaneLength <= vehLength or (timeBeforeLeaveFront == timeBeforeEnterBack == 0)
210 : // vehicle length on detector at timeBeforeLeaveFront
211 : double lengthOnLaneAtLeaveFront;
212 15903022 : if (timeBeforeLeaveFront == timeBeforeEnter) {
213 : // for the case that front already left
214 : lengthOnLaneAtLeaveFront = lengthOnLaneAtStepStart;
215 7974432 : } 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 15903022 : integratedLengthOnLane += (timeBeforeLeaveFront - timeBeforeEnter) * (lengthOnLaneAtLeaveFront + lengthOnLaneAtStepStart) * 0.5;
226 : // linear quadrature of occupancy between timeBeforeLeaveFront and timeBeforeEnterBack
227 15903022 : integratedLengthOnLane += (timeBeforeEnterBack - timeBeforeLeaveFront) * lengthOnLaneAtLeaveFront;
228 : // and until vehicle leaves/stepEnd
229 15903022 : integratedLengthOnLane += (timeBeforeLeave - timeBeforeEnterBack) * (lengthOnLaneAtLeaveFront + lengthOnLaneAtStepEnd) * 0.5;
230 : }
231 :
232 482174393 : 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 482174393 : const double travelledDistanceFrontOnLane = MSGlobals::gSemiImplicitEulerUpdate ? frontOnLane * newSpeed
244 162629688 : : MAX2(0., MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.));
245 563489237 : const double travelledDistanceVehicleOnLane = MSGlobals::gSemiImplicitEulerUpdate ? timeOnLane * newSpeed
246 162629688 : : 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 482174393 : ScopedLocker<> lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
253 : #endif
254 482174393 : notifyMoveInternal(veh, frontOnLane, timeOnLane, (enterSpeed + leaveSpeedFront) / 2., (enterSpeed + leaveSpeed) / 2., travelledDistanceFrontOnLane, travelledDistanceVehicleOnLane, meanLengthOnLane);
255 : return ret;
256 : }
257 :
258 :
259 : bool
260 1183104 : MSMeanData::MeanDataValues::notifyLeave(SUMOTrafficObject& /*veh*/, double /*lastPos*/, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
261 1183104 : if (MSGlobals::gUseMesoSim) {
262 : return false; // reminder is re-added on every segment (@recheck for performance)
263 : }
264 1028810 : return reason == MSMoveReminder::NOTIFICATION_JUNCTION;
265 : }
266 :
267 :
268 : bool
269 2951641 : MSMeanData::MeanDataValues::isEmpty() const {
270 2951641 : return sampleSeconds == 0;
271 : }
272 :
273 :
274 : void
275 0 : MSMeanData::MeanDataValues::update() {
276 0 : }
277 :
278 :
279 : double
280 1033803 : MSMeanData::MeanDataValues::getSamples() const {
281 1033803 : return sampleSeconds;
282 : }
283 :
284 :
285 : // ---------------------------------------------------------------------------
286 : // MSMeanData::MeanDataValueTracker - methods
287 : // ---------------------------------------------------------------------------
288 2744 : MSMeanData::MeanDataValueTracker::MeanDataValueTracker(MSLane* const lane,
289 : const double length,
290 2744 : const MSMeanData* const parent)
291 2744 : : MSMeanData::MeanDataValues(lane, length, true, parent) {
292 2744 : myCurrentData.push_back(std::make_shared<TrackerEntry>(parent->createValuesSubData(lane, length, false)));
293 2744 : }
294 :
295 :
296 8232 : MSMeanData::MeanDataValueTracker::~MeanDataValueTracker() {}
297 :
298 :
299 : void
300 164304 : MSMeanData::MeanDataValueTracker::reset(bool afterWrite) {
301 164304 : if (afterWrite) {
302 70360 : if (!myCurrentData.empty()) {
303 70360 : myCurrentData.pop_front();
304 : }
305 : } else {
306 187888 : myCurrentData.push_back(std::make_shared<TrackerEntry>(myParent->createValuesSubData(myLane, myLaneLength, false)));
307 : }
308 164304 : }
309 :
310 :
311 : void
312 0 : MSMeanData::MeanDataValueTracker::addTo(MSMeanData::MeanDataValues& val) const {
313 0 : myCurrentData.front()->myValues->addTo(val);
314 0 : }
315 :
316 :
317 : void
318 15012 : 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) {
319 15012 : myTrackedData[&veh]->myValues->notifyMoveInternal(veh, frontOnLane, timeOnLane, meanSpeedFrontOnLane, meanSpeedVehicleOnLane, travelledDistanceFrontOnLane, travelledDistanceVehicleOnLane, meanLengthOnLane);
320 15012 : }
321 :
322 :
323 : bool
324 787 : MSMeanData::MeanDataValueTracker::notifyLeave(SUMOTrafficObject& veh, double lastPos, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
325 787 : if (myParent == nullptr || reason != MSMoveReminder::NOTIFICATION_SEGMENT) {
326 387 : myTrackedData[&veh]->myNumVehicleLeft++;
327 : }
328 787 : return myTrackedData[&veh]->myValues->notifyLeave(veh, lastPos, reason);
329 : }
330 :
331 :
332 : bool
333 3402 : MSMeanData::MeanDataValueTracker::notifyEnter(SUMOTrafficObject& veh, MSMoveReminder::Notification reason, const MSLane* enteredLane) {
334 : #ifdef DEBUG_NOTIFY_ENTER
335 : std::cout << "\n" << SIMTIME << " MSMeanData::MeanDataValueTracker: veh '" << veh.getID() << "' enters lane '" << enteredLane->getID() << "'" << std::endl;
336 : #else
337 : UNUSED_PARAMETER(enteredLane);
338 : #endif
339 3402 : if (reason == MSMoveReminder::NOTIFICATION_SEGMENT) {
340 : return true;
341 : }
342 5772 : if (myParent->vehicleApplies(veh) && myTrackedData.find(&veh) == myTrackedData.end()) {
343 507 : myTrackedData[&veh] = myCurrentData.back();
344 507 : myTrackedData[&veh]->myNumVehicleEntered++;
345 507 : if (!myTrackedData[&veh]->myValues->notifyEnter(veh, reason)) {
346 0 : myTrackedData[&veh]->myNumVehicleLeft++;
347 0 : myTrackedData.erase(&veh);
348 0 : return false;
349 : }
350 : return true;
351 : }
352 : return false;
353 : }
354 :
355 :
356 : bool
357 91696 : MSMeanData::MeanDataValueTracker::isEmpty() const {
358 91696 : return myCurrentData.front()->myValues->isEmpty();
359 : }
360 :
361 :
362 : void
363 368 : MSMeanData::MeanDataValueTracker::write(OutputDevice& dev,
364 : const SumoXMLAttrMask& attributeMask,
365 : const SUMOTime period,
366 : const int numLanes,
367 : const double speedLimit,
368 : const double defaultTravelTime,
369 : const int /*numVehicles*/) const {
370 368 : myCurrentData.front()->myValues->write(dev, attributeMask, period, numLanes, speedLimit,
371 : defaultTravelTime,
372 : myCurrentData.front()->myNumVehicleEntered);
373 368 : }
374 :
375 :
376 : int
377 63116 : MSMeanData::MeanDataValueTracker::getNumReady() const {
378 : int result = 0;
379 1445056 : for (const auto& it : myCurrentData) {
380 1384592 : if (it->myNumVehicleEntered == it->myNumVehicleLeft) {
381 1381940 : result++;
382 : } else {
383 : break;
384 : }
385 : }
386 63116 : return result;
387 : }
388 :
389 :
390 : double
391 368 : MSMeanData::MeanDataValueTracker::getSamples() const {
392 368 : return myCurrentData.front()->myValues->getSamples();
393 : }
394 :
395 :
396 : // ---------------------------------------------------------------------------
397 : // MSMeanData - methods
398 : // ---------------------------------------------------------------------------
399 24276 : MSMeanData::MSMeanData(const std::string& id,
400 : const SUMOTime dumpBegin, const SUMOTime dumpEnd,
401 : const bool useLanes, const std::string& excludeEmpty, const bool withInternal,
402 : const bool trackVehicles,
403 : const int detectPersons,
404 : const double maxTravelTime,
405 : const double minSamples,
406 : const std::string& vTypes,
407 : const std::string& writeAttributes,
408 : const std::vector<MSEdge*>& edges,
409 24276 : AggregateType aggregate) :
410 : MSDetectorFileOutput(id, vTypes, "", detectPersons),
411 24276 : myMinSamples(minSamples),
412 24276 : myMaxTravelTime(maxTravelTime),
413 24276 : myAmEdgeBased(!useLanes),
414 24276 : myDumpBegin(dumpBegin),
415 24276 : myDumpEnd(dumpEnd),
416 24276 : myInitTime(SUMOTime_MAX),
417 24276 : myEdges(edges),
418 166 : myDumpInternal(withInternal && MSGlobals::gUsingInternalLanes),
419 24276 : myTrackVehicles(trackVehicles),
420 97104 : myWrittenAttributes(OutputDevice::parseWrittenAttributes(StringTokenizer(writeAttributes).getVector(), "meandata '" + id + "'")),
421 72828 : myAggregate(aggregate) {
422 : try {
423 24276 : myDumpEmpty = !StringUtils::toBool(excludeEmpty);
424 84 : } catch (const BoolFormatException&) {
425 84 : if (excludeEmpty == "default" || excludeEmpty == "defaults") {
426 78 : myPrintDefaults = true;
427 6 : } else if (excludeEmpty == "modified") {
428 6 : myDumpEmpty = false;
429 6 : myPrintDefaults = true;
430 6 : myPrintModified = true;
431 : } else {
432 0 : throw;
433 : }
434 84 : }
435 24276 : }
436 :
437 :
438 : void
439 23351 : MSMeanData::init() {
440 23351 : myInitTime = MSNet::getInstance()->getCurrentTimeStep();
441 23351 : if (myEdges.empty()) {
442 : // use all edges by default
443 819534 : for (MSEdge* const edge : MSNet::getInstance()->getEdgeControl().getEdges()) {
444 796253 : if ((myDumpInternal || !edge->isInternal()) &&
445 529751 : ((detectsPersons() && myDumpInternal) || (!edge->isCrossing() && !edge->isWalkingArea()))) {
446 351652 : myEdges.push_back(edge);
447 : }
448 : }
449 : }
450 : int index = 0;
451 375117 : for (MSEdge* edge : myEdges) {
452 351766 : myMeasures.push_back(std::vector<MeanDataValues*>());
453 351766 : myEdgeIndex[edge] = index++;
454 351766 : const std::vector<MSLane*>& lanes = edge->getLanes();
455 351766 : if (MSGlobals::gUseMesoSim) {
456 : MeanDataValues* data;
457 30538 : if (!myAmEdgeBased) {
458 85 : for (MSLane* const lane : lanes) {
459 52 : data = createValues(lane, lanes[0]->getLength(), false);
460 52 : myMeasures.back().push_back(data);
461 52 : MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
462 310 : while (s != nullptr) {
463 258 : s->addDetector(data, lane->getIndex());
464 258 : s->prepareDetectorForWriting(*data, lane->getIndex());
465 : s = s->getNextSegment();
466 : }
467 52 : data->reset();
468 52 : data->reset(true);
469 : }
470 : } else {
471 30505 : if (myTrackVehicles) {
472 880 : data = new MeanDataValueTracker(nullptr, lanes[0]->getLength(), this);
473 : } else {
474 29625 : data = createValues(nullptr, lanes[0]->getLength(), false);
475 : }
476 61010 : data->setDescription("meandata_" + getID() + "|" + edge->getID());
477 30505 : myMeasures.back().push_back(data);
478 30505 : MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
479 153162 : while (s != nullptr) {
480 122657 : s->addDetector(data);
481 122657 : s->prepareDetectorForWriting(*data);
482 : s = s->getNextSegment();
483 : }
484 30505 : data->reset();
485 30505 : data->reset(true);
486 : }
487 : continue;
488 30538 : }
489 321228 : if (myAmEdgeBased && myTrackVehicles) {
490 936 : myMeasures.back().push_back(new MeanDataValueTracker(nullptr, lanes[0]->getLength(), this));
491 : }
492 849019 : for (MSLane* const lane : lanes) {
493 527791 : if (myTrackVehicles) {
494 2016 : if (myAmEdgeBased) {
495 1088 : lane->addMoveReminder(myMeasures.back().back());
496 : } else {
497 928 : myMeasures.back().push_back(new MeanDataValueTracker(lane, lane->getLength(), this));
498 : }
499 : } else {
500 525775 : myMeasures.back().push_back(createValues(lane, lane->getLength(), true));
501 : }
502 : }
503 : }
504 23351 : if (myAggregate == AggregateType::TAZ) {
505 532 : for (const MSEdge* e : MSEdge::getAllEdges()) {
506 524 : if (e->isTazConnector()) {
507 188 : myTAZ.push_back(e);
508 : }
509 : }
510 : }
511 23351 : if (mySubData != nullptr) {
512 6 : mySubData->init();
513 6 : std::vector<std::vector<MeanDataValues*> >::const_iterator subMeasureList = mySubData->myMeasures.begin();
514 48 : for (const std::vector<MeanDataValues*>& valueList : myMeasures) {
515 : std::vector<MeanDataValues*>::const_iterator subMeasures = subMeasureList->begin();
516 84 : for (MeanDataValues* values : valueList) {
517 42 : values->setSubData(*subMeasures);
518 : subMeasures++;
519 : }
520 : subMeasureList++;
521 : }
522 : }
523 23351 : }
524 :
525 :
526 24227 : MSMeanData::~MSMeanData() {
527 375456 : for (const std::vector<MeanDataValues*>& valueList : myMeasures) {
528 908416 : for (MeanDataValues* const values : valueList) {
529 557187 : delete values;
530 : }
531 : }
532 24227 : delete mySubData;
533 24227 : }
534 :
535 :
536 : void
537 12645 : MSMeanData::resetOnly(SUMOTime stopTime) {
538 : UNUSED_PARAMETER(stopTime);
539 12645 : if (MSGlobals::gUseMesoSim) {
540 : MSEdgeVector::iterator edge = myEdges.begin();
541 117300 : for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i, ++edge) {
542 113716 : MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(**edge);
543 227432 : for (MeanDataValues* data : *i) {
544 602292 : while (s != nullptr) {
545 488576 : s->prepareDetectorForWriting(*data);
546 : s = s->getNextSegment();
547 : }
548 113716 : data->reset();
549 : }
550 : }
551 : return;
552 : }
553 257304 : for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
554 529990 : for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
555 281747 : (*j)->reset();
556 : }
557 : }
558 : }
559 :
560 :
561 : std::string
562 586108 : MSMeanData::getEdgeID(const MSEdge* const edge) {
563 586108 : return edge->getID();
564 : }
565 :
566 :
567 : void
568 938 : MSMeanData::writeAggregated(OutputDevice& dev, SUMOTime startTime, SUMOTime stopTime) {
569 938 : if (myTrackVehicles) {
570 0 : throw ProcessError(TL("aggregated meanData output not yet implemented for trackVehicles"));
571 : }
572 :
573 : double edgeLengthSum = 0;
574 : int laneNumber = 0;
575 : double speedSum = 0;
576 : double totalTT = 0;
577 42146 : for (MSEdge* edge : myEdges) {
578 41208 : edgeLengthSum += edge->getLength();
579 41208 : laneNumber += edge->getNumDrivingLanes();
580 41208 : speedSum += edge->getSpeedLimit();
581 41208 : totalTT += edge->getLength() / edge->getSpeedLimit();
582 : }
583 938 : MeanDataValues* sumData = createValuesSubData(nullptr, edgeLengthSum, false);
584 42146 : for (const std::vector<MeanDataValues*>& edgeValues : myMeasures) {
585 82440 : for (MeanDataValues* meanData : edgeValues) {
586 41232 : meanData->addTo(*sumData);
587 41232 : if (!MSNet::getInstance()->skipFinalReset()) {
588 41232 : meanData->reset();
589 : }
590 : }
591 : }
592 938 : if (MSGlobals::gUseMesoSim) {
593 14040 : for (int i = 0; i < (int)myEdges.size(); i++) {
594 13728 : MSEdge* edge = myEdges[i];
595 : std::vector<MeanDataValues*>& edgeValues = myMeasures[i];
596 13728 : MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
597 68640 : while (s != nullptr) {
598 109824 : for (MeanDataValues* meanData : edgeValues) {
599 54912 : s->prepareDetectorForWriting(*meanData);
600 54912 : meanData->addTo(*sumData);
601 54912 : if (!MSNet::getInstance()->skipFinalReset()) {
602 54912 : meanData->reset();
603 : }
604 : }
605 : s = s->getNextSegment();
606 : }
607 : }
608 : }
609 :
610 938 : if (myDumpEmpty || !sumData->isEmpty()) {
611 1864 : writePrefix(dev, *sumData, SUMO_TAG_EDGE, "AGGREGATED");
612 932 : dev.writeAttr(SUMO_ATTR_NUMEDGES, myEdges.size());
613 1864 : for (MeanDataValues* data = sumData; data != nullptr; data = data->getSubData()) {
614 932 : data->write(dev, myWrittenAttributes, stopTime - startTime, laneNumber, speedSum / (double)myEdges.size(),
615 932 : myPrintDefaults ? totalTT : -1.);
616 : }
617 1864 : dev.closeTag();
618 : }
619 938 : delete sumData;
620 938 : }
621 :
622 :
623 : void
624 20 : MSMeanData::writeAggregatedTAZ(OutputDevice& dev, SUMOTime startTime, SUMOTime stopTime) {
625 20 : if (myTrackVehicles) {
626 0 : throw ProcessError(TL("aggregated meanData output not yet implemented for trackVehicles"));
627 : }
628 :
629 568 : for (const MSEdge* taz : myTAZ) {
630 : double edgeLengthSum = 0;
631 : int laneNumber = 0;
632 : double speedSum = 0;
633 : double totalTT = 0;
634 : std::set<const MSEdge*> connected;
635 1348 : for (const MSEdge* edge : taz->getSuccessors()) {
636 : connected.insert(edge);
637 : }
638 1348 : for (const MSEdge* edge : taz->getPredecessors()) {
639 : connected.insert(edge);
640 : }
641 2148 : for (const MSEdge* edge : connected) {
642 1600 : edgeLengthSum += edge->getLength();
643 1600 : laneNumber += edge->getNumDrivingLanes();
644 1600 : speedSum += edge->getSpeedLimit();
645 1600 : totalTT += edge->getLength() / edge->getSpeedLimit();
646 : }
647 548 : MeanDataValues* sumData = createValuesSubData(nullptr, edgeLengthSum, false);
648 24404 : for (int i = 0; i < (int)myEdges.size(); i++) {
649 23856 : MSEdge* edge = myEdges[i];
650 : if (connected.count(edge) != 0) {
651 : std::vector<MeanDataValues*>& edgeValues = myMeasures[i];
652 1600 : if (MSGlobals::gUseMesoSim) {
653 528 : MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
654 2640 : while (s != nullptr) {
655 4224 : for (MeanDataValues* meanData : edgeValues) {
656 2112 : s->prepareDetectorForWriting(*meanData);
657 2112 : meanData->addTo(*sumData);
658 : }
659 : s = s->getNextSegment();
660 : }
661 : } else {
662 2160 : for (MeanDataValues* meanData : edgeValues) {
663 1088 : meanData->addTo(*sumData);
664 : }
665 : }
666 : }
667 : }
668 548 : if (myDumpEmpty || !sumData->isEmpty()) {
669 240 : writePrefix(dev, *sumData, SUMO_TAG_EDGE, taz->getID());
670 80 : dev.writeAttr(SUMO_ATTR_NUMEDGES, connected.size());
671 160 : for (MeanDataValues* data = sumData; data != nullptr; data = data->getSubData()) {
672 80 : data->write(dev, myWrittenAttributes, stopTime - startTime, laneNumber, speedSum / (double)connected.size(),
673 80 : myPrintDefaults ? totalTT : -1.);
674 : }
675 160 : dev.closeTag();
676 : }
677 548 : delete sumData;
678 : }
679 :
680 20 : if (!MSNet::getInstance()->skipFinalReset()) {
681 836 : for (const std::vector<MeanDataValues*>& edgeValues : myMeasures) {
682 1656 : for (MeanDataValues* meanData : edgeValues) {
683 840 : meanData->reset();
684 : }
685 : }
686 : }
687 20 : }
688 :
689 :
690 : void
691 17900563 : MSMeanData::writeEdge(OutputDevice& dev,
692 : const std::vector<MeanDataValues*>& edgeValues,
693 : const MSEdge* const edge, SUMOTime startTime, SUMOTime stopTime) {
694 17900563 : if (MSGlobals::gUseMesoSim) {
695 : int idx = 0;
696 2732225 : for (MeanDataValues* const data : edgeValues) {
697 1366136 : MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
698 7013948 : while (s != nullptr) {
699 5648154 : s->prepareDetectorForWriting(*data, myAmEdgeBased ? -1 : idx);
700 : s = s->getNextSegment();
701 : }
702 1366136 : idx++;
703 : }
704 1366089 : if (myAmEdgeBased) {
705 1366042 : MeanDataValues* const data = edgeValues.front();
706 1366042 : if (myDumpEmpty || (myPrintModified && edge->getLanes()[0]->isSpeedModified()) || !data->isEmpty()) {
707 63680 : writePrefix(dev, *data, SUMO_TAG_EDGE, getEdgeID(edge));
708 127384 : for (MeanDataValues* d = data; d != nullptr; d = d->getSubData()) {
709 63704 : d->write(dev, myWrittenAttributes, stopTime - startTime,
710 : edge->getNumDrivingLanes(),
711 : edge->getSpeedLimit(),
712 63704 : myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
713 : }
714 127360 : dev.closeTag();
715 : }
716 1366042 : if (!MSNet::getInstance()->skipFinalReset()) {
717 1366042 : data->reset(true);
718 : }
719 1366042 : return;
720 : }
721 : }
722 16534521 : if (!myAmEdgeBased) {
723 8025399 : bool writeCheck = myDumpEmpty;
724 8025399 : if (!writeCheck) {
725 15611485 : for (const MeanDataValues* const laneData : edgeValues) {
726 7913040 : if (!laneData->isEmpty() || (myPrintModified && laneData->getLane()->isSpeedModified())) {
727 : writeCheck = true;
728 : break;
729 : }
730 : }
731 : }
732 7901692 : if (writeCheck) {
733 326954 : dev.openTag(SUMO_TAG_EDGE).writeAttr(SUMO_ATTR_ID, edge->getID());
734 : }
735 16170619 : for (MeanDataValues* const laneData : edgeValues) {
736 : const MSLane* const lane = laneData->getLane();
737 8145220 : if (myDumpEmpty || (myPrintModified && lane->isSpeedModified()) || !laneData->isEmpty()) {
738 870722 : writePrefix(dev, *laneData, SUMO_TAG_LANE, lane->getID());
739 870722 : for (MeanDataValues* data = laneData; data != nullptr; data = data->getSubData()) {
740 435361 : data->write(dev, myWrittenAttributes, stopTime - startTime, 1, lane->getSpeedLimit(),
741 435361 : myPrintDefaults ? lane->getLength() / lane->getSpeedLimit() : -1.);
742 : }
743 870722 : dev.closeTag();
744 : }
745 8145220 : if (!MSNet::getInstance()->skipFinalReset()) {
746 8145220 : laneData->reset(true);
747 : }
748 : }
749 8025399 : if (writeCheck) {
750 653908 : dev.closeTag();
751 : }
752 : } else {
753 8509122 : if (myTrackVehicles) {
754 22440 : MeanDataValues* meanData = *edgeValues.begin();
755 22440 : if (myDumpEmpty || !meanData->isEmpty()) {
756 160 : writePrefix(dev, *meanData, SUMO_TAG_EDGE, edge->getID());
757 320 : for (MeanDataValues* data = meanData; data != nullptr; data = data->getSubData()) {
758 160 : data->write(dev, myWrittenAttributes, stopTime - startTime, edge->getNumDrivingLanes(), edge->getSpeedLimit(),
759 160 : myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
760 : }
761 320 : dev.closeTag();
762 : }
763 22440 : if (!MSNet::getInstance()->skipFinalReset()) {
764 22440 : meanData->reset(true);
765 : }
766 : } else {
767 8486682 : MeanDataValues* sumData = createValuesSubData(nullptr, edge->getLength(), false);
768 8486682 : bool writeCheck = myDumpEmpty;
769 17142570 : for (MeanDataValues* const laneData : edgeValues) {
770 8655888 : laneData->addTo(*sumData);
771 8655888 : if (myPrintModified && laneData->getLane()->isSpeedModified()) {
772 : writeCheck = true;
773 : }
774 8655888 : if (!MSNet::getInstance()->skipFinalReset()) {
775 8655888 : laneData->reset();
776 : }
777 : }
778 8486682 : if (writeCheck || !sumData->isEmpty()) {
779 525160 : writePrefix(dev, *sumData, SUMO_TAG_EDGE, getEdgeID(edge));
780 1050372 : for (MeanDataValues* data = sumData; data != nullptr; data = data->getSubData()) {
781 525212 : data->write(dev, myWrittenAttributes, stopTime - startTime, edge->getNumDrivingLanes(), edge->getSpeedLimit(),
782 525212 : myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
783 : }
784 1050319 : dev.closeTag();
785 : }
786 8486681 : delete sumData;
787 : }
788 : }
789 : }
790 :
791 :
792 : void
793 438196 : MSMeanData::openInterval(OutputDevice& dev, const SUMOTime startTime, const SUMOTime stopTime) {
794 438196 : dev.openTag(SUMO_TAG_INTERVAL).writeAttr(SUMO_ATTR_BEGIN, time2string(startTime)).writeAttr(SUMO_ATTR_END, time2string(stopTime));
795 438196 : dev.writeAttr(SUMO_ATTR_ID, myID);
796 438196 : }
797 :
798 :
799 : void
800 1022617 : MSMeanData::writePrefix(OutputDevice& dev, const MeanDataValues& values, const SumoXMLTag tag, const std::string id) const {
801 1022617 : dev.openTag(tag);
802 1022617 : dev.writeAttr(SUMO_ATTR_ID, id);
803 1022617 : dev.writeOptionalAttr(SUMO_ATTR_SAMPLEDSECONDS, values.getSamples(), myWrittenAttributes);
804 1022617 : }
805 :
806 :
807 : void
808 449507 : MSMeanData::writeXMLOutput(OutputDevice& dev,
809 : SUMOTime startTime, SUMOTime stopTime) {
810 : // check whether this dump shall be written for the current time
811 449507 : int numReady = myDumpBegin < stopTime && myDumpEnd - DELTA_T >= startTime ? 1 : 0;
812 449507 : if (myTrackVehicles && myDumpBegin < stopTime) {
813 2124 : myPendingIntervals.push_back(std::make_pair(startTime, stopTime));
814 2124 : numReady = (int)myPendingIntervals.size();
815 63312 : for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
816 124304 : for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
817 63116 : numReady = MIN2(numReady, ((MeanDataValueTracker*)*j)->getNumReady());
818 63116 : if (numReady == 0) {
819 : break;
820 : }
821 : }
822 63092 : if (numReady == 0) {
823 : break;
824 : }
825 : }
826 : }
827 449507 : const bool partialInterval = startTime < myInitTime;
828 449507 : if (numReady == 0 || myTrackVehicles || partialInterval) {
829 12645 : resetOnly(stopTime);
830 : }
831 449507 : if (partialInterval) {
832 : return;
833 : }
834 887946 : while (numReady-- > 0) {
835 438450 : if (!myPendingIntervals.empty()) {
836 1588 : startTime = myPendingIntervals.front().first;
837 1588 : stopTime = myPendingIntervals.front().second;
838 1588 : myPendingIntervals.pop_front();
839 : }
840 438450 : openInterval(dev, startTime, stopTime);
841 438450 : if (myAggregate == AggregateType::YES) {
842 938 : writeAggregated(dev, startTime, stopTime);
843 437512 : } else if (myAggregate == AggregateType::TAZ) {
844 20 : writeAggregatedTAZ(dev, startTime, stopTime);
845 : } else {
846 : MSEdgeVector::const_iterator edge = myEdges.begin();
847 18338054 : for (const std::vector<MeanDataValues*>& measures : myMeasures) {
848 17900563 : writeEdge(dev, measures, *edge, startTime, stopTime);
849 : ++edge;
850 : }
851 : }
852 876898 : dev.closeTag();
853 : }
854 : dev.flush();
855 : }
856 :
857 :
858 : void
859 23323 : MSMeanData::writeXMLDetectorProlog(OutputDevice& dev) const {
860 46646 : dev.writeXMLHeader("meandata", "meandata_file.xsd");
861 23323 : }
862 :
863 :
864 : void
865 26504997 : MSMeanData::detectorUpdate(const SUMOTime step) {
866 26504997 : if (step + DELTA_T == myDumpBegin) {
867 639 : init();
868 : }
869 26504997 : }
870 :
871 :
872 : const std::vector<MSMeanData::MeanDataValues*>*
873 0 : MSMeanData::getEdgeValues(const MSEdge* edge) const {
874 : auto it = myEdgeIndex.find(edge);
875 0 : if (it != myEdgeIndex.end()) {
876 0 : return &myMeasures[it->second];
877 : } else {
878 : return nullptr;
879 : }
880 : }
881 :
882 :
883 : const std::vector<MSMoveReminder*>
884 1 : MSMeanData::getReminders() const {
885 : std::vector<MSMoveReminder*> result;
886 45 : for (auto vec : myMeasures) {
887 44 : result.insert(result.end(), vec.begin(), vec.end());
888 44 : }
889 1 : return result;
890 0 : }
891 :
892 :
893 : double
894 0 : MSMeanData::getAttributeValue(const MSLane* lane, SumoXMLAttr a, double defaultValue) const {
895 : double result = defaultValue;
896 0 : const std::vector<MeanDataValues*>* edgeValues = getEdgeValues(&lane->getEdge());
897 0 : if (edgeValues == nullptr) {
898 : return result;
899 : }
900 : MeanDataValues* values = nullptr;
901 0 : if (!myAmEdgeBased) {
902 0 : values = (*edgeValues)[lane->getIndex()];
903 : } else {
904 0 : MeanDataValues* sumData = createValuesSubData(nullptr, lane->getLength(), false);
905 0 : for (MeanDataValues* meanData : (*edgeValues)) {
906 0 : meanData->addTo(*sumData);
907 : }
908 : values = sumData;
909 : }
910 : const SUMOTime myLastResetTime = 0; // XXX store last reset time
911 0 : const SUMOTime period = SIMSTEP - myLastResetTime;
912 0 : result = values->getAttributeValue(a, period, lane->getEdge().getNumLanes(), lane->getSpeedLimit());
913 0 : if (myAmEdgeBased) {
914 0 : delete values;
915 : }
916 : return result;
917 : }
918 :
919 :
920 : MSMeanData::MeanDataValues*
921 8584856 : MSMeanData::createValuesSubData(MSLane* const lane, const double length, const bool doAdd) const {
922 8584856 : MeanDataValues* values = createValues(lane, length, doAdd);
923 8584856 : if (mySubData != nullptr) {
924 280 : values->setSubData(mySubData->createValues(lane, length, doAdd));
925 : }
926 8584856 : return values;
927 : }
928 :
929 :
930 : /****************************************************************************/
|