Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSInductLoop.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2023 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/****************************************************************************/
23// An unextended detector measuring at a fixed position on a fixed lane.
24/****************************************************************************/
25#include <config.h>
26
27#include "MSInductLoop.h"
28#include <cassert>
29#include <numeric>
30#include <utility>
31#ifdef HAVE_FOX
33#endif
37#include <microsim/MSLane.h>
38#include <microsim/MSEdge.h>
39#include <microsim/MSVehicle.h>
40#include <microsim/MSNet.h>
47
48#define HAS_NOT_LEFT_DETECTOR -1
49
50//#define DEBUG_E1_NOTIFY_MOVE
51
52#define DEBUG_COND (true)
53//#define DEBUG_COND (isSelected())
54//#define DEBUG_COND (getID()=="")
55
56// ===========================================================================
57// method definitions
58// ===========================================================================
59MSInductLoop::MSInductLoop(const std::string& id, MSLane* const lane,
60 double positionInMeters,
61 double length, std::string name,
62 const std::string& vTypes,
63 const std::string& nextEdges,
64 int detectPersons,
65 const bool needLocking) :
66 MSMoveReminder(id, lane),
67 MSDetectorFileOutput(id, vTypes, nextEdges, detectPersons),
68 myName(name),
69 myPosition(positionInMeters),
70 myEndPosition(myPosition + length),
71 myNeedLock(needLocking || MSGlobals::gNumSimThreads > 1),
72 myLastLeaveTime(SIMTIME),
73 myOverrideTime(-1),
74 myOverrideEntryTime(-1),
75 myVehicleDataCont(),
76 myVehiclesOnDet(),
77 myLastIntervalEnd(-1) {
78 assert(length >= 0);
79 assert(myPosition >= 0 && myEndPosition <= myLane->getLength());
80 reset();
81}
82
83
86
87
88void
99
100
101bool
102MSInductLoop::notifyEnter(SUMOTrafficObject& veh, Notification reason, const MSLane* /* enteredLane */) {
103 // vehicles must be kept if the "inductionloop" wants to detect passeengers
104 if (!vehicleApplies(veh) && (veh.isPerson() || myDetectPersons <= (int)PersonMode::WALK)) {
105 return false;
106 }
107 if (reason != NOTIFICATION_JUNCTION) { // the junction case is handled in notifyMove
109 return false;
110 }
111 if (veh.getPositionOnLane() >= myPosition) {
112#ifdef HAVE_FOX
113 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
114#endif
115 myVehiclesOnDet[&veh] = SIMTIME;
117 }
118 }
119 return true;
120}
121
122
123bool
125 double newPos, double newSpeed) {
126 if (newPos < myPosition) {
127 // detector not reached yet
128 return true;
129 }
130 if (myDetectPersons > (int)PersonMode::WALK && !veh.isPerson()) {
131 bool keep = false;
132 MSBaseVehicle& v = dynamic_cast<MSBaseVehicle&>(veh);
133 for (MSTransportable* p : v.getPersons()) {
134 keep = notifyMove(*p, oldPos, newPos, newSpeed);
135 }
136 return keep;
137 }
138#ifdef HAVE_FOX
139 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
140#endif
141 const double oldSpeed = veh.getPreviousSpeed();
142 if (newPos >= myPosition && oldPos < myPosition) {
143 // entered the detector by move
144 const double timeBeforeEnter = MSCFModel::passingTime(oldPos, myPosition, newPos, oldSpeed, newSpeed);
145 myVehiclesOnDet[&veh] = SIMTIME + timeBeforeEnter;
147#ifdef DEBUG_E1_NOTIFY_MOVE
148 if (DEBUG_COND) {
149 std::cout << SIMTIME << " det=" << getID() << " enteredVeh=" << veh.getID() << "\n";
150 }
151#endif
152 }
153 double oldBackPos = oldPos - veh.getVehicleType().getLength();
154 double newBackPos = newPos - veh.getVehicleType().getLength();
155 if (newBackPos > myEndPosition) {
156 // vehicle passed the detector (it may have changed onto this lane somewhere past the detector)
157 // assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed > 0 || myVehiclesOnDet.find(&veh) == myVehiclesOnDet.end());
158 // assertion is invalid in case of teleportation
159 if (oldBackPos <= myEndPosition) {
160 const std::map<SUMOTrafficObject*, double>::iterator it = myVehiclesOnDet.find(&veh);
161 if (it != myVehiclesOnDet.end()) {
162 const double entryTime = it->second;
163 const double leaveTime = SIMTIME + MSCFModel::passingTime(oldBackPos, myEndPosition, newBackPos, oldSpeed, newSpeed);
164 myVehiclesOnDet.erase(it);
165 assert(entryTime <= leaveTime);
166 myVehicleDataCont.push_back(VehicleData(veh, entryTime, leaveTime, false));
167 myLastLeaveTime = leaveTime;
168#ifdef DEBUG_E1_NOTIFY_MOVE
169 if (DEBUG_COND) {
170 std::cout << SIMTIME << " det=" << getID() << " leftVeh=" << veh.getID() << " oldBackPos=" << oldBackPos << " newBackPos=" << newBackPos << "\n";
171 }
172#endif
173 } else {
174#ifdef DEBUG_E1_NOTIFY_MOVE
175 if (DEBUG_COND) {
176 std::cout << SIMTIME << " det=" << getID() << " leftVeh=" << veh.getID() << " oldBackPos=" << oldBackPos << " newBackPos=" << newBackPos << " (notFound)\n";
177 }
178#endif
179 }
180 } else {
181 // vehicle is already beyond the detector...
182 // This can happen even if it is still registered in myVehiclesOnDet, e.g., after teleport.
183 myVehiclesOnDet.erase(&veh);
184#ifdef DEBUG_E1_NOTIFY_MOVE
185 if (DEBUG_COND) {
186 std::cout << SIMTIME << " det=" << getID() << " leftVeh=" << veh.getID() << " oldBackPos=" << oldBackPos << " newBackPos=" << newBackPos << " (unusual)\n";
187 }
188#endif
189 }
190 return false;
191 }
192 // vehicle stays on the detector
193 return true;
194}
195
196
197bool
198MSInductLoop::notifyLeave(SUMOTrafficObject& veh, double lastPos, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
199 if (veh.isPerson() && myDetectPersons != (int)PersonMode::NONE) {
200 const int lastDir = lastPos < 0 ? MSPModel::BACKWARD : MSPModel::FORWARD;
201 notifyMovePerson(dynamic_cast<MSTransportable*>(&veh), lastDir, lastPos);
202 }
204#ifdef HAVE_FOX
205 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
206#endif
207 const std::map<SUMOTrafficObject*, double>::iterator it = myVehiclesOnDet.find(&veh);
208 if (it != myVehiclesOnDet.end()) {
209 const double entryTime = it->second;
210 const double leaveTime = SIMTIME + TS;
211 myVehiclesOnDet.erase(it);
212 myVehicleDataCont.push_back(VehicleData(veh, entryTime, leaveTime, true));
213 myLastLeaveTime = leaveTime;
214 }
215 return false;
216 }
217 return true;
218}
219
220
221double
222MSInductLoop::getSpeed(const int offset) const {
223 const std::vector<VehicleData>& d = collectVehiclesOnDet(SIMSTEP - offset);
224 return d.empty() ? -1. : std::accumulate(d.begin(), d.end(), 0.0, speedSum) / (double) d.size();
225}
226
227
228double
229MSInductLoop::getVehicleLength(const int offset) const {
230 const std::vector<VehicleData>& d = collectVehiclesOnDet(SIMSTEP - offset);
231 return d.empty() ? -1. : std::accumulate(d.begin(), d.end(), 0.0, lengthSum) / (double)d.size();
232}
233
234
235double
237 if (myOverrideTime >= 0) {
238 return myOverrideTime < TS ? (TS - myOverrideTime) / TS * 100 : 0;
239 }
240 const SUMOTime tbeg = SIMSTEP - DELTA_T;
241 double occupancy = 0;
242 const double csecond = SIMTIME;
243 for (const VehicleData& i : collectVehiclesOnDet(tbeg, false, false, true)) {
244 const double leaveTime = i.leaveTimeM == HAS_NOT_LEFT_DETECTOR ? csecond : MIN2(i.leaveTimeM, csecond);
245 const double entryTime = MAX2(i.entryTimeM, STEPS2TIME(tbeg));
246 occupancy += MIN2(leaveTime - entryTime, TS);
247 }
248 return occupancy / TS * 100.;
249}
250
251
252double
253MSInductLoop::getEnteredNumber(const int offset) const {
254 if (myOverrideTime >= 0) {
255 return myOverrideTime < TS ? 1 : 0;
256 }
257 return (double)collectVehiclesOnDet(SIMSTEP - offset, true, true).size();
258}
259
260
261std::vector<std::string>
262MSInductLoop::getVehicleIDs(const int offset) const {
263 std::vector<std::string> ret;
264 for (const VehicleData& i : collectVehiclesOnDet(SIMSTEP - offset, true, true)) {
265 ret.push_back(i.idM);
266 }
267 return ret;
268}
269
270
271double
273 if (myOverrideTime >= 0) {
274 return myOverrideTime;
275 }
276 if (myVehiclesOnDet.size() != 0) {
277 // detector is occupied
278 return 0;
279 }
280 return SIMTIME - myLastLeaveTime;
281}
282
283
284double
286#ifdef HAVE_FOX
287 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
288#endif
289 if (myOverrideTime >= 0) {
291 }
292 if (myVehiclesOnDet.size() == 0) {
293 // detector is unoccupied
294 return 0;
295 } else {
296 double minEntry = std::numeric_limits<double>::max();
297 for (const auto& i : myVehiclesOnDet) {
298 minEntry = MIN2(i.second, minEntry);
299 }
300 return SIMTIME - minEntry;
301 }
302}
303
304
305
308 if (myOverrideTime >= 0) {
310 }
311 if (myVehiclesOnDet.size() != 0) {
313 }
315}
316
317
318double
319MSInductLoop::getIntervalOccupancy(bool lastInterval) const {
320 double occupancy = 0;
321 const double csecond = lastInterval ? STEPS2TIME(myLastIntervalEnd) : SIMTIME;
322 const double aggTime = csecond - STEPS2TIME(lastInterval ? myLastIntervalBegin : myLastIntervalEnd);
323 if (aggTime == 0) {
324 return 0;
325 }
326 for (const VehicleData& i : collectVehiclesOnDet(myLastIntervalEnd, false, false, true, lastInterval)) {
327 const double leaveTime = i.leaveTimeM == HAS_NOT_LEFT_DETECTOR ? csecond : MIN2(i.leaveTimeM, csecond);
328 const double entryTime = MAX2(i.entryTimeM, STEPS2TIME(lastInterval ? myLastIntervalBegin : myLastIntervalEnd));
329 occupancy += MIN2(leaveTime - entryTime, aggTime);
330 }
331 return occupancy / aggTime * 100.;
332}
333
334
335double
336MSInductLoop::getIntervalMeanSpeed(bool lastInterval) const {
337 const std::vector<VehicleData>& d = collectVehiclesOnDet(myLastIntervalEnd, false, false, false, lastInterval);
338 return d.empty() ? -1. : std::accumulate(d.begin(), d.end(), 0.0, speedSum) / (double) d.size();
339}
340
341
342int
344 return (int)collectVehiclesOnDet(myLastIntervalEnd, false, false, false, lastInterval).size();
345}
346
347
348std::vector<std::string>
349MSInductLoop::getIntervalVehicleIDs(bool lastInterval) const {
350 std::vector<std::string> ret;
351 for (const VehicleData& i : collectVehiclesOnDet(myLastIntervalEnd, false, false, false, lastInterval)) {
352 ret.push_back(i.idM);
353 }
354 return ret;
355}
356
357
358void
360 myOverrideTime = time;
361 if (time < 0) {
363 } else {
364 const double entryTime = MAX2(0.0, SIMTIME - time);
365 if (myOverrideEntryTime >= 0) {
366 // maintain earlier entry time to achive continous detection
368 } else {
369 myOverrideEntryTime = entryTime;
370 }
371 }
372}
373
374void
376 dev.writeXMLHeader("detector", "det_e1_file.xsd");
377}
378
379
380void
382 if (dev.isNull()) {
383 reset();
384 return;
385 }
386 const double t(STEPS2TIME(stopTime - startTime));
387 double occupancy = 0.;
388 double speedSum = 0.;
389 double lengthSum = 0.;
390 int contrib = 0;
391 // to approximate the space mean speed
392 double inverseSpeedSum = 0.;
393 for (const VehicleData& vData : myVehicleDataCont) {
394 const double timeOnDetDuringInterval = vData.leaveTimeM - MAX2(STEPS2TIME(startTime), vData.entryTimeM);
395 occupancy += MIN2(timeOnDetDuringInterval, t);
396 if (!vData.leftEarlyM) {
397 speedSum += vData.speedM;
398 assert(vData.speedM > 0.);
399 inverseSpeedSum += 1. / vData.speedM;
400 lengthSum += vData.lengthM;
401 contrib++;
402 }
403 }
404 const double flow = (double)contrib / t * 3600.;
405 for (std::map< SUMOTrafficObject*, double >::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
406 occupancy += STEPS2TIME(stopTime) - MAX2(STEPS2TIME(startTime), i->second);
407 }
408 occupancy *= 100. / t;
409 const double meanSpeed = contrib != 0 ? speedSum / (double)contrib : -1;
410 const double harmonicMeanSpeed = contrib != 0 ? (double)contrib / inverseSpeedSum : -1;
411 const double meanLength = contrib != 0 ? lengthSum / (double)contrib : -1;
413 dev.writeAttr(SUMO_ATTR_ID, StringUtils::escapeXML(getID())).writeAttr("nVehContrib", contrib);
414 dev.writeAttr("flow", flow).writeAttr("occupancy", occupancy).writeAttr("speed", meanSpeed).writeAttr("harmonicMeanSpeed", harmonicMeanSpeed);
415 dev.writeAttr("length", meanLength).writeAttr("nVehEntered", myEnteredVehicleNumber).closeTag();
416 reset();
417}
418
419
420void
422 if (myDetectPersons == (int)PersonMode::NONE) {
423 return;
424 }
425 if (myLane->hasPedestrians()) {
426 for (MSTransportable* p : myLane->getEdge().getPersons()) {
427 if (p->getLane() != myLane || !vehicleApplies(*p)) {
428 continue;
429 }
430 notifyMovePerson(p, p->getDirection(), p->getPositionOnLane());
431 }
432 }
433}
434
435
436void
438 if (personApplies(*p, dir)) {
439 const double newSpeed = p->getSpeed();
440 const double newPos = (dir == MSPModel::FORWARD
441 ? pos
442 // position relative to detector
443 : myPosition - (pos - myPosition));
444 const double oldPos = newPos - SPEED2DIST(newSpeed);
445 if (oldPos - p->getVehicleType().getLength() <= myPosition) {
446 notifyMove(*p, oldPos, newPos, newSpeed);
447 }
448 }
449}
450
451
452std::vector<MSInductLoop::VehicleData>
453MSInductLoop::collectVehiclesOnDet(SUMOTime tMS, bool includeEarly, bool leaveTime, bool forOccupancy, bool lastInterval) const {
454#ifdef HAVE_FOX
455 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
456#endif
457 const double t = STEPS2TIME(tMS);
458 std::vector<VehicleData> ret;
459 for (const VehicleData& i : myVehicleDataCont) {
460 if ((includeEarly || !i.leftEarlyM) && (!lastInterval || i.entryTimeM < t)) {
461 if (i.entryTimeM >= t || (leaveTime && i.leaveTimeM >= t)) {
462 ret.push_back(i);
463 }
464 }
465 }
466 for (const VehicleData& i : myLastVehicleDataCont) {
467 if (includeEarly || !i.leftEarlyM) {
468 if ((!lastInterval && (i.entryTimeM >= t || (leaveTime && i.leaveTimeM >= t)))
469 || (lastInterval && i.leaveTimeM <= t)) {
470 ret.push_back(i);
471 }
472 }
473 }
474 for (const auto& i : myVehiclesOnDet) {
475 if ((!lastInterval && (i.second >= t || leaveTime || forOccupancy))
476 || (lastInterval && i.second < t)) { // no need to check leave time, they are still on the detector
477 SUMOTrafficObject* const v = i.first;
478 VehicleData d(*v, i.second, HAS_NOT_LEFT_DETECTOR, false);
479 d.speedM = v->getSpeed();
480 ret.push_back(d);
481 }
482 }
483 return ret;
484}
485
486
488 double leaveTimestep, const bool leftEarly)
489 : idM(v.getID()), lengthM(v.getVehicleType().getLength()), entryTimeM(entryTimestep), leaveTimeM(leaveTimestep),
490 speedM(v.getVehicleType().getLength() / MAX2(leaveTimestep - entryTimestep, NUMERICAL_EPS)), typeIDM(v.getVehicleType().getID()),
491 leftEarlyM(leftEarly) {}
492
493
494void
502
503/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define HAS_NOT_LEFT_DETECTOR
SUMOTime DELTA_T
Definition SUMOTime.cpp:38
#define STEPS2TIME(x)
Definition SUMOTime.h:55
#define SPEED2DIST(x)
Definition SUMOTime.h:45
#define SIMSTEP
Definition SUMOTime.h:61
#define TS
Definition SUMOTime.h:42
#define SIMTIME
Definition SUMOTime.h:62
#define TIME2STEPS(x)
Definition SUMOTime.h:57
@ SUMO_TAG_INTERVAL
an aggreagated-output interval
@ SUMO_ATTR_BEGIN
weights: time range begin
@ SUMO_ATTR_END
weights: time range end
@ SUMO_ATTR_ID
T MIN2(T a, T b)
Definition StdDefs.h:76
T MAX2(T a, T b)
Definition StdDefs.h:82
The base class for microscopic and mesoscopic vehicles.
const std::vector< MSTransportable * > & getPersons() const
retrieve riding persons
static double passingTime(const double lastPos, const double passedPos, const double currentPos, const double lastSpeed, const double currentSpeed)
Calculates the time at which the position passedPosition has been passed In case of a ballistic updat...
Base of value-generating classes (detectors)
bool vehicleApplies(const SUMOTrafficObject &veh) const
Checks whether the detector measures vehicles of the given type.
const int myDetectPersons
Whether pedestrians shall be detected instead of vehicles.
bool personApplies(const MSTransportable &p, int dir) const
const std::set< MSTransportable *, ComparatorNumericalIdLess > & getPersons() const
Returns this edge's persons set.
Definition MSEdge.h:201
double getOccupancyTime() const
Returns the time of continous occupation by the same vehicle in seconds or 0 if there is no vehicle o...
static double lengthSum(double sumSoFar, const MSInductLoop::VehicleData &data)
Adds up VehicleData::lengthM.
double getOccupancy() const
Returns the current occupancy.
double getIntervalOccupancy(bool lastInterval=false) const
std::vector< std::string > getIntervalVehicleIDs(bool lastInterval=false) const
int myEnteredVehicleNumber
The number of entered vehicles.
double getEnteredNumber(const int offset) const
Returns the number of vehicles that have passed the detector.
int getIntervalVehicleNumber(bool lastInterval=false) const
void writeXMLOutput(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Writes collected values into the given stream.
static double speedSum(double sumSoFar, const MSInductLoop::VehicleData &data)
Adds up VehicleData::speedM.
std::vector< VehicleData > collectVehiclesOnDet(SUMOTime t, bool includeEarly=false, bool leaveTime=false, bool forOccupancy=false, bool lastInterval=false) const
Returns vehicle data for vehicles that have been on the detector starting at the given time.
VehicleDataCont myVehicleDataCont
Data of vehicles that have completely passed the detector.
void overrideTimeSinceDetection(double time)
double myOverrideEntryTime
records the time at which overrideTimeSinceDetection was activated
double getSpeed(const int offset) const
Returns the speed of the vehicle on the detector.
SUMOTime myLastIntervalEnd
std::vector< std::string > getVehicleIDs(const int offset) const
Returns the ids of vehicles that have passed the detector.
double getVehicleLength(const int offset) const
Returns the length of the vehicle on the detector.
SUMOTime myLastIntervalBegin
virtual void reset()
Resets all generated values to allow computation of next interval.
const double myPosition
Detector's position on lane [m].
VehicleDataCont myLastVehicleDataCont
Data of vehicles that have completely passed the detector in the last time interval.
const double myEndPosition
Detector's end position (defaults to myPosition)
~MSInductLoop()
Destructor.
void writeXMLDetectorProlog(OutputDevice &dev) const
Opens the XML-output using "detector" as root element.
void detectorUpdate(const SUMOTime step)
Updates the detector (computes values) only used when detecting persons.
bool notifyMove(SUMOTrafficObject &veh, double oldPos, double newPos, double newSpeed)
Checks whether the vehicle shall be counted and/or shall still touch this MSMoveReminder.
void notifyMovePerson(MSTransportable *p, int dir, double pos)
helper function for mapping person movement
double myOverrideTime
overrides the time since last detection
MSInductLoop(const std::string &id, MSLane *const lane, double positionInMeters, double length, std::string name, const std::string &vTypes, const std::string &nextEdges, int detectPersons, const bool needLocking)
Constructor.
double getTimeSinceLastDetection() const
Returns the time since the last vehicle left the detector.
double myLastLeaveTime
Leave-time of the last vehicle detected [s].
const bool myNeedLock
whether internals need to be guarded against concurrent access (GUI or multi threading)
double getIntervalMeanSpeed(bool lastInterval=false) const
bool notifyEnter(SUMOTrafficObject &veh, Notification reason, const MSLane *enteredLane=0)
Checks whether the reminder is activated by a vehicle entering the lane.
virtual void clearState(SUMOTime time)
Remove all vehicles before quick-loading state.
std::map< SUMOTrafficObject *, double > myVehiclesOnDet
Data for vehicles that have entered the detector (vehicle -> enter time)
SUMOTime getLastDetectionTime() const
return last time a vehicle was on the detector
bool notifyLeave(SUMOTrafficObject &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Dismisses the vehicle if it is on the detector due to a lane change.
Representation of a lane in the micro simulation.
Definition MSLane.h:84
bool hasPedestrians() const
whether the lane has pedestrians on it
Definition MSLane.cpp:4344
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:745
Something on a lane to be noticed about vehicle movement.
MSLane *const myLane
Lane on which the reminder works.
Notification
Definition of a vehicle state.
@ NOTIFICATION_JUNCTION
The vehicle arrived at a junction.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:183
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:322
static const int BACKWARD
Definition MSPModel.h:120
static const int FORWARD
Definition MSPModel.h:119
virtual double getSpeed() const
the current speed of the transportable
const MSVehicleType & getVehicleType() const
Returns the object's "vehicle" type.
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.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
virtual bool isNull()
returns the information whether the device will discard all output
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >(), bool includeConfig=true)
Writes an XML header with optional configuration.
Representation of a vehicle, person, or container.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual double getPreviousSpeed() const =0
Returns the object's previous speed.
virtual double getSpeed() const =0
Returns the object's current speed.
virtual bool isPerson() const
Whether it is a person.
virtual double getBackPositionOnLane(const MSLane *lane) const =0
Get the object's back position along the given lane.
virtual double getPositionOnLane() const =0
Get the object's position along the lane.
A scoped lock which only triggers on condition.
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.
#define DEBUG_COND
Struct to store the data of the counted vehicle internally.
VehicleData(const SUMOTrafficObject &v, double entryTimestep, double leaveTimestep, const bool leftEarly)
Constructor.
double speedM
Speed of the vehicle in [m/s].