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