Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSE3Collector.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/****************************************************************************/
22// A detector of vehicles passing an area between entry/exit points
23/****************************************************************************/
24#include <config.h>
25
26#include <algorithm>
27#ifdef HAVE_FOX
29#endif
30#include <microsim/MSLane.h>
31#include <microsim/MSEdge.h>
32#include <microsim/MSNet.h>
33#include <microsim/MSVehicle.h>
38#include "MSE3Collector.h"
39
40//#define DEBUG_E3_NOTIFY_MOVE
41//#define DEBUG_E3_NOTIFY_ENTER
42//#define DEBUG_E3_NOTIFY_LEAVE
43//#define DEBUG_E3_DETECTORUPDATE
44
45//#define DEBUG_COND(obj) ((obj.getID() == ""))
46//#define DEBUG_COND_VEH(veh) ((veh).getID() == "")
47//#define DEBUG_COND_VEH(veh) ((veh).isSelected())
48//#define DEBUG_COND(collector) (true)
49//#define DEBUG_COND_VEH(veh) (true)
50
51
52// ===========================================================================
53// method definitions
54// ===========================================================================
55/* -------------------------------------------------------------------------
56 * MSE3Collector::MSE3EntryReminder - definitions
57 * ----------------------------------------------------------------------- */
59 const MSCrossSection& crossSection, MSE3Collector& collector) :
60 MSMoveReminder(collector.getID() + "_entry", crossSection.myLane),
61 myCollector(collector), myPosition(crossSection.myPosition) {
62}
63
64
65bool
67#ifdef DEBUG_E3_NOTIFY_ENTER
68 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
69 std::cout << SIMTIME
70 << " MSE3EntryReminder::notifyEnter() (" << getDescription() << " on lane '" << myLane->getID() << "')"
71 << " vehicle '" << veh.getID() << "'"
72 << " enteredLane=" << enteredLane->getID()
73 << " reason=" << reason
74 << "\n";
75 }
76#endif
77 if (reason != NOTIFICATION_JUNCTION) {
78 const double posOnLane = veh.getBackPositionOnLane(enteredLane) + veh.getVehicleType().getLength();
79 if (myLane == enteredLane && posOnLane > myPosition) {
80#ifdef HAVE_FOX
81 ScopedLocker<> lock(myCollector.myContainerMutex, MSGlobals::gNumSimThreads > 1);
82#endif
83 const auto& itVeh = myCollector.myEnteredContainer.find(&veh);
84 if (itVeh == myCollector.myEnteredContainer.end() ||
85 itVeh->second.entryReminder != this) {
86#ifdef DEBUG_E3_NOTIFY_ENTER
87 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
88 std::cout << " assume already known\n";
89 }
90#endif
91 // if the vehicle changes into a covered section we assume it was already registered on another lane
92 return false;
93 }
94 }
95 }
96 return true;
97}
98
99
100bool
102 double newPos, double newSpeed) {
103#ifdef DEBUG_E3_NOTIFY_MOVE
104 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
105 std::cout << SIMTIME
106 << " MSE3EntryReminder::notifyMove() (" << getDescription() << " on lane '" << myLane->getID() << "')"
107 << " vehicle '" << veh.getID() << "'"
108 << " entered. oldPos=" << oldPos << " newPos=" << newPos << " newSpeed=" << newSpeed
109 << " myPosition=" << myPosition
110 << "\n";
111 }
112#endif
113#ifdef HAVE_FOX
114 ScopedLocker<> lock(myCollector.myContainerMutex, MSGlobals::gNumSimThreads > 1);
115#endif
116 if ((myCollector.myEnteredContainer.find(&veh) == myCollector.myEnteredContainer.end() ||
117 (veh.isPerson() && dynamic_cast<const MSTransportable&>(veh).getDirection() != MSPModel::FORWARD))
118 && newPos > myPosition) {
119 if (oldPos > myPosition) {
120 // was behind the detector already in the last step
121#ifdef DEBUG_E3_NOTIFY_MOVE
122 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
123 std::cout << " already behind, isPerson=" << veh.isPerson() << "\n";
124 }
125#endif
126 return false;
127 } else {
128 if (veh.isVehicle() && &veh.getLane()->getEdge() == &myLane->getEdge() && veh.getLane() != myLane) {
129#ifdef DEBUG_E3_NOTIFY_ENTER
130 std::cout << veh.getID() << " is on the wrong lane\n";
131#endif
132 return true;
133 }
134 // entered in this step
135 const double oldSpeed = veh.getPreviousSpeed();
136 const double entryTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
137 assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the detector otherwise
138 const double timeBeforeEnter = MSCFModel::passingTime(oldPos, myPosition, newPos, oldSpeed, newSpeed);
139 const double fractionTimeOnDet = TS - timeBeforeEnter;
140 myCollector.enter(veh, entryTime - fractionTimeOnDet, fractionTimeOnDet, this);
141#ifdef DEBUG_E3_NOTIFY_MOVE
142 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
143 std::cout << " enter\n";
144 }
145#endif
146 }
147 }
148 return true;
149}
150
151
152bool
154#ifdef DEBUG_E3_NOTIFY_LEAVE
155 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
156 std::cout << SIMTIME
157 << " MSE3EntryReminder::notifyLeave() (" << getDescription() << " on lane '" << myLane->getID() << "')"
158 << " vehicle '" << veh.getID() << "'"
159 << " reason=" << reason
160 << "\n";
161 }
162#endif
164#ifdef HAVE_FOX
165 ScopedLocker<> lock(myCollector.myContainerMutex, MSGlobals::gNumSimThreads > 1);
166#endif
167 if (myCollector.myEnteredContainer.erase(&veh) > 0) {
168 if (!myCollector.myExpectArrival) {
169 WRITE_WARNINGF("Vehicle '%' arrived inside % '%', time=%.", veh.getID(), toString(SUMO_TAG_E3DETECTOR), myCollector.getID(), time2string(SIMSTEP));
170 }
171 }
172 return false;
173 }
174 return true;
175}
176
177
178/* -------------------------------------------------------------------------
179 * MSE3Collector::MSE3LeaveReminder - definitions
180 * ----------------------------------------------------------------------- */
182 const MSCrossSection& crossSection, MSE3Collector& collector) :
183 MSMoveReminder(collector.getID() + "_exit", crossSection.myLane),
184 myCollector(collector), myPosition(crossSection.myPosition) {}
185
186
187bool
189#ifdef DEBUG_E3_NOTIFY_ENTER
190 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
191 std::cout << SIMTIME
192 << " MSE3LeaveReminder::notifyEnter() (" << getDescription() << " on lane '" << myLane->getID() << "')"
193 << " vehicle '" << veh.getID() << "'"
194 << " enteredLane=" << enteredLane->getID()
195 << " reason=" << reason
196 << "\n";
197 }
198#endif
199 // this method does not access containers, so no locking here
200 if (reason != NOTIFICATION_JUNCTION) {
201 const double backPosOnLane = veh.getBackPositionOnLane(enteredLane);
202 if (backPosOnLane > myPosition) {
203 // if the vehicle changes into a covered section we assume it was already registered on another lane
204 // however, if it is not fully past the detector we still need to track it
205#ifdef DEBUG_E3_NOTIFY_ENTER
206 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
207 std::cout << " assume already known\n";
208 }
209#endif
210 return false;
211 }
212 }
213 return true;
214}
215
216
217bool
219 double newPos, double newSpeed) {
220#ifdef DEBUG_E3_NOTIFY_MOVE
221 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
222 std::cout << SIMTIME
223 << " MSE3LeaveReminder::notifyMove() (" << getDescription() << " on lane '" << myLane->getID() << "')"
224 << " vehicle '" << veh.getID() << "'"
225 << " entered. oldPos=" << oldPos << " newPos=" << newPos << " newSpeed=" << newSpeed
226 << " myPosition=" << myPosition
227 << "\n";
228 }
229#endif
230 if (newPos < myPosition) {
231 // crossSection not yet reached
232 return true;
233 }
234#ifdef HAVE_FOX
235 ScopedLocker<> lock(myCollector.myContainerMutex, MSGlobals::gNumSimThreads > 1);
236#endif
237 const double oldSpeed = veh.getPreviousSpeed();
238 if (oldPos < myPosition) {
239 assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the detector otherwise
240 const double timeBeforeLeave = MSCFModel::passingTime(oldPos, myPosition, newPos, oldSpeed, newSpeed);
241// const double leaveTimeFront = SIMTIME - TS + (myPosition - oldPos) / newSpeed;
242 const double leaveTimeFront = SIMTIME - TS + timeBeforeLeave;
243 myCollector.leaveFront(veh, leaveTimeFront);
244#ifdef DEBUG_E3_NOTIFY_MOVE
245 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
246 std::cout << " leaveFront\n";
247 }
248#endif
249 }
250 const double backPos = newPos - veh.getVehicleType().getLength();
251 if (backPos < myPosition) {
252 // crossSection not yet left
253 return true;
254 }
255 // crossSection left
256 const double oldBackPos = oldPos - veh.getVehicleType().getLength();
257 const double leaveStep = SIMTIME;
258 assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the detector otherwise
259 const double timeBeforeLeave = MSCFModel::passingTime(oldBackPos, myPosition, backPos, oldSpeed, newSpeed);
260 myCollector.leave(veh, leaveStep - TS + timeBeforeLeave, timeBeforeLeave);
261#ifdef DEBUG_E3_NOTIFY_MOVE
262 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
263 std::cout << " leave\n";
264 }
265#endif
266 return false;
267}
268
269
270bool
272#ifdef DEBUG_E3_NOTIFY_LEAVE
273 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
274 std::cout << SIMTIME
275 << " MSE3LeaveReminder::notifyLeave() (" << getDescription() << " on lane '" << myLane->getID() << "')"
276 << " vehicle '" << veh.getID() << "'"
277 << " reason=" << reason
278 << "\n";
279 }
280#endif
281 if (reason == MSMoveReminder::NOTIFICATION_LANE_CHANGE && &enteredLane->getEdge() == &myLane->getEdge()) {
282 // keep the detector when changing while still on the exit detector but already on a new lane (#4803)
283#ifdef DEBUG_E3_NOTIFY_LEAVE
284 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
285 std::cout << " remove reminder, keep in container\n";
286 }
287#endif
288 return false;
289 }
290#ifdef HAVE_FOX
291 ScopedLocker<> lock(myCollector.myContainerMutex, MSGlobals::gNumSimThreads > 1);
292#endif
294 WRITE_WARNINGF("Vehicle '%' teleported from % '%'.", veh.getID(), toString(SUMO_TAG_E3DETECTOR), myCollector.getID());
295 myCollector.myEnteredContainer.erase(&veh);
296 return false;
297 }
299 if (myCollector.myEnteredContainer.erase(&veh) > 0) {
300 if (!myCollector.myExpectArrival) {
301 WRITE_WARNINGF("Vehicle '%' arrived inside % '%', time=%.", veh.getID(), toString(SUMO_TAG_E3DETECTOR), myCollector.getID(), time2string(SIMSTEP));
302 }
303 }
304 return false;
305 }
306 return true;
307}
308
309/* -------------------------------------------------------------------------
310 * MSE3Collector - definitions
311 * ----------------------------------------------------------------------- */
312MSE3Collector::MSE3Collector(const std::string& id,
313 const CrossSectionVector& entries,
314 const CrossSectionVector& exits,
315 double haltingSpeedThreshold,
316 SUMOTime haltingTimeThreshold,
317 const std::string name, const std::string& vTypes,
318 const std::string& nextEdges,
319 int detectPersons,
320 bool openEntry, bool expectArrival) :
321 MSDetectorFileOutput(id, vTypes, nextEdges, detectPersons),
322 myName(name),
323 myEntries(entries),
324 myExits(exits),
325 myHaltingTimeThreshold(haltingTimeThreshold), myHaltingSpeedThreshold(haltingSpeedThreshold),
328 myLastResetTime(-1), myOpenEntry(openEntry), myExpectArrival(expectArrival) {
329 // Set MoveReminders to entries and exits
330 for (CrossSectionVectorConstIt crossSec1 = entries.begin(); crossSec1 != entries.end(); ++crossSec1) {
331 myEntryReminders.push_back(new MSE3EntryReminder(*crossSec1, *this));
332 }
333 for (CrossSectionVectorConstIt crossSec2 = exits.begin(); crossSec2 != exits.end(); ++crossSec2) {
334 myLeaveReminders.push_back(new MSE3LeaveReminder(*crossSec2, *this));
335 }
336 reset();
337}
338
339
341 for (std::vector<MSE3EntryReminder*>::iterator i = myEntryReminders.begin(); i != myEntryReminders.end(); ++i) {
342 delete *i;
343 }
344 for (std::vector<MSE3LeaveReminder*>::iterator i = myLeaveReminders.begin(); i != myLeaveReminders.end(); ++i) {
345 delete *i;
346 }
347}
348
349
350void
354
355
356
357void
358MSE3Collector::enter(const SUMOTrafficObject& veh, const double entryTimestep, const double fractionTimeOnDet, MSE3EntryReminder* entryReminder, bool isBackward) {
359 if (myDetectPersons > (int)PersonMode::WALK && !veh.isPerson()) {
360 const MSBaseVehicle& v = dynamic_cast<const MSBaseVehicle&>(veh);
361 for (MSTransportable* p : v.getPersons()) {
362 enter(*p, entryTimestep, fractionTimeOnDet, entryReminder);
363 }
364 return;
365 }
366 if (!vehicleApplies(veh)) {
367 return;
368 }
369 if (veh.isPerson() && !isBackward && dynamic_cast<const MSTransportable&>(veh).getDirection() != MSPModel::FORWARD) {
370 // walking backward over an entry detector means "leaving"
371 // std::cout << veh.getID() << " leave at entryDetector\n";
372 leave(veh, entryTimestep, fractionTimeOnDet, true);
373 return;
374 }
375 if (myEnteredContainer.find(&veh) != myEnteredContainer.end()) {
376 WRITE_WARNINGF("Vehicle '%' reentered % '%', time=%.", veh.getID(), toString(SUMO_TAG_E3DETECTOR), getID(), time2string(SIMSTEP));
377 return;
378 }
379#ifdef DEBUG_E3_NOTIFY_ENTER
380 std::cout << veh.getID() << " enters\n";
381#endif
382 const double speedFraction = veh.getSpeed() * fractionTimeOnDet;
383 E3Values v;
384 v.entryTime = entryTimestep;
385 v.frontLeaveTime = 0;
386 v.backLeaveTime = 0;
387 v.speedSum = speedFraction;
388 v.haltingBegin = veh.getSpeed() < myHaltingSpeedThreshold ? TIME2STEPS(entryTimestep) : -1;
389 v.intervalSpeedSum = entryTimestep >= STEPS2TIME(myLastResetTime) ? speedFraction : 0;
390 v.haltings = 0;
391 v.intervalHaltings = 0;
392 if (veh.getSpeed() < myHaltingSpeedThreshold) {
393 if (TIME2STEPS(fractionTimeOnDet) > myHaltingTimeThreshold) {
394 v.haltings++;
396 }
397 }
398 v.hadUpdate = false;
399 if (!MSGlobals::gUseMesoSim && veh.isVehicle()) {
400 v.timeLoss = dynamic_cast<const MSVehicle&>(veh).getTimeLoss();
402 }
403 v.entryReminder = entryReminder;
404 myEnteredContainer[&veh] = v;
405}
406
407
408void
409MSE3Collector::leaveFront(const SUMOTrafficObject& veh, const double leaveTimestep) {
410 if (myDetectPersons > (int)PersonMode::WALK && !veh.isPerson()) {
411 const MSBaseVehicle& v = dynamic_cast<const MSBaseVehicle&>(veh);
412 for (MSTransportable* p : v.getPersons()) {
413 leaveFront(*p, leaveTimestep);
414 }
415 return;
416 }
417 if (!vehicleApplies(veh)) {
418 return;
419 }
420 if (myEnteredContainer.find(&veh) == myEnteredContainer.end()) {
421 if (!myOpenEntry && veh.isVehicle()) {
422 WRITE_WARNINGF("Vehicle '%' left % '%' without entering it, time=%.", veh.getID(), toString(SUMO_TAG_E3DETECTOR), getID(), time2string(SIMSTEP));
423 }
424 } else {
425 myEnteredContainer[&veh].frontLeaveTime = leaveTimestep;
426 }
427}
428
429
430void
431MSE3Collector::leave(const SUMOTrafficObject& veh, const double leaveTimestep, const double fractionTimeOnDet, bool isBackward) {
432 if (myDetectPersons > (int)PersonMode::WALK && !veh.isPerson()) {
433 const MSBaseVehicle& v = dynamic_cast<const MSBaseVehicle&>(veh);
434 for (MSTransportable* p : v.getPersons()) {
435 leave(*p, leaveTimestep, fractionTimeOnDet);
436 }
437 return;
438 }
439 if (!vehicleApplies(veh)) {
440 return;
441 }
442 if (veh.isPerson() && !isBackward && dynamic_cast<const MSTransportable&>(veh).getDirection() != MSPModel::FORWARD) {
443 // walking backward over an exit detector means "entering"
444 // std::cout << veh.getID() << " enter at exitDetector\n";
445 enter(veh, leaveTimestep, fractionTimeOnDet, nullptr, true);
446 return;
447 }
448 if (myEnteredContainer.find(&veh) == myEnteredContainer.end()) {
449 if (!myOpenEntry && veh.isVehicle()) {
450 WRITE_WARNINGF("Vehicle '%' left % '%' without entering it, time=%.", veh.getID(), toString(SUMO_TAG_E3DETECTOR), getID(), time2string(SIMSTEP));
451 }
452 } else {
453#ifdef DEBUG_E3_NOTIFY_LEAVE
454 std::cout << veh.getID() << " leaves\n";
455#endif
456 E3Values values = myEnteredContainer[&veh];
457 values.backLeaveTime = leaveTimestep;
458 const double speedFraction = veh.getSpeed() * (TS - fractionTimeOnDet);
459 values.speedSum -= speedFraction;
460 values.intervalSpeedSum -= speedFraction;
461 if (MSGlobals::gUseMesoSim || !veh.isVehicle()) {
462 // not yet supported
463 values.timeLoss = 0;
464 if (isBackward) {
465 // leaveFront may not have been called
466 values.frontLeaveTime = leaveTimestep;
467 }
468 } else {
469 // timeLoss was initialized when entering
470 values.timeLoss = dynamic_cast<const MSVehicle&>(veh).getTimeLoss() - values.timeLoss;
471 }
472 myEnteredContainer.erase(&veh);
473 myLeftContainer.push_back(values);
474 }
475}
476
477
478void
480 SUMOTime startTime, SUMOTime stopTime) {
483 // collect values about vehicles that have left the area
484 myLastVehicleSum = (int) myLeftContainer.size();
486 double meanOverlapTravelTime = 0.;
487 double meanSpeed = 0.;
490 for (const E3Values& values : myLeftContainer) {
491 myLastMeanHaltsPerVehicle += (double)values.haltings;
492 myLastMeanTravelTime += values.frontLeaveTime - values.entryTime;
493 const double steps = values.backLeaveTime - values.entryTime;
494 meanOverlapTravelTime += steps;
495 meanSpeed += (values.speedSum / steps);
496 myLastMeanTimeLoss += STEPS2TIME(values.timeLoss);
497 }
499 meanOverlapTravelTime = myLastVehicleSum != 0 ? meanOverlapTravelTime / (double)myLastVehicleSum : -1;
500 meanSpeed = myLastVehicleSum != 0 ? meanSpeed / (double)myLastVehicleSum : -1;
503 // clear container
504 myLeftContainer.clear();
505
506 // collect values about vehicles within the container
507 const int vehicleSumWithin = (int) myEnteredContainer.size();
508 double meanSpeedWithin = 0.;
509 double meanDurationWithin = 0.;
510 double meanHaltsPerVehicleWithin = 0.;
511 double meanIntervalSpeedWithin = 0.;
512 double meanIntervalHaltsPerVehicleWithin = 0.;
513 double meanIntervalDurationWithin = 0.;
514 double meanTimeLossWithin = 0.;
515 for (std::map<const SUMOTrafficObject*, E3Values>::iterator i = myEnteredContainer.begin(); i != myEnteredContainer.end(); ++i) {
516 meanHaltsPerVehicleWithin += (double)(*i).second.haltings;
517 meanIntervalHaltsPerVehicleWithin += (double)(*i).second.intervalHaltings;
518 const double end = (*i).second.backLeaveTime == 0 ? STEPS2TIME(stopTime) : (*i).second.backLeaveTime;
519 const double time = end - (*i).second.entryTime;
520 const double timeWithin = MIN2(time, end - STEPS2TIME(startTime));
521 if (i->second.speedSum > 0.) {
522 meanSpeedWithin += i->second.speedSum / time;
523 }
524 if (i->second.intervalSpeedSum > 0.) {
525 meanIntervalSpeedWithin += i->second.intervalSpeedSum / timeWithin;
526 }
527 meanDurationWithin += time;
528 meanIntervalDurationWithin += timeWithin;
529 // reset interval values
530 (*i).second.intervalHaltings = 0;
531 (*i).second.intervalSpeedSum = 0;
532
533 if (!MSGlobals::gUseMesoSim && i->first->isVehicle()) {
534 const SUMOTime currentTimeLoss = dynamic_cast<const MSVehicle*>(i->first)->getTimeLoss();
535 meanTimeLossWithin += STEPS2TIME(currentTimeLoss - (*i).second.intervalTimeLoss);
536 (*i).second.intervalTimeLoss = currentTimeLoss;
537 }
538 }
539 myLastResetTime = stopTime;
540 meanSpeedWithin = vehicleSumWithin != 0 ? meanSpeedWithin / (double) vehicleSumWithin : -1;
541 meanHaltsPerVehicleWithin = vehicleSumWithin != 0 ? meanHaltsPerVehicleWithin / (double) vehicleSumWithin : -1;
542 meanDurationWithin = vehicleSumWithin != 0 ? meanDurationWithin / (double) vehicleSumWithin : -1;
543 meanIntervalSpeedWithin = vehicleSumWithin != 0 ? meanIntervalSpeedWithin / (double) vehicleSumWithin : -1;
544 meanIntervalHaltsPerVehicleWithin = vehicleSumWithin != 0 ? meanIntervalHaltsPerVehicleWithin / (double) vehicleSumWithin : -1;
545 meanIntervalDurationWithin = vehicleSumWithin != 0 ? meanIntervalDurationWithin / (double) vehicleSumWithin : -1;
546 meanTimeLossWithin = vehicleSumWithin != 0 ? meanTimeLossWithin / (double) vehicleSumWithin : -1;
547
548 // write values
549 dev.writeAttr("meanTravelTime", myLastMeanTravelTime)
550 .writeAttr("meanOverlapTravelTime", meanOverlapTravelTime)
551 .writeAttr("meanSpeed", meanSpeed)
552 .writeAttr("meanHaltsPerVehicle", myLastMeanHaltsPerVehicle)
553 .writeAttr("meanTimeLoss", myLastMeanTimeLoss)
554 .writeAttr("vehicleSum", myLastVehicleSum)
555 .writeAttr("meanSpeedWithin", meanSpeedWithin)
556 .writeAttr("meanHaltsPerVehicleWithin", meanHaltsPerVehicleWithin)
557 .writeAttr("meanDurationWithin", meanDurationWithin)
558 .writeAttr("vehicleSumWithin", vehicleSumWithin)
559 .writeAttr("meanIntervalSpeedWithin", meanIntervalSpeedWithin)
560 .writeAttr("meanIntervalHaltsPerVehicleWithin", meanIntervalHaltsPerVehicleWithin)
561 .writeAttr("meanIntervalDurationWithin", meanIntervalDurationWithin)
562 .writeAttr("meanTimeLossWithin", meanTimeLossWithin)
563 .closeTag();
564}
565
566
567void
569 dev.writeXMLHeader("e3Detector", "det_e3_file.xsd");
570}
571
572
573void
574MSE3Collector::notifyMovePerson(MSTransportable* p, MSMoveReminder* rem, double detPos, int dir, double pos) {
575 if (personApplies(*p, dir)) {
576 const double newSpeed = p->getSpeed();
577 const double newPos = (dir == MSPModel::FORWARD
578 ? pos
579 // position relative to detector end position
580 : detPos - (pos - detPos));
581 const double oldPos = newPos - SPEED2DIST(newSpeed);
582 if (oldPos - p->getVehicleType().getLength() <= detPos) {
583 rem->notifyMove(*p, oldPos, newPos, newSpeed);
584 }
585 }
586}
587
588
589void
591
592 if (myDetectPersons != (int)PersonMode::NONE) {
593 for (auto rem : myEntryReminders) {
594 const MSLane* lane = rem->getLane();
595 if (lane->hasPedestrians()) {
596 for (MSTransportable* p : lane->getEdge().getPersons()) {
597 if (p->getLane() == lane && vehicleApplies(*p)) {
598 notifyMovePerson(p, rem, rem->getPosition(), p->getDirection(), p->getPositionOnLane());
599 }
600 }
601 }
602 }
603 for (auto rem : myLeaveReminders) {
604 const MSLane* lane = rem->getLane();
605 if (lane->hasPedestrians()) {
606 for (MSTransportable* p : lane->getEdge().getPersons()) {
607 if (p->getLane() == lane && vehicleApplies(*p)) {
608 notifyMovePerson(p, rem, rem->getPosition(), p->getDirection(), p->getPositionOnLane());
609 }
610 }
611 }
612 }
613 }
614
617 for (std::map<const SUMOTrafficObject*, E3Values>::iterator pair = myEnteredContainer.begin(); pair != myEnteredContainer.end(); ++pair) {
618 const SUMOTrafficObject* veh = pair->first;
619#ifdef DEBUG_E3_DETECTORUPDATE
620 //if (DEBUG_COND(*this) && DEBUG_COND_VEH(*veh)) {
621 if (DEBUG_COND(*this)) {
622 std::cout << SIMTIME << " vehPtr=" << veh << "\n";
623 std::cout << " veh=" << veh->getID() << "\n";
624 }
625#endif
626 E3Values& values = pair->second;
628 values.hadUpdate = true;
629 values.speedSum += veh->getSpeed() * TS;
630 values.intervalSpeedSum += veh->getSpeed() * TS;
631 if (veh->getSpeed() < myHaltingSpeedThreshold) {
632 if (values.haltingBegin == -1) {
633 values.haltingBegin = step;
634 }
635 SUMOTime haltingDuration = step - values.haltingBegin;
636 if (haltingDuration >= myHaltingTimeThreshold
637 && haltingDuration < (myHaltingTimeThreshold + DELTA_T)) {
638 values.haltings++;
639 values.intervalHaltings++;
641 }
642 } else {
643 values.haltingBegin = -1;
644 }
645 }
646 if (myEnteredContainer.size() == 0) {
648 } else {
649 myCurrentMeanSpeed /= (double)myEnteredContainer.size();
650 }
651}
652
653
656 return myEntries;
657}
658
659
662 return myExits;
663}
664
665
666double
670
671
672int
676
677
678int
680 return (int) myEnteredContainer.size();
681}
682
683
684std::vector<std::string>
686 std::vector<std::string> ret;
687 for (std::map<const SUMOTrafficObject*, E3Values>::const_iterator pair = myEnteredContainer.begin(); pair != myEnteredContainer.end(); ++pair) {
688 ret.push_back((*pair).first->getID());
689 }
690 std::sort(ret.begin(), ret.end());
691 return ret;
692}
693
694void
696 myEnteredContainer.clear();
697 myLeftContainer.clear();
698}
699
700/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
CrossSectionVector::const_iterator CrossSectionVectorConstIt
std::vector< MSCrossSection > CrossSectionVector
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
SUMOTime DELTA_T
Definition SUMOTime.cpp:38
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:91
#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_TAG_E3DETECTOR
an e3 detector
@ 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
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:49
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...
A simple description of a position on a lane (crossing of a lane)
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
A place on the road net (at a certain lane and position on it) where the E3 area begins.
bool notifyMove(SUMOTrafficObject &veh, double, double newPos, double)
Checks whether the vehicle enters.
MSE3EntryReminder(const MSCrossSection &crossSection, MSE3Collector &collector)
Constructor.
bool notifyLeave(SUMOTrafficObject &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Processes state changes of a vehicle.
bool notifyEnter(SUMOTrafficObject &veh, Notification reason, const MSLane *enteredLane)
Checks whether the reminder is activated by a vehicle entering the lane.
A place on the road net (at a certain lane and position on it) where the E3 area ends.
MSE3LeaveReminder(const MSCrossSection &crossSection, MSE3Collector &collector)
Constructor.
bool notifyEnter(SUMOTrafficObject &veh, Notification reason, const MSLane *enteredLane)
Checks whether the reminder is activated by a vehicle entering the lane.
bool notifyMove(SUMOTrafficObject &veh, double oldPos, double newPos, double)
Checks whether the vehicle leaves.
bool notifyLeave(SUMOTrafficObject &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Processes state changes of a vehicle.
A detector of vehicles passing an area between entry/exit points.
std::vector< E3Values > myLeftContainer
Container for vehicles that have left the area.
std::map< const SUMOTrafficObject *, E3Values > myEnteredContainer
Container for vehicles that have entered the area.
double myHaltingSpeedThreshold
Speed-threshold to determine if a vehicle is halting.
const CrossSectionVector & getEntries() const
Returns the entry cross sections.
virtual void clearState(SUMOTime step)
Remove all vehicles before quick-loading state.
double myCurrentMeanSpeed
The current mean speed of known vehicles (inside)
void reset()
Resets all generated values to allow computation of next interval.
double myLastMeanTravelTime
CrossSectionVector myExits
The detector's exits.
void enter(const SUMOTrafficObject &veh, const double entryTimestep, const double fractionTimeOnDet, MSE3EntryReminder *entryReminder, bool isBackward=false)
Called if a vehicle touches an entry-cross-section.
int myCurrentHaltingsNumber
The current number of haltings (inside)
SUMOTime myLastResetTime
Information when the last reset has been done.
int getVehiclesWithin() const
Returns the number of vehicles within the area.
std::vector< MSE3EntryReminder * > myEntryReminders
The detector's built entry reminder.
const bool myOpenEntry
whether this dector is declared as having incomplete entry detectors
std::vector< MSE3LeaveReminder * > myLeaveReminders
The detector's built exit reminder.
double myLastMeanHaltsPerVehicle
const CrossSectionVector & getExits() const
Returns the exit cross sections.
double myLastMeanTimeLoss
void notifyMovePerson(MSTransportable *p, MSMoveReminder *rem, double detPos, int dir, double pos)
std::string myName
name
std::vector< std::string > getCurrentVehicleIDs() const
Returns the number of vehicles within the area.
const bool myExpectArrival
Whether the detector expects vehicles to arrive inside (and doesn't issue a warning in this case)
virtual ~MSE3Collector()
Destructor.
MSE3Collector(const std::string &id, const CrossSectionVector &entries, const CrossSectionVector &exits, double haltingSpeedThreshold, SUMOTime haltingTimeThreshold, const std::string name, const std::string &vTypes, const std::string &nextEdges, int detectPersons, bool openEntry, bool expectArrival)
Constructor.
void writeXMLDetectorProlog(OutputDevice &dev) const
Opens the XML-output using "e3Detector" as root element.
double getCurrentMeanSpeed() const
Returns the mean speed within the area.
int getCurrentHaltingNumber() const
Returns the number of current haltings within the area.
void detectorUpdate(const SUMOTime step)
Computes the detector values in each time step.
SUMOTime myHaltingTimeThreshold
CrossSectionVector myEntries
The detector's entrys.
void writeXMLOutput(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Writes collected values into the given stream.
void leave(const SUMOTrafficObject &veh, const double leaveTimestep, const double fractionTimeOnDet, bool isBackward=false)
Called if a vehicle back passes a leave-cross-section.
void leaveFront(const SUMOTrafficObject &veh, const double leaveTimestep)
Called if a vehicle front passes a leave-cross-section.
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 bool gSemiImplicitEulerUpdate
Definition MSGlobals.h:53
static int gNumSimThreads
how many threads to use for simulation
Definition MSGlobals.h:146
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:4579
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:775
Something on a lane to be noticed about vehicle movement.
virtual bool notifyMove(SUMOTrafficObject &veh, double oldPos, double newPos, double newSpeed)
Checks whether the reminder still has to be notified about the vehicle moves.
Notification
Definition of a vehicle state.
@ NOTIFICATION_ARRIVED
The vehicle arrived at its destination (is deleted)
@ NOTIFICATION_LANE_CHANGE
The vehicle changes lanes (micro only)
@ NOTIFICATION_TELEPORT
The vehicle is being teleported.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:187
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.
virtual int getDirection() const
Return the movement directon on the edge.
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
double getLength() const
Get vehicle's length [m].
std::string myID
The name of the object.
Definition Named.h:125
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
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 bool isVehicle() const
Whether it is a vehicle.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual const MSLane * getLane() const =0
Returns the lane the object is currently at.
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.
A scoped lock which only triggers on condition.
#define DEBUG_COND
Internal storage for values from a vehicle.
int intervalHaltings
The sum of haltings the vehicle has/had within the area during the current interval.
MSE3EntryReminder * entryReminder
the reminder on which the vehicle entered the detector
SUMOTime timeLoss
The timeLoss of the vehicle when entering. Updated to the actual time loss within the area when leavi...
double frontLeaveTime
The time the vehicle's front was crossing the leave line.
double entryTime
The vehicle's entry time.
SUMOTime intervalTimeLoss
The timeLoss of the vehicle when entering. Updated to the current timeLoss at interval write.
double speedSum
The sum of registered speeds the vehicle has/had inside the area.
bool hadUpdate
An internal information whether the update step was performed.
SUMOTime haltingBegin
Begin time of last halt begin.
double intervalSpeedSum
The sum of registered speeds the vehicle has/had inside the area during the current interval.
int haltings
The sum of haltings the vehicle has/had within the area.
double backLeaveTime
The time the vehicle's back was crossing the leave line.