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>
45#include <mesosim/MELoop.h>
46#include <mesosim/MESegment.h>
47#include <mesosim/MEVehicle.h>
52
53#define HAS_NOT_LEFT_DETECTOR -1
54
55//#define DEBUG_E1_NOTIFY_MOVE
56
57#define DEBUG_COND (true)
58//#define DEBUG_COND (isSelected())
59//#define DEBUG_COND (getID()=="")
60
61// ===========================================================================
62// method definitions
63// ===========================================================================
64MSInductLoop::MSInductLoop(const std::string& id, MSLane* const lane,
65 double positionInMeters,
66 double length, std::string name,
67 const std::string& vTypes,
68 const std::string& nextEdges,
69 int detectPersons,
70 const bool needLocking) :
71 MSMoveReminder(id, lane),
72 MSDetectorFileOutput(id, vTypes, nextEdges, detectPersons),
73 myName(name),
74 myPosition(positionInMeters),
75 myEndPosition(myPosition + length),
76 myNeedLock(needLocking || MSGlobals::gNumSimThreads > 1),
77 // initialize in a way which doesn't impact actualted traffic lights at simulation start (yet doesn't look ugly in the outputs)
78 myLastLeaveTime(-3600),
79 myOverrideTime(-1),
80 myOverrideEntryTime(-1),
81 myVehicleDataCont(),
82 myVehiclesOnDet(),
83 myLastIntervalEnd(-1),
84 mySegment(nullptr) {
85 assert(length >= 0);
86 assert(myPosition >= 0 && myEndPosition <= myLane->getLength());
87 reset();
89 // used by actuated tls
93 }
94}
95
96
99
100
101void
103#ifdef HAVE_FOX
104 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
105#endif
108 myVehicleDataCont.clear();
111}
112
113
114bool
115MSInductLoop::notifyEnter(SUMOTrafficObject& veh, Notification reason, const MSLane* /* enteredLane */) {
116 // vehicles must be kept if the "inductionloop" wants to detect passeengers
117 if (!vehicleApplies(veh) && (veh.isPerson() || myDetectPersons <= (int)PersonMode::WALK)) {
118 return false;
119 }
121 MEVehicle* mesoveh = dynamic_cast<MEVehicle*>(&veh);
122 assert(mesoveh != nullptr);
123 const MESegment* seg = mesoveh->getSegment();
124 if (seg != nullptr && (seg->numQueues() == 1 || mesoveh->getQueIndex() == myLane->getIndex())) {
125 const SUMOTime onSegTime = mesoveh->getEventTime() - mesoveh->getLastEntryTime();
126 // extrapolate movement
127 const SUMOTime exLeaveTime = mesoveh->getLastEntryTime() + (SUMOTime)((double)onSegTime * mySegmentPos / seg->getLength());
128 //std::cout << SIMTIME << " det=" << getID() << " veh=" << veh.getID() << " entry=" << STEPS2TIME(mesoveh->getLastEntryTime()) << " et=" << STEPS2TIME(mesoveh->getEventTime()) << " exLeaveTime=" << STEPS2TIME(exLeaveTime) << "\n";
129 myNextMesoLeaveTimes.push(exLeaveTime);
130 }
131 return true;
132 }
133 if (reason != NOTIFICATION_JUNCTION) { // the junction case is handled in notifyMove
135 return false;
136 }
137 if (veh.getPositionOnLane() >= myPosition) {
138#ifdef HAVE_FOX
139 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
140#endif
141 myVehiclesOnDet[&veh] = SIMTIME;
143 }
144 }
145 return true;
146}
147
148
149bool
151 double newPos, double newSpeed) {
152 if (newPos < myPosition) {
153 // detector not reached yet
154 return true;
155 }
156 if (myDetectPersons > (int)PersonMode::WALK && !veh.isPerson()) {
157 bool keep = false;
158 MSBaseVehicle& v = dynamic_cast<MSBaseVehicle&>(veh);
159 for (MSTransportable* p : v.getPersons()) {
160 keep = notifyMove(*p, oldPos, newPos, newSpeed);
161 }
162 return keep;
163 }
164#ifdef HAVE_FOX
165 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
166#endif
167 const double oldSpeed = veh.getPreviousSpeed();
168 if (newPos >= myPosition && oldPos < myPosition) {
169 // entered the detector by move
170 const double timeBeforeEnter = MSCFModel::passingTime(oldPos, myPosition, newPos, oldSpeed, newSpeed);
171 myVehiclesOnDet[&veh] = SIMTIME + timeBeforeEnter;
173#ifdef DEBUG_E1_NOTIFY_MOVE
174 if (DEBUG_COND) {
175 std::cout << SIMTIME << " det=" << getID() << " enteredVeh=" << veh.getID() << "\n";
176 }
177#endif
178 }
179 double oldBackPos = oldPos - veh.getVehicleType().getLength();
180 double newBackPos = newPos - veh.getVehicleType().getLength();
181 if (newBackPos > myEndPosition) {
182 // vehicle passed the detector (it may have changed onto this lane somewhere past the detector)
183 // assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed > 0 || myVehiclesOnDet.find(&veh) == myVehiclesOnDet.end());
184 // assertion is invalid in case of teleportation
185 if (oldBackPos <= myEndPosition) {
186 const std::map<SUMOTrafficObject*, double>::iterator it = myVehiclesOnDet.find(&veh);
187 if (it != myVehiclesOnDet.end()) {
188 const double entryTime = it->second;
189 const double leaveTime = SIMTIME + MSCFModel::passingTime(oldBackPos, myEndPosition, newBackPos, oldSpeed, newSpeed);
190 myVehiclesOnDet.erase(it);
191 assert(entryTime <= leaveTime);
192 myVehicleDataCont.push_back(VehicleData(veh, entryTime, leaveTime, false, myEndPosition - myPosition));
193 myLastLeaveTime = leaveTime;
194#ifdef DEBUG_E1_NOTIFY_MOVE
195 if (DEBUG_COND) {
196 std::cout << SIMTIME << " det=" << getID() << " leftVeh=" << veh.getID() << " oldBackPos=" << oldBackPos << " newBackPos=" << newBackPos << "\n";
197 }
198#endif
199 } else {
200#ifdef DEBUG_E1_NOTIFY_MOVE
201 if (DEBUG_COND) {
202 std::cout << SIMTIME << " det=" << getID() << " leftVeh=" << veh.getID() << " oldBackPos=" << oldBackPos << " newBackPos=" << newBackPos << " (notFound)\n";
203 }
204#endif
205 }
206 } else {
207 // vehicle is already beyond the detector...
208 // This can happen even if it is still registered in myVehiclesOnDet, e.g., after teleport.
209 myVehiclesOnDet.erase(&veh);
210#ifdef DEBUG_E1_NOTIFY_MOVE
211 if (DEBUG_COND) {
212 std::cout << SIMTIME << " det=" << getID() << " leftVeh=" << veh.getID() << " oldBackPos=" << oldBackPos << " newBackPos=" << newBackPos << " (unusual)\n";
213 }
214#endif
215 }
216 return false;
217 }
218 // vehicle stays on the detector
219 return true;
220}
221
222
223bool
224MSInductLoop::notifyLeave(SUMOTrafficObject& veh, double lastPos, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
225 if (veh.isPerson() && myDetectPersons != (int)PersonMode::NONE) {
226 const int lastDir = lastPos < 0 ? MSPModel::BACKWARD : MSPModel::FORWARD;
227 notifyMovePerson(dynamic_cast<MSTransportable*>(&veh), lastDir, lastPos);
228 }
230 MEVehicle* mesoveh = dynamic_cast<MEVehicle*>(&veh);
231 assert(mesoveh != nullptr);
232 const MESegment* seg = mesoveh->getSegment();
233 if (seg != nullptr && (seg->numQueues() == 1 || mesoveh->getQueIndex() == myLane->getIndex())) {
234 // interpolate movement + 1 extra second
235 // We can only interpolate the passing time at the detector after the vehicle leaves the segment. Consequently our information is always out of date
236 // (by the time the current vehicle left, the follower vehicle should already have reached the detector so the estimated time gap to the last detection is always too large)
237 // the prior implementation used seg->getBlockTime() which included the headway which somewhat worked around this deficit by accident
238 const SUMOTime inLeaveTime = mesoveh->getEventTime() - TIME2STEPS((seg->getLength() - mySegmentPos - mesoveh->getLength()) / myLane->getSpeedLimit());
239 //std::cout << SIMTIME << " det=" << getID() << " veh=" << veh.getID() << " et=" << STEPS2TIME(mesoveh->getEventTime()) << " inLeaveTime=" << STEPS2TIME(inLeaveTime) << "\n";
240 auto q = seg->getQueue(mesoveh->getQueIndex());
241 if (q.size() > 1 && vehicleApplies(*q[q.size() - 2])) {
242 myLastMesoLeaveTimes.push(inLeaveTime + TIME2STEPS(seg->getLastHeadwaySeconds()));
243 //std::cout << " inLeaveTime2=" << (STEPS2TIME(inLeaveTime) + seg->getLastHeadwaySeconds()) << "\n";
244 }
245 myLastMesoLeaveTimes.push(inLeaveTime);
247 }
248 return false;
249 }
251#ifdef HAVE_FOX
252 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
253#endif
254 const std::map<SUMOTrafficObject*, double>::iterator it = myVehiclesOnDet.find(&veh);
255 if (it != myVehiclesOnDet.end()) {
256 const double entryTime = it->second;
257 const double leaveTime = SIMTIME + TS;
258 myVehiclesOnDet.erase(it);
259 myVehicleDataCont.push_back(VehicleData(veh, entryTime, leaveTime, true));
260 myLastLeaveTime = leaveTime;
261 }
262 return false;
263 }
264 return true;
265}
266
267
268double
269MSInductLoop::getSpeed(const int offset) const {
270 const std::vector<VehicleData>& d = collectVehiclesOnDet(SIMSTEP - offset);
271 return d.empty() ? -1. : std::accumulate(d.begin(), d.end(), 0.0, speedSum) / (double) d.size();
272}
273
274
275double
276MSInductLoop::getVehicleLength(const int offset) const {
277 const std::vector<VehicleData>& d = collectVehiclesOnDet(SIMSTEP - offset);
278 return d.empty() ? -1. : std::accumulate(d.begin(), d.end(), 0.0, lengthSum) / (double)d.size();
279}
280
281
282double
284 if (myOverrideTime >= 0) {
285 return myOverrideTime < TS ? (TS - myOverrideTime) / TS * 100 : 0;
286 }
287 const SUMOTime tbeg = SIMSTEP - DELTA_T;
288 double occupancy = 0;
289 const double csecond = SIMTIME;
290 for (const VehicleData& i : collectVehiclesOnDet(tbeg, false, false, true)) {
291 const double leaveTime = i.leaveTimeM == HAS_NOT_LEFT_DETECTOR ? csecond : MIN2(i.leaveTimeM, csecond);
292 const double entryTime = MAX2(i.entryTimeM, STEPS2TIME(tbeg));
293 occupancy += MIN2(leaveTime - entryTime, TS);
294 }
295 return occupancy / TS * 100.;
296}
297
298
299double
300MSInductLoop::getEnteredNumber(const int offset) const {
301 if (myOverrideTime >= 0) {
302 return myOverrideTime < TS ? 1 : 0;
303 }
304 return (double)collectVehiclesOnDet(SIMSTEP - offset, true, true).size();
305}
306
307
308std::vector<std::string>
309MSInductLoop::getVehicleIDs(const int offset) const {
310 std::vector<std::string> ret;
311 for (const VehicleData& i : collectVehiclesOnDet(SIMSTEP - offset, true, true)) {
312 ret.push_back(i.idM);
313 }
314 return ret;
315}
316
317
318double
320 if (myOverrideTime >= 0) {
321 return myOverrideTime;
322 }
323 if (myVehiclesOnDet.size() != 0) {
324 // detector is occupied
325 return 0;
326 }
328 //std::cout << SIMTIME << " det=" << getID() << " qBefore=" << myNextMesoLeaveTimes.size() << " last=" << STEPS2TIME(getLastDetectionTime()) << " qAfter=" << myNextMesoLeaveTimes.size() << " top=" << (myNextMesoLeaveTimes.empty() ? -1 : myNextMesoLeaveTimes.top()) << "\n";
330 }
331 return SIMTIME - myLastLeaveTime;
332}
333
334
335void
339
340
341double
343#ifdef HAVE_FOX
344 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
345#endif
346 if (myOverrideTime >= 0) {
348 }
349 if (myVehiclesOnDet.size() == 0) {
350 // detector is unoccupied
351 return 0;
352 } else {
353 double minEntry = std::numeric_limits<double>::max();
354 for (const auto& i : myVehiclesOnDet) {
355 minEntry = MIN2(i.second, minEntry);
356 }
357 return SIMTIME - minEntry;
358 }
359}
360
361
362double
364#ifdef HAVE_FOX
365 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
366#endif
368 double result = -INVALID_DOUBLE;
369 for (const auto& item : collectVehiclesOnDet(SIMSTEP - DELTA_T)) {
370 SUMOVehicle* v = vc.getVehicle(item.idM);
371 if (v != nullptr) {
372 MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(v);
373 double ad = veh->getStopArrivalDelay();
374 if (ad != INVALID_DOUBLE) {
375 result = MAX2(result, ad);
376 }
377 }
378 }
379 return result;
380}
381
382
383void
385 // discard times in the past except for the latest one
386 SUMOTime last = tq.top();
387 if (tq.size() > 1) {
388 tq.pop();
389 while (tq.size() > 0 && tq.top() < now) {
390 last = tq.top();
391 tq.pop();
392 }
393 tq.push(last);
394 }
395}
396
397
400 if (myOverrideTime >= 0) {
402 }
403 if (myVehiclesOnDet.size() != 0) {
405 }
406 const SUMOTime now = SIMSTEP;
408 && !myNextMesoLeaveTimes.empty()
409 && myNextMesoLeaveTimes.top() < now) {
411 SUMOTime last = myNextMesoLeaveTimes.top();
412 if (!myLastMesoLeaveTimes.empty() && myLastMesoLeaveTimes.top() < now) {
414 last = MAX2(last, myLastMesoLeaveTimes.top());
415 }
416 //std::cout << SIMTIME << " det=" << getID() << " result=" << last << " last=" << myNextMesoLeaveTimes.top() << " last2=" << (myLastMesoLeaveTimes.size() > 0 ? myLastMesoLeaveTimes.top() : -1) << "\n";
417 return last;
418 }
420}
421
422
423double
424MSInductLoop::getIntervalOccupancy(bool lastInterval) const {
425 double occupancy = 0;
426 const double csecond = lastInterval ? STEPS2TIME(myLastIntervalEnd) : SIMTIME;
427 const double aggTime = csecond - STEPS2TIME(lastInterval ? myLastIntervalBegin : myLastIntervalEnd);
428 if (aggTime == 0) {
429 return 0;
430 }
431 for (const VehicleData& i : collectVehiclesOnDet(myLastIntervalEnd, false, false, true, lastInterval)) {
432 const double leaveTime = i.leaveTimeM == HAS_NOT_LEFT_DETECTOR ? csecond : MIN2(i.leaveTimeM, csecond);
433 const double entryTime = MAX2(i.entryTimeM, STEPS2TIME(lastInterval ? myLastIntervalBegin : myLastIntervalEnd));
434 occupancy += MIN2(leaveTime - entryTime, aggTime);
435 }
436 return occupancy / aggTime * 100.;
437}
438
439
440double
441MSInductLoop::getIntervalMeanSpeed(bool lastInterval) const {
442 const std::vector<VehicleData>& d = collectVehiclesOnDet(myLastIntervalEnd, false, false, false, lastInterval);
443 return d.empty() ? -1. : std::accumulate(d.begin(), d.end(), 0.0, speedSum) / (double) d.size();
444}
445
446
447int
449 return (int)collectVehiclesOnDet(myLastIntervalEnd, false, false, false, lastInterval).size();
450}
451
452
453std::vector<std::string>
454MSInductLoop::getIntervalVehicleIDs(bool lastInterval) const {
455 std::vector<std::string> ret;
456 for (const VehicleData& i : collectVehiclesOnDet(myLastIntervalEnd, false, false, false, lastInterval)) {
457 ret.push_back(i.idM);
458 }
459 return ret;
460}
461
462
463void
465 myOverrideTime = time;
466 if (time < 0) {
468 } else {
469 const double entryTime = MAX2(0.0, SIMTIME - time);
470 if (myOverrideEntryTime >= 0) {
471 // maintain earlier entry time to achive continous detection
473 } else {
474 myOverrideEntryTime = entryTime;
475 }
476 }
477}
478
479void
481 dev.writeXMLHeader("detector", "det_e1_file.xsd");
482}
483
484
485void
487 if (dev.isNull()) {
488 reset();
489 return;
490 }
491 const double t(STEPS2TIME(stopTime - startTime));
492 double occupancy = 0.;
493 double speedSum = 0.;
494 double lengthSum = 0.;
495 int contrib = 0;
496 // to approximate the space mean speed
497 double inverseSpeedSum = 0.;
498 for (const VehicleData& vData : myVehicleDataCont) {
499 const double timeOnDetDuringInterval = vData.leaveTimeM - MAX2(STEPS2TIME(startTime), vData.entryTimeM);
500 occupancy += MIN2(timeOnDetDuringInterval, t);
501 if (!vData.leftEarlyM) {
502 speedSum += vData.speedM;
503 assert(vData.speedM > 0.);
504 inverseSpeedSum += 1. / vData.speedM;
505 lengthSum += vData.lengthM;
506 contrib++;
507 }
508 }
510 contrib = myEnteredVehicleNumber;
511 }
512 const double flow = (double)contrib / t * 3600.;
513 for (std::map< SUMOTrafficObject*, double >::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
514 occupancy += STEPS2TIME(stopTime) - MAX2(STEPS2TIME(startTime), i->second);
515 }
516 occupancy *= 100. / t;
517 const double meanSpeed = contrib != 0 ? speedSum / (double)contrib : -1;
518 const double harmonicMeanSpeed = contrib != 0 ? (double)contrib / inverseSpeedSum : -1;
519 const double meanLength = contrib != 0 ? lengthSum / (double)contrib : -1;
521 dev.writeAttr(SUMO_ATTR_ID, StringUtils::escapeXML(getID())).writeAttr("nVehContrib", contrib);
522 dev.writeAttr("flow", flow).writeAttr("occupancy", occupancy).writeAttr("speed", meanSpeed).writeAttr("harmonicMeanSpeed", harmonicMeanSpeed);
523 dev.writeAttr("length", meanLength).writeAttr("nVehEntered", myEnteredVehicleNumber).closeTag();
524 reset();
525}
526
527
528void
530 if (myDetectPersons == (int)PersonMode::NONE) {
531 return;
532 }
533 if (myLane->hasPedestrians()) {
534 for (MSTransportable* p : myLane->getEdge().getPersons()) {
535 if (p->getLane() != myLane || !vehicleApplies(*p)) {
536 continue;
537 }
538 notifyMovePerson(p, p->getDirection(), p->getPositionOnLane());
539 }
540 }
541}
542
543
544void
546 if (personApplies(*p, dir)) {
547 const double newSpeed = p->getSpeed();
548 const double newPos = (dir == MSPModel::FORWARD
549 ? pos
550 // position relative to detector
551 : myPosition - (pos - myPosition));
552 const double oldPos = newPos - SPEED2DIST(newSpeed);
553 if (oldPos - p->getVehicleType().getLength() <= myPosition) {
554 notifyMove(*p, oldPos, newPos, newSpeed);
555 }
556 }
557}
558
559
560std::vector<MSInductLoop::VehicleData>
561MSInductLoop::collectVehiclesOnDet(SUMOTime tMS, bool includeEarly, bool leaveTime, bool forOccupancy, bool lastInterval) const {
562#ifdef HAVE_FOX
563 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
564#endif
565 const double t = STEPS2TIME(tMS);
566 std::vector<VehicleData> ret;
567 for (const VehicleData& i : myVehicleDataCont) {
568 if ((includeEarly || !i.leftEarlyM) && (!lastInterval || i.entryTimeM < t)) {
569 if (i.entryTimeM >= t || (leaveTime && i.leaveTimeM >= t)) {
570 ret.push_back(i);
571 }
572 }
573 }
574 for (const VehicleData& i : myLastVehicleDataCont) {
575 if (includeEarly || !i.leftEarlyM) {
576 if ((!lastInterval && (i.entryTimeM >= t || (leaveTime && i.leaveTimeM >= t)))
577 || (lastInterval && i.leaveTimeM <= t + STEPS2TIME(myLastIntervalEnd - myLastIntervalBegin))) { // TODO: check duration of last interval
578 ret.push_back(i);
579 }
580 }
581 }
582 for (const auto& i : myVehiclesOnDet) {
583 if ((!lastInterval && (i.second >= t || leaveTime || forOccupancy))
584 || (lastInterval && i.second < t && t - i.second < STEPS2TIME(DELTA_T))) { // no need to check leave time, they are still on the detector
585 SUMOTrafficObject* const v = i.first;
586 VehicleData d(*v, i.second, HAS_NOT_LEFT_DETECTOR, false);
587 d.speedM = v->getSpeed();
588 ret.push_back(d);
589 }
590 }
591 return ret;
592}
593
594
596 double leaveTimestep, const bool leftEarly, const double detLength)
597 : idM(v.getID()), lengthM(v.getVehicleType().getLength()), entryTimeM(entryTimestep), leaveTimeM(leaveTimestep),
598 speedM((v.getVehicleType().getLength() + detLength) / MAX2(leaveTimestep - entryTimestep, NUMERICAL_EPS)), typeIDM(v.getVehicleType().getID()),
599 leftEarlyM(leftEarly) {}
600
601
602void
610
611/****************************************************************************/
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
const double INVALID_DOUBLE
invalid double
Definition StdDefs.h:68
T MIN2(T a, T b)
Definition StdDefs.h:80
T MAX2(T a, T b)
Definition StdDefs.h:86
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition MELoop.cpp:344
A single mesoscopic segment (cell)
Definition MESegment.h:50
void addDetector(MSMoveReminder *data, int queueIndex=-1)
Adds a data collector for a detector to this segment.
double getLastHeadwaySeconds() const
get the last headway time in seconds
Definition MESegment.h:396
double getLength() const
Returns the length of the segment in meters.
Definition MESegment.h:254
const std::vector< MEVehicle * > & getQueue(int index) const
Returns the cars in the queue with the given index for visualization.
Definition MESegment.h:224
int numQueues() const
return the number of queues
Definition MESegment.h:218
int getIndex() const
Returns the running index of the segment in the edge (0 is the most upstream).
Definition MESegment.h:238
A vehicle from the mesoscopic point of view.
Definition MEVehicle.h:42
SUMOTime getLastEntryTime() const
Returns the time the vehicle entered the current segment.
Definition MEVehicle.h:277
MESegment * getSegment() const
Returns the current segment the vehicle is on.
Definition MEVehicle.h:246
int getQueIndex() const
Returns the index of the que the vehicle is in.
Definition MEVehicle.h:255
SUMOTime getEventTime() const
Returns the (planned) time at which the vehicle leaves its current segment.
Definition MEVehicle.h:215
The base class for microscopic and mesoscopic vehicles.
const std::vector< MSTransportable * > & getPersons() const
retrieve riding persons
double getLength() const
Returns the vehicle's length.
virtual double getStopArrivalDelay() const
Returns the estimated public transport stop arrival delay in seconds.
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
static bool gUseMesoSim
Definition MSGlobals.h:106
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition MSGlobals.h:115
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.
std::priority_queue< SUMOTime, std::vector< SUMOTime >, std::greater< SUMOTime > > TimeQueue
helper function for managing meso timings
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.
MESegment * mySegment
current segment (for actuated tls in meso)
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
static void discardOldTimes(TimeQueue &tq, SUMOTime now)
TimeQueue myLastMesoLeaveTimes
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 getArrivalDelay() const
Returns the maximum stop arrival delay of public transport vehicles that are on the detector or passe...
double getTimeSinceLastDetection() const
Returns the time since the last vehicle left the detector.
double myLastLeaveTime
Leave-time of the last vehicle detected [s].
TimeQueue myNextMesoLeaveTimes
extrapolated leave times for meso vehicle
const bool myNeedLock
whether internals need to be guarded against concurrent access (GUI or multi threading)
double mySegmentPos
position relative to the current segment
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
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition MSLane.h:602
bool hasPedestrians() const
whether the lane has pedestrians on it
Definition MSLane.cpp:4638
int getIndex() const
Returns the lane's index.
Definition MSLane.h:668
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:790
Something on a lane to be noticed about vehicle movement.
Notification
Definition of a vehicle state.
@ NOTIFICATION_SEGMENT
The vehicle changes the segment (meso only)
@ 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
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:402
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.
The class responsible for building and deletion of vehicles.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
double getLength() const
Get vehicle's length [m].
const std::string & getID() const
Returns the id.
Definition Named.h:73
Static storage of an output device and its base (abstract) implementation.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const ATTR_TYPE &attr, const T &val, const bool isNull=false, const bool escape=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.
Representation of a vehicle.
Definition SUMOVehicle.h:63
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].