Eclipse SUMO - Simulation of Urban MObility
MSMeanData_Net.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2004-2020 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 /****************************************************************************/
20 // Network state mean data collector for edges/lanes
21 /****************************************************************************/
22 #include <config.h>
23 
24 #include <microsim/MSEdgeControl.h>
25 #include <microsim/MSEdge.h>
26 #include <microsim/MSLane.h>
27 #include <microsim/MSVehicle.h>
28 #include <utils/common/SUMOTime.h>
29 #include <utils/common/ToString.h>
31 #include "MSMeanData_Net.h"
32 
33 #include <microsim/MSGlobals.h>
34 #include <mesosim/MELoop.h>
35 #include <mesosim/MESegment.h>
36 
37 // ===========================================================================
38 // debug constants
39 // ===========================================================================
40 //#define DEBUG_OCCUPANCY
41 //#define DEBUG_OCCUPANCY2
42 //#define DEBUG_NOTIFY_ENTER
43 //#define DEBUG_COND (veh.getLane()->getID() == "31to211_0")
44 #define DEBUG_COND (false)
45 
46 
47 // ===========================================================================
48 // method definitions
49 // ===========================================================================
50 // ---------------------------------------------------------------------------
51 // MSMeanData_Net::MSLaneMeanDataValues - methods
52 // ---------------------------------------------------------------------------
54  const double length,
55  const bool doAdd,
56  const MSMeanData_Net* parent)
57  : MSMeanData::MeanDataValues(lane, length, doAdd, parent),
58  nVehDeparted(0), nVehArrived(0), nVehEntered(0), nVehLeft(0),
59  nVehVaporized(0), waitSeconds(0), timeLoss(0),
60  nVehLaneChangeFrom(0), nVehLaneChangeTo(0),
61  frontSampleSeconds(0), frontTravelledDistance(0),
62  vehLengthSum(0), occupationSum(0),
63  minimalVehicleLength(INVALID_DOUBLE),
64  myParent(parent) {}
65 
66 
68 }
69 
70 
71 void
73  nVehDeparted = 0;
74  nVehArrived = 0;
75  nVehEntered = 0;
76  nVehLeft = 0;
77  nVehVaporized = 0;
78  nVehLaneChangeFrom = 0;
79  nVehLaneChangeTo = 0;
80  sampleSeconds = 0.;
81  travelledDistance = 0;
82  waitSeconds = 0;
83  timeLoss = 0;
84  frontSampleSeconds = 0;
85  frontTravelledDistance = 0;
86  vehLengthSum = 0;
87  occupationSum = 0;
88  minimalVehicleLength = INVALID_DOUBLE;
89 }
90 
91 
92 void
95  v.nVehDeparted += nVehDeparted;
96  v.nVehArrived += nVehArrived;
97  v.nVehEntered += nVehEntered;
98  v.nVehLeft += nVehLeft;
99  v.nVehVaporized += nVehVaporized;
100  v.nVehLaneChangeFrom += nVehLaneChangeFrom;
101  v.nVehLaneChangeTo += nVehLaneChangeTo;
102  v.sampleSeconds += sampleSeconds;
103  v.travelledDistance += travelledDistance;
104  v.waitSeconds += waitSeconds;
105  v.timeLoss += timeLoss;
106  v.frontSampleSeconds += frontSampleSeconds;
107  v.frontTravelledDistance += frontTravelledDistance;
108  v.vehLengthSum += vehLengthSum;
109  v.occupationSum += occupationSum;
111  v.minimalVehicleLength = minimalVehicleLength;
112  } else {
113  v.minimalVehicleLength = MIN2(minimalVehicleLength, v.minimalVehicleLength);
114  }
115 }
116 
117 
118 void
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;
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 (!veh.isStopped()) {
155  if (myParent != nullptr && meanSpeedVehicleOnLane < myParent->myHaltSpeed) {
156  waitSeconds += timeOnLane;
157  }
158  const double vmax = veh.getLane() == nullptr ? veh.getEdge()->getVehicleMaxSpeed(&veh) : veh.getLane()->getVehicleMaxSpeed(&veh);
159  if (vmax > 0) {
160  timeLoss += timeOnLane * MAX2(0.0, vmax - meanSpeedVehicleOnLane) / vmax;
161  }
162  }
163  frontSampleSeconds += frontOnLane;
164  frontTravelledDistance += travelledDistanceFrontOnLane;
165  if (minimalVehicleLength == INVALID_DOUBLE) {
166  minimalVehicleLength = veh.getVehicleType().getLengthWithGap();
167  } else {
168  minimalVehicleLength = MIN2(minimalVehicleLength, veh.getVehicleType().getLengthWithGap());
169  }
170 #ifdef DEBUG_OCCUPANCY2
171  // refs #3265
172  std::cout << SIMTIME << "ID: " << getDescription() << " minVehicleLength=" << minimalVehicleLength << std::endl;
173 #endif
174 }
175 
176 
177 bool
179  if ((myParent == nullptr || myParent->vehicleApplies(veh)) && (
180  getLane() == nullptr || !veh.isVehicle() || getLane() == static_cast<MSVehicle&>(veh).getLane())) {
181 #ifdef HAVE_FOX
182  FXConditionalLock lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
183 #endif
185  removeFromVehicleUpdateValues(veh);
186  }
187  if (reason == MSMoveReminder::NOTIFICATION_ARRIVED) {
188  ++nVehArrived;
189  } else if (reason == MSMoveReminder::NOTIFICATION_LANE_CHANGE) {
190  ++nVehLaneChangeFrom;
191  } else if (myParent == nullptr || reason != MSMoveReminder::NOTIFICATION_SEGMENT) {
192  ++nVehLeft;
194  ++nVehVaporized;
195  }
196  }
197  }
199  return false;
200  }
201  return reason == MSMoveReminder::NOTIFICATION_JUNCTION;
202 }
203 
204 
205 bool
207 #ifdef DEBUG_NOTIFY_ENTER
208  std::cout << "\n" << SIMTIME << " MSMeanData_Net::MSLaneMeanDataValues: veh '" << veh.getID() << "' enters lane '" << enteredLane->getID() << "'" << std::endl;
209 #else
210  UNUSED_PARAMETER(enteredLane);
211 #endif
212  if (myParent == nullptr || myParent->vehicleApplies(veh)) {
213  if (getLane() == nullptr || !veh.isVehicle() || getLane() == static_cast<MSVehicle&>(veh).getLane()) {
214 #ifdef HAVE_FOX
215  FXConditionalLock lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
216 #endif
218  ++nVehDeparted;
219  } else if (reason == MSMoveReminder::NOTIFICATION_LANE_CHANGE) {
220  ++nVehLaneChangeTo;
221  } else if (myParent == nullptr || reason != MSMoveReminder::NOTIFICATION_SEGMENT) {
222  ++nVehEntered;
223  }
224  }
225  return true;
226  }
227  return false;
228 }
229 
230 
231 bool
233  return sampleSeconds == 0 && nVehDeparted == 0 && nVehArrived == 0 && nVehEntered == 0
234  && nVehLeft == 0 && nVehVaporized == 0 && nVehLaneChangeFrom == 0 && nVehLaneChangeTo == 0;
235 }
236 
237 
238 void
239 MSMeanData_Net::MSLaneMeanDataValues::write(OutputDevice& dev, long long int attributeMask, const SUMOTime period,
240  const double numLanes, const double defaultTravelTime, const int numVehicles) const {
241 
242  const double density = MIN2(sampleSeconds / STEPS2TIME(period) * (double) 1000 / myLaneLength,
243  1000. * numLanes / MAX2(minimalVehicleLength, NUMERICAL_EPS));
244  const double laneDensity = density / numLanes;
245 #ifdef DEBUG_OCCUPANCY2
246  // tests #3264
247  double occupancy = occupationSum / STEPS2TIME(period) / myLaneLength / numLanes * (double) 100;
248  if (occupancy > 100) {
249  std::cout << SIMTIME << " Encountered bad occupancy: " << occupancy
250  << ", myLaneLength=" << myLaneLength << ", period=" << STEPS2TIME(period) << ", occupationSum=" << occupationSum
251  << std::endl;
252  }
253  // refs #3265
254  std::cout << SIMTIME << "ID: " << getDescription() << " minVehicleLength=" << minimalVehicleLength
255  << "\ndensity=" << density << "\n";
256 #endif
257 
258  if (myParent == nullptr) {
259  if (sampleSeconds > 0) {
260  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_DENSITY, density);
261  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_LANEDENSITY, laneDensity);
262  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_OCCUPANCY, occupationSum / STEPS2TIME(period) / myLaneLength / numLanes * (double) 100);
263  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_WAITINGTIME, waitSeconds);
264  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_TIMELOSS, timeLoss);
265  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_SPEED, travelledDistance / sampleSeconds);
266  }
267  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_DEPARTED, nVehDeparted);
268  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_ARRIVED, nVehArrived);
269  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_ENTERED, nVehEntered);
270  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_LEFT, nVehLeft);
271  if (nVehVaporized > 0) {
272  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_VAPORIZED, nVehVaporized);
273  }
274  dev.closeTag();
275  return;
276  }
277  if (sampleSeconds > myParent->myMinSamples) {
278  double overlapTraveltime = myParent->myMaxTravelTime;
279  if (travelledDistance > 0.f) {
280  // one vehicle has to drive lane length + vehicle length before it has left the lane
281  // thus we need to scale with an extended length, approximated by lane length + average vehicle length
282  overlapTraveltime = MIN2(overlapTraveltime, (myLaneLength + vehLengthSum / sampleSeconds) * sampleSeconds / travelledDistance);
283  }
284  if (numVehicles > 0) {
285  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_TRAVELTIME, sampleSeconds / numVehicles);
286  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_WAITINGTIME, waitSeconds);
287  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_TIMELOSS, timeLoss);
288  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_SPEED, travelledDistance / sampleSeconds);
289  } else {
290  double traveltime = myParent->myMaxTravelTime;
291  if (frontTravelledDistance > NUMERICAL_EPS) {
292  traveltime = MIN2(traveltime, myLaneLength * frontSampleSeconds / frontTravelledDistance);
293  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_TRAVELTIME, traveltime);
294  } else if (defaultTravelTime >= 0.) {
295  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_TRAVELTIME, defaultTravelTime);
296  }
297  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_OVERLAPTRAVELTIME, overlapTraveltime);
298  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_DENSITY, density);
299  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_LANEDENSITY, laneDensity);
300  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_OCCUPANCY, occupationSum / STEPS2TIME(period) / myLaneLength / numLanes * (double) 100);
301  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_WAITINGTIME, waitSeconds);
302  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_TIMELOSS, timeLoss);
303  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_SPEED, travelledDistance / sampleSeconds);
304  }
305  } else if (defaultTravelTime >= 0.) {
306  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_TRAVELTIME, defaultTravelTime);
307  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_SPEED, myLaneLength / defaultTravelTime);
308  }
309  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_DEPARTED, nVehDeparted);
310  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_ARRIVED, nVehArrived);
311  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_ENTERED, nVehEntered);
312  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_LEFT, nVehLeft);
313  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_LANECHANGEDFROM, nVehLaneChangeFrom);
314  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_LANECHANGEDTO, nVehLaneChangeTo);
315  if (nVehVaporized > 0) {
316  checkWriteAttribute(dev, attributeMask, SUMO_ATTR_VAPORIZED, nVehVaporized);
317  }
318  dev.closeTag();
319 }
320 
321 // ---------------------------------------------------------------------------
322 // MSMeanData_Net - methods
323 // ---------------------------------------------------------------------------
324 MSMeanData_Net::MSMeanData_Net(const std::string& id,
325  const SUMOTime dumpBegin,
326  const SUMOTime dumpEnd, const bool useLanes,
327  const bool withEmpty, const bool printDefaults,
328  const bool withInternal,
329  const bool trackVehicles,
330  const int detectPersons,
331  const double maxTravelTime,
332  const double minSamples,
333  const double haltSpeed,
334  const std::string& vTypes,
335  const std::string& writeAttributes) :
336  MSMeanData(id, dumpBegin, dumpEnd, useLanes, withEmpty, printDefaults,
337  withInternal, trackVehicles, detectPersons, maxTravelTime, minSamples, vTypes, writeAttributes),
338  myHaltSpeed(haltSpeed)
339 { }
340 
341 
343 
344 
346 MSMeanData_Net::createValues(MSLane* const lane, const double length, const bool doAdd) const {
347  return new MSLaneMeanDataValues(lane, length, doAdd, this);
348 }
349 
350 
351 /****************************************************************************/
#define DEBUG_COND
#define STEPS2TIME(x)
Definition: SUMOTime.h:53
#define TS
Definition: SUMOTime.h:40
#define SIMTIME
Definition: SUMOTime.h:60
long long int SUMOTime
Definition: SUMOTime.h:31
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_WAITINGTIME
@ SUMO_ATTR_OVERLAPTRAVELTIME
@ SUMO_ATTR_LANECHANGEDFROM
@ SUMO_ATTR_TRAVELTIME
@ SUMO_ATTR_ARRIVED
@ SUMO_ATTR_LANECHANGEDTO
@ SUMO_ATTR_TIMELOSS
@ SUMO_ATTR_VAPORIZED
@ SUMO_ATTR_OCCUPANCY
@ SUMO_ATTR_ENTERED
@ SUMO_ATTR_DEPARTED
@ SUMO_ATTR_LANEDENSITY
@ SUMO_ATTR_DENSITY
@ SUMO_ATTR_LEFT
const double INVALID_DOUBLE
Definition: StdDefs.h:62
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:29
T MIN2(T a, T b)
Definition: StdDefs.h:73
T MAX2(T a, T b)
Definition: StdDefs.h:79
A scoped lock which only triggers on condition.
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the maximum speed the vehicle may use on this edge.
Definition: MSEdge.cpp:931
static bool gUseMesoSim
Definition: MSGlobals.h:88
static int gNumSimThreads
how many threads to use for simulation
Definition: MSGlobals.h:115
Representation of a lane in the micro simulation.
Definition: MSLane.h:82
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Definition: MSLane.h:517
Data structure for mean (aggregated) edge/lane values.
Definition: MSMeanData.h:66
double travelledDistance
The sum of the distances the vehicles travelled.
Definition: MSMeanData.h:181
Data structure for mean (aggregated) edge/lane values.
bool notifyLeave(SUMOTrafficObject &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Called if the vehicle leaves the reminder's lane.
double frontTravelledDistance
The travelled distance regarding the vehicle front.
void addTo(MSMeanData::MeanDataValues &val) const
Add the values of this to the given one and store them there.
int nVehLaneChangeTo
The number of vehicles that changed to this lane.
int nVehVaporized
The number of vehicles that left this lane within the sample interval.
double minimalVehicleLength
minimal vehicle length in the current interval (used to determine a maximal density,...
bool isEmpty() const
Returns whether any data was collected.
bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Computes current values and adds them to their sums.
MSLaneMeanDataValues(MSLane *const lane, const double length, const bool doAdd, const MSMeanData_Net *parent)
Constructor.
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)
Internal notification about the vehicle moves.
int nVehLeft
The number of vehicles that left this lane within the sample interval.
int nVehLaneChangeFrom
The number of vehicles that changed from this lane.
double timeLoss
The time loss accrued by vehicle probes.
double frontSampleSeconds
The number of vehicle probes regarding the vehicle front.
void write(OutputDevice &dev, long long int attributeMask, const SUMOTime period, const double numLanes, const double defaultTravelTime, const int numVehicles=-1) const
Writes output values into the given stream.
int nVehArrived
The number of vehicles that finished on the lane.
double waitSeconds
The number of vehicle probes with small speed.
virtual ~MSLaneMeanDataValues()
Destructor.
double occupationSum
The sum of the occupation of the lane.
int nVehEntered
The number of vehicles that entered this lane within the sample interval.
double vehLengthSum
The sum of the lengths the vehicles had.
void reset(bool afterWrite=false)
Resets values so they may be used for the next interval.
Network state mean data collector for edges/lanes.
virtual ~MSMeanData_Net()
Destructor.
MSMeanData_Net(const std::string &id, const SUMOTime dumpBegin, const SUMOTime dumpEnd, const bool useLanes, const bool withEmpty, const bool printDefaults, const bool withInternal, const bool trackVehicles, const int detectPersons, const double maxTravelTime, const double minSamples, const double haltSpeed, const std::string &vTypes, const std::string &writeAttributes)
Constructor.
MSMeanData::MeanDataValues * createValues(MSLane *const lane, const double length, const bool doAdd) const
Create an instance of MeanDataValues.
const double myHaltSpeed
the minimum sample seconds
Data collector for edges/lanes.
Definition: MSMeanData.h:57
Notification
Definition of a vehicle state.
@ NOTIFICATION_ARRIVED
The vehicle arrived at its destination (is deleted)
@ NOTIFICATION_DEPARTED
The vehicle has departed (was inserted into the network)
@ NOTIFICATION_SEGMENT
The vehicle changes the segment (meso only)
@ NOTIFICATION_LANE_CHANGE
The vehicle changes lanes (micro only)
@ NOTIFICATION_JUNCTION
The vehicle arrived at a junction.
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
double getLength() const
Get vehicle's length [m].
const std::string & getID() const
Returns the id.
Definition: Named.h:73
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:60
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
Representation of a vehicle, person, or container.
virtual bool isVehicle() const
Whether it is a vehicle.
virtual bool isStopped() const =0
Returns whether the object is at a stop.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual const MSLane * getLane() const =0
Returns the lane the object is currently at.
virtual const MSEdge * getEdge() const =0
Returns the edge the object is currently at.