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>
54
55#define HAS_NOT_LEFT_DETECTOR -1
56
57//#define DEBUG_E1_NOTIFY_MOVE
58
59#define DEBUG_COND (true)
60//#define DEBUG_COND (isSelected())
61//#define DEBUG_COND (getID()=="")
62
63// ===========================================================================
64// method definitions
65// ===========================================================================
66MSInductLoop::MSInductLoop(const std::string& id, MSLane* const lane,
67 double positionInMeters,
68 double length, std::string name,
69 const std::string& vTypes,
70 const std::string& nextEdges,
71 int detectPersons,
72 const bool needLocking) :
73 MSMoveReminder(id, lane),
74 MSDetectorFileOutput(id, vTypes, nextEdges, detectPersons),
75 myName(name),
76 myPosition(positionInMeters),
77 myEndPosition(myPosition + length),
78 myNeedLock(needLocking || MSGlobals::gNumSimThreads > 1),
79 // initialize in a way which doesn't impact actualted traffic lights at simulation start (yet doesn't look ugly in the outputs)
80 myLastLeaveTime(-3600),
81 myOverrideTime(-1),
82 myOverrideEntryTime(-1),
83 myVehicleDataCont(),
84 myVehiclesOnDet(),
85 myLastIntervalEnd(-1),
86 mySegment(nullptr) {
87 assert(length >= 0);
88 assert(myPosition >= 0 && myEndPosition <= myLane->getLength());
89 reset();
91 // used by actuated tls
95 }
96}
97
98
101
102
103void
105#ifdef HAVE_FOX
106 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
107#endif
110 myVehicleDataCont.clear();
113}
114
115
116bool
117MSInductLoop::notifyEnter(SUMOTrafficObject& veh, Notification reason, const MSLane* /* enteredLane */) {
118 // vehicles must be kept if the "inductionloop" wants to detect passeengers
119 if (!vehicleApplies(veh) && (veh.isPerson() || myDetectPersons <= (int)PersonMode::WALK)) {
120 return false;
121 }
123 MEVehicle* mesoveh = dynamic_cast<MEVehicle*>(&veh);
124 assert(mesoveh != nullptr);
125 const MESegment* seg = mesoveh->getSegment();
126 if (seg != nullptr && (seg->numQueues() == 1 || mesoveh->getQueIndex() == myLane->getIndex())) {
127 const SUMOTime onSegTime = mesoveh->getEventTime() - mesoveh->getLastEntryTime();
128 // extrapolate movement
129 const SUMOTime exLeaveTime = mesoveh->getLastEntryTime() + (SUMOTime)((double)onSegTime * mySegmentPos / seg->getLength());
130 //std::cout << SIMTIME << " det=" << getID() << " veh=" << veh.getID() << " entry=" << STEPS2TIME(mesoveh->getLastEntryTime()) << " et=" << STEPS2TIME(mesoveh->getEventTime()) << " exLeaveTime=" << STEPS2TIME(exLeaveTime) << "\n";
131 myNextMesoLeaveTimes.push(exLeaveTime);
132 }
133 return true;
134 }
135 if (reason != NOTIFICATION_JUNCTION) { // the junction case is handled in notifyMove
137 return false;
138 }
139 if (veh.getPositionOnLane() >= myPosition) {
140#ifdef HAVE_FOX
141 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
142#endif
143 myVehiclesOnDet[&veh] = SIMTIME;
145 }
146 }
147 return true;
148}
149
150
151bool
153 double newPos, double newSpeed) {
154 if (newPos < myPosition) {
155 // detector not reached yet
156 return true;
157 }
158 if (myDetectPersons > (int)PersonMode::WALK && !veh.isPerson()) {
159 bool keep = false;
160 MSBaseVehicle& v = dynamic_cast<MSBaseVehicle&>(veh);
161 for (MSTransportable* p : v.getPersons()) {
162 keep = notifyMove(*p, oldPos, newPos, newSpeed);
163 }
164 return keep;
165 }
166#ifdef HAVE_FOX
167 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
168#endif
169 const double oldSpeed = veh.getPreviousSpeed();
170 if (newPos >= myPosition && oldPos < myPosition) {
171 // entered the detector by move
172 const double timeBeforeEnter = MSCFModel::passingTime(oldPos, myPosition, newPos, oldSpeed, newSpeed);
173 myVehiclesOnDet[&veh] = SIMTIME + timeBeforeEnter;
175#ifdef DEBUG_E1_NOTIFY_MOVE
176 if (DEBUG_COND) {
177 std::cout << SIMTIME << " det=" << getID() << " enteredVeh=" << veh.getID() << "\n";
178 }
179#endif
180 }
181 double oldBackPos = oldPos - veh.getVehicleType().getLength();
182 double newBackPos = newPos - veh.getVehicleType().getLength();
183 if (newBackPos > myEndPosition) {
184 // vehicle passed the detector (it may have changed onto this lane somewhere past the detector)
185 // assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed > 0 || myVehiclesOnDet.find(&veh) == myVehiclesOnDet.end());
186 // assertion is invalid in case of teleportation
187 if (oldBackPos <= myEndPosition) {
188 const std::map<SUMOTrafficObject*, double>::iterator it = myVehiclesOnDet.find(&veh);
189 if (it != myVehiclesOnDet.end()) {
190 const double entryTime = it->second;
191 const double leaveTime = SIMTIME + MSCFModel::passingTime(oldBackPos, myEndPosition, newBackPos, oldSpeed, newSpeed);
192 myVehiclesOnDet.erase(it);
193 assert(entryTime <= leaveTime);
194 myVehicleDataCont.push_back(VehicleData(veh, entryTime, leaveTime, false, myEndPosition - myPosition));
195 myLastLeaveTime = leaveTime;
196#ifdef DEBUG_E1_NOTIFY_MOVE
197 if (DEBUG_COND) {
198 std::cout << SIMTIME << " det=" << getID() << " leftVeh=" << veh.getID() << " oldBackPos=" << oldBackPos << " newBackPos=" << newBackPos << "\n";
199 }
200#endif
201 } else {
202#ifdef DEBUG_E1_NOTIFY_MOVE
203 if (DEBUG_COND) {
204 std::cout << SIMTIME << " det=" << getID() << " leftVeh=" << veh.getID() << " oldBackPos=" << oldBackPos << " newBackPos=" << newBackPos << " (notFound)\n";
205 }
206#endif
207 }
208 } else {
209 // vehicle is already beyond the detector...
210 // This can happen even if it is still registered in myVehiclesOnDet, e.g., after teleport.
211 myVehiclesOnDet.erase(&veh);
212#ifdef DEBUG_E1_NOTIFY_MOVE
213 if (DEBUG_COND) {
214 std::cout << SIMTIME << " det=" << getID() << " leftVeh=" << veh.getID() << " oldBackPos=" << oldBackPos << " newBackPos=" << newBackPos << " (unusual)\n";
215 }
216#endif
217 }
218 return false;
219 }
220 // vehicle stays on the detector
221 return true;
222}
223
224
225bool
226MSInductLoop::notifyLeave(SUMOTrafficObject& veh, double lastPos, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
227 if (veh.isPerson() && myDetectPersons != (int)PersonMode::NONE) {
228 const int lastDir = lastPos < 0 ? MSPModel::BACKWARD : MSPModel::FORWARD;
229 notifyMovePerson(dynamic_cast<MSTransportable*>(&veh), lastDir, lastPos);
230 }
232 MEVehicle* mesoveh = dynamic_cast<MEVehicle*>(&veh);
233 assert(mesoveh != nullptr);
234 const MESegment* seg = mesoveh->getSegment();
235 if (seg != nullptr && (seg->numQueues() == 1 || mesoveh->getQueIndex() == myLane->getIndex())) {
236 // interpolate movement + 1 extra second
237 // We can only interpolate the passing time at the detector after the vehicle leaves the segment. Consequently our information is always out of date
238 // (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)
239 // the prior implementation used seg->getBlockTime() which included the headway which somewhat worked around this deficit by accident
240 const SUMOTime inLeaveTime = mesoveh->getEventTime() - TIME2STEPS((seg->getLength() - mySegmentPos - mesoveh->getLength()) / myLane->getSpeedLimit());
241 //std::cout << SIMTIME << " det=" << getID() << " veh=" << veh.getID() << " et=" << STEPS2TIME(mesoveh->getEventTime()) << " inLeaveTime=" << STEPS2TIME(inLeaveTime) << "\n";
242 auto q = seg->getQueue(mesoveh->getQueIndex());
243 if (q.size() > 1 && vehicleApplies(*q[q.size() - 2])) {
244 myLastMesoLeaveTimes.push(inLeaveTime + TIME2STEPS(seg->getLastHeadwaySeconds()));
245 //std::cout << " inLeaveTime2=" << (STEPS2TIME(inLeaveTime) + seg->getLastHeadwaySeconds()) << "\n";
246 }
247 myLastMesoLeaveTimes.push(inLeaveTime);
249 }
250 return false;
251 }
253#ifdef HAVE_FOX
254 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
255#endif
256 const std::map<SUMOTrafficObject*, double>::iterator it = myVehiclesOnDet.find(&veh);
257 if (it != myVehiclesOnDet.end()) {
258 const double entryTime = it->second;
259 const double leaveTime = SIMTIME + TS;
260 myVehiclesOnDet.erase(it);
261 myVehicleDataCont.push_back(VehicleData(veh, entryTime, leaveTime, true));
262 myLastLeaveTime = leaveTime;
263 }
264 return false;
265 }
266 return true;
267}
268
269
270double
271MSInductLoop::getSpeed(const int offset) const {
272 const std::vector<VehicleData>& d = collectVehiclesOnDet(SIMSTEP - offset);
273 return d.empty() ? -1. : std::accumulate(d.begin(), d.end(), 0.0, speedSum) / (double) d.size();
274}
275
276
277double
278MSInductLoop::getVehicleLength(const int offset) const {
279 const std::vector<VehicleData>& d = collectVehiclesOnDet(SIMSTEP - offset);
280 return d.empty() ? -1. : std::accumulate(d.begin(), d.end(), 0.0, lengthSum) / (double)d.size();
281}
282
283
284double
286 if (myOverrideTime >= 0) {
287 return myOverrideTime < TS ? (TS - myOverrideTime) / TS * 100 : 0;
288 }
289 const SUMOTime tbeg = SIMSTEP - DELTA_T;
290 double occupancy = 0;
291 const double csecond = SIMTIME;
292 for (const VehicleData& i : collectVehiclesOnDet(tbeg, false, false, true)) {
293 const double leaveTime = i.leaveTimeM == HAS_NOT_LEFT_DETECTOR ? csecond : MIN2(i.leaveTimeM, csecond);
294 const double entryTime = MAX2(i.entryTimeM, STEPS2TIME(tbeg));
295 occupancy += MIN2(leaveTime - entryTime, TS);
296 }
297 return occupancy / TS * 100.;
298}
299
300
301double
302MSInductLoop::getEnteredNumber(const int offset) const {
303 if (myOverrideTime >= 0) {
304 return myOverrideTime < TS ? 1 : 0;
305 }
306 return (double)collectVehiclesOnDet(SIMSTEP - offset, true, true).size();
307}
308
309
310std::vector<std::string>
311MSInductLoop::getVehicleIDs(const int offset) const {
312 std::vector<std::string> ret;
313 for (const VehicleData& i : collectVehiclesOnDet(SIMSTEP - offset, true, true)) {
314 ret.push_back(i.idM);
315 }
316 return ret;
317}
318
319
320double
322 if (myOverrideTime >= 0) {
323 return myOverrideTime;
324 }
325 if (myVehiclesOnDet.size() != 0) {
326 // detector is occupied
327 return 0;
328 }
330 //std::cout << SIMTIME << " det=" << getID() << " qBefore=" << myNextMesoLeaveTimes.size() << " last=" << STEPS2TIME(getLastDetectionTime()) << " qAfter=" << myNextMesoLeaveTimes.size() << " top=" << (myNextMesoLeaveTimes.empty() ? -1 : myNextMesoLeaveTimes.top()) << "\n";
332 }
333 return SIMTIME - myLastLeaveTime;
334}
335
336
337void
342 if (mySegment != nullptr) {
345 // used for the next detection when a vehicle leaves the segment
346 out.writeAttr(SUMO_ATTR_HEADWAY, toString<SUMOTime>(mySegment->getLastHeadway()));
347 }
348 out.closeTag();
349}
350
351
352void
354 bool ok = true;
355 myLastLeaveTime = attrs.get<double>(SUMO_ATTR_TIME, getID().c_str(), ok) - STEPS2TIME(offset);
356 if (mySegment != nullptr) {
357 for (const std::string& t : StringTokenizer(attrs.getString(SUMO_ATTR_NEXT)).getVector()) {
359 }
360 for (const std::string& t : StringTokenizer(attrs.getString(SUMO_ATTR_LAST)).getVector()) {
362 }
364 }
365}
366
367
368double
370#ifdef HAVE_FOX
371 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
372#endif
373 if (myOverrideTime >= 0) {
375 }
376 if (myVehiclesOnDet.size() == 0) {
377 // detector is unoccupied
378 return 0;
379 } else {
380 double minEntry = std::numeric_limits<double>::max();
381 for (const auto& i : myVehiclesOnDet) {
382 minEntry = MIN2(i.second, minEntry);
383 }
384 return SIMTIME - minEntry;
385 }
386}
387
388
389double
391#ifdef HAVE_FOX
392 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
393#endif
395 double result = -INVALID_DOUBLE;
396 for (const auto& item : collectVehiclesOnDet(SIMSTEP - DELTA_T)) {
397 SUMOVehicle* v = vc.getVehicle(item.idM);
398 if (v != nullptr) {
399 MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(v);
400 double ad = veh->getStopArrivalDelay();
401 if (ad != INVALID_DOUBLE) {
402 result = MAX2(result, ad);
403 }
404 }
405 }
406 return result;
407}
408
409
410void
412 // discard times in the past except for the latest one
413 SUMOTime last = tq.top();
414 if (tq.size() > 1) {
415 tq.pop();
416 while (tq.size() > 0 && tq.top() < now) {
417 last = tq.top();
418 tq.pop();
419 }
420 tq.push(last);
421 }
422}
423
424
425std::vector<SUMOTime>
427 std::vector<SUMOTime> result;
428 if (!tq.empty()) {
429 // the next query discards them anyway
430 discardOldTimes(tq, now);
431 }
432 while (!tq.empty()) {
433 result.push_back(tq.top());
434 tq.pop();
435 }
436 return result;
437}
438
439
442 if (myOverrideTime >= 0) {
444 }
445 if (myVehiclesOnDet.size() != 0) {
447 }
448 const SUMOTime now = SIMSTEP;
450 && !myNextMesoLeaveTimes.empty()
451 && myNextMesoLeaveTimes.top() < now) {
453 SUMOTime last = myNextMesoLeaveTimes.top();
454 if (!myLastMesoLeaveTimes.empty() && myLastMesoLeaveTimes.top() < now) {
456 last = MAX2(last, myLastMesoLeaveTimes.top());
457 }
458 //std::cout << SIMTIME << " det=" << getID() << " result=" << last << " last=" << myNextMesoLeaveTimes.top() << " last2=" << (myLastMesoLeaveTimes.size() > 0 ? myLastMesoLeaveTimes.top() : -1) << "\n";
459 return last;
460 }
462}
463
464
465double
466MSInductLoop::getIntervalOccupancy(bool lastInterval) const {
467 double occupancy = 0;
468 const double csecond = lastInterval ? STEPS2TIME(myLastIntervalEnd) : SIMTIME;
469 const double aggTime = csecond - STEPS2TIME(lastInterval ? myLastIntervalBegin : myLastIntervalEnd);
470 if (aggTime == 0) {
471 return 0;
472 }
473 for (const VehicleData& i : collectVehiclesOnDet(myLastIntervalEnd, false, false, true, lastInterval)) {
474 const double leaveTime = i.leaveTimeM == HAS_NOT_LEFT_DETECTOR ? csecond : MIN2(i.leaveTimeM, csecond);
475 const double entryTime = MAX2(i.entryTimeM, STEPS2TIME(lastInterval ? myLastIntervalBegin : myLastIntervalEnd));
476 occupancy += MIN2(leaveTime - entryTime, aggTime);
477 }
478 return occupancy / aggTime * 100.;
479}
480
481
482double
483MSInductLoop::getIntervalMeanSpeed(bool lastInterval) const {
484 const std::vector<VehicleData>& d = collectVehiclesOnDet(myLastIntervalEnd, false, false, false, lastInterval);
485 return d.empty() ? -1. : std::accumulate(d.begin(), d.end(), 0.0, speedSum) / (double) d.size();
486}
487
488
489int
491 return (int)collectVehiclesOnDet(myLastIntervalEnd, false, false, false, lastInterval).size();
492}
493
494
495std::vector<std::string>
496MSInductLoop::getIntervalVehicleIDs(bool lastInterval) const {
497 std::vector<std::string> ret;
498 for (const VehicleData& i : collectVehiclesOnDet(myLastIntervalEnd, false, false, false, lastInterval)) {
499 ret.push_back(i.idM);
500 }
501 return ret;
502}
503
504
505void
507 myOverrideTime = time;
508 if (time < 0) {
510 } else {
511 const double entryTime = MAX2(0.0, SIMTIME - time);
512 if (myOverrideEntryTime >= 0) {
513 // maintain earlier entry time to achive continous detection
515 } else {
516 myOverrideEntryTime = entryTime;
517 }
518 }
519}
520
521void
523 dev.writeXMLHeader("detector", "det_e1_file.xsd");
524}
525
526
527void
529 if (dev.isNull()) {
530 reset();
531 return;
532 }
533 const double t(STEPS2TIME(stopTime - startTime));
534 double occupancy = 0.;
535 double speedSum = 0.;
536 double lengthSum = 0.;
537 int contrib = 0;
538 // to approximate the space mean speed
539 double inverseSpeedSum = 0.;
540 for (const VehicleData& vData : myVehicleDataCont) {
541 const double timeOnDetDuringInterval = vData.leaveTimeM - MAX2(STEPS2TIME(startTime), vData.entryTimeM);
542 occupancy += MIN2(timeOnDetDuringInterval, t);
543 if (!vData.leftEarlyM) {
544 speedSum += vData.speedM;
545 assert(vData.speedM > 0.);
546 inverseSpeedSum += 1. / vData.speedM;
547 lengthSum += vData.lengthM;
548 contrib++;
549 }
550 }
552 contrib = myEnteredVehicleNumber;
553 }
554 const double flow = (double)contrib / t * 3600.;
555 for (std::map< SUMOTrafficObject*, double >::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
556 occupancy += STEPS2TIME(stopTime) - MAX2(STEPS2TIME(startTime), i->second);
557 }
558 occupancy *= 100. / t;
559 const double meanSpeed = contrib != 0 ? speedSum / (double)contrib : -1;
560 const double harmonicMeanSpeed = contrib != 0 ? (double)contrib / inverseSpeedSum : -1;
561 const double meanLength = contrib != 0 ? lengthSum / (double)contrib : -1;
563 dev.writeAttr(SUMO_ATTR_ID, StringUtils::escapeXML(getID())).writeAttr("nVehContrib", contrib);
564 dev.writeAttr("flow", flow).writeAttr("occupancy", occupancy).writeAttr("speed", meanSpeed).writeAttr("harmonicMeanSpeed", harmonicMeanSpeed);
565 dev.writeAttr("length", meanLength).writeAttr("nVehEntered", myEnteredVehicleNumber).closeTag();
566 reset();
567}
568
569
570void
572 if (myDetectPersons == (int)PersonMode::NONE) {
573 return;
574 }
575 if (myLane->hasPedestrians()) {
576 for (MSTransportable* p : myLane->getEdge().getPersons()) {
577 if (p->getLane() != myLane || !vehicleApplies(*p)) {
578 continue;
579 }
580 notifyMovePerson(p, p->getDirection(), p->getPositionOnLane());
581 }
582 }
583}
584
585
586void
588 if (personApplies(*p, dir)) {
589 const double newSpeed = p->getSpeed();
590 const double newPos = (dir == MSPModel::FORWARD
591 ? pos
592 // position relative to detector
593 : myPosition - (pos - myPosition));
594 const double oldPos = newPos - SPEED2DIST(newSpeed);
595 if (oldPos - p->getVehicleType().getLength() <= myPosition) {
596 notifyMove(*p, oldPos, newPos, newSpeed);
597 }
598 }
599}
600
601
602std::vector<MSInductLoop::VehicleData>
603MSInductLoop::collectVehiclesOnDet(SUMOTime tMS, bool includeEarly, bool leaveTime, bool forOccupancy, bool lastInterval) const {
604#ifdef HAVE_FOX
605 ScopedLocker<> lock(myNotificationMutex, myNeedLock);
606#endif
607 const double t = STEPS2TIME(tMS);
608 std::vector<VehicleData> ret;
609 for (const VehicleData& i : myVehicleDataCont) {
610 if ((includeEarly || !i.leftEarlyM) && (!lastInterval || i.entryTimeM < t)) {
611 if (i.entryTimeM >= t || (leaveTime && i.leaveTimeM >= t)) {
612 ret.push_back(i);
613 }
614 }
615 }
616 for (const VehicleData& i : myLastVehicleDataCont) {
617 if (includeEarly || !i.leftEarlyM) {
618 if ((!lastInterval && (i.entryTimeM >= t || (leaveTime && i.leaveTimeM >= t)))
619 || (lastInterval && i.leaveTimeM <= t + STEPS2TIME(myLastIntervalEnd - myLastIntervalBegin))) { // TODO: check duration of last interval
620 ret.push_back(i);
621 }
622 }
623 }
624 for (const auto& i : myVehiclesOnDet) {
625 if ((!lastInterval && (i.second >= t || leaveTime || forOccupancy))
626 || (lastInterval && i.second < t && t - i.second < STEPS2TIME(DELTA_T))) { // no need to check leave time, they are still on the detector
627 SUMOTrafficObject* const v = i.first;
628 VehicleData d(*v, i.second, HAS_NOT_LEFT_DETECTOR, false);
629 d.speedM = v->getSpeed();
630 ret.push_back(d);
631 }
632 }
633 return ret;
634}
635
636
638 double leaveTimestep, const bool leftEarly, const double detLength)
639 : idM(v.getID()), lengthM(v.getVehicleType().getLength()), entryTimeM(entryTimestep), leaveTimeM(leaveTimestep),
640 speedM((v.getVehicleType().getLength() + detLength) / MAX2(leaveTimestep - entryTimestep, NUMERICAL_EPS)), typeIDM(v.getVehicleType().getID()),
641 leftEarlyM(leftEarly) {}
642
643
644void
654
655/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define HAS_NOT_LEFT_DETECTOR
SUMOTime DELTA_T
Definition SUMOTime.cpp:39
#define STEPS2TIME(x)
Definition SUMOTime.h:58
#define SPEED2DIST(x)
Definition SUMOTime.h:48
#define SIMSTEP
Definition SUMOTime.h:69
constexpr SUMOTime TIME2STEPS(double x)
Definition SUMOTime.h:60
#define TS
Definition SUMOTime.h:45
#define SIMTIME
Definition SUMOTime.h:70
@ SUMO_TAG_INTERVAL
an aggreagated-output interval
@ SUMO_TAG_INDUCTION_LOOP
alternative tag for e1 detector
@ SUMO_ATTR_LAST
@ SUMO_ATTR_BEGIN
weights: time range begin
@ SUMO_ATTR_NEXT
succesor phase index
@ SUMO_ATTR_HEADWAY
@ SUMO_ATTR_END
weights: time range end
@ SUMO_ATTR_ID
@ SUMO_ATTR_TIME
trigger: the time of the step
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:397
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:403
double getLength() const
Returns the length of the segment in meters.
Definition MESegment.h:261
SUMOTime getLastHeadway() const
get the last headway time
Definition MESegment.h:408
const std::vector< MEVehicle * > & getQueue(int index) const
Returns the cars in the queue with the given index for visualization.
Definition MESegment.h:231
int numQueues() const
return the number of queues
Definition MESegment.h:225
void setLastHeadway(SUMOTime headway)
restores the last headway time (when loading state)
Definition MESegment.h:413
int getIndex() const
Returns the running index of the segment in the edge (0 is the most upstream).
Definition MESegment.h:245
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:290
MESegment * getSegment() const
Returns the current segment the vehicle is on.
Definition MEVehicle.h:259
int getQueIndex() const
Returns the index of the que the vehicle is in.
Definition MEVehicle.h:268
SUMOTime getEventTime() const
Returns the (planned) time at which the vehicle leaves its current segment.
Definition MEVehicle.h:218
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:205
static bool gUseMesoSim
Definition MSGlobals.h:106
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition MSGlobals.h:115
void writeXMLDetectorProlog(OutputDevice &dev) const override
Opens the XML-output using "detector" as root element.
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
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
void loadState(const SUMOSAXAttributes &attrs, const SUMOTime offset) override
Loads the detection state, shifting all times by the given offset.
bool notifyLeave(SUMOTrafficObject &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0) override
Dismisses the vehicle if it is on the detector due to a lane change.
static std::vector< SUMOTime > getTimes(TimeQueue tq, SUMOTime now)
bool notifyEnter(SUMOTrafficObject &veh, Notification reason, const MSLane *enteredLane=0) override
Checks whether the reminder is activated by a vehicle entering the lane.
static void discardOldTimes(TimeQueue &tq, SUMOTime now)
TimeQueue myLastMesoLeaveTimes
void detectorUpdate(const SUMOTime step) override
Updates the detector (computes values) only used when detecting persons.
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
void writeXMLOutput(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime) override
Writes collected values into the given stream.
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.
bool notifyMove(SUMOTrafficObject &veh, double oldPos, double newPos, double newSpeed) override
Checks whether the vehicle shall be counted and/or shall still touch this MSMoveReminder.
void saveState(OutputDevice &out) const override
Saves the time of the last detection and the pending meso detections.
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)
virtual void reset() override
Resets all generated values to allow computation of next interval.
double mySegmentPos
position relative to the current segment
double getIntervalMeanSpeed(bool lastInterval=false) const
virtual void clearState(SUMOTime time) override
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
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:4670
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:201
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)
Encapsulated SAX-Attributes.
virtual std::string getString(int id, bool *isPresent=nullptr) const =0
Returns the string-value of the named (by its enum-value) attribute.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
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.
std::vector< std::string > getVector()
return vector of strings
static long long int toLong(const std::string &sData)
converts a string into the long value described by it by calling the char-type converter,...
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].