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-2024 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
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>
36#include "MSE3Collector.h"
37
38//#define DEBUG_E3_NOTIFY_MOVE
39//#define DEBUG_E3_NOTIFY_ENTER
40//#define DEBUG_E3_NOTIFY_LEAVE
41//#define DEBUG_E3_DETECTORUPDATE
42
43//#define DEBUG_COND(obj) ((obj.getID() == ""))
44//#define DEBUG_COND_VEH(veh) ((veh).getID() == "")
45//#define DEBUG_COND_VEH(veh) ((veh).isSelected())
46//#define DEBUG_COND(collector) (true)
47//#define DEBUG_COND_VEH(veh) (true)
48
49
50// ===========================================================================
51// method definitions
52// ===========================================================================
53/* -------------------------------------------------------------------------
54 * MSE3Collector::MSE3EntryReminder - definitions
55 * ----------------------------------------------------------------------- */
57 const MSCrossSection& crossSection, MSE3Collector& collector) :
58 MSMoveReminder(collector.getID() + "_entry", crossSection.myLane),
59 myCollector(collector), myPosition(crossSection.myPosition) {
60}
61
62
63bool
65#ifdef DEBUG_E3_NOTIFY_ENTER
66 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
67 std::cout << SIMTIME
68 << " MSE3EntryReminder::notifyEnter() (" << getDescription() << "on lane '" << myLane->getID() << "')"
69 << " vehicle '" << veh.getID() << "'"
70 << " enteredLane=" << enteredLane->getID()
71 << " reason=" << reason
72 << "\n";
73 }
74#endif
75 if (reason != NOTIFICATION_JUNCTION) {
76 const double posOnLane = veh.getBackPositionOnLane(enteredLane) + veh.getVehicleType().getLength();
77 if (myLane == enteredLane && posOnLane > myPosition) {
78#ifdef HAVE_FOX
79 ScopedLocker<> lock(myCollector.myContainerMutex, MSGlobals::gNumSimThreads > 1);
80#endif
81 const auto& itVeh = myCollector.myEnteredContainer.find(&veh);
82 if (itVeh == myCollector.myEnteredContainer.end() ||
83 itVeh->second.entryReminder != this) {
84#ifdef DEBUG_E3_NOTIFY_ENTER
85 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
86 std::cout << " assume already known\n";
87 }
88#endif
89 // if the vehicle changes into a covered section we assume it was already registered on another lane
90 return false;
91 }
92 }
93 }
94 return true;
95}
96
97
98bool
100 double newPos, double newSpeed) {
101#ifdef DEBUG_E3_NOTIFY_MOVE
102 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
103 std::cout << SIMTIME
104 << " MSE3EntryReminder::notifyMove() (" << getDescription() << "on lane '" << myLane->getID() << "')"
105 << " vehicle '" << veh.getID() << "'"
106 << " entered. oldPos=" << oldPos << " newPos=" << newPos << " newSpeed=" << newSpeed
107 << " myPosition=" << myPosition
108 << "\n";
109 }
110#endif
111#ifdef HAVE_FOX
112 ScopedLocker<> lock(myCollector.myContainerMutex, MSGlobals::gNumSimThreads > 1);
113#endif
114 if ((myCollector.myEnteredContainer.find(&veh) == myCollector.myEnteredContainer.end() ||
115 (veh.isPerson() && dynamic_cast<const MSTransportable&>(veh).getDirection() != MSPModel::FORWARD))
116 && newPos > myPosition) {
117 if (oldPos > myPosition) {
118 // was behind the detector already in the last step
119#ifdef DEBUG_E3_NOTIFY_MOVE
120 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
121 std::cout << " already behind\n";
122 }
123#endif
124 return false;
125 } else {
126 // entered in this step
127 const double oldSpeed = veh.getPreviousSpeed();
128 const double entryTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
129 assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the detector otherwise
130 const double timeBeforeEnter = MSCFModel::passingTime(oldPos, myPosition, newPos, oldSpeed, newSpeed);
131 const double fractionTimeOnDet = TS - timeBeforeEnter;
132 myCollector.enter(veh, entryTime - fractionTimeOnDet, fractionTimeOnDet, this);
133#ifdef DEBUG_E3_NOTIFY_MOVE
134 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
135 std::cout << " enter\n";
136 }
137#endif
138 }
139 }
140 return true;
141}
142
143
144bool
146#ifdef DEBUG_E3_NOTIFY_LEAVE
147 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
148 std::cout << SIMTIME
149 << " MSE3EntryReminder::notifyLeave() (" << getDescription() << "on lane '" << myLane->getID() << "')"
150 << " vehicle '" << veh.getID() << "'"
151 << " reason=" << reason
152 << "\n";
153 }
154#endif
156#ifdef HAVE_FOX
157 ScopedLocker<> lock(myCollector.myContainerMutex, MSGlobals::gNumSimThreads > 1);
158#endif
159 if (myCollector.myEnteredContainer.erase(&veh) > 0) {
160 if (!myCollector.myExpectArrival) {
161 WRITE_WARNINGF("Vehicle '%' arrived inside % '%', time=%.", veh.getID(), toString(SUMO_TAG_E3DETECTOR), myCollector.getID(), time2string(SIMSTEP));
162 }
163 }
164 return false;
165 }
166 return true;
167}
168
169
170/* -------------------------------------------------------------------------
171 * MSE3Collector::MSE3LeaveReminder - definitions
172 * ----------------------------------------------------------------------- */
174 const MSCrossSection& crossSection, MSE3Collector& collector) :
175 MSMoveReminder(collector.getID() + "_exit", crossSection.myLane),
176 myCollector(collector), myPosition(crossSection.myPosition) {}
177
178
179bool
181#ifdef DEBUG_E3_NOTIFY_ENTER
182 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
183 std::cout << SIMTIME
184 << " MSE3LeaveReminder::notifyEnter() (" << getDescription() << "on lane '" << myLane->getID() << "')"
185 << " vehicle '" << veh.getID() << "'"
186 << " enteredLane=" << enteredLane->getID()
187 << " reason=" << reason
188 << "\n";
189 }
190#endif
191 // this method does not access containers, so no locking here
192 if (reason != NOTIFICATION_JUNCTION) {
193 const double backPosOnLane = veh.getBackPositionOnLane(enteredLane);
194 if (backPosOnLane > myPosition) {
195 // if the vehicle changes into a covered section we assume it was already registered on another lane
196 // however, if it is not fully past the detector we still need to track it
197#ifdef DEBUG_E3_NOTIFY_ENTER
198 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
199 std::cout << " assume already known\n";
200 }
201#endif
202 return false;
203 }
204 }
205 return true;
206}
207
208
209bool
211 double newPos, double newSpeed) {
212#ifdef DEBUG_E3_NOTIFY_MOVE
213 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
214 std::cout << SIMTIME
215 << " MSE3LeaveReminder::notifyMove() (" << getDescription() << " on lane '" << myLane->getID() << "')"
216 << " vehicle '" << veh.getID() << "'"
217 << " entered. oldPos=" << oldPos << " newPos=" << newPos << " newSpeed=" << newSpeed
218 << " myPosition=" << myPosition
219 << "\n";
220 }
221#endif
222 if (newPos < myPosition) {
223 // crossSection not yet reached
224 return true;
225 }
226#ifdef HAVE_FOX
227 ScopedLocker<> lock(myCollector.myContainerMutex, MSGlobals::gNumSimThreads > 1);
228#endif
229 const double oldSpeed = veh.getPreviousSpeed();
230 if (oldPos < myPosition) {
231 assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the detector otherwise
232 const double timeBeforeLeave = MSCFModel::passingTime(oldPos, myPosition, newPos, oldSpeed, newSpeed);
233// const double leaveTimeFront = SIMTIME - TS + (myPosition - oldPos) / newSpeed;
234 const double leaveTimeFront = SIMTIME - TS + timeBeforeLeave;
235 myCollector.leaveFront(veh, leaveTimeFront);
236#ifdef DEBUG_E3_NOTIFY_MOVE
237 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
238 std::cout << " leaveFront\n";
239 }
240#endif
241 }
242 const double backPos = newPos - veh.getVehicleType().getLength();
243 if (backPos < myPosition) {
244 // crossSection not yet left
245 return true;
246 }
247 // crossSection left
248 const double oldBackPos = oldPos - veh.getVehicleType().getLength();
249 const double leaveStep = SIMTIME;
250 assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the detector otherwise
251 const double timeBeforeLeave = MSCFModel::passingTime(oldBackPos, myPosition, backPos, oldSpeed, newSpeed);
252 myCollector.leave(veh, leaveStep - TS + timeBeforeLeave, timeBeforeLeave);
253#ifdef DEBUG_E3_NOTIFY_MOVE
254 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
255 std::cout << " leave\n";
256 }
257#endif
258 return false;
259}
260
261
262bool
264#ifdef DEBUG_E3_NOTIFY_LEAVE
265 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
266 std::cout << SIMTIME
267 << " MSE3LeaveReminder::notifyLeave() (" << getDescription() << "on lane '" << myLane->getID() << "')"
268 << " vehicle '" << veh.getID() << "'"
269 << " reason=" << reason
270 << "\n";
271 }
272#endif
273 if (reason == MSMoveReminder::NOTIFICATION_LANE_CHANGE && &enteredLane->getEdge() == &myLane->getEdge()) {
274 // keep the detector when changing while still on the exit detector but already on a new lane (#4803)
275#ifdef DEBUG_E3_NOTIFY_LEAVE
276 if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
277 std::cout << " remove reminder, keep in container\n";
278 }
279#endif
280 return false;
281 }
282#ifdef HAVE_FOX
283 ScopedLocker<> lock(myCollector.myContainerMutex, MSGlobals::gNumSimThreads > 1);
284#endif
286 WRITE_WARNINGF("Vehicle '%' teleported from % '%'.", veh.getID(), toString(SUMO_TAG_E3DETECTOR), myCollector.getID());
287 myCollector.myEnteredContainer.erase(&veh);
288 return false;
289 }
291 if (myCollector.myEnteredContainer.erase(&veh) > 0) {
292 if (!myCollector.myExpectArrival) {
293 WRITE_WARNINGF("Vehicle '%' arrived inside % '%', time=%.", veh.getID(), toString(SUMO_TAG_E3DETECTOR), myCollector.getID(), time2string(SIMSTEP));
294 }
295 }
296 return false;
297 }
298 return true;
299}
300
301/* -------------------------------------------------------------------------
302 * MSE3Collector - definitions
303 * ----------------------------------------------------------------------- */
304MSE3Collector::MSE3Collector(const std::string& id,
305 const CrossSectionVector& entries,
306 const CrossSectionVector& exits,
307 double haltingSpeedThreshold,
308 SUMOTime haltingTimeThreshold,
309 const std::string name, const std::string& vTypes,
310 const std::string& nextEdges,
311 int detectPersons,
312 bool openEntry, bool expectArrival) :
313 MSDetectorFileOutput(id, vTypes, nextEdges, detectPersons),
314 myName(name),
315 myEntries(entries),
316 myExits(exits),
317 myHaltingTimeThreshold(haltingTimeThreshold), myHaltingSpeedThreshold(haltingSpeedThreshold),
320 myLastResetTime(-1), myOpenEntry(openEntry), myExpectArrival(expectArrival) {
321 // Set MoveReminders to entries and exits
322 for (CrossSectionVectorConstIt crossSec1 = entries.begin(); crossSec1 != entries.end(); ++crossSec1) {
323 myEntryReminders.push_back(new MSE3EntryReminder(*crossSec1, *this));
324 }
325 for (CrossSectionVectorConstIt crossSec2 = exits.begin(); crossSec2 != exits.end(); ++crossSec2) {
326 myLeaveReminders.push_back(new MSE3LeaveReminder(*crossSec2, *this));
327 }
328 reset();
329}
330
331
333 for (std::vector<MSE3EntryReminder*>::iterator i = myEntryReminders.begin(); i != myEntryReminders.end(); ++i) {
334 delete *i;
335 }
336 for (std::vector<MSE3LeaveReminder*>::iterator i = myLeaveReminders.begin(); i != myLeaveReminders.end(); ++i) {
337 delete *i;
338 }
339}
340
341
342void
346
347
348
349void
350MSE3Collector::enter(const SUMOTrafficObject& veh, const double entryTimestep, const double fractionTimeOnDet, MSE3EntryReminder* entryReminder, bool isBackward) {
351 if (myDetectPersons > (int)PersonMode::WALK && !veh.isPerson()) {
352 const MSBaseVehicle& v = dynamic_cast<const MSBaseVehicle&>(veh);
353 for (MSTransportable* p : v.getPersons()) {
354 enter(*p, entryTimestep, fractionTimeOnDet, entryReminder);
355 }
356 return;
357 }
358 if (!vehicleApplies(veh)) {
359 return;
360 }
361 if (veh.isPerson() && !isBackward && dynamic_cast<const MSTransportable&>(veh).getDirection() != MSPModel::FORWARD) {
362 // walking backward over an entry detector means "leaving"
363 // std::cout << veh.getID() << " leave at entryDetector\n";
364 leave(veh, entryTimestep, fractionTimeOnDet, true);
365 return;
366 }
367 if (myEnteredContainer.find(&veh) != myEnteredContainer.end()) {
368 WRITE_WARNINGF("Vehicle '%' reentered % '%', time=%.", veh.getID(), toString(SUMO_TAG_E3DETECTOR), getID(), time2string(SIMSTEP));
369 return;
370 }
371#ifdef DEBUG_E3_NOTIFY_ENTER
372 std::cout << veh.getID() << " enters\n";
373#endif
374 const double speedFraction = veh.getSpeed() * fractionTimeOnDet;
375 E3Values v;
376 v.entryTime = entryTimestep;
377 v.frontLeaveTime = 0;
378 v.backLeaveTime = 0;
379 v.speedSum = speedFraction;
380 v.haltingBegin = veh.getSpeed() < myHaltingSpeedThreshold ? TIME2STEPS(entryTimestep) : -1;
381 v.intervalSpeedSum = entryTimestep >= STEPS2TIME(myLastResetTime) ? speedFraction : 0;
382 v.haltings = 0;
383 v.intervalHaltings = 0;
384 if (veh.getSpeed() < myHaltingSpeedThreshold) {
385 if (TIME2STEPS(fractionTimeOnDet) > myHaltingTimeThreshold) {
386 v.haltings++;
388 }
389 }
390 v.hadUpdate = false;
391 if (!MSGlobals::gUseMesoSim && veh.isVehicle()) {
392 v.timeLoss = dynamic_cast<const MSVehicle&>(veh).getTimeLoss();
394 }
395 v.entryReminder = entryReminder;
396 myEnteredContainer[&veh] = v;
397}
398
399
400void
401MSE3Collector::leaveFront(const SUMOTrafficObject& veh, const double leaveTimestep) {
402 if (myDetectPersons > (int)PersonMode::WALK && !veh.isPerson()) {
403 const MSBaseVehicle& v = dynamic_cast<const MSBaseVehicle&>(veh);
404 for (MSTransportable* p : v.getPersons()) {
405 leaveFront(*p, leaveTimestep);
406 }
407 return;
408 }
409 if (!vehicleApplies(veh)) {
410 return;
411 }
412 if (myEnteredContainer.find(&veh) == myEnteredContainer.end()) {
413 if (!myOpenEntry && veh.isVehicle()) {
414 WRITE_WARNINGF("Vehicle '%' left % '%' without entering it, time=%.", veh.getID(), toString(SUMO_TAG_E3DETECTOR), getID(), time2string(SIMSTEP));
415 }
416 } else {
417 myEnteredContainer[&veh].frontLeaveTime = leaveTimestep;
418 }
419}
420
421
422void
423MSE3Collector::leave(const SUMOTrafficObject& veh, const double leaveTimestep, const double fractionTimeOnDet, bool isBackward) {
424 if (myDetectPersons > (int)PersonMode::WALK && !veh.isPerson()) {
425 const MSBaseVehicle& v = dynamic_cast<const MSBaseVehicle&>(veh);
426 for (MSTransportable* p : v.getPersons()) {
427 leave(*p, leaveTimestep, fractionTimeOnDet);
428 }
429 return;
430 }
431 if (!vehicleApplies(veh)) {
432 return;
433 }
434 if (veh.isPerson() && !isBackward && dynamic_cast<const MSTransportable&>(veh).getDirection() != MSPModel::FORWARD) {
435 // walking backward over an exit detector means "entering"
436 // std::cout << veh.getID() << " enter at exitDetector\n";
437 enter(veh, leaveTimestep, fractionTimeOnDet, nullptr, true);
438 return;
439 }
440 if (myEnteredContainer.find(&veh) == myEnteredContainer.end()) {
441 if (!myOpenEntry && veh.isVehicle()) {
442 WRITE_WARNINGF("Vehicle '%' left % '%' without entering it, time=%.", veh.getID(), toString(SUMO_TAG_E3DETECTOR), getID(), time2string(SIMSTEP));
443 }
444 } else {
445#ifdef DEBUG_E3_NOTIFY_LEAVE
446 std::cout << veh.getID() << " leaves\n";
447#endif
448 E3Values values = myEnteredContainer[&veh];
449 values.backLeaveTime = leaveTimestep;
450 const double speedFraction = veh.getSpeed() * (TS - fractionTimeOnDet);
451 values.speedSum -= speedFraction;
452 values.intervalSpeedSum -= speedFraction;
453 if (MSGlobals::gUseMesoSim || !veh.isVehicle()) {
454 // not yet supported
455 values.timeLoss = 0;
456 if (isBackward) {
457 // leaveFront may not have been called
458 values.frontLeaveTime = leaveTimestep;
459 }
460 } else {
461 // timeLoss was initialized when entering
462 values.timeLoss = dynamic_cast<const MSVehicle&>(veh).getTimeLoss() - values.timeLoss;
463 }
464 myEnteredContainer.erase(&veh);
465 myLeftContainer.push_back(values);
466 }
467}
468
469
470void
472 SUMOTime startTime, SUMOTime stopTime) {
473 dev << " <interval begin=\"" << time2string(startTime) << "\" end=\"" << time2string(stopTime) << "\" " << "id=\"" << myID << "\" ";
474 // collect values about vehicles that have left the area
475 myLastVehicleSum = (int) myLeftContainer.size();
477 double meanOverlapTravelTime = 0.;
478 double meanSpeed = 0.;
481 for (const E3Values& values : myLeftContainer) {
482 myLastMeanHaltsPerVehicle += (double)values.haltings;
483 myLastMeanTravelTime += values.frontLeaveTime - values.entryTime;
484 const double steps = values.backLeaveTime - values.entryTime;
485 meanOverlapTravelTime += steps;
486 meanSpeed += (values.speedSum / steps);
487 myLastMeanTimeLoss += STEPS2TIME(values.timeLoss);
488 }
490 meanOverlapTravelTime = myLastVehicleSum != 0 ? meanOverlapTravelTime / (double)myLastVehicleSum : -1;
491 meanSpeed = myLastVehicleSum != 0 ? meanSpeed / (double)myLastVehicleSum : -1;
494 // clear container
495 myLeftContainer.clear();
496
497 // collect values about vehicles within the container
498 const int vehicleSumWithin = (int) myEnteredContainer.size();
499 double meanSpeedWithin = 0.;
500 double meanDurationWithin = 0.;
501 double meanHaltsPerVehicleWithin = 0.;
502 double meanIntervalSpeedWithin = 0.;
503 double meanIntervalHaltsPerVehicleWithin = 0.;
504 double meanIntervalDurationWithin = 0.;
505 double meanTimeLossWithin = 0.;
506 for (std::map<const SUMOTrafficObject*, E3Values>::iterator i = myEnteredContainer.begin(); i != myEnteredContainer.end(); ++i) {
507 meanHaltsPerVehicleWithin += (double)(*i).second.haltings;
508 meanIntervalHaltsPerVehicleWithin += (double)(*i).second.intervalHaltings;
509 const double end = (*i).second.backLeaveTime == 0 ? STEPS2TIME(stopTime) : (*i).second.backLeaveTime;
510 const double time = end - (*i).second.entryTime;
511 const double timeWithin = MIN2(time, end - STEPS2TIME(startTime));
512 if (i->second.speedSum > 0.) {
513 meanSpeedWithin += i->second.speedSum / time;
514 }
515 if (i->second.intervalSpeedSum > 0.) {
516 meanIntervalSpeedWithin += i->second.intervalSpeedSum / timeWithin;
517 }
518 meanDurationWithin += time;
519 meanIntervalDurationWithin += timeWithin;
520 // reset interval values
521 (*i).second.intervalHaltings = 0;
522 (*i).second.intervalSpeedSum = 0;
523
524 if (!MSGlobals::gUseMesoSim && i->first->isVehicle()) {
525 const SUMOTime currentTimeLoss = dynamic_cast<const MSVehicle*>(i->first)->getTimeLoss();
526 meanTimeLossWithin += STEPS2TIME(currentTimeLoss - (*i).second.intervalTimeLoss);
527 (*i).second.intervalTimeLoss = currentTimeLoss;
528 }
529 }
530 myLastResetTime = stopTime;
531 meanSpeedWithin = vehicleSumWithin != 0 ? meanSpeedWithin / (double) vehicleSumWithin : -1;
532 meanHaltsPerVehicleWithin = vehicleSumWithin != 0 ? meanHaltsPerVehicleWithin / (double) vehicleSumWithin : -1;
533 meanDurationWithin = vehicleSumWithin != 0 ? meanDurationWithin / (double) vehicleSumWithin : -1;
534 meanIntervalSpeedWithin = vehicleSumWithin != 0 ? meanIntervalSpeedWithin / (double) vehicleSumWithin : -1;
535 meanIntervalHaltsPerVehicleWithin = vehicleSumWithin != 0 ? meanIntervalHaltsPerVehicleWithin / (double) vehicleSumWithin : -1;
536 meanIntervalDurationWithin = vehicleSumWithin != 0 ? meanIntervalDurationWithin / (double) vehicleSumWithin : -1;
537 meanTimeLossWithin = vehicleSumWithin != 0 ? meanTimeLossWithin / (double) vehicleSumWithin : -1;
538
539 // write values
540 dev << "meanTravelTime=\"" << myLastMeanTravelTime
541 << "\" meanOverlapTravelTime=\"" << meanOverlapTravelTime
542 << "\" meanSpeed=\"" << meanSpeed
543 << "\" meanHaltsPerVehicle=\"" << myLastMeanHaltsPerVehicle
544 << "\" meanTimeLoss=\"" << myLastMeanTimeLoss
545 << "\" vehicleSum=\"" << myLastVehicleSum
546 << "\" meanSpeedWithin=\"" << meanSpeedWithin
547 << "\" meanHaltsPerVehicleWithin=\"" << meanHaltsPerVehicleWithin
548 << "\" meanDurationWithin=\"" << meanDurationWithin
549 << "\" vehicleSumWithin=\"" << vehicleSumWithin
550 << "\" meanIntervalSpeedWithin=\"" << meanIntervalSpeedWithin
551 << "\" meanIntervalHaltsPerVehicleWithin=\"" << meanIntervalHaltsPerVehicleWithin
552 << "\" meanIntervalDurationWithin=\"" << meanIntervalDurationWithin
553 << "\" meanTimeLossWithin=\"" << meanTimeLossWithin
554 << "\"/>\n";
555}
556
557
558void
560 dev.writeXMLHeader("e3Detector", "det_e3_file.xsd");
561}
562
563
564void
565MSE3Collector::notifyMovePerson(MSTransportable* p, MSMoveReminder* rem, double detPos, int dir, double pos) {
566 if (personApplies(*p, dir)) {
567 const double newSpeed = p->getSpeed();
568 const double newPos = (dir == MSPModel::FORWARD
569 ? pos
570 // position relative to detector end position
571 : detPos - (pos - detPos));
572 const double oldPos = newPos - SPEED2DIST(newSpeed);
573 if (oldPos - p->getVehicleType().getLength() <= detPos) {
574 rem->notifyMove(*p, oldPos, newPos, newSpeed);
575 }
576 }
577}
578
579
580void
582
583 if (myDetectPersons != (int)PersonMode::NONE) {
584 for (auto rem : myEntryReminders) {
585 const MSLane* lane = rem->getLane();
586 if (lane->hasPedestrians()) {
587 for (MSTransportable* p : lane->getEdge().getPersons()) {
588 if (p->getLane() == lane && vehicleApplies(*p)) {
589 notifyMovePerson(p, rem, rem->getPosition(), p->getDirection(), p->getPositionOnLane());
590 }
591 }
592 }
593 }
594 for (auto rem : myLeaveReminders) {
595 const MSLane* lane = rem->getLane();
596 if (lane->hasPedestrians()) {
597 for (MSTransportable* p : lane->getEdge().getPersons()) {
598 if (p->getLane() == lane && vehicleApplies(*p)) {
599 notifyMovePerson(p, rem, rem->getPosition(), p->getDirection(), p->getPositionOnLane());
600 }
601 }
602 }
603 }
604 }
605
608 for (std::map<const SUMOTrafficObject*, E3Values>::iterator pair = myEnteredContainer.begin(); pair != myEnteredContainer.end(); ++pair) {
609 const SUMOTrafficObject* veh = pair->first;
610#ifdef DEBUG_E3_DETECTORUPDATE
611 //if (DEBUG_COND(*this) && DEBUG_COND_VEH(*veh)) {
612 if (DEBUG_COND(*this)) {
613 std::cout << SIMTIME << " vehPtr=" << veh << "\n";
614 std::cout << " veh=" << veh->getID() << "\n";
615 }
616#endif
617 E3Values& values = pair->second;
619 values.hadUpdate = true;
620 values.speedSum += veh->getSpeed() * TS;
621 values.intervalSpeedSum += veh->getSpeed() * TS;
622 if (veh->getSpeed() < myHaltingSpeedThreshold) {
623 if (values.haltingBegin == -1) {
624 values.haltingBegin = step;
625 }
626 SUMOTime haltingDuration = step - values.haltingBegin;
627 if (haltingDuration >= myHaltingTimeThreshold
628 && haltingDuration < (myHaltingTimeThreshold + DELTA_T)) {
629 values.haltings++;
630 values.intervalHaltings++;
632 }
633 } else {
634 values.haltingBegin = -1;
635 }
636 }
637 if (myEnteredContainer.size() == 0) {
639 } else {
640 myCurrentMeanSpeed /= (double)myEnteredContainer.size();
641 }
642}
643
644
647 return myEntries;
648}
649
650
653 return myExits;
654}
655
656
657double
661
662
663int
667
668
669int
671 return (int) myEnteredContainer.size();
672}
673
674
675std::vector<std::string>
677 std::vector<std::string> ret;
678 for (std::map<const SUMOTrafficObject*, E3Values>::const_iterator pair = myEnteredContainer.begin(); pair != myEnteredContainer.end(); ++pair) {
679 ret.push_back((*pair).first->getID());
680 }
681 std::sort(ret.begin(), ret.end());
682 return ret;
683}
684
685void
687 myEnteredContainer.clear();
688 myLeftContainer.clear();
689}
690
691/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
CrossSectionVector::const_iterator CrossSectionVectorConstIt
std::vector< MSCrossSection > CrossSectionVector
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:296
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:69
#define STEPS2TIME(x)
Definition SUMOTime.h:55
#define SPEED2DIST(x)
Definition SUMOTime.h:45
#define SIMSTEP
Definition SUMOTime.h:61
#define TS
Definition SUMOTime.h:42
#define SIMTIME
Definition SUMOTime.h:62
#define TIME2STEPS(x)
Definition SUMOTime.h:57
@ SUMO_TAG_E3DETECTOR
an e3 detector
T MIN2(T a, T b)
Definition StdDefs.h:76
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
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:4484
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:764
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:186
static const int FORWARD
Definition MSPModel.h:54
virtual double getSpeed() const
the current speed of the transportable
const MSVehicleType & getVehicleType() const
Returns the object's "vehicle" type.
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.
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >(), bool includeConfig=true)
Writes an XML header with optional configuration.
Representation of a vehicle, person, or container.
virtual bool isVehicle() const
Whether it is a vehicle.
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.
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.