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-2024 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/****************************************************************************/
24// An unextended detector measuring at a fixed position on a fixed lane.
25/****************************************************************************/
26#include <config.h>
27
28#include "MSInductLoop.h"
29#include <cassert>
30#include <numeric>
31#include <utility>
32#ifdef HAVE_FOX
34#endif
38#include <microsim/MSLane.h>
39#include <microsim/MSEdge.h>
40#include <microsim/MSVehicle.h>
41#include <microsim/MSNet.h>
48
49#define HAS_NOT_LEFT_DETECTOR -1
50
51//#define DEBUG_E1_NOTIFY_MOVE
52
53#define DEBUG_COND (true)
54//#define DEBUG_COND (isSelected())
55//#define DEBUG_COND (getID()=="")
56
57// ===========================================================================
58// method definitions
59// ===========================================================================
60MSInductLoop::MSInductLoop(const std::string& id, MSLane* const lane,
61 double positionInMeters,
62 double length, std::string name,
63 const std::string& vTypes,
64 const std::string& nextEdges,
65 int detectPersons,
66 const bool needLocking) :
67 MSMoveReminder(id, lane),
68 MSDetectorFileOutput(id, vTypes, nextEdges, detectPersons),
69 myName(name),
70 myPosition(positionInMeters),
71 myEndPosition(myPosition + length),
72 myNeedLock(needLocking || MSGlobals::gNumSimThreads > 1),
73 // initialize in a way which doesn't impact actualted traffic lights at simulation start (yet doesn't look ugly in the outputs)
74 myLastLeaveTime(-3600),
75 myOverrideTime(-1),
76 myOverrideEntryTime(-1),
77 myVehicleDataCont(),
78 myVehiclesOnDet(),
79 myLastIntervalEnd(-1) {
80 assert(length >= 0);
81 assert(myPosition >= 0 && myEndPosition <= myLane->getLength());
82 reset();
83}
84
85
88
89
90void
101
102
103bool
104MSInductLoop::notifyEnter(SUMOTrafficObject& veh, Notification reason, const MSLane* /* enteredLane */) {
105 // vehicles must be kept if the "inductionloop" wants to detect passeengers
106 if (!vehicleApplies(veh) && (veh.isPerson() || myDetectPersons <= (int)PersonMode::WALK)) {
107 return false;
108 }
109 if (reason != NOTIFICATION_JUNCTION) { // the junction case is handled in notifyMove
111 return false;
112 }
113 if (veh.getPositionOnLane() >= myPosition) {
114#ifdef HAVE_FOX
115 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
116#endif
117 myVehiclesOnDet[&veh] = SIMTIME;
119 }
120 }
121 return true;
122}
123
124
125bool
127 double newPos, double newSpeed) {
128 if (newPos < myPosition) {
129 // detector not reached yet
130 return true;
131 }
132 if (myDetectPersons > (int)PersonMode::WALK && !veh.isPerson()) {
133 bool keep = false;
134 MSBaseVehicle& v = dynamic_cast<MSBaseVehicle&>(veh);
135 for (MSTransportable* p : v.getPersons()) {
136 keep = notifyMove(*p, oldPos, newPos, newSpeed);
137 }
138 return keep;
139 }
140#ifdef HAVE_FOX
141 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
142#endif
143 const double oldSpeed = veh.getPreviousSpeed();
144 if (newPos >= myPosition && oldPos < myPosition) {
145 // entered the detector by move
146 const double timeBeforeEnter = MSCFModel::passingTime(oldPos, myPosition, newPos, oldSpeed, newSpeed);
147 myVehiclesOnDet[&veh] = SIMTIME + timeBeforeEnter;
149#ifdef DEBUG_E1_NOTIFY_MOVE
150 if (DEBUG_COND) {
151 std::cout << SIMTIME << " det=" << getID() << " enteredVeh=" << veh.getID() << "\n";
152 }
153#endif
154 }
155 double oldBackPos = oldPos - veh.getVehicleType().getLength();
156 double newBackPos = newPos - veh.getVehicleType().getLength();
157 if (newBackPos > myEndPosition) {
158 // vehicle passed the detector (it may have changed onto this lane somewhere past the detector)
159 // assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed > 0 || myVehiclesOnDet.find(&veh) == myVehiclesOnDet.end());
160 // assertion is invalid in case of teleportation
161 if (oldBackPos <= myEndPosition) {
162 const std::map<SUMOTrafficObject*, double>::iterator it = myVehiclesOnDet.find(&veh);
163 if (it != myVehiclesOnDet.end()) {
164 const double entryTime = it->second;
165 const double leaveTime = SIMTIME + MSCFModel::passingTime(oldBackPos, myEndPosition, newBackPos, oldSpeed, newSpeed);
166 myVehiclesOnDet.erase(it);
167 assert(entryTime <= leaveTime);
168 myVehicleDataCont.push_back(VehicleData(veh, entryTime, leaveTime, false, myEndPosition - myPosition));
169 myLastLeaveTime = leaveTime;
170#ifdef DEBUG_E1_NOTIFY_MOVE
171 if (DEBUG_COND) {
172 std::cout << SIMTIME << " det=" << getID() << " leftVeh=" << veh.getID() << " oldBackPos=" << oldBackPos << " newBackPos=" << newBackPos << "\n";
173 }
174#endif
175 } else {
176#ifdef DEBUG_E1_NOTIFY_MOVE
177 if (DEBUG_COND) {
178 std::cout << SIMTIME << " det=" << getID() << " leftVeh=" << veh.getID() << " oldBackPos=" << oldBackPos << " newBackPos=" << newBackPos << " (notFound)\n";
179 }
180#endif
181 }
182 } else {
183 // vehicle is already beyond the detector...
184 // This can happen even if it is still registered in myVehiclesOnDet, e.g., after teleport.
185 myVehiclesOnDet.erase(&veh);
186#ifdef DEBUG_E1_NOTIFY_MOVE
187 if (DEBUG_COND) {
188 std::cout << SIMTIME << " det=" << getID() << " leftVeh=" << veh.getID() << " oldBackPos=" << oldBackPos << " newBackPos=" << newBackPos << " (unusual)\n";
189 }
190#endif
191 }
192 return false;
193 }
194 // vehicle stays on the detector
195 return true;
196}
197
198
199bool
200MSInductLoop::notifyLeave(SUMOTrafficObject& veh, double lastPos, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
201 if (veh.isPerson() && myDetectPersons != (int)PersonMode::NONE) {
202 const int lastDir = lastPos < 0 ? MSPModel::BACKWARD : MSPModel::FORWARD;
203 notifyMovePerson(dynamic_cast<MSTransportable*>(&veh), lastDir, lastPos);
204 }
206#ifdef HAVE_FOX
207 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
208#endif
209 const std::map<SUMOTrafficObject*, double>::iterator it = myVehiclesOnDet.find(&veh);
210 if (it != myVehiclesOnDet.end()) {
211 const double entryTime = it->second;
212 const double leaveTime = SIMTIME + TS;
213 myVehiclesOnDet.erase(it);
214 myVehicleDataCont.push_back(VehicleData(veh, entryTime, leaveTime, true));
215 myLastLeaveTime = leaveTime;
216 }
217 return false;
218 }
219 return true;
220}
221
222
223double
224MSInductLoop::getSpeed(const int offset) const {
225 const std::vector<VehicleData>& d = collectVehiclesOnDet(SIMSTEP - offset);
226 return d.empty() ? -1. : std::accumulate(d.begin(), d.end(), 0.0, speedSum) / (double) d.size();
227}
228
229
230double
231MSInductLoop::getVehicleLength(const int offset) const {
232 const std::vector<VehicleData>& d = collectVehiclesOnDet(SIMSTEP - offset);
233 return d.empty() ? -1. : std::accumulate(d.begin(), d.end(), 0.0, lengthSum) / (double)d.size();
234}
235
236
237double
239 if (myOverrideTime >= 0) {
240 return myOverrideTime < TS ? (TS - myOverrideTime) / TS * 100 : 0;
241 }
242 const SUMOTime tbeg = SIMSTEP - DELTA_T;
243 double occupancy = 0;
244 const double csecond = SIMTIME;
245 for (const VehicleData& i : collectVehiclesOnDet(tbeg, false, false, true)) {
246 const double leaveTime = i.leaveTimeM == HAS_NOT_LEFT_DETECTOR ? csecond : MIN2(i.leaveTimeM, csecond);
247 const double entryTime = MAX2(i.entryTimeM, STEPS2TIME(tbeg));
248 occupancy += MIN2(leaveTime - entryTime, TS);
249 }
250 return occupancy / TS * 100.;
251}
252
253
254double
255MSInductLoop::getEnteredNumber(const int offset) const {
256 if (myOverrideTime >= 0) {
257 return myOverrideTime < TS ? 1 : 0;
258 }
259 return (double)collectVehiclesOnDet(SIMSTEP - offset, true, true).size();
260}
261
262
263std::vector<std::string>
264MSInductLoop::getVehicleIDs(const int offset) const {
265 std::vector<std::string> ret;
266 for (const VehicleData& i : collectVehiclesOnDet(SIMSTEP - offset, true, true)) {
267 ret.push_back(i.idM);
268 }
269 return ret;
270}
271
272
273double
275 if (myOverrideTime >= 0) {
276 return myOverrideTime;
277 }
278 if (myVehiclesOnDet.size() != 0) {
279 // detector is occupied
280 return 0;
281 }
282 return SIMTIME - myLastLeaveTime;
283}
284
285
286double
288#ifdef HAVE_FOX
289 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
290#endif
291 if (myOverrideTime >= 0) {
293 }
294 if (myVehiclesOnDet.size() == 0) {
295 // detector is unoccupied
296 return 0;
297 } else {
298 double minEntry = std::numeric_limits<double>::max();
299 for (const auto& i : myVehiclesOnDet) {
300 minEntry = MIN2(i.second, minEntry);
301 }
302 return SIMTIME - minEntry;
303 }
304}
305
306
307
310 if (myOverrideTime >= 0) {
312 }
313 if (myVehiclesOnDet.size() != 0) {
315 }
317}
318
319
320double
321MSInductLoop::getIntervalOccupancy(bool lastInterval) const {
322 double occupancy = 0;
323 const double csecond = lastInterval ? STEPS2TIME(myLastIntervalEnd) : SIMTIME;
324 const double aggTime = csecond - STEPS2TIME(lastInterval ? myLastIntervalBegin : myLastIntervalEnd);
325 if (aggTime == 0) {
326 return 0;
327 }
328 for (const VehicleData& i : collectVehiclesOnDet(myLastIntervalEnd, false, false, true, lastInterval)) {
329 const double leaveTime = i.leaveTimeM == HAS_NOT_LEFT_DETECTOR ? csecond : MIN2(i.leaveTimeM, csecond);
330 const double entryTime = MAX2(i.entryTimeM, STEPS2TIME(lastInterval ? myLastIntervalBegin : myLastIntervalEnd));
331 occupancy += MIN2(leaveTime - entryTime, aggTime);
332 }
333 return occupancy / aggTime * 100.;
334}
335
336
337double
338MSInductLoop::getIntervalMeanSpeed(bool lastInterval) const {
339 const std::vector<VehicleData>& d = collectVehiclesOnDet(myLastIntervalEnd, false, false, false, lastInterval);
340 return d.empty() ? -1. : std::accumulate(d.begin(), d.end(), 0.0, speedSum) / (double) d.size();
341}
342
343
344int
346 return (int)collectVehiclesOnDet(myLastIntervalEnd, false, false, false, lastInterval).size();
347}
348
349
350std::vector<std::string>
351MSInductLoop::getIntervalVehicleIDs(bool lastInterval) const {
352 std::vector<std::string> ret;
353 for (const VehicleData& i : collectVehiclesOnDet(myLastIntervalEnd, false, false, false, lastInterval)) {
354 ret.push_back(i.idM);
355 }
356 return ret;
357}
358
359
360void
362 myOverrideTime = time;
363 if (time < 0) {
365 } else {
366 const double entryTime = MAX2(0.0, SIMTIME - time);
367 if (myOverrideEntryTime >= 0) {
368 // maintain earlier entry time to achive continous detection
370 } else {
371 myOverrideEntryTime = entryTime;
372 }
373 }
374}
375
376void
378 dev.writeXMLHeader("detector", "det_e1_file.xsd");
379}
380
381
382void
384 if (dev.isNull()) {
385 reset();
386 return;
387 }
388 const double t(STEPS2TIME(stopTime - startTime));
389 double occupancy = 0.;
390 double speedSum = 0.;
391 double lengthSum = 0.;
392 int contrib = 0;
393 // to approximate the space mean speed
394 double inverseSpeedSum = 0.;
395 for (const VehicleData& vData : myVehicleDataCont) {
396 const double timeOnDetDuringInterval = vData.leaveTimeM - MAX2(STEPS2TIME(startTime), vData.entryTimeM);
397 occupancy += MIN2(timeOnDetDuringInterval, t);
398 if (!vData.leftEarlyM) {
399 speedSum += vData.speedM;
400 assert(vData.speedM > 0.);
401 inverseSpeedSum += 1. / vData.speedM;
402 lengthSum += vData.lengthM;
403 contrib++;
404 }
405 }
406 const double flow = (double)contrib / t * 3600.;
407 for (std::map< SUMOTrafficObject*, double >::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
408 occupancy += STEPS2TIME(stopTime) - MAX2(STEPS2TIME(startTime), i->second);
409 }
410 occupancy *= 100. / t;
411 const double meanSpeed = contrib != 0 ? speedSum / (double)contrib : -1;
412 const double harmonicMeanSpeed = contrib != 0 ? (double)contrib / inverseSpeedSum : -1;
413 const double meanLength = contrib != 0 ? lengthSum / (double)contrib : -1;
415 dev.writeAttr(SUMO_ATTR_ID, StringUtils::escapeXML(getID())).writeAttr("nVehContrib", contrib);
416 dev.writeAttr("flow", flow).writeAttr("occupancy", occupancy).writeAttr("speed", meanSpeed).writeAttr("harmonicMeanSpeed", harmonicMeanSpeed);
417 dev.writeAttr("length", meanLength).writeAttr("nVehEntered", myEnteredVehicleNumber).closeTag();
418 reset();
419}
420
421
422void
424 if (myDetectPersons == (int)PersonMode::NONE) {
425 return;
426 }
427 if (myLane->hasPedestrians()) {
428 for (MSTransportable* p : myLane->getEdge().getPersons()) {
429 if (p->getLane() != myLane || !vehicleApplies(*p)) {
430 continue;
431 }
432 notifyMovePerson(p, p->getDirection(), p->getPositionOnLane());
433 }
434 }
435}
436
437
438void
440 if (personApplies(*p, dir)) {
441 const double newSpeed = p->getSpeed();
442 const double newPos = (dir == MSPModel::FORWARD
443 ? pos
444 // position relative to detector
445 : myPosition - (pos - myPosition));
446 const double oldPos = newPos - SPEED2DIST(newSpeed);
447 if (oldPos - p->getVehicleType().getLength() <= myPosition) {
448 notifyMove(*p, oldPos, newPos, newSpeed);
449 }
450 }
451}
452
453
454std::vector<MSInductLoop::VehicleData>
455MSInductLoop::collectVehiclesOnDet(SUMOTime tMS, bool includeEarly, bool leaveTime, bool forOccupancy, bool lastInterval) const {
456#ifdef HAVE_FOX
457 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
458#endif
459 const double t = STEPS2TIME(tMS);
460 std::vector<VehicleData> ret;
461 for (const VehicleData& i : myVehicleDataCont) {
462 if ((includeEarly || !i.leftEarlyM) && (!lastInterval || i.entryTimeM < t)) {
463 if (i.entryTimeM >= t || (leaveTime && i.leaveTimeM >= t)) {
464 ret.push_back(i);
465 }
466 }
467 }
468 for (const VehicleData& i : myLastVehicleDataCont) {
469 if (includeEarly || !i.leftEarlyM) {
470 if ((!lastInterval && (i.entryTimeM >= t || (leaveTime && i.leaveTimeM >= t)))
471 || (lastInterval && i.leaveTimeM <= t)) {
472 ret.push_back(i);
473 }
474 }
475 }
476 for (const auto& i : myVehiclesOnDet) {
477 if ((!lastInterval && (i.second >= t || leaveTime || forOccupancy))
478 || (lastInterval && i.second < t)) { // no need to check leave time, they are still on the detector
479 SUMOTrafficObject* const v = i.first;
480 VehicleData d(*v, i.second, HAS_NOT_LEFT_DETECTOR, false);
481 d.speedM = v->getSpeed();
482 ret.push_back(d);
483 }
484 }
485 return ret;
486}
487
488
490 double leaveTimestep, const bool leftEarly, const double detLength)
491 : idM(v.getID()), lengthM(v.getVehicleType().getLength()), entryTimeM(entryTimestep), leaveTimeM(leaveTimestep),
492 speedM((v.getVehicleType().getLength() + detLength) / MAX2(leaveTimestep - entryTimestep, NUMERICAL_EPS)), typeIDM(v.getVehicleType().getID()),
493 leftEarlyM(leftEarly) {}
494
495
496void
504
505/****************************************************************************/
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:204
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:4484
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:764
Something on a lane to be noticed about vehicle movement.
Notification
Definition of a vehicle state.
@ NOTIFICATION_JUNCTION
The vehicle arrived at a junction.
MSLane * myLane
Lane on which the reminder works.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:186
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:320
static const int BACKWARD
Definition MSPModel.h:55
static const int FORWARD
Definition MSPModel.h:54
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, const double detLength=0)
Constructor.
double speedM
Speed of the vehicle in [m/s].