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-2026 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
286void
290
291
292double
294#ifdef HAVE_FOX
295 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
296#endif
297 if (myOverrideTime >= 0) {
299 }
300 if (myVehiclesOnDet.size() == 0) {
301 // detector is unoccupied
302 return 0;
303 } else {
304 double minEntry = std::numeric_limits<double>::max();
305 for (const auto& i : myVehiclesOnDet) {
306 minEntry = MIN2(i.second, minEntry);
307 }
308 return SIMTIME - minEntry;
309 }
310}
311
312
313
316 if (myOverrideTime >= 0) {
318 }
319 if (myVehiclesOnDet.size() != 0) {
321 }
323}
324
325
326double
327MSInductLoop::getIntervalOccupancy(bool lastInterval) const {
328 double occupancy = 0;
329 const double csecond = lastInterval ? STEPS2TIME(myLastIntervalEnd) : SIMTIME;
330 const double aggTime = csecond - STEPS2TIME(lastInterval ? myLastIntervalBegin : myLastIntervalEnd);
331 if (aggTime == 0) {
332 return 0;
333 }
334 for (const VehicleData& i : collectVehiclesOnDet(myLastIntervalEnd, false, false, true, lastInterval)) {
335 const double leaveTime = i.leaveTimeM == HAS_NOT_LEFT_DETECTOR ? csecond : MIN2(i.leaveTimeM, csecond);
336 const double entryTime = MAX2(i.entryTimeM, STEPS2TIME(lastInterval ? myLastIntervalBegin : myLastIntervalEnd));
337 occupancy += MIN2(leaveTime - entryTime, aggTime);
338 }
339 return occupancy / aggTime * 100.;
340}
341
342
343double
344MSInductLoop::getIntervalMeanSpeed(bool lastInterval) const {
345 const std::vector<VehicleData>& d = collectVehiclesOnDet(myLastIntervalEnd, false, false, false, lastInterval);
346 return d.empty() ? -1. : std::accumulate(d.begin(), d.end(), 0.0, speedSum) / (double) d.size();
347}
348
349
350int
352 return (int)collectVehiclesOnDet(myLastIntervalEnd, false, false, false, lastInterval).size();
353}
354
355
356std::vector<std::string>
357MSInductLoop::getIntervalVehicleIDs(bool lastInterval) const {
358 std::vector<std::string> ret;
359 for (const VehicleData& i : collectVehiclesOnDet(myLastIntervalEnd, false, false, false, lastInterval)) {
360 ret.push_back(i.idM);
361 }
362 return ret;
363}
364
365
366void
368 myOverrideTime = time;
369 if (time < 0) {
371 } else {
372 const double entryTime = MAX2(0.0, SIMTIME - time);
373 if (myOverrideEntryTime >= 0) {
374 // maintain earlier entry time to achive continous detection
376 } else {
377 myOverrideEntryTime = entryTime;
378 }
379 }
380}
381
382void
384 dev.writeXMLHeader("detector", "det_e1_file.xsd");
385}
386
387
388void
390 if (dev.isNull()) {
391 reset();
392 return;
393 }
394 const double t(STEPS2TIME(stopTime - startTime));
395 double occupancy = 0.;
396 double speedSum = 0.;
397 double lengthSum = 0.;
398 int contrib = 0;
399 // to approximate the space mean speed
400 double inverseSpeedSum = 0.;
401 for (const VehicleData& vData : myVehicleDataCont) {
402 const double timeOnDetDuringInterval = vData.leaveTimeM - MAX2(STEPS2TIME(startTime), vData.entryTimeM);
403 occupancy += MIN2(timeOnDetDuringInterval, t);
404 if (!vData.leftEarlyM) {
405 speedSum += vData.speedM;
406 assert(vData.speedM > 0.);
407 inverseSpeedSum += 1. / vData.speedM;
408 lengthSum += vData.lengthM;
409 contrib++;
410 }
411 }
412 const double flow = (double)contrib / t * 3600.;
413 for (std::map< SUMOTrafficObject*, double >::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
414 occupancy += STEPS2TIME(stopTime) - MAX2(STEPS2TIME(startTime), i->second);
415 }
416 occupancy *= 100. / t;
417 const double meanSpeed = contrib != 0 ? speedSum / (double)contrib : -1;
418 const double harmonicMeanSpeed = contrib != 0 ? (double)contrib / inverseSpeedSum : -1;
419 const double meanLength = contrib != 0 ? lengthSum / (double)contrib : -1;
421 dev.writeAttr(SUMO_ATTR_ID, StringUtils::escapeXML(getID())).writeAttr("nVehContrib", contrib);
422 dev.writeAttr("flow", flow).writeAttr("occupancy", occupancy).writeAttr("speed", meanSpeed).writeAttr("harmonicMeanSpeed", harmonicMeanSpeed);
423 dev.writeAttr("length", meanLength).writeAttr("nVehEntered", myEnteredVehicleNumber).closeTag();
424 reset();
425}
426
427
428void
430 if (myDetectPersons == (int)PersonMode::NONE) {
431 return;
432 }
433 if (myLane->hasPedestrians()) {
434 for (MSTransportable* p : myLane->getEdge().getPersons()) {
435 if (p->getLane() != myLane || !vehicleApplies(*p)) {
436 continue;
437 }
438 notifyMovePerson(p, p->getDirection(), p->getPositionOnLane());
439 }
440 }
441}
442
443
444void
446 if (personApplies(*p, dir)) {
447 const double newSpeed = p->getSpeed();
448 const double newPos = (dir == MSPModel::FORWARD
449 ? pos
450 // position relative to detector
451 : myPosition - (pos - myPosition));
452 const double oldPos = newPos - SPEED2DIST(newSpeed);
453 if (oldPos - p->getVehicleType().getLength() <= myPosition) {
454 notifyMove(*p, oldPos, newPos, newSpeed);
455 }
456 }
457}
458
459
460std::vector<MSInductLoop::VehicleData>
461MSInductLoop::collectVehiclesOnDet(SUMOTime tMS, bool includeEarly, bool leaveTime, bool forOccupancy, bool lastInterval) const {
462#ifdef HAVE_FOX
463 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
464#endif
465 const double t = STEPS2TIME(tMS);
466 std::vector<VehicleData> ret;
467 for (const VehicleData& i : myVehicleDataCont) {
468 if ((includeEarly || !i.leftEarlyM) && (!lastInterval || i.entryTimeM < t)) {
469 if (i.entryTimeM >= t || (leaveTime && i.leaveTimeM >= t)) {
470 ret.push_back(i);
471 }
472 }
473 }
474 for (const VehicleData& i : myLastVehicleDataCont) {
475 if (includeEarly || !i.leftEarlyM) {
476 if ((!lastInterval && (i.entryTimeM >= t || (leaveTime && i.leaveTimeM >= t)))
477 || (lastInterval && i.leaveTimeM <= t + STEPS2TIME(myLastIntervalEnd - myLastIntervalBegin))) { // TODO: check duration of last interval
478 ret.push_back(i);
479 }
480 }
481 }
482 for (const auto& i : myVehiclesOnDet) {
483 if ((!lastInterval && (i.second >= t || leaveTime || forOccupancy))
484 || (lastInterval && i.second < t && t - i.second < STEPS2TIME(DELTA_T))) { // no need to check leave time, they are still on the detector
485 SUMOTrafficObject* const v = i.first;
486 VehicleData d(*v, i.second, HAS_NOT_LEFT_DETECTOR, false);
487 d.speedM = v->getSpeed();
488 ret.push_back(d);
489 }
490 }
491 return ret;
492}
493
494
496 double leaveTimestep, const bool leftEarly, const double detLength)
497 : idM(v.getID()), lengthM(v.getVehicleType().getLength()), entryTimeM(entryTimestep), leaveTimeM(leaveTimestep),
498 speedM((v.getVehicleType().getLength() + detLength) / MAX2(leaveTimestep - entryTimestep, NUMERICAL_EPS)), typeIDM(v.getVehicleType().getID()),
499 leftEarlyM(leftEarly) {}
500
501
502void
510
511/****************************************************************************/
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:58
#define SPEED2DIST(x)
Definition SUMOTime.h:48
#define SIMSTEP
Definition SUMOTime.h:64
#define TS
Definition SUMOTime.h:45
#define SIMTIME
Definition SUMOTime.h:65
#define TIME2STEPS(x)
Definition SUMOTime.h:60
@ 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:80
T MAX2(T a, T b)
Definition StdDefs.h:86
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 loadTimeSinceLastDetection(double time)
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:4594
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:775
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:199
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
static const int BACKWARD
Definition MSPModel.h:55
static const int FORWARD
Definition MSPModel.h:54
virtual double getSpeed() const override
the current speed of the transportable
const MSVehicleType & getVehicleType() const override
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 & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const ATTR_TYPE &attr, const T &val, const bool isNull=false)
writes a named attribute
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.
OutputDevice & writeTime(const SumoXMLAttr attr, const SUMOTime val)
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].