1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2004-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    MSMeanData_Net.cpp
11 /// @author  Daniel Krajzewicz
12 /// @author  Michael Behrisch
13 /// @author  Jakob Erdmann
14 /// @date    Mon, 10.05.2004
15 /// @version $Id$
16 ///
17 // Network state mean data collector for edges/lanes
18 /****************************************************************************/
19 
20 
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #include <config.h>
25 
26 #include <microsim/MSEdgeControl.h>
27 #include <microsim/MSEdge.h>
28 #include <microsim/MSLane.h>
29 #include <microsim/MSVehicle.h>
30 #include <utils/common/SUMOTime.h>
31 #include <utils/common/ToString.h>
32 #include <utils/iodevices/OutputDevice.h>
33 #include "MSMeanData_Net.h"
34 
35 #include <microsim/MSGlobals.h>
36 #include <mesosim/MELoop.h>
37 #include <mesosim/MESegment.h>
38 
39 // ===========================================================================
40 // debug constants
41 // ===========================================================================
42 //#define DEBUG_OCCUPANCY
43 //#define DEBUG_OCCUPANCY2
44 //#define DEBUG_NOTIFY_ENTER
45 //#define DEBUG_COND (veh.getLane()->getID() == "31to211_0")
46 #define DEBUG_COND (false)
47 
48 
49 // ===========================================================================
50 // method definitions
51 // ===========================================================================
52 // ---------------------------------------------------------------------------
53 // MSMeanData_Net::MSLaneMeanDataValues - methods
54 // ---------------------------------------------------------------------------
MSLaneMeanDataValues(MSLane * const lane,const double length,const bool doAdd,const MSMeanData_Net * parent)55 MSMeanData_Net::MSLaneMeanDataValues::MSLaneMeanDataValues(MSLane* const lane,
56         const double length,
57         const bool doAdd,
58         const MSMeanData_Net* parent)
59     : MSMeanData::MeanDataValues(lane, length, doAdd, parent),
60       nVehDeparted(0), nVehArrived(0), nVehEntered(0), nVehLeft(0),
61       nVehVaporized(0), waitSeconds(0),
62       nVehLaneChangeFrom(0), nVehLaneChangeTo(0),
63       frontSampleSeconds(0), frontTravelledDistance(0),
64       vehLengthSum(0), occupationSum(0),
65       minimalVehicleLength(INVALID_DOUBLE),
66       myParent(parent) {}
67 
68 
~MSLaneMeanDataValues()69 MSMeanData_Net::MSLaneMeanDataValues::~MSLaneMeanDataValues() {
70 }
71 
72 
73 void
reset(bool)74 MSMeanData_Net::MSLaneMeanDataValues::reset(bool) {
75     nVehDeparted = 0;
76     nVehArrived = 0;
77     nVehEntered = 0;
78     nVehLeft = 0;
79     nVehVaporized = 0;
80     nVehLaneChangeFrom = 0;
81     nVehLaneChangeTo = 0;
82     sampleSeconds = 0.;
83     travelledDistance = 0;
84     waitSeconds = 0;
85     frontSampleSeconds = 0;
86     frontTravelledDistance = 0;
87     vehLengthSum = 0;
88     occupationSum = 0;
89     minimalVehicleLength = INVALID_DOUBLE;
90 }
91 
92 
93 void
addTo(MSMeanData::MeanDataValues & val) const94 MSMeanData_Net::MSLaneMeanDataValues::addTo(MSMeanData::MeanDataValues& val) const {
95     MSLaneMeanDataValues& v = (MSLaneMeanDataValues&) val;
96     v.nVehDeparted += nVehDeparted;
97     v.nVehArrived += nVehArrived;
98     v.nVehEntered += nVehEntered;
99     v.nVehLeft += nVehLeft;
100     v.nVehVaporized += nVehVaporized;
101     v.nVehLaneChangeFrom += nVehLaneChangeFrom;
102     v.nVehLaneChangeTo += nVehLaneChangeTo;
103     v.sampleSeconds += sampleSeconds;
104     v.travelledDistance += travelledDistance;
105     v.waitSeconds += waitSeconds;
106     v.frontSampleSeconds += frontSampleSeconds;
107     v.frontTravelledDistance += frontTravelledDistance;
108     v.vehLengthSum += vehLengthSum;
109     v.occupationSum += occupationSum;
110     if (v.minimalVehicleLength == INVALID_DOUBLE) {
111         v.minimalVehicleLength = minimalVehicleLength;
112     } else {
113         v.minimalVehicleLength = MIN2(minimalVehicleLength, v.minimalVehicleLength);
114     }
115 }
116 
117 
118 void
notifyMoveInternal(const SUMOTrafficObject & veh,const double frontOnLane,const double timeOnLane,const double,const double meanSpeedVehicleOnLane,const double travelledDistanceFrontOnLane,const double travelledDistanceVehicleOnLane,const double meanLengthOnLane)119 MSMeanData_Net::MSLaneMeanDataValues::notifyMoveInternal(
120     const SUMOTrafficObject& veh, const double frontOnLane,
121     const double timeOnLane, const double /* meanSpeedFrontOnLane */,
122     const double meanSpeedVehicleOnLane,
123     const double travelledDistanceFrontOnLane,
124     const double travelledDistanceVehicleOnLane,
125     const double meanLengthOnLane) {
126 #ifdef DEBUG_OCCUPANCY
127     if DEBUG_COND {
128     std::cout << SIMTIME << "\n  MSMeanData_Net::MSLaneMeanDataValues::notifyMoveInternal()\n"
129               << "  veh '" << veh.getID() << "' on lane '" << veh.getLane()->getID() << "'"
130                   << ", timeOnLane=" << timeOnLane
131                   << ", meanSpeedVehicleOnLane=" << meanSpeedVehicleOnLane
132                   << ",\ntravelledDistanceFrontOnLane=" << travelledDistanceFrontOnLane
133                   << ", travelledDistanceVehicleOnLane=" << travelledDistanceVehicleOnLane
134                   << ", meanLengthOnLane=" << meanLengthOnLane
135                   << std::endl;
136     }
137 #endif
138     if (myParent != nullptr && !myParent->vehicleApplies(veh)) {
139         return;
140     }
141     sampleSeconds += timeOnLane;
142     travelledDistance += travelledDistanceVehicleOnLane;
143     vehLengthSum += veh.getVehicleType().getLength() * timeOnLane;
144     if (MSGlobals::gUseMesoSim) {
145         // For the mesosim case no information on whether the vehicle was occupying
146         // the lane with its whole length is available. We assume the whole length
147         // Therefore this increment is taken out with more information on the vehicle movement.
148         occupationSum += veh.getVehicleType().getLength() * timeOnLane;
149     } else {
150         // for the microsim case more elaborate calculation of the average length on the lane,
151         // is taken out in notifyMove(), refs #153
152         occupationSum += meanLengthOnLane * TS;
153     }
154     if (myParent != nullptr && meanSpeedVehicleOnLane < myParent->myHaltSpeed) {
155         waitSeconds += timeOnLane;
156     }
157     frontSampleSeconds += frontOnLane;
158     frontTravelledDistance += travelledDistanceFrontOnLane;
159     if (minimalVehicleLength == INVALID_DOUBLE) {
160         minimalVehicleLength = veh.getVehicleType().getLength();
161     } else {
162         minimalVehicleLength = MIN2(minimalVehicleLength, veh.getVehicleType().getLength());
163     }
164 #ifdef DEBUG_OCCUPANCY2
165     // refs #3265
166     std::cout << SIMTIME << "ID: " << getDescription() << " minVehicleLength=" << minimalVehicleLength << std::endl;
167 #endif
168 }
169 
170 
171 bool
172 MSMeanData_Net::MSLaneMeanDataValues::notifyLeave(SUMOTrafficObject& veh, double /*lastPos*/, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
173     if ((myParent == nullptr || myParent->vehicleApplies(veh)) && (
174                 getLane() == nullptr || !veh.isVehicle() || getLane() == static_cast<MSVehicle&>(veh).getLane())) {
175         if (MSGlobals::gUseMesoSim) {
176             removeFromVehicleUpdateValues(veh);
177         }
178         if (reason == MSMoveReminder::NOTIFICATION_ARRIVED) {
179             ++nVehArrived;
180         } else if (reason == MSMoveReminder::NOTIFICATION_LANE_CHANGE) {
181             ++nVehLaneChangeFrom;
182         } else if (myParent == nullptr || reason != MSMoveReminder::NOTIFICATION_SEGMENT) {
183             ++nVehLeft;
184             if (reason == MSMoveReminder::NOTIFICATION_VAPORIZED) {
185                 ++nVehVaporized;
186             }
187         }
188     }
189     if (MSGlobals::gUseMesoSim) {
190         return false;
191     }
192     return reason == MSMoveReminder::NOTIFICATION_JUNCTION;
193 }
194 
195 
196 bool
197 MSMeanData_Net::MSLaneMeanDataValues::notifyEnter(SUMOTrafficObject& veh, MSMoveReminder::Notification reason, const MSLane* enteredLane) {
198 #ifdef DEBUG_NOTIFY_ENTER
199     std::cout << "\n" << SIMTIME << " MSMeanData_Net::MSLaneMeanDataValues: veh '" << veh.getID() << "' enters lane '" << enteredLane->getID() << "'" << std::endl;
200 #else
201     UNUSED_PARAMETER(enteredLane);
202 #endif
203     if (myParent == nullptr || myParent->vehicleApplies(veh)) {
204         if (getLane() == nullptr || !veh.isVehicle() || getLane() == static_cast<MSVehicle&>(veh).getLane()) {
205             if (reason == MSMoveReminder::NOTIFICATION_DEPARTED) {
206                 ++nVehDeparted;
207             } else if (reason == MSMoveReminder::NOTIFICATION_LANE_CHANGE) {
208                 ++nVehLaneChangeTo;
209             } else if (myParent == nullptr || reason != MSMoveReminder::NOTIFICATION_SEGMENT) {
210                 ++nVehEntered;
211             }
212         }
213         return true;
214     }
215     return false;
216 }
217 
218 
219 bool
220 MSMeanData_Net::MSLaneMeanDataValues::isEmpty() const {
221     return sampleSeconds == 0 && nVehDeparted == 0 && nVehArrived == 0 && nVehEntered == 0
222            && nVehLeft == 0 && nVehVaporized == 0 && nVehLaneChangeFrom == 0 && nVehLaneChangeTo == 0;
223 }
224 
225 
226 void
227 MSMeanData_Net::MSLaneMeanDataValues::write(OutputDevice& dev, const SUMOTime period,
228         const double numLanes, const double defaultTravelTime, const int numVehicles) const {
229 
230 #ifdef DEBUG_OCCUPANCY2
231     // tests #3264
232     double occupancy = occupationSum / STEPS2TIME(period) / myLaneLength / numLanes * (double) 100;
233     if (occupancy > 100) {
234         std::cout << SIMTIME << " Encountered bad occupancy: " << occupancy
235                   << ", myLaneLength=" << myLaneLength << ", period=" << STEPS2TIME(period) << ", occupationSum=" << occupationSum
236                   << std::endl;
237     }
238     // refs #3265
239     std::cout << SIMTIME << "ID: " << getDescription() << " minVehicleLength=" << minimalVehicleLength
240               << "\ndensity=" << MIN2(sampleSeconds / STEPS2TIME(period) * (double) 1000 / myLaneLength, 1. / MAX2(minimalVehicleLength, NUMERICAL_EPS)) << std::endl;
241 #endif
242 
243     if (myParent == nullptr) {
244         if (sampleSeconds > 0) {
245             dev.writeAttr("density", MIN2(sampleSeconds / STEPS2TIME(period) * (double) 1000 / myLaneLength, 1000. * numLanes / MAX2(minimalVehicleLength, NUMERICAL_EPS)))
246             .writeAttr("occupancy", occupationSum / STEPS2TIME(period) / myLaneLength / numLanes * (double) 100)
247             .writeAttr("waitingTime", waitSeconds).writeAttr("speed", travelledDistance / sampleSeconds);
248         }
249         dev.writeAttr("departed", nVehDeparted).writeAttr("arrived", nVehArrived).writeAttr("entered", nVehEntered).writeAttr("left", nVehLeft);
250         if (nVehVaporized > 0) {
251             dev.writeAttr("vaporized", nVehVaporized);
252         }
253         dev.closeTag();
254         return;
255     }
256     if (sampleSeconds > myParent->myMinSamples) {
257         double overlapTraveltime = myParent->myMaxTravelTime;
258         if (travelledDistance > 0.f) {
259             // one vehicle has to drive lane length + vehicle length before it has left the lane
260             // thus we need to scale with an extended length, approximated by lane length + average vehicle length
261             overlapTraveltime = MIN2(overlapTraveltime, (myLaneLength + vehLengthSum / sampleSeconds) * sampleSeconds / travelledDistance);
262         }
263         if (numVehicles > 0) {
264             dev.writeAttr("traveltime", sampleSeconds / numVehicles).writeAttr("waitingTime", waitSeconds).writeAttr("speed", travelledDistance / sampleSeconds);
265         } else {
266             double traveltime = myParent->myMaxTravelTime;
267             if (frontTravelledDistance > NUMERICAL_EPS) {
268                 traveltime = MIN2(traveltime, myLaneLength * frontSampleSeconds / frontTravelledDistance);
269                 dev.writeAttr("traveltime", traveltime);
270             } else if (defaultTravelTime >= 0.) {
271                 dev.writeAttr("traveltime", defaultTravelTime);
272             }
273             dev.writeAttr("overlapTraveltime", overlapTraveltime)
274             .writeAttr("density", MIN2(sampleSeconds / STEPS2TIME(period) * (double) 1000 / myLaneLength, 1000. * numLanes / MAX2(minimalVehicleLength, NUMERICAL_EPS)))
275             .writeAttr("occupancy", occupationSum / STEPS2TIME(period) / myLaneLength / numLanes * (double) 100)
276             .writeAttr("waitingTime", waitSeconds).writeAttr("speed", travelledDistance / sampleSeconds);
277         }
278     } else if (defaultTravelTime >= 0.) {
279         dev.writeAttr("traveltime", defaultTravelTime).writeAttr("speed", myLaneLength / defaultTravelTime);
280     }
281     dev.writeAttr("departed", nVehDeparted).writeAttr("arrived", nVehArrived).writeAttr("entered", nVehEntered).writeAttr("left", nVehLeft)
282     .writeAttr("laneChangedFrom", nVehLaneChangeFrom).writeAttr("laneChangedTo", nVehLaneChangeTo);
283     if (nVehVaporized > 0) {
284         dev.writeAttr("vaporized", nVehVaporized);
285     }
286     dev.closeTag();
287 }
288 
289 // ---------------------------------------------------------------------------
290 // MSMeanData_Net - methods
291 // ---------------------------------------------------------------------------
292 MSMeanData_Net::MSMeanData_Net(const std::string& id,
293                                const SUMOTime dumpBegin,
294                                const SUMOTime dumpEnd, const bool useLanes,
295                                const bool withEmpty, const bool printDefaults,
296                                const bool withInternal,
297                                const bool trackVehicles,
298                                const int detectPersons,
299                                const double maxTravelTime,
300                                const double minSamples,
301                                const double haltSpeed,
302                                const std::string& vTypes)
303     : MSMeanData(id, dumpBegin, dumpEnd, useLanes, withEmpty, printDefaults,
304                  withInternal, trackVehicles, detectPersons, maxTravelTime, minSamples, vTypes),
305       myHaltSpeed(haltSpeed) {
306 }
307 
308 
309 MSMeanData_Net::~MSMeanData_Net() {}
310 
311 
312 MSMeanData::MeanDataValues*
313 MSMeanData_Net::createValues(MSLane* const lane, const double length, const bool doAdd) const {
314     return new MSLaneMeanDataValues(lane, length, doAdd, this);
315 }
316 
317 
318 /****************************************************************************/
319 
320