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-2022 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 #ifdef HAVE_FOX
26 #endif
27 #include <utils/common/SUMOTime.h>
28 #include <utils/common/ToString.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() == "31to211_0")
47 #define DEBUG_COND (false)
48 
49 
50 // ===========================================================================
51 // method definitions
52 // ===========================================================================
53 // ---------------------------------------------------------------------------
54 // MSMeanData_Net::MSLaneMeanDataValues - methods
55 // ---------------------------------------------------------------------------
57  const double length,
58  const bool doAdd,
59  const MSMeanData_Net* parent)
60  : MSMeanData::MeanDataValues(lane, length, doAdd, parent),
61  nVehDeparted(0), nVehArrived(0), nVehEntered(0), nVehLeft(0),
62  nVehVaporized(0), nVehTeleported(0), waitSeconds(0), timeLoss(0),
63  nVehLaneChangeFrom(0), nVehLaneChangeTo(0),
64  frontSampleSeconds(0), frontTravelledDistance(0),
65  vehLengthSum(0), occupationSum(0),
66  minimalVehicleLength(INVALID_DOUBLE),
67  myParent(parent) {}
68 
69 
71 }
72 
73 
74 void
76  nVehDeparted = 0;
77  nVehArrived = 0;
78  nVehEntered = 0;
79  nVehLeft = 0;
80  nVehVaporized = 0;
81  nVehTeleported = 0;
82  nVehLaneChangeFrom = 0;
83  nVehLaneChangeTo = 0;
84  sampleSeconds = 0.;
85  travelledDistance = 0;
86  waitSeconds = 0;
87  timeLoss = 0;
88  frontSampleSeconds = 0;
89  frontTravelledDistance = 0;
90  vehLengthSum = 0;
91  occupationSum = 0;
92  minimalVehicleLength = INVALID_DOUBLE;
93 }
94 
95 
96 void
99  v.nVehDeparted += nVehDeparted;
100  v.nVehArrived += nVehArrived;
101  v.nVehEntered += nVehEntered;
102  v.nVehLeft += nVehLeft;
103  v.nVehVaporized += nVehVaporized;
104  v.nVehTeleported += nVehTeleported;
105  v.nVehLaneChangeFrom += nVehLaneChangeFrom;
106  v.nVehLaneChangeTo += nVehLaneChangeTo;
107  v.sampleSeconds += sampleSeconds;
108  v.travelledDistance += travelledDistance;
109  v.waitSeconds += waitSeconds;
110  v.timeLoss += timeLoss;
111  v.frontSampleSeconds += frontSampleSeconds;
112  v.frontTravelledDistance += frontTravelledDistance;
113  v.vehLengthSum += vehLengthSum;
114  v.occupationSum += occupationSum;
116  v.minimalVehicleLength = minimalVehicleLength;
117  } else {
118  v.minimalVehicleLength = MIN2(minimalVehicleLength, v.minimalVehicleLength);
119  }
120 }
121 
122 
123 void
125  const SUMOTrafficObject& veh, const double frontOnLane,
126  const double timeOnLane, const double /* meanSpeedFrontOnLane */,
127  const double meanSpeedVehicleOnLane,
128  const double travelledDistanceFrontOnLane,
129  const double travelledDistanceVehicleOnLane,
130  const double meanLengthOnLane) {
131 #ifdef DEBUG_OCCUPANCY
132  if (DEBUG_COND) {
133  std::cout << SIMTIME << "\n MSMeanData_Net::MSLaneMeanDataValues::notifyMoveInternal()\n"
134  << " veh '" << veh.getID() << "' on lane '" << veh.getLane()->getID() << "'"
135  << ", timeOnLane=" << timeOnLane
136  << ", meanSpeedVehicleOnLane=" << meanSpeedVehicleOnLane
137  << ",\ntravelledDistanceFrontOnLane=" << travelledDistanceFrontOnLane
138  << ", travelledDistanceVehicleOnLane=" << travelledDistanceVehicleOnLane
139  << ", meanLengthOnLane=" << meanLengthOnLane
140  << std::endl;
141  }
142 #endif
143  if (myParent != nullptr && !myParent->vehicleApplies(veh)) {
144  return;
145  }
146  sampleSeconds += timeOnLane;
147  travelledDistance += travelledDistanceVehicleOnLane;
148  vehLengthSum += veh.getVehicleType().getLength() * timeOnLane;
150  // For the mesosim case no information on whether the vehicle was occupying
151  // the lane with its whole length is available. We assume the whole length
152  // Therefore this increment is taken out with more information on the vehicle movement.
153  occupationSum += veh.getVehicleType().getLength() * timeOnLane;
154  } else {
155  // for the microsim case more elaborate calculation of the average length on the lane,
156  // is taken out in notifyMove(), refs #153
157  occupationSum += meanLengthOnLane * TS;
158  }
159  if (!veh.isStopped()) {
160  if (myParent != nullptr && meanSpeedVehicleOnLane < myParent->myHaltSpeed) {
161  waitSeconds += timeOnLane;
162  }
163  const double vmax = veh.getLane() == nullptr ? veh.getEdge()->getVehicleMaxSpeed(&veh) : veh.getLane()->getVehicleMaxSpeed(&veh);
164  if (vmax > 0) {
165  timeLoss += timeOnLane * MAX2(0.0, vmax - meanSpeedVehicleOnLane) / vmax;
166  }
167  }
168  frontSampleSeconds += frontOnLane;
169  frontTravelledDistance += travelledDistanceFrontOnLane;
170  if (minimalVehicleLength == INVALID_DOUBLE) {
171  minimalVehicleLength = veh.getVehicleType().getLengthWithGap();
172  } else {
173  minimalVehicleLength = MIN2(minimalVehicleLength, veh.getVehicleType().getLengthWithGap());
174  }
175 #ifdef DEBUG_OCCUPANCY2
176  // refs #3265
177  std::cout << SIMTIME << "ID: " << getDescription() << " minVehicleLength=" << minimalVehicleLength << std::endl;
178 #endif
179 }
180 
181 
182 bool
184  if ((myParent == nullptr || myParent->vehicleApplies(veh)) && (
185  getLane() == nullptr || !veh.isVehicle() || getLane() == static_cast<MSVehicle&>(veh).getLane())) {
186 #ifdef HAVE_FOX
187  ScopedLocker<> lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
188 #endif
190  removeFromVehicleUpdateValues(veh);
191  }
192  if (reason == MSMoveReminder::NOTIFICATION_ARRIVED) {
193  ++nVehArrived;
194  } else if (reason == MSMoveReminder::NOTIFICATION_LANE_CHANGE) {
195  ++nVehLaneChangeFrom;
196  } else if (myParent == nullptr || reason != MSMoveReminder::NOTIFICATION_SEGMENT) {
197  ++nVehLeft;
199  ++nVehTeleported;
201  ++nVehVaporized;
202  }
203  }
204  }
206  return false;
207  }
208  return reason == MSMoveReminder::NOTIFICATION_JUNCTION;
209 }
210 
211 
212 bool
214 #ifdef DEBUG_NOTIFY_ENTER
215  std::cout << "\n" << SIMTIME << " MSMeanData_Net::MSLaneMeanDataValues: veh '" << veh.getID() << "' enters lane '" << enteredLane->getID() << "'" << std::endl;
216 #else
217  UNUSED_PARAMETER(enteredLane);
218 #endif
219  if (myParent == nullptr || myParent->vehicleApplies(veh)) {
220  if (getLane() == nullptr || !veh.isVehicle() || getLane() == static_cast<MSVehicle&>(veh).getLane()) {
221 #ifdef HAVE_FOX
222  ScopedLocker<> lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
223 #endif
225  ++nVehDeparted;
226  } else if (reason == MSMoveReminder::NOTIFICATION_LANE_CHANGE) {
227  ++nVehLaneChangeTo;
228  } else if (myParent == nullptr || reason != MSMoveReminder::NOTIFICATION_SEGMENT) {
229  ++nVehEntered;
230  }
231  }
232  return true;
233  }
234  return false;
235 }
236 
237 
238 bool
240  return sampleSeconds == 0 && nVehDeparted == 0 && nVehArrived == 0 && nVehEntered == 0
241  && nVehLeft == 0 && nVehVaporized == 0 && nVehTeleported == 0 && nVehLaneChangeFrom == 0 && nVehLaneChangeTo == 0;
242 }
243 
244 
245 void
246 MSMeanData_Net::MSLaneMeanDataValues::write(OutputDevice& dev, long long int attributeMask, const SUMOTime period,
247  const double numLanes, const double speedLimit, const double defaultTravelTime, const int numVehicles) const {
248 
249  const double density = MIN2(sampleSeconds / STEPS2TIME(period) * (double) 1000 / myLaneLength,
250  1000. * numLanes / MAX2(minimalVehicleLength, NUMERICAL_EPS));
251  const double laneDensity = density / numLanes;
252 #ifdef DEBUG_OCCUPANCY2
253  // tests #3264
254  double occupancy = occupationSum / STEPS2TIME(period) / myLaneLength / numLanes * (double) 100;
255  if (occupancy > 100) {
256  std::cout << SIMTIME << " Encountered bad occupancy: " << occupancy
257  << ", myLaneLength=" << myLaneLength << ", period=" << STEPS2TIME(period) << ", occupationSum=" << occupationSum
258  << std::endl;
259  }
260  // refs #3265
261  std::cout << SIMTIME << "ID: " << getDescription() << " minVehicleLength=" << minimalVehicleLength
262  << "\ndensity=" << density << "\n";
263 #endif
264 
265  if (myParent == nullptr) {
266  if (sampleSeconds > 0) {
267  dev.writeOptionalAttr(SUMO_ATTR_DENSITY, density, attributeMask);
268  dev.writeOptionalAttr(SUMO_ATTR_LANEDENSITY, laneDensity, attributeMask);
269  dev.writeOptionalAttr(SUMO_ATTR_OCCUPANCY, occupationSum / STEPS2TIME(period) / myLaneLength / numLanes * (double) 100, attributeMask);
270  dev.writeOptionalAttr(SUMO_ATTR_WAITINGTIME, waitSeconds, attributeMask);
271  dev.writeOptionalAttr(SUMO_ATTR_TIMELOSS, timeLoss, attributeMask);
272  dev.writeOptionalAttr(SUMO_ATTR_SPEED, travelledDistance / sampleSeconds, attributeMask);
273  dev.writeOptionalAttr(SUMO_ATTR_SPEEDREL, speedLimit == 0. ? 0. : travelledDistance / sampleSeconds / speedLimit, attributeMask);
274  }
275  dev.writeOptionalAttr(SUMO_ATTR_DEPARTED, nVehDeparted, attributeMask);
276  dev.writeOptionalAttr(SUMO_ATTR_ARRIVED, nVehArrived, attributeMask);
277  dev.writeOptionalAttr(SUMO_ATTR_ENTERED, nVehEntered, attributeMask);
278  dev.writeOptionalAttr(SUMO_ATTR_LEFT, nVehLeft, attributeMask);
279  if (nVehVaporized > 0) {
280  dev.writeOptionalAttr(SUMO_ATTR_VAPORIZED, nVehVaporized, attributeMask);
281  }
282  if (nVehTeleported > 0) {
283  dev.writeOptionalAttr(SUMO_ATTR_TELEPORTED, nVehTeleported, attributeMask);
284  }
285  dev.closeTag();
286  return;
287  }
288  if (sampleSeconds > myParent->myMinSamples) {
289  double overlapTraveltime = myParent->myMaxTravelTime;
290  if (travelledDistance > 0.f) {
291  // one vehicle has to drive lane length + vehicle length before it has left the lane
292  // thus we need to scale with an extended length, approximated by lane length + average vehicle length
293  overlapTraveltime = MIN2(overlapTraveltime, (myLaneLength + vehLengthSum / sampleSeconds) * sampleSeconds / travelledDistance);
294  }
295  if (numVehicles > 0) {
296  dev.writeOptionalAttr(SUMO_ATTR_TRAVELTIME, sampleSeconds / numVehicles, attributeMask);
297  dev.writeOptionalAttr(SUMO_ATTR_WAITINGTIME, waitSeconds, attributeMask);
298  dev.writeOptionalAttr(SUMO_ATTR_TIMELOSS, timeLoss, attributeMask);
299  dev.writeOptionalAttr(SUMO_ATTR_SPEED, travelledDistance / sampleSeconds, attributeMask);
300  dev.writeOptionalAttr(SUMO_ATTR_SPEEDREL, speedLimit == 0. ? 0. : travelledDistance / sampleSeconds / speedLimit, attributeMask);
301  } else {
302  double traveltime = myParent->myMaxTravelTime;
303  if (frontTravelledDistance > NUMERICAL_EPS) {
304  traveltime = MIN2(traveltime, myLaneLength * frontSampleSeconds / frontTravelledDistance);
305  dev.writeOptionalAttr(SUMO_ATTR_TRAVELTIME, traveltime, attributeMask);
306  } else if (defaultTravelTime >= 0.) {
307  dev.writeOptionalAttr(SUMO_ATTR_TRAVELTIME, defaultTravelTime, attributeMask);
308  }
309  dev.writeOptionalAttr(SUMO_ATTR_OVERLAPTRAVELTIME, overlapTraveltime, attributeMask);
310  dev.writeOptionalAttr(SUMO_ATTR_DENSITY, density, attributeMask);
311  dev.writeOptionalAttr(SUMO_ATTR_LANEDENSITY, laneDensity, attributeMask);
312  dev.writeOptionalAttr(SUMO_ATTR_OCCUPANCY, occupationSum / STEPS2TIME(period) / myLaneLength / numLanes * (double) 100, attributeMask);
313  dev.writeOptionalAttr(SUMO_ATTR_WAITINGTIME, waitSeconds, attributeMask);
314  dev.writeOptionalAttr(SUMO_ATTR_TIMELOSS, timeLoss, attributeMask);
315  dev.writeOptionalAttr(SUMO_ATTR_SPEED, travelledDistance / sampleSeconds, attributeMask);
316  dev.writeOptionalAttr(SUMO_ATTR_SPEEDREL, speedLimit == 0. ? 0. : travelledDistance / sampleSeconds / speedLimit, attributeMask);
317  }
318  } else if (defaultTravelTime >= 0.) {
319  dev.writeOptionalAttr(SUMO_ATTR_TRAVELTIME, defaultTravelTime, attributeMask);
320  dev.writeOptionalAttr(SUMO_ATTR_SPEED, myLaneLength / defaultTravelTime, attributeMask);
321  dev.writeOptionalAttr(SUMO_ATTR_SPEEDREL, speedLimit == 0. ? 0. : myLaneLength / defaultTravelTime / speedLimit, attributeMask);
322  }
323  dev.writeOptionalAttr(SUMO_ATTR_DEPARTED, nVehDeparted, attributeMask);
324  dev.writeOptionalAttr(SUMO_ATTR_ARRIVED, nVehArrived, attributeMask);
325  dev.writeOptionalAttr(SUMO_ATTR_ENTERED, nVehEntered, attributeMask);
326  dev.writeOptionalAttr(SUMO_ATTR_LEFT, nVehLeft, attributeMask);
327  dev.writeOptionalAttr(SUMO_ATTR_LANECHANGEDFROM, nVehLaneChangeFrom, attributeMask);
328  dev.writeOptionalAttr(SUMO_ATTR_LANECHANGEDTO, nVehLaneChangeTo, attributeMask);
329  if (nVehVaporized > 0) {
330  dev.writeOptionalAttr(SUMO_ATTR_VAPORIZED, nVehVaporized, attributeMask);
331  }
332  if (nVehTeleported > 0) {
333  dev.writeOptionalAttr(SUMO_ATTR_TELEPORTED, nVehTeleported, attributeMask);
334  }
335  dev.closeTag();
336 }
337 
338 // ---------------------------------------------------------------------------
339 // MSMeanData_Net - methods
340 // ---------------------------------------------------------------------------
341 MSMeanData_Net::MSMeanData_Net(const std::string& id,
342  const SUMOTime dumpBegin,
343  const SUMOTime dumpEnd, const bool useLanes,
344  const bool withEmpty, const bool printDefaults,
345  const bool withInternal,
346  const bool trackVehicles,
347  const int detectPersons,
348  const double maxTravelTime,
349  const double minSamples,
350  const double haltSpeed,
351  const std::string& vTypes,
352  const std::string& writeAttributes) :
353  MSMeanData(id, dumpBegin, dumpEnd, useLanes, withEmpty, printDefaults,
354  withInternal, trackVehicles, detectPersons, maxTravelTime, minSamples, vTypes, writeAttributes),
355  myHaltSpeed(haltSpeed)
356 { }
357 
358 
360 
361 
363 MSMeanData_Net::createValues(MSLane* const lane, const double length, const bool doAdd) const {
364  return new MSLaneMeanDataValues(lane, length, doAdd, this);
365 }
366 
367 
368 /****************************************************************************/
#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:32
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_WAITINGTIME
@ SUMO_ATTR_OVERLAPTRAVELTIME
@ SUMO_ATTR_LANECHANGEDFROM
@ SUMO_ATTR_TRAVELTIME
@ SUMO_ATTR_SPEEDREL
@ SUMO_ATTR_ARRIVED
@ SUMO_ATTR_TELEPORTED
@ 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:63
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:74
T MAX2(T a, T b)
Definition: StdDefs.h:80
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the maximum speed the vehicle may use on this edge.
Definition: MSEdge.cpp:1002
static bool gUseMesoSim
Definition: MSGlobals.h:94
static int gNumSimThreads
how many threads to use for simulation
Definition: MSGlobals.h:133
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:519
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:173
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 via vaporization 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.
void write(OutputDevice &dev, long long int attributeMask, const SUMOTime period, const double numLanes, const double speedLimit, const double defaultTravelTime, const int numVehicles=-1) const
Writes output values into the given stream.
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.
int nVehTeleported
The number of vehicles that left this lane via teleporting within the sample interval.
double timeLoss
The time loss accrued by vehicle probes.
double frontSampleSeconds
The number of vehicle probes regarding the vehicle front.
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_TELEPORT_ARRIVED
The vehicle was teleported out of the net.
@ NOTIFICATION_VAPORIZED_CALIBRATOR
The vehicle got removed by a calibrator.
@ 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.
@ NOTIFICATION_TELEPORT
The vehicle is being teleported.
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:75
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:74
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & writeOptionalAttr(const SumoXMLAttr attr, const T &val, long long int attributeMask)
writes a named attribute unless filtered
Definition: OutputDevice.h:265
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.
A scoped lock which only triggers on condition.
Definition: ScopedLocker.h:40