Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2004-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_Net.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Michael Behrisch
17 : /// @author Jakob Erdmann
18 : /// @date Mon, 10.05.2004
19 : ///
20 : // Network state mean data collector for edges/lanes
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #ifdef HAVE_FOX
25 : #include <utils/common/ScopedLocker.h>
26 : #endif
27 : #include <utils/common/SUMOTime.h>
28 : #include <utils/common/ToString.h>
29 : #include <utils/iodevices/OutputDevice.h>
30 : #include <microsim/MSEdgeControl.h>
31 : #include <microsim/MSEdge.h>
32 : #include <microsim/MSLane.h>
33 : #include <microsim/MSVehicle.h>
34 : #include <microsim/MSGlobals.h>
35 : #include <mesosim/MELoop.h>
36 : #include <mesosim/MESegment.h>
37 : #include "MSMeanData_Net.h"
38 :
39 :
40 : // ===========================================================================
41 : // debug constants
42 : // ===========================================================================
43 : //#define DEBUG_OCCUPANCY
44 : //#define DEBUG_OCCUPANCY2
45 : //#define DEBUG_NOTIFY_ENTER
46 : //#define DEBUG_COND (veh.getLane()->getID() == "")
47 : //#define DEBUG_COND (false)
48 : //#define DEBUG_COND2 (veh.getEdge()->getID() == "")
49 :
50 :
51 : // ===========================================================================
52 : // method definitions
53 : // ===========================================================================
54 : // ---------------------------------------------------------------------------
55 : // MSMeanData_Net::MSLaneMeanDataValues - methods
56 : // ---------------------------------------------------------------------------
57 8328777 : MSMeanData_Net::MSLaneMeanDataValues::MSLaneMeanDataValues(MSLane* const lane,
58 : const double length,
59 : const bool doAdd,
60 8328777 : const MSMeanData_Net* parent)
61 : : MSMeanData::MeanDataValues(lane, length, doAdd, parent),
62 8328777 : nVehDeparted(0), nVehArrived(0), nVehEntered(0), nVehLeft(0),
63 8328777 : nVehVaporized(0), nVehTeleported(0), waitSeconds(0), timeLoss(0),
64 8328777 : nVehLaneChangeFrom(0), nVehLaneChangeTo(0),
65 8328777 : frontSampleSeconds(0), frontTravelledDistance(0),
66 8328777 : vehLengthSum(0), occupationSum(0),
67 8328777 : minimalVehicleLength(INVALID_DOUBLE),
68 8328777 : myParent(parent) {}
69 :
70 :
71 16654209 : MSMeanData_Net::MSLaneMeanDataValues::~MSLaneMeanDataValues() {
72 16654209 : }
73 :
74 :
75 : void
76 16953750 : MSMeanData_Net::MSLaneMeanDataValues::reset(bool) {
77 16953750 : nVehDeparted = 0;
78 16953750 : nVehArrived = 0;
79 16953750 : nVehEntered = 0;
80 16953750 : nVehLeft = 0;
81 16953750 : nVehVaporized = 0;
82 16953750 : nVehTeleported = 0;
83 16953750 : nVehLaneChangeFrom = 0;
84 16953750 : nVehLaneChangeTo = 0;
85 16953750 : sampleSeconds = 0.;
86 16953750 : travelledDistance = 0;
87 16953750 : waitSeconds = 0;
88 16953750 : timeLoss = 0;
89 16953750 : frontSampleSeconds = 0;
90 16953750 : frontTravelledDistance = 0;
91 16953750 : vehLengthSum = 0;
92 16953750 : occupationSum = 0;
93 16953750 : minimalVehicleLength = INVALID_DOUBLE;
94 16953750 : resetTime = SIMSTEP;
95 16953750 : }
96 :
97 :
98 : void
99 8661150 : MSMeanData_Net::MSLaneMeanDataValues::addTo(MSMeanData::MeanDataValues& val) const {
100 : MSLaneMeanDataValues& v = (MSLaneMeanDataValues&) val;
101 8661150 : v.nVehDeparted += nVehDeparted;
102 8661150 : v.nVehArrived += nVehArrived;
103 8661150 : v.nVehEntered += nVehEntered;
104 8661150 : v.nVehLeft += nVehLeft;
105 8661150 : v.nVehVaporized += nVehVaporized;
106 8661150 : v.nVehTeleported += nVehTeleported;
107 8661150 : v.nVehLaneChangeFrom += nVehLaneChangeFrom;
108 8661150 : v.nVehLaneChangeTo += nVehLaneChangeTo;
109 8661150 : v.sampleSeconds += sampleSeconds;
110 8661150 : v.travelledDistance += travelledDistance;
111 8661150 : v.waitSeconds += waitSeconds;
112 8661150 : v.timeLoss += timeLoss;
113 8661150 : v.frontSampleSeconds += frontSampleSeconds;
114 8661150 : v.frontTravelledDistance += frontTravelledDistance;
115 8661150 : v.vehLengthSum += vehLengthSum;
116 8661150 : v.occupationSum += occupationSum;
117 8661150 : if (v.minimalVehicleLength == INVALID_DOUBLE) {
118 8569091 : v.minimalVehicleLength = minimalVehicleLength;
119 : } else {
120 178028 : v.minimalVehicleLength = MIN2(minimalVehicleLength, v.minimalVehicleLength);
121 : }
122 8661150 : if (mySubData != nullptr) {
123 280 : mySubData->addTo(*val.getSubData());
124 : }
125 8661150 : }
126 :
127 :
128 : void
129 416949670 : MSMeanData_Net::MSLaneMeanDataValues::notifyMoveInternal(
130 : const SUMOTrafficObject& veh, const double frontOnLane,
131 : const double timeOnLane, const double /* meanSpeedFrontOnLane */,
132 : const double meanSpeedVehicleOnLane,
133 : const double travelledDistanceFrontOnLane,
134 : const double travelledDistanceVehicleOnLane,
135 : const double meanLengthOnLane) {
136 : #ifdef DEBUG_OCCUPANCY
137 : if (DEBUG_COND2) {
138 : std::cout << SIMTIME << "\n MSMeanData_Net::MSLaneMeanDataValues::notifyMoveInternal()\n"
139 : << " veh '" << veh.getID() << "' on edge '" << veh.getEdge()->getID() << "'"
140 : << ", timeOnLane=" << timeOnLane
141 : << ", meanSpeedVehicleOnLane=" << meanSpeedVehicleOnLane
142 : << ",\ntravelledDistanceFrontOnLane=" << travelledDistanceFrontOnLane
143 : << ", travelledDistanceVehicleOnLane=" << travelledDistanceVehicleOnLane
144 : << ", meanLengthOnLane=" << meanLengthOnLane
145 : << std::endl;
146 : }
147 : #endif
148 416949670 : if (myParent != nullptr && !myParent->vehicleApplies(veh)) {
149 : return;
150 : }
151 416907350 : sampleSeconds += timeOnLane;
152 416907350 : travelledDistance += travelledDistanceVehicleOnLane;
153 416907350 : vehLengthSum += veh.getVehicleType().getLength() * timeOnLane;
154 416907350 : if (MSGlobals::gUseMesoSim) {
155 : // For the mesosim case no information on whether the vehicle was occupying
156 : // the lane with its whole length is available. We assume the whole length
157 : // Therefore this increment is taken out with more information on the vehicle movement.
158 10341512 : occupationSum += veh.getVehicleType().getLength() * timeOnLane;
159 : } else {
160 : // for the microsim case more elaborate calculation of the average length on the lane,
161 : // is taken out in notifyMove(), refs #153
162 406565838 : occupationSum += meanLengthOnLane * TS;
163 : }
164 416907350 : if (!veh.isStopped()) {
165 400859960 : if (myParent != nullptr && (meanSpeedVehicleOnLane < myParent->myHaltSpeed
166 340253907 : || (myParent->myHaltSpeedRel > 0 && meanSpeedVehicleOnLane / veh.getCurrentEdge()->getSpeedLimit(veh.getVClass()) < myParent->myHaltSpeedRel))) {
167 60549319 : waitSeconds += timeOnLane;
168 340310641 : } else if (MSGlobals::gUseMesoSim) {
169 10284991 : waitSeconds += STEPS2TIME(veh.getWaitingTime());
170 : }
171 400859960 : const double vmax = veh.getLane() == nullptr ? veh.getEdge()->getVehicleMaxSpeed(&veh) : veh.getLane()->getVehicleMaxSpeed(&veh);
172 400859960 : if (vmax > 0) {
173 799932825 : timeLoss += timeOnLane * MAX2(0.0, vmax - meanSpeedVehicleOnLane) / vmax;
174 : }
175 : }
176 416907350 : frontSampleSeconds += frontOnLane;
177 416907350 : frontTravelledDistance += travelledDistanceFrontOnLane;
178 416907350 : if (minimalVehicleLength == INVALID_DOUBLE) {
179 698743 : minimalVehicleLength = veh.getVehicleType().getLengthWithGap();
180 : } else {
181 830983047 : minimalVehicleLength = MIN2(minimalVehicleLength, veh.getVehicleType().getLengthWithGap());
182 : }
183 : #ifdef DEBUG_OCCUPANCY2
184 : // refs #3265
185 : std::cout << SIMTIME << "ID: " << getDescription() << " minVehicleLength=" << minimalVehicleLength << std::endl;
186 : #endif
187 : }
188 :
189 :
190 : bool
191 27502088 : MSMeanData_Net::MSLaneMeanDataValues::notifyLeave(SUMOTrafficObject& veh, double /*lastPos*/, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
192 27502088 : if ((myParent == nullptr || myParent->vehicleApplies(veh)) && (
193 18380870 : getLane() == nullptr || !veh.isVehicle() || getLane() == static_cast<MSVehicle&>(veh).getLane())) {
194 : #ifdef HAVE_FOX
195 23087203 : ScopedLocker<> lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
196 : #endif
197 23087203 : if (MSGlobals::gUseMesoSim) {
198 9121059 : removeFromVehicleUpdateValues(veh);
199 : }
200 23087203 : if (reason == MSMoveReminder::NOTIFICATION_ARRIVED) {
201 3000818 : ++nVehArrived;
202 20086385 : } else if (reason == MSMoveReminder::NOTIFICATION_LANE_CHANGE) {
203 132119 : ++nVehLaneChangeFrom;
204 19954266 : } else if (myParent == nullptr || reason != MSMoveReminder::NOTIFICATION_SEGMENT) {
205 12080606 : ++nVehLeft;
206 12080606 : if (reason == MSMoveReminder::NOTIFICATION_TELEPORT || reason == MSMoveReminder::NOTIFICATION_TELEPORT_ARRIVED) {
207 6860 : ++nVehTeleported;
208 12073746 : } else if (reason >= MSMoveReminder::NOTIFICATION_VAPORIZED_CALIBRATOR) {
209 70303 : ++nVehVaporized;
210 : }
211 : }
212 : }
213 27502088 : if (MSGlobals::gUseMesoSim || !veh.isVehicle()) {
214 : // only microsim vehicles keep the reminder until their back has fully left the edge/lane
215 9134181 : return false;
216 : }
217 18367907 : return reason == MSMoveReminder::NOTIFICATION_JUNCTION;
218 : }
219 :
220 :
221 : bool
222 24112450 : MSMeanData_Net::MSLaneMeanDataValues::notifyEnter(SUMOTrafficObject& veh, MSMoveReminder::Notification reason, const MSLane* enteredLane) {
223 : #ifdef DEBUG_NOTIFY_ENTER
224 : std::cout << "\n" << SIMTIME << " MSMeanData_Net::MSLaneMeanDataValues: veh '" << veh.getID() << "' enters lane '" << enteredLane->getID() << "'" << std::endl;
225 : #else
226 : UNUSED_PARAMETER(enteredLane);
227 : #endif
228 24112450 : if (myParent == nullptr || myParent->vehicleApplies(veh)) {
229 23196380 : if (getLane() == nullptr || !veh.isVehicle() || getLane() == static_cast<MSVehicle&>(veh).getLane()) {
230 : #ifdef HAVE_FOX
231 23187540 : ScopedLocker<> lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
232 : #endif
233 23187540 : if (reason == MSMoveReminder::NOTIFICATION_DEPARTED) {
234 3178211 : ++nVehDeparted;
235 20009329 : } else if (reason == MSMoveReminder::NOTIFICATION_LANE_CHANGE) {
236 131779 : ++nVehLaneChangeTo;
237 19877550 : } else if (myParent == nullptr || reason != MSMoveReminder::NOTIFICATION_SEGMENT) {
238 12034065 : ++nVehEntered;
239 : }
240 : }
241 23196380 : return true;
242 : }
243 : return false;
244 : }
245 :
246 :
247 : bool
248 22488293 : MSMeanData_Net::MSLaneMeanDataValues::isEmpty() const {
249 21827159 : return sampleSeconds == 0 && nVehDeparted == 0 && nVehArrived == 0 && nVehEntered == 0
250 44315004 : && nVehLeft == 0 && nVehVaporized == 0 && nVehTeleported == 0 && nVehLaneChangeFrom == 0 && nVehLaneChangeTo == 0;
251 : }
252 :
253 : double
254 965538 : MSMeanData_Net::MSLaneMeanDataValues::getOccupancy(SUMOTime period, int numLanes) const {
255 965538 : return occupationSum / STEPS2TIME(period) / myLaneLength / (double)numLanes * 100.;
256 : }
257 :
258 : void
259 965416 : MSMeanData_Net::MSLaneMeanDataValues::write(OutputDevice& dev, const SumoXMLAttrMask& attributeMask, const SUMOTime period,
260 : const int numLanes, const double speedLimit, const double defaultTravelTime, const int numVehicles) const {
261 :
262 965416 : double density = frontSampleSeconds / STEPS2TIME(period) * 1000. / myLaneLength;
263 965416 : double overlapDensity = sampleSeconds / STEPS2TIME(period) * 1000. / myLaneLength;
264 965416 : if (MSGlobals::gLateralResolution < 0) {
265 : // avoid exceeding upper bound
266 911371 : density = MIN2(density, 1000 * (double)numLanes / MAX2(minimalVehicleLength, NUMERICAL_EPS));
267 909763 : overlapDensity = MIN2(overlapDensity, 1000 * (double)numLanes / MAX2(minimalVehicleLength, NUMERICAL_EPS));
268 : }
269 965416 : const double laneDensity = density / (double)numLanes;
270 965416 : const double occupancy = getOccupancy(period, numLanes);
271 : #ifdef DEBUG_OCCUPANCY2
272 : // tests #3264
273 : if (occupancy > 100) {
274 : std::cout << SIMTIME << " Encountered bad occupancy: " << occupancy
275 : << ", myLaneLength=" << myLaneLength << ", period=" << STEPS2TIME(period) << ", occupationSum=" << occupationSum
276 : << std::endl;
277 : }
278 : // refs #3265
279 : std::cout << SIMTIME << "ID: " << getDescription() << " minVehicleLength=" << minimalVehicleLength
280 : << "\ndensity=" << density << "\n";
281 : #endif
282 :
283 965416 : if (myParent == nullptr) {
284 10065 : const double speed = sampleSeconds == 0 ? 0. : travelledDistance / sampleSeconds;
285 10065 : const double frontSpeed = frontSampleSeconds == 0 ? 0. : frontTravelledDistance / frontSampleSeconds;
286 10065 : dev.writeOptionalAttr(SUMO_ATTR_DENSITY, density, attributeMask, sampleSeconds == 0);
287 10065 : dev.writeOptionalAttr(SUMO_ATTR_LANEDENSITY, laneDensity, attributeMask, sampleSeconds == 0);
288 10065 : dev.writeOptionalAttr(SUMO_ATTR_OCCUPANCY, occupancy, attributeMask, sampleSeconds == 0);
289 10065 : dev.writeOptionalAttr(SUMO_ATTR_WAITINGTIME, waitSeconds, attributeMask, sampleSeconds == 0);
290 10065 : dev.writeOptionalAttr(SUMO_ATTR_TIMELOSS, timeLoss, attributeMask, sampleSeconds == 0);
291 10065 : dev.writeOptionalAttr(SUMO_ATTR_SPEED, speed, attributeMask, sampleSeconds == 0);
292 10065 : dev.writeOptionalAttr(SUMO_ATTR_SPEEDREL, speedLimit == 0. || sampleSeconds == 0 ? 0. : travelledDistance / sampleSeconds / speedLimit,
293 10065 : attributeMask, sampleSeconds == 0);
294 10065 : dev.writeOptionalAttr(SUMO_ATTR_DEPARTED, nVehDeparted, attributeMask);
295 10065 : dev.writeOptionalAttr(SUMO_ATTR_ARRIVED, nVehArrived, attributeMask);
296 10065 : dev.writeOptionalAttr(SUMO_ATTR_ENTERED, nVehEntered, attributeMask);
297 10065 : dev.writeOptionalAttr(SUMO_ATTR_LEFT, nVehLeft, attributeMask);
298 10065 : dev.writeOptionalAttr(SUMO_ATTR_VAPORIZED, nVehVaporized, attributeMask, nVehVaporized == 0);
299 10065 : dev.writeOptionalAttr(SUMO_ATTR_TELEPORTED, nVehTeleported, attributeMask, nVehTeleported == 0);
300 10065 : dev.writeOptionalAttr(SUMO_ATTR_FLOW, density * frontSpeed * 3.6, attributeMask, frontSampleSeconds == 0);
301 10065 : dev.writeOptionalAttr(SUMO_ATTR_DISTANCE, frontTravelledDistance, attributeMask);
302 20130 : dev.closeTag();
303 : return;
304 : }
305 955351 : const bool haveSamples = sampleSeconds > myParent->myMinSamples;
306 955351 : const bool haveFrontSamples = frontSampleSeconds > myParent->myMinSamples;
307 955351 : const bool haveSamplesOrDefault = haveSamples || defaultTravelTime >= 0.;
308 : bool haveTravelTime = haveSamplesOrDefault;
309 955351 : double traveltime = myParent->myMaxTravelTime;
310 955351 : if (haveSamples) {
311 623115 : if (numVehicles > 0) {
312 244 : traveltime = sampleSeconds / numVehicles;
313 : } else {
314 : traveltime = myParent->myMaxTravelTime;
315 622871 : if (frontTravelledDistance > NUMERICAL_EPS) {
316 851201 : traveltime = MIN2(traveltime, myLaneLength * frontSampleSeconds / frontTravelledDistance);
317 197129 : } else if (defaultTravelTime >= 0.) {
318 0 : traveltime = defaultTravelTime;
319 : } else {
320 : haveTravelTime = false;
321 : }
322 : }
323 332236 : } else if (defaultTravelTime >= 0.) {
324 2638 : traveltime = defaultTravelTime;
325 : }
326 955351 : dev.writeOptionalAttr(SUMO_ATTR_TRAVELTIME, traveltime, attributeMask, !haveTravelTime);
327 955351 : double overlapTraveltime = myParent->myMaxTravelTime;
328 955351 : if (travelledDistance > 0.) {
329 : // one vehicle has to drive lane length + vehicle length before it has left the lane
330 : // thus we need to scale with an extended length, approximated by lane length + average vehicle length
331 856735 : overlapTraveltime = MIN2(overlapTraveltime, (myLaneLength + vehLengthSum / sampleSeconds) * sampleSeconds / travelledDistance);
332 : }
333 955351 : dev.writeOptionalAttr(SUMO_ATTR_OVERLAPTRAVELTIME, overlapTraveltime, attributeMask, !haveSamples || numVehicles > 0);
334 955351 : dev.writeOptionalAttr(SUMO_ATTR_DENSITY, density, attributeMask, !haveSamples || numVehicles > 0);
335 955351 : dev.writeOptionalAttr(SUMO_ATTR_OVERLAPDENSITY, overlapDensity, attributeMask, sampleSeconds == 0);
336 955351 : dev.writeOptionalAttr(SUMO_ATTR_LANEDENSITY, laneDensity, attributeMask, !haveSamples || numVehicles > 0);
337 955351 : dev.writeOptionalAttr(SUMO_ATTR_OCCUPANCY, occupancy, attributeMask, !haveSamples || numVehicles > 0);
338 955351 : dev.writeOptionalAttr(SUMO_ATTR_WAITINGTIME, waitSeconds, attributeMask, !haveSamples);
339 955351 : dev.writeOptionalAttr(SUMO_ATTR_TIMELOSS, timeLoss, attributeMask, !haveSamples);
340 955351 : double speed = 0.;
341 : double frontSpeed = 0.;
342 955351 : if (haveSamples) {
343 623115 : speed = travelledDistance / sampleSeconds;
344 332236 : } else if (defaultTravelTime > 0.) {
345 2638 : speed = myLaneLength / defaultTravelTime;
346 : }
347 955351 : if (haveFrontSamples) {
348 582442 : frontSpeed = frontTravelledDistance / frontSampleSeconds;
349 372909 : } else if (defaultTravelTime > 0.) {
350 2638 : frontSpeed = myLaneLength / defaultTravelTime;
351 : }
352 955351 : dev.writeOptionalAttr(SUMO_ATTR_SPEED, speed, attributeMask, !haveSamplesOrDefault);
353 955351 : dev.writeOptionalAttr(SUMO_ATTR_SPEEDREL, speedLimit == 0. ? 0. : speed / speedLimit, attributeMask, !haveSamplesOrDefault);
354 955351 : dev.writeOptionalAttr(SUMO_ATTR_DEPARTED, nVehDeparted, attributeMask);
355 955351 : dev.writeOptionalAttr(SUMO_ATTR_ARRIVED, nVehArrived, attributeMask);
356 955351 : dev.writeOptionalAttr(SUMO_ATTR_ENTERED, nVehEntered, attributeMask);
357 955351 : dev.writeOptionalAttr(SUMO_ATTR_LEFT, nVehLeft, attributeMask);
358 955351 : dev.writeOptionalAttr(SUMO_ATTR_LANECHANGEDFROM, nVehLaneChangeFrom, attributeMask);
359 955351 : dev.writeOptionalAttr(SUMO_ATTR_LANECHANGEDTO, nVehLaneChangeTo, attributeMask);
360 955351 : dev.writeOptionalAttr(SUMO_ATTR_VAPORIZED, nVehVaporized, attributeMask, nVehVaporized == 0);
361 955351 : dev.writeOptionalAttr(SUMO_ATTR_TELEPORTED, nVehTeleported, attributeMask, nVehTeleported == 0);
362 955351 : dev.writeOptionalAttr(SUMO_ATTR_FLOW, density * frontSpeed * 3.6, attributeMask, !haveSamples || numVehicles == 0);
363 955351 : dev.writeOptionalAttr(SUMO_ATTR_DISTANCE, frontTravelledDistance, attributeMask);
364 : }
365 :
366 :
367 : double
368 0 : MSMeanData_Net::MSLaneMeanDataValues::getAttributeValue(SumoXMLAttr a,
369 : const SUMOTime period, const double numLanes, const double speedLimit) const {
370 : /// @todo: remove redundancy in derived values (density, laneDensity)
371 0 : switch (a) {
372 0 : case SUMO_ATTR_DENSITY:
373 0 : return MIN2(frontSampleSeconds / STEPS2TIME(period) * (double) 1000 / myLaneLength,
374 0 : 1000. * numLanes / MAX2(minimalVehicleLength, NUMERICAL_EPS));
375 0 : case SUMO_ATTR_LANEDENSITY: {
376 0 : const double density = MIN2(frontSampleSeconds / STEPS2TIME(period) * (double) 1000 / myLaneLength,
377 0 : 1000. * numLanes / MAX2(minimalVehicleLength, NUMERICAL_EPS));
378 0 : return density / numLanes;
379 : }
380 0 : case SUMO_ATTR_OVERLAPDENSITY: {
381 0 : const double overlapDensity = MIN2(sampleSeconds / STEPS2TIME(period) * (double) 1000 / myLaneLength,
382 0 : 1000. * numLanes / MAX2(minimalVehicleLength, NUMERICAL_EPS));
383 0 : return overlapDensity / numLanes;
384 : }
385 0 : case SUMO_ATTR_OCCUPANCY:
386 0 : return occupationSum / STEPS2TIME(period) / myLaneLength / numLanes * (double) 1000;
387 0 : case SUMO_ATTR_WAITINGTIME:
388 0 : return waitSeconds;
389 0 : case SUMO_ATTR_TIMELOSS:
390 0 : return timeLoss;
391 0 : case SUMO_ATTR_SPEED:
392 0 : return travelledDistance / sampleSeconds;
393 0 : case SUMO_ATTR_SPEEDREL:
394 0 : return speedLimit == 0. ? 0. : travelledDistance / sampleSeconds / speedLimit;
395 0 : case SUMO_ATTR_DEPARTED:
396 0 : return nVehDeparted;
397 0 : case SUMO_ATTR_ARRIVED:
398 0 : return nVehArrived;
399 0 : case SUMO_ATTR_ENTERED:
400 0 : return nVehEntered;
401 0 : case SUMO_ATTR_LEFT:
402 0 : return nVehLeft;
403 0 : case SUMO_ATTR_VAPORIZED:
404 0 : return nVehVaporized;
405 0 : case SUMO_ATTR_TELEPORTED:
406 0 : return nVehTeleported;
407 0 : case SUMO_ATTR_FLOW: {
408 0 : const double density = MIN2(frontSampleSeconds / STEPS2TIME(period) * (double) 1000 / myLaneLength,
409 0 : 1000. * numLanes / MAX2(minimalVehicleLength, NUMERICAL_EPS));
410 0 : const double speed = frontTravelledDistance / frontSampleSeconds;
411 0 : return density * speed * 3.6;
412 : }
413 0 : case SUMO_ATTR_DISTANCE:
414 0 : return frontTravelledDistance;
415 : default:
416 : return 0;
417 : }
418 : }
419 :
420 :
421 : // ---------------------------------------------------------------------------
422 : // MSMeanData_Net - methods
423 : // ---------------------------------------------------------------------------
424 22943 : MSMeanData_Net::MSMeanData_Net(const std::string& id,
425 : const SUMOTime dumpBegin,
426 : const SUMOTime dumpEnd, const bool useLanes,
427 : const std::string& excludeEmpty,
428 : const bool withInternal,
429 : const bool trackVehicles,
430 : const int detectPersons,
431 : const double maxTravelTime,
432 : const double minSamples,
433 : const double haltSpeed,
434 : const double haltSpeedRel,
435 : const std::string& vTypes,
436 : const std::string& writeAttributes,
437 : const std::vector<MSEdge*>& edges,
438 22943 : AggregateType aggregate) :
439 : MSMeanData(id, dumpBegin, dumpEnd, useLanes, excludeEmpty,
440 : withInternal, trackVehicles, detectPersons, maxTravelTime, minSamples, vTypes, writeAttributes, edges, aggregate),
441 22943 : myHaltSpeed(haltSpeed),
442 22943 : myHaltSpeedRel(haltSpeedRel)
443 22943 : { }
444 :
445 :
446 44867 : MSMeanData_Net::~MSMeanData_Net() {}
447 :
448 :
449 : MSMeanData::MeanDataValues*
450 8326499 : MSMeanData_Net::createValues(MSLane* const lane, const double length, const bool doAdd) const {
451 8326499 : return new MSLaneMeanDataValues(lane, length, doAdd, this);
452 : }
453 :
454 :
455 : std::vector<std::string>
456 0 : MSMeanData_Net::getAttributeNames() const {
457 : std::vector<std::string> result;
458 0 : result.push_back(toString(SUMO_ATTR_DENSITY));
459 0 : result.push_back(toString(SUMO_ATTR_LANEDENSITY));
460 0 : result.push_back(toString(SUMO_ATTR_OVERLAPDENSITY));
461 0 : result.push_back(toString(SUMO_ATTR_OCCUPANCY));
462 0 : result.push_back(toString(SUMO_ATTR_WAITINGTIME));
463 0 : result.push_back(toString(SUMO_ATTR_TIMELOSS));
464 0 : result.push_back(toString(SUMO_ATTR_SPEED));
465 0 : result.push_back(toString(SUMO_ATTR_SPEEDREL));
466 0 : result.push_back(toString(SUMO_ATTR_DEPARTED));
467 0 : result.push_back(toString(SUMO_ATTR_ARRIVED));
468 0 : result.push_back(toString(SUMO_ATTR_ENTERED));
469 0 : result.push_back(toString(SUMO_ATTR_LEFT));
470 0 : result.push_back(toString(SUMO_ATTR_LANECHANGEDFROM));
471 0 : result.push_back(toString(SUMO_ATTR_LANECHANGEDTO));
472 0 : result.push_back(toString(SUMO_ATTR_VAPORIZED));
473 0 : result.push_back(toString(SUMO_ATTR_TELEPORTED));
474 0 : result.push_back(toString(SUMO_ATTR_FLOW));
475 0 : result.push_back(toString(SUMO_ATTR_DISTANCE));
476 0 : return result;
477 0 : }
478 :
479 :
480 : bool
481 95 : MSMeanData_Net::supports(const SumoXMLAttrMask& attributeMask) {
482 : return
483 95 : attributeMask.test(SUMO_ATTR_DENSITY) ||
484 95 : attributeMask.test(SUMO_ATTR_LANEDENSITY) ||
485 95 : attributeMask.test(SUMO_ATTR_OVERLAPDENSITY) ||
486 95 : attributeMask.test(SUMO_ATTR_OCCUPANCY) ||
487 95 : attributeMask.test(SUMO_ATTR_WAITINGTIME) ||
488 95 : attributeMask.test(SUMO_ATTR_TIMELOSS) ||
489 71 : attributeMask.test(SUMO_ATTR_SPEED) ||
490 71 : attributeMask.test(SUMO_ATTR_SPEEDREL) ||
491 71 : attributeMask.test(SUMO_ATTR_DEPARTED) ||
492 42 : attributeMask.test(SUMO_ATTR_ARRIVED) ||
493 42 : attributeMask.test(SUMO_ATTR_ENTERED) ||
494 24 : attributeMask.test(SUMO_ATTR_LEFT) ||
495 10 : attributeMask.test(SUMO_ATTR_LANECHANGEDFROM) ||
496 10 : attributeMask.test(SUMO_ATTR_LANECHANGEDTO) ||
497 10 : attributeMask.test(SUMO_ATTR_VAPORIZED) ||
498 10 : attributeMask.test(SUMO_ATTR_TELEPORTED) ||
499 105 : attributeMask.test(SUMO_ATTR_FLOW) ||
500 95 : attributeMask.test(SUMO_ATTR_DISTANCE);
501 : }
502 :
503 :
504 : /****************************************************************************/
|