Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
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 8584072 : MSMeanData::MeanDataValues::MeanDataValues(
61 : MSLane* const lane, const double length, const bool doAdd,
62 8584072 : const MSMeanData* const parent) :
63 8584072 : MSMoveReminder("meandata_" + (lane == nullptr ? "NULL" : lane->getID()), lane, doAdd),
64 8584072 : myParent(parent),
65 8584072 : myLaneLength(length),
66 8584072 : sampleSeconds(0),
67 25752216 : travelledDistance(0) {}
68 :
69 :
70 8513779 : MSMeanData::MeanDataValues::~MeanDataValues() {
71 8513779 : }
72 :
73 :
74 : bool
75 610523 : 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 610523 : return myParent == nullptr || myParent->vehicleApplies(veh);
83 : }
84 :
85 :
86 : bool
87 401987325 : 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 401987325 : const double oldSpeed = veh.getPreviousSpeed();
91 401987325 : 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 401987325 : double timeOnLane = TS;
96 401987325 : 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 401987325 : 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 401987325 : if (oldPos < 0 && newPos >= 0) {
107 : // Vehicle was not on this lane in the last time step
108 6609287 : timeBeforeEnter = MSCFModel::passingTime(oldPos, 0, newPos, oldSpeed, newSpeed);
109 6609287 : timeOnLane = TS - timeBeforeEnter;
110 : frontOnLane = timeOnLane;
111 6609287 : enterSpeed = MSCFModel::speedAfterTime(timeBeforeEnter, oldSpeed, newPos - oldPos);
112 : }
113 :
114 401987325 : const double oldBackPos = oldPos - veh.getVehicleType().getLength();
115 401987325 : const double newBackPos = newPos - veh.getVehicleType().getLength();
116 :
117 : // Determine the time before the vehicle back enters
118 401987325 : if (oldBackPos < 0. && newBackPos > 0.) {
119 6799348 : timeBeforeEnterBack = MSCFModel::passingTime(oldBackPos, 0., newBackPos, oldSpeed, newSpeed);
120 395187977 : } else if (newBackPos <= 0) {
121 3463966 : 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 401987325 : if (newBackPos > myLaneLength // vehicle's back has left the lane
128 7133515 : && 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 7133515 : timeBeforeLeave = MSCFModel::passingTime(oldBackPos, myLaneLength, newBackPos, oldSpeed, newSpeed);
132 7133515 : const double timeAfterLeave = TS - timeBeforeLeave;
133 7133515 : timeOnLane -= timeAfterLeave;
134 7133515 : leaveSpeed = MSCFModel::speedAfterTime(timeBeforeLeave, oldSpeed, newPos - oldPos);
135 : // XXX: Do we really need this? Why would this "reduce rounding errors"? (Leo) Refs. #2579
136 7133515 : if (fabs(timeOnLane) < NUMERICAL_EPS) { // reduce rounding errors
137 : timeOnLane = 0.;
138 : }
139 7133515 : ret = veh.hasArrived();
140 : }
141 :
142 : // Treat the case that the vehicle's front left the lane in the last step
143 401987325 : 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 7462242 : timeBeforeLeaveFront = MSCFModel::passingTime(oldPos, myLaneLength, newPos, oldSpeed, newSpeed);
147 7462242 : const double timeAfterLeave = TS - timeBeforeLeaveFront;
148 7462242 : frontOnLane -= timeAfterLeave;
149 : // XXX: Do we really need this? Why would this "reduce rounding errors"? (Leo) Refs. #2579
150 7462242 : if (fabs(frontOnLane) < NUMERICAL_EPS) { // reduce rounding errors
151 : frontOnLane = 0.;
152 : }
153 7462242 : leaveSpeedFront = MSCFModel::speedAfterTime(timeBeforeLeaveFront, oldSpeed, newPos - oldPos);
154 : }
155 :
156 : assert(frontOnLane <= TS);
157 : assert(timeOnLane <= TS);
158 :
159 401987325 : 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 401987325 : if (timeOnLane == 0) {
164 17965 : 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 401969360 : double vehLength = veh.getVehicleType().getLength();
192 : // occupied lane length at timeBeforeEnter (resp. stepStart if already on lane)
193 401969360 : double lengthOnLaneAtStepStart = MAX2(0., MIN4(myLaneLength, vehLength, vehLength - (oldPos - myLaneLength), oldPos));
194 : // occupied lane length at timeBeforeLeave (resp. stepEnd if still on lane)
195 401969360 : double lengthOnLaneAtStepEnd = MAX2(0., MIN4(myLaneLength, vehLength, vehLength - (newPos - myLaneLength), newPos));
196 : double integratedLengthOnLane = 0.;
197 401969360 : if (timeBeforeEnterBack < timeBeforeLeaveFront) {
198 : // => timeBeforeLeaveFront>0, myLaneLength>vehLength
199 : // vehicle length on detector at timeBeforeEnterBack
200 394990782 : double lengthOnLaneAtBackEnter = MIN2(veh.getVehicleType().getLength(), newPos);
201 : // linear quadrature of occupancy between timeBeforeEnter and timeBeforeEnterBack
202 394990782 : 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 394990782 : integratedLengthOnLane += (timeBeforeLeaveFront - timeBeforeEnterBack) * vehLength;
206 : // and until vehicle leaves/stepEnd
207 394990782 : integratedLengthOnLane += (timeBeforeLeave - timeBeforeLeaveFront) * (vehLength + lengthOnLaneAtStepEnd) * 0.5;
208 6978578 : } else if (timeBeforeEnterBack >= timeBeforeLeaveFront) {
209 : // => myLaneLength <= vehLength or (timeBeforeLeaveFront == timeBeforeEnterBack == 0)
210 : // vehicle length on detector at timeBeforeLeaveFront
211 : double lengthOnLaneAtLeaveFront;
212 6978578 : if (timeBeforeLeaveFront == timeBeforeEnter) {
213 : // for the case that front already left
214 : lengthOnLaneAtLeaveFront = lengthOnLaneAtStepStart;
215 3501304 : } 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 6978578 : integratedLengthOnLane += (timeBeforeLeaveFront - timeBeforeEnter) * (lengthOnLaneAtLeaveFront + lengthOnLaneAtStepStart) * 0.5;
226 : // linear quadrature of occupancy between timeBeforeLeaveFront and timeBeforeEnterBack
227 6978578 : integratedLengthOnLane += (timeBeforeEnterBack - timeBeforeLeaveFront) * lengthOnLaneAtLeaveFront;
228 : // and until vehicle leaves/stepEnd
229 6978578 : integratedLengthOnLane += (timeBeforeLeave - timeBeforeEnterBack) * (lengthOnLaneAtLeaveFront + lengthOnLaneAtStepEnd) * 0.5;
230 : }
231 :
232 401969360 : 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 401969360 : const double travelledDistanceFrontOnLane = MSGlobals::gSemiImplicitEulerUpdate ? frontOnLane * newSpeed
244 161457552 : : MAX2(0., MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.));
245 482698136 : const double travelledDistanceVehicleOnLane = MSGlobals::gSemiImplicitEulerUpdate ? timeOnLane * newSpeed
246 161457552 : : 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 401969360 : ScopedLocker<> lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
253 : #endif
254 401969360 : notifyMoveInternal(veh, frontOnLane, timeOnLane, (enterSpeed + leaveSpeedFront) / 2., (enterSpeed + leaveSpeed) / 2., travelledDistanceFrontOnLane, travelledDistanceVehicleOnLane, meanLengthOnLane);
255 : return ret;
256 : }
257 :
258 :
259 : bool
260 1097959 : MSMeanData::MeanDataValues::notifyLeave(SUMOTrafficObject& /*veh*/, double /*lastPos*/, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
261 1097959 : if (MSGlobals::gUseMesoSim) {
262 : return false; // reminder is re-added on every segment (@recheck for performance)
263 : }
264 994753 : return reason == MSMoveReminder::NOTIFICATION_JUNCTION;
265 : }
266 :
267 :
268 : bool
269 2951733 : MSMeanData::MeanDataValues::isEmpty() const {
270 2951733 : return sampleSeconds == 0;
271 : }
272 :
273 :
274 : void
275 0 : MSMeanData::MeanDataValues::update() {
276 0 : }
277 :
278 :
279 : double
280 705592 : MSMeanData::MeanDataValues::getSamples() const {
281 705592 : return sampleSeconds;
282 : }
283 :
284 :
285 : // ---------------------------------------------------------------------------
286 : // MSMeanData::MeanDataValueTracker - methods
287 : // ---------------------------------------------------------------------------
288 2672 : MSMeanData::MeanDataValueTracker::MeanDataValueTracker(MSLane* const lane,
289 : const double length,
290 2672 : const MSMeanData* const parent)
291 2672 : : MSMeanData::MeanDataValues(lane, length, true, parent) {
292 2672 : myCurrentData.push_back(new TrackerEntry(parent->createValues(lane, length, false)));
293 2672 : }
294 :
295 :
296 5344 : MSMeanData::MeanDataValueTracker::~MeanDataValueTracker() {
297 : std::list<TrackerEntry*>::iterator i;
298 28928 : for (i = myCurrentData.begin(); i != myCurrentData.end(); i++) {
299 26256 : 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 5344 : }
310 :
311 :
312 : void
313 164160 : MSMeanData::MeanDataValueTracker::reset(bool afterWrite) {
314 164160 : if (afterWrite) {
315 70288 : if (myCurrentData.begin() != myCurrentData.end()) {
316 : // delete myCurrentData.front();
317 70288 : myCurrentData.pop_front();
318 : }
319 : } else {
320 93872 : myCurrentData.push_back(new TrackerEntry(myParent->createValues(myLane, myLaneLength, false)));
321 : }
322 164160 : }
323 :
324 :
325 : void
326 0 : MSMeanData::MeanDataValueTracker::addTo(MSMeanData::MeanDataValues& val) const {
327 0 : myCurrentData.front()->myValues->addTo(val);
328 0 : }
329 :
330 :
331 : void
332 14872 : MSMeanData::MeanDataValueTracker::notifyMoveInternal(const SUMOTrafficObject& veh, const double frontOnLane, const double timeOnLane, const double meanSpeedFrontOnLane, const double meanSpeedVehicleOnLane, const double travelledDistanceFrontOnLane, const double travelledDistanceVehicleOnLane, const double meanLengthOnLane) {
333 14872 : myTrackedData[&veh]->myValues->notifyMoveInternal(veh, frontOnLane, timeOnLane, meanSpeedFrontOnLane, meanSpeedVehicleOnLane, travelledDistanceFrontOnLane, travelledDistanceVehicleOnLane, meanLengthOnLane);
334 14872 : }
335 :
336 :
337 : bool
338 760 : MSMeanData::MeanDataValueTracker::notifyLeave(SUMOTrafficObject& veh, double lastPos, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
339 760 : if (myParent == nullptr || reason != MSMoveReminder::NOTIFICATION_SEGMENT) {
340 360 : myTrackedData[&veh]->myNumVehicleLeft++;
341 : }
342 760 : return myTrackedData[&veh]->myValues->notifyLeave(veh, lastPos, reason);
343 : }
344 :
345 :
346 : bool
347 1220 : MSMeanData::MeanDataValueTracker::notifyEnter(SUMOTrafficObject& veh, MSMoveReminder::Notification reason, const MSLane* enteredLane) {
348 : #ifdef DEBUG_NOTIFY_ENTER
349 : std::cout << "\n" << SIMTIME << " MSMeanData::MeanDataValueTracker: veh '" << veh.getID() << "' enters lane '" << enteredLane->getID() << "'" << std::endl;
350 : #else
351 : UNUSED_PARAMETER(enteredLane);
352 : #endif
353 1220 : if (reason == MSMoveReminder::NOTIFICATION_SEGMENT) {
354 : return true;
355 : }
356 1420 : if (myParent->vehicleApplies(veh) && myTrackedData.find(&veh) == myTrackedData.end()) {
357 480 : myTrackedData[&veh] = myCurrentData.back();
358 480 : myTrackedData[&veh]->myNumVehicleEntered++;
359 480 : if (!myTrackedData[&veh]->myValues->notifyEnter(veh, reason)) {
360 0 : myTrackedData[&veh]->myNumVehicleLeft++;
361 0 : myTrackedData.erase(&veh);
362 0 : return false;
363 : }
364 : return true;
365 : }
366 : return false;
367 : }
368 :
369 :
370 : bool
371 91696 : MSMeanData::MeanDataValueTracker::isEmpty() const {
372 91696 : return myCurrentData.front()->myValues->isEmpty();
373 : }
374 :
375 :
376 : void
377 296 : MSMeanData::MeanDataValueTracker::write(OutputDevice& dev,
378 : long long int attributeMask,
379 : const SUMOTime period,
380 : const int numLanes,
381 : const double speedLimit,
382 : const double defaultTravelTime,
383 : const int /*numVehicles*/) const {
384 296 : myCurrentData.front()->myValues->write(dev, attributeMask, period, numLanes, speedLimit,
385 : defaultTravelTime,
386 : myCurrentData.front()->myNumVehicleEntered);
387 296 : }
388 :
389 :
390 : int
391 63044 : MSMeanData::MeanDataValueTracker::getNumReady() const {
392 : int result = 0;
393 1444912 : for (std::list<TrackerEntry*>::const_iterator it = myCurrentData.begin(); it != myCurrentData.end(); ++it) {
394 1384520 : if ((*it)->myNumVehicleEntered == (*it)->myNumVehicleLeft) {
395 1381868 : result++;
396 : } else {
397 : break;
398 : }
399 : }
400 63044 : return result;
401 : }
402 :
403 :
404 : double
405 296 : MSMeanData::MeanDataValueTracker::getSamples() const {
406 296 : return myCurrentData.front()->myValues->getSamples();
407 : }
408 :
409 :
410 : // ---------------------------------------------------------------------------
411 : // MSMeanData - methods
412 : // ---------------------------------------------------------------------------
413 5140 : MSMeanData::MSMeanData(const std::string& id,
414 : const SUMOTime dumpBegin, const SUMOTime dumpEnd,
415 : const bool useLanes, const bool withEmpty,
416 : const bool printDefaults, const bool withInternal,
417 : const bool trackVehicles,
418 : const int detectPersons,
419 : const double maxTravelTime,
420 : const double minSamples,
421 : const std::string& vTypes,
422 : const std::string& writeAttributes,
423 : const std::vector<MSEdge*>& edges,
424 5140 : bool aggregate) :
425 : MSDetectorFileOutput(id, vTypes, "", detectPersons),
426 5140 : myMinSamples(minSamples),
427 5140 : myMaxTravelTime(maxTravelTime),
428 5140 : myDumpEmpty(withEmpty),
429 5140 : myAmEdgeBased(!useLanes),
430 5140 : myDumpBegin(dumpBegin),
431 5140 : myDumpEnd(dumpEnd),
432 5140 : myInitTime(SUMOTime_MAX),
433 5140 : myEdges(edges),
434 5140 : myPrintDefaults(printDefaults),
435 5140 : myDumpInternal(withInternal),
436 5140 : myTrackVehicles(trackVehicles),
437 5140 : myWrittenAttributes(initWrittenAttributes(writeAttributes, id)),
438 15420 : myAggregate(aggregate)
439 5140 : { }
440 :
441 :
442 : void
443 4278 : MSMeanData::init() {
444 4278 : myInitTime = MSNet::getInstance()->getCurrentTimeStep();
445 4278 : if (myEdges.empty()) {
446 : // use all edges by default
447 156205 : for (MSEdge* const edge : MSNet::getInstance()->getEdgeControl().getEdges()) {
448 151984 : if ((myDumpInternal || !edge->isInternal()) &&
449 129101 : ((detectPersons() && myDumpInternal) || (!edge->isCrossing() && !edge->isWalkingArea()))) {
450 128603 : myEdges.push_back(edge);
451 : }
452 : }
453 : }
454 : int index = 0;
455 132978 : for (MSEdge* edge : myEdges) {
456 128700 : myMeasures.push_back(std::vector<MeanDataValues*>());
457 128700 : myEdgeIndex[edge] = index++;
458 128700 : const std::vector<MSLane*>& lanes = edge->getLanes();
459 128700 : if (MSGlobals::gUseMesoSim) {
460 : MeanDataValues* data;
461 29273 : if (!myAmEdgeBased) {
462 85 : for (MSLane* const lane : lanes) {
463 52 : data = createValues(lane, lanes[0]->getLength(), false);
464 52 : myMeasures.back().push_back(data);
465 52 : MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
466 310 : while (s != nullptr) {
467 258 : s->addDetector(data, lane->getIndex());
468 258 : s->prepareDetectorForWriting(*data, lane->getIndex());
469 : s = s->getNextSegment();
470 : }
471 52 : data->reset();
472 52 : data->reset(true);
473 : }
474 : } else {
475 29240 : if (myTrackVehicles) {
476 880 : data = new MeanDataValueTracker(nullptr, lanes[0]->getLength(), this);
477 : } else {
478 28360 : data = createValues(nullptr, lanes[0]->getLength(), false);
479 : }
480 58480 : data->setDescription("meandata_" + edge->getID());
481 29240 : myMeasures.back().push_back(data);
482 29240 : MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
483 147000 : while (s != nullptr) {
484 117760 : s->addDetector(data);
485 117760 : s->prepareDetectorForWriting(*data);
486 : s = s->getNextSegment();
487 : }
488 29240 : data->reset();
489 29240 : data->reset(true);
490 : }
491 : continue;
492 29273 : }
493 99427 : if (myAmEdgeBased && myTrackVehicles) {
494 912 : myMeasures.back().push_back(new MeanDataValueTracker(nullptr, lanes[0]->getLength(), this));
495 : }
496 207476 : for (MSLane* const lane : lanes) {
497 108049 : if (myTrackVehicles) {
498 1920 : if (myAmEdgeBased) {
499 1040 : lane->addMoveReminder(myMeasures.back().back());
500 : } else {
501 880 : myMeasures.back().push_back(new MeanDataValueTracker(lane, lane->getLength(), this));
502 : }
503 : } else {
504 106129 : myMeasures.back().push_back(createValues(lane, lane->getLength(), true));
505 : }
506 : }
507 : }
508 4278 : }
509 :
510 :
511 5139 : MSMeanData::~MSMeanData() {
512 133834 : for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
513 265903 : for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
514 137208 : delete *j;
515 : }
516 : }
517 5139 : }
518 :
519 :
520 : void
521 11333 : MSMeanData::resetOnly(SUMOTime stopTime) {
522 : UNUSED_PARAMETER(stopTime);
523 11333 : if (MSGlobals::gUseMesoSim) {
524 : MSEdgeVector::iterator edge = myEdges.begin();
525 117278 : for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i, ++edge) {
526 113696 : MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(**edge);
527 227392 : for (MeanDataValues* data : *i) {
528 602142 : while (s != nullptr) {
529 488446 : s->prepareDetectorForWriting(*data);
530 : s = s->getNextSegment();
531 : }
532 113696 : data->reset();
533 : }
534 : }
535 : return;
536 : }
537 240334 : for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
538 483094 : for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
539 250511 : (*j)->reset();
540 : }
541 : }
542 : }
543 :
544 :
545 : std::string
546 9706655 : MSMeanData::getEdgeID(const MSEdge* const edge) {
547 9706655 : return edge->getID();
548 : }
549 :
550 :
551 : void
552 36 : MSMeanData::writeAggregated(OutputDevice& dev, SUMOTime startTime, SUMOTime stopTime) {
553 36 : if (myTrackVehicles) {
554 0 : throw ProcessError(TL("aggregated meanData output not yet implemented for trackVehicles"));
555 : }
556 :
557 : double edgeLengthSum = 0;
558 : int laneNumber = 0;
559 : double speedSum = 0;
560 : double totalTT = 0;
561 1620 : for (MSEdge* edge : myEdges) {
562 1584 : edgeLengthSum += edge->getLength();
563 1584 : laneNumber += edge->getNumDrivingLanes();
564 1584 : speedSum += edge->getSpeedLimit();
565 1584 : totalTT += edge->getLength() / edge->getSpeedLimit();
566 : }
567 36 : MeanDataValues* sumData = createValues(nullptr, edgeLengthSum, false);
568 1620 : for (const std::vector<MeanDataValues*>& edgeValues : myMeasures) {
569 3168 : for (MeanDataValues* meanData : edgeValues) {
570 1584 : meanData->addTo(*sumData);
571 1584 : if (!MSNet::getInstance()->skipFinalReset()) {
572 1584 : meanData->reset();
573 : }
574 : }
575 : }
576 36 : if (MSGlobals::gUseMesoSim) {
577 540 : for (MSEdge* edge : myEdges) {
578 528 : MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
579 2640 : while (s != nullptr) {
580 2112 : s->prepareDetectorForWriting(*sumData);
581 : s = s->getNextSegment();
582 : }
583 : }
584 : }
585 :
586 72 : if (writePrefix(dev, *sumData, SUMO_TAG_EDGE, "AGGREGATED")) {
587 36 : dev.writeAttr(SUMO_ATTR_NUMEDGES, myEdges.size());
588 36 : sumData->write(dev, myWrittenAttributes, stopTime - startTime, laneNumber, speedSum / (double)myEdges.size(),
589 36 : myPrintDefaults ? totalTT : -1.);
590 : }
591 36 : delete sumData;
592 36 : }
593 :
594 :
595 : void
596 17641298 : MSMeanData::writeEdge(OutputDevice& dev,
597 : const std::vector<MeanDataValues*>& edgeValues,
598 : const MSEdge* const edge, SUMOTime startTime, SUMOTime stopTime) {
599 17641298 : if (MSGlobals::gUseMesoSim) {
600 : int idx = 0;
601 2723221 : for (MeanDataValues* const data : edgeValues) {
602 1361634 : MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
603 6992236 : while (s != nullptr) {
604 5630944 : s->prepareDetectorForWriting(*data, myAmEdgeBased ? -1 : idx);
605 : s = s->getNextSegment();
606 : }
607 1361634 : idx++;
608 : }
609 1361587 : if (myAmEdgeBased) {
610 1361540 : MeanDataValues* data = edgeValues.front();
611 2723080 : if (writePrefix(dev, *data, SUMO_TAG_EDGE, getEdgeID(edge))) {
612 60428 : data->write(dev, myWrittenAttributes, stopTime - startTime,
613 : edge->getNumDrivingLanes(),
614 : edge->getSpeedLimit(),
615 60428 : myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
616 : }
617 1361540 : if (!MSNet::getInstance()->skipFinalReset()) {
618 1361540 : data->reset(true);
619 : }
620 : return;
621 : }
622 : }
623 : std::vector<MeanDataValues*>::const_iterator lane;
624 16279758 : if (!myAmEdgeBased) {
625 7909203 : bool writeCheck = myDumpEmpty;
626 7909203 : if (!writeCheck) {
627 15610294 : for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
628 7912194 : if (!(*lane)->isEmpty()) {
629 : writeCheck = true;
630 : break;
631 : }
632 : }
633 : }
634 7901035 : if (writeCheck) {
635 422206 : dev.openTag(SUMO_TAG_EDGE).writeAttr(SUMO_ATTR_ID, edge->getID());
636 : }
637 15831853 : for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
638 7922650 : MeanDataValues& meanData = **lane;
639 23767950 : if (writePrefix(dev, meanData, SUMO_TAG_LANE, meanData.getLane()->getID())) {
640 213325 : meanData.write(dev, myWrittenAttributes, stopTime - startTime, 1, meanData.getLane()->getSpeedLimit(),
641 213325 : myPrintDefaults ? meanData.getLane()->getLength() / meanData.getLane()->getSpeedLimit() : -1.);
642 : }
643 7922650 : if (!MSNet::getInstance()->skipFinalReset()) {
644 7922650 : meanData.reset(true);
645 : }
646 : }
647 7909203 : if (writeCheck) {
648 422206 : dev.closeTag();
649 : }
650 : } else {
651 8370555 : if (myTrackVehicles) {
652 22416 : MeanDataValues& meanData = **edgeValues.begin();
653 67248 : if (writePrefix(dev, meanData, SUMO_TAG_EDGE, edge->getID())) {
654 136 : meanData.write(dev, myWrittenAttributes, stopTime - startTime, edge->getNumDrivingLanes(), edge->getSpeedLimit(),
655 136 : myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
656 : }
657 22416 : if (!MSNet::getInstance()->skipFinalReset()) {
658 22416 : meanData.reset(true);
659 : }
660 : } else {
661 8348139 : MeanDataValues* sumData = createValues(nullptr, edge->getLength(), false);
662 16755054 : for (lane = edgeValues.begin(); lane != edgeValues.end(); ++lane) {
663 8406915 : MeanDataValues& meanData = **lane;
664 8406915 : meanData.addTo(*sumData);
665 8406915 : if (!MSNet::getInstance()->skipFinalReset()) {
666 8406915 : meanData.reset();
667 : }
668 : }
669 16696278 : if (writePrefix(dev, *sumData, SUMO_TAG_EDGE, getEdgeID(edge))) {
670 391796 : sumData->write(dev, myWrittenAttributes, stopTime - startTime, edge->getNumDrivingLanes(), edge->getSpeedLimit(),
671 391796 : myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
672 : }
673 8348139 : delete sumData;
674 : }
675 : }
676 : }
677 :
678 :
679 : void
680 414799 : MSMeanData::openInterval(OutputDevice& dev, const SUMOTime startTime, const SUMOTime stopTime) {
681 1244397 : dev.openTag(SUMO_TAG_INTERVAL).writeAttr(SUMO_ATTR_BEGIN, time2string(startTime)).writeAttr(SUMO_ATTR_END, time2string(stopTime));
682 414799 : dev.writeAttr(SUMO_ATTR_ID, myID);
683 414799 : }
684 :
685 :
686 : bool
687 17651757 : MSMeanData::writePrefix(OutputDevice& dev, const MeanDataValues& values, const SumoXMLTag tag, const std::string id) const {
688 17651757 : if (myDumpEmpty || !values.isEmpty()) {
689 663001 : dev.openTag(tag);
690 : dev.writeAttr(SUMO_ATTR_ID, id);
691 663001 : dev.writeOptionalAttr(SUMO_ATTR_SAMPLEDSECONDS, values.getSamples(), myWrittenAttributes);
692 663001 : return true;
693 : }
694 : return false;
695 : }
696 :
697 :
698 : void
699 424800 : MSMeanData::writeXMLOutput(OutputDevice& dev,
700 : SUMOTime startTime, SUMOTime stopTime) {
701 : // check whether this dump shall be written for the current time
702 424800 : int numReady = myDumpBegin < stopTime && myDumpEnd - DELTA_T >= startTime ? 1 : 0;
703 424800 : if (myTrackVehicles && myDumpBegin < stopTime) {
704 2120 : myPendingIntervals.push_back(std::make_pair(startTime, stopTime));
705 2120 : numReady = (int)myPendingIntervals.size();
706 63260 : for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
707 124184 : for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
708 63044 : numReady = MIN2(numReady, ((MeanDataValueTracker*)*j)->getNumReady());
709 63044 : if (numReady == 0) {
710 : break;
711 : }
712 : }
713 63044 : if (numReady == 0) {
714 : break;
715 : }
716 : }
717 : }
718 424800 : const bool partialInterval = startTime < myInitTime;
719 424800 : if (numReady == 0 || myTrackVehicles || partialInterval) {
720 11333 : resetOnly(stopTime);
721 : }
722 424800 : if (partialInterval) {
723 : return;
724 : }
725 839845 : while (numReady-- > 0) {
726 415051 : if (!myPendingIntervals.empty()) {
727 1584 : startTime = myPendingIntervals.front().first;
728 1584 : stopTime = myPendingIntervals.front().second;
729 1584 : myPendingIntervals.pop_front();
730 : }
731 415051 : openInterval(dev, startTime, stopTime);
732 415051 : if (myAggregate) {
733 36 : writeAggregated(dev, startTime, stopTime);
734 : } else {
735 : MSEdgeVector::const_iterator edge = myEdges.begin();
736 18056313 : for (const std::vector<MeanDataValues*>& measures : myMeasures) {
737 17641298 : writeEdge(dev, measures, *edge, startTime, stopTime);
738 : ++edge;
739 : }
740 : }
741 830102 : dev.closeTag();
742 : }
743 : dev.flush();
744 : }
745 :
746 :
747 : void
748 4254 : MSMeanData::writeXMLDetectorProlog(OutputDevice& dev) const {
749 8508 : dev.writeXMLHeader("meandata", "meandata_file.xsd");
750 4254 : }
751 :
752 :
753 : void
754 6811552 : MSMeanData::detectorUpdate(const SUMOTime step) {
755 6811552 : if (step + DELTA_T == myDumpBegin) {
756 639 : init();
757 : }
758 6811552 : }
759 :
760 :
761 : long long int
762 5140 : MSMeanData::initWrittenAttributes(const std::string writeAttributes, const std::string& id) {
763 : long long int result = 0;
764 10430 : for (std::string attrName : StringTokenizer(writeAttributes).getVector()) {
765 150 : if (!SUMOXMLDefinitions::Attrs.hasString(attrName)) {
766 0 : WRITE_ERRORF(TL("Unknown attribute '%' to write in meanData '%'."), attrName, id);
767 : continue;
768 : }
769 150 : int attr = SUMOXMLDefinitions::Attrs.get(attrName);
770 : assert(attr < 63);
771 150 : result |= ((long long int)1 << attr);
772 5140 : }
773 5140 : return result;
774 : }
775 :
776 : const std::vector<MSMeanData::MeanDataValues*>*
777 0 : MSMeanData::getEdgeValues(const MSEdge* edge) const {
778 : auto it = myEdgeIndex.find(edge);
779 0 : if (it != myEdgeIndex.end()) {
780 0 : return &myMeasures[it->second];
781 : } else {
782 : return nullptr;
783 : }
784 : }
785 :
786 : /****************************************************************************/
|