Eclipse SUMO - Simulation of Urban MObility
MSE3Collector.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2020 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 
28 #include "MSE3Collector.h"
29 #include <microsim/MSNet.h>
30 #include <microsim/MSVehicle.h>
31 
32 //#define DEBUG_E3_NOTIFY_MOVE
33 //#define DEBUG_E3_NOTIFY_ENTER
34 //#define DEBUG_E3_NOTIFY_LEAVE
35 //#define DEBUG_E3_DETECTORUPDATE
36 
37 //#define DEBUG_COND(obj) ((obj.getID() == ""))
38 //#define DEBUG_COND_VEH(veh) ((veh).getID() == "")
39 //#define DEBUG_COND_VEH(veh) ((veh).isSelected())
40 //#define DEBUG_COND(collector) (true)
41 //#define DEBUG_COND_VEH(veh) (true)
42 
43 
44 // ===========================================================================
45 // method definitions
46 // ===========================================================================
47 /* -------------------------------------------------------------------------
48  * MSE3Collector::MSE3EntryReminder - definitions
49  * ----------------------------------------------------------------------- */
51  const MSCrossSection& crossSection, MSE3Collector& collector) :
52  MSMoveReminder(collector.getID() + "_entry", crossSection.myLane),
53  myCollector(collector), myPosition(crossSection.myPosition) {
54 }
55 
56 
57 bool
59 #ifdef DEBUG_E3_NOTIFY_ENTER
60  if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
61  std::cout << SIMTIME
62  << " MSE3EntryReminder::notifyEnter() (" << getDescription() << "on lane '" << myLane->getID() << "')"
63  << " vehicle '" << veh.getID() << "'"
64  << " enteredLane=" << enteredLane->getID()
65  << " reason=" << reason
66  << "\n";
67  }
68 #endif
69  if (reason != NOTIFICATION_JUNCTION) {
70  const double posOnLane = veh.getBackPositionOnLane(enteredLane) + veh.getVehicleType().getLength();
71  if (myLane == enteredLane && posOnLane > myPosition) {
72 #ifdef HAVE_FOX
73  FXConditionalLock lock(myCollector.myContainerMutex, MSGlobals::gNumSimThreads > 1);
74 #endif
75  const auto& itVeh = myCollector.myEnteredContainer.find(&veh);
76  if (itVeh == myCollector.myEnteredContainer.end() ||
77  itVeh->second.entryReminder != this) {
78 #ifdef DEBUG_E3_NOTIFY_ENTER
79  if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
80  std::cout << " assume already known\n";
81  }
82 #endif
83  // if the vehicle changes into a covered section we assume it was already registered on another lane
84  return false;
85  }
86  }
87  }
88  return true;
89 }
90 
91 
92 bool
94  double newPos, double newSpeed) {
95 #ifdef DEBUG_E3_NOTIFY_MOVE
96  if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
97  std::cout << SIMTIME
98  << " MSE3EntryReminder::notifyMove() (" << getDescription() << "on lane '" << myLane->getID() << "')"
99  << " vehicle '" << veh.getID() << "'"
100  << " entered. oldPos=" << oldPos << " newPos=" << newPos << " newSpeed=" << newSpeed
101  << " myPosition=" << myPosition
102  << "\n";
103  }
104 #endif
105 #ifdef HAVE_FOX
106  FXConditionalLock lock(myCollector.myContainerMutex, MSGlobals::gNumSimThreads > 1);
107 #endif
108  if (myCollector.myEnteredContainer.find(&veh) == myCollector.myEnteredContainer.end() && newPos > myPosition) {
109  if (oldPos > myPosition) {
110  // was behind the detector already in the last step
111 #ifdef DEBUG_E3_NOTIFY_MOVE
112  if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
113  std::cout << " already behind\n";
114  }
115 #endif
116  return false;
117  } else {
118  // entered in this step
119  const double oldSpeed = veh.getPreviousSpeed();
120  const double entryTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
121  assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the detector otherwise
122  const double timeBeforeEnter = MSCFModel::passingTime(oldPos, myPosition, newPos, oldSpeed, newSpeed);
123  const double fractionTimeOnDet = TS - timeBeforeEnter;
124  myCollector.enter(veh, entryTime - fractionTimeOnDet, fractionTimeOnDet, this);
125 #ifdef DEBUG_E3_NOTIFY_MOVE
126  if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
127  std::cout << " enter\n";
128  }
129 #endif
130  }
131  }
132  return true;
133 }
134 
135 
136 bool
138 #ifdef DEBUG_E3_NOTIFY_LEAVE
139  if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
140  std::cout << SIMTIME
141  << " MSE3EntryReminder::notifyLeave() (" << getDescription() << "on lane '" << myLane->getID() << "')"
142  << " vehicle '" << veh.getID() << "'"
143  << " reason=" << reason
144  << "\n";
145  }
146 #endif
147  if (reason >= MSMoveReminder::NOTIFICATION_ARRIVED) {
148 #ifdef HAVE_FOX
149  FXConditionalLock lock(myCollector.myContainerMutex, MSGlobals::gNumSimThreads > 1);
150 #endif
151  if (myCollector.myEnteredContainer.erase(&veh) > 0) {
152  WRITE_WARNING("Vehicle '" + veh.getID() + "' arrived inside " + toString(SUMO_TAG_E3DETECTOR) + " '" + myCollector.getID() + "'.");
153  }
154  return false;
155  }
156  return true;
157 }
158 
159 
160 /* -------------------------------------------------------------------------
161  * MSE3Collector::MSE3LeaveReminder - definitions
162  * ----------------------------------------------------------------------- */
164  const MSCrossSection& crossSection, MSE3Collector& collector) :
165  MSMoveReminder(collector.getID() + "_exit", crossSection.myLane),
166  myCollector(collector), myPosition(crossSection.myPosition) {}
167 
168 
169 bool
171 #ifdef DEBUG_E3_NOTIFY_ENTER
172  if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
173  std::cout << SIMTIME
174  << " MSE3LeaveReminder::notifyEnter() (" << getDescription() << "on lane '" << myLane->getID() << "')"
175  << " vehicle '" << veh.getID() << "'"
176  << " enteredLane=" << enteredLane->getID()
177  << " reason=" << reason
178  << "\n";
179  }
180 #endif
181  // this method does not access containers, so no locking here
182  if (reason != NOTIFICATION_JUNCTION) {
183  const double backPosOnLane = veh.getBackPositionOnLane(enteredLane);
184  if (backPosOnLane > myPosition) {
185  // if the vehicle changes into a covered section we assume it was already registered on another lane
186  // however, if it is not fully past the detector we still need to track it
187 #ifdef DEBUG_E3_NOTIFY_ENTER
188  if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
189  std::cout << " assume already known\n";
190  }
191 #endif
192  return false;
193  }
194  }
195  return true;
196 }
197 
198 
199 bool
201  double newPos, double newSpeed) {
202 #ifdef DEBUG_E3_NOTIFY_MOVE
203  if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
204  std::cout << SIMTIME
205  << " MSE3LeaveReminder::notifyMove() (" << getDescription() << " on lane '" << myLane->getID() << "')"
206  << " vehicle '" << veh.getID() << "'"
207  << " entered. oldPos=" << oldPos << " newPos=" << newPos << " newSpeed=" << newSpeed
208  << " myPosition=" << myPosition
209  << "\n";
210  }
211 #endif
212  if (newPos < myPosition) {
213  // crossSection not yet reached
214  return true;
215  }
216 #ifdef HAVE_FOX
217  FXConditionalLock lock(myCollector.myContainerMutex, MSGlobals::gNumSimThreads > 1);
218 #endif
219  const double oldSpeed = veh.getPreviousSpeed();
220  if (oldPos < myPosition) {
221  assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the detector otherwise
222  const double timeBeforeLeave = MSCFModel::passingTime(oldPos, myPosition, newPos, oldSpeed, newSpeed);
223 // const double leaveTimeFront = SIMTIME - TS + (myPosition - oldPos) / newSpeed;
224  const double leaveTimeFront = SIMTIME - TS + timeBeforeLeave;
225  myCollector.leaveFront(veh, leaveTimeFront);
226 #ifdef DEBUG_E3_NOTIFY_MOVE
227  if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
228  std::cout << " leaveFront\n";
229  }
230 #endif
231  }
232  const double backPos = newPos - veh.getVehicleType().getLength();
233  if (backPos < myPosition) {
234  // crossSection not yet left
235  return true;
236  }
237  // crossSection left
238  const double oldBackPos = oldPos - veh.getVehicleType().getLength();
239  const double leaveStep = SIMTIME;
240  assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the detector otherwise
241  const double timeBeforeLeave = MSCFModel::passingTime(oldBackPos, myPosition, backPos, oldSpeed, newSpeed);
242  myCollector.leave(veh, leaveStep - TS + timeBeforeLeave, timeBeforeLeave);
243 #ifdef DEBUG_E3_NOTIFY_MOVE
244  if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
245  std::cout << " leave\n";
246  }
247 #endif
248  return false;
249 }
250 
251 
252 bool
254 #ifdef DEBUG_E3_NOTIFY_LEAVE
255  if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
256  std::cout << SIMTIME
257  << " MSE3LeaveReminder::notifyLeave() (" << getDescription() << "on lane '" << myLane->getID() << "')"
258  << " vehicle '" << veh.getID() << "'"
259  << " reason=" << reason
260  << "\n";
261  }
262 #endif
263  if (reason == MSMoveReminder::NOTIFICATION_LANE_CHANGE && &enteredLane->getEdge() == &myLane->getEdge()) {
264  // keep the detector when changing while still on the exit detector but already on a new lane (#4803)
265 #ifdef DEBUG_E3_NOTIFY_LEAVE
266  if (DEBUG_COND(myCollector) && DEBUG_COND_VEH(veh)) {
267  std::cout << " remove reminder, keep in container\n";
268  }
269 #endif
270  return false;
271  }
272 #ifdef HAVE_FOX
273  FXConditionalLock lock(myCollector.myContainerMutex, MSGlobals::gNumSimThreads > 1);
274 #endif
276  WRITE_WARNING("Vehicle '" + veh.getID() + "' teleported from " + toString(SUMO_TAG_E3DETECTOR) + " '" + myCollector.getID() + "'.");
277  myCollector.myEnteredContainer.erase(&veh);
278  return false;
279  }
280  if (reason >= MSMoveReminder::NOTIFICATION_ARRIVED) {
281  if (myCollector.myEnteredContainer.erase(&veh) > 0) {
282  WRITE_WARNING("Vehicle '" + veh.getID() + "' arrived inside " + toString(SUMO_TAG_E3DETECTOR) + " '" + myCollector.getID() + "'.");
283  }
284  return false;
285  }
286  return true;
287 }
288 
289 /* -------------------------------------------------------------------------
290  * MSE3Collector - definitions
291  * ----------------------------------------------------------------------- */
292 MSE3Collector::MSE3Collector(const std::string& id,
293  const CrossSectionVector& entries,
294  const CrossSectionVector& exits,
295  double haltingSpeedThreshold,
296  SUMOTime haltingTimeThreshold,
297  const std::string& vTypes,
298  bool openEntry) :
299  MSDetectorFileOutput(id, vTypes), myEntries(entries), myExits(exits),
300  myHaltingTimeThreshold(haltingTimeThreshold), myHaltingSpeedThreshold(haltingSpeedThreshold),
302  myOpenEntry(openEntry) {
303  // Set MoveReminders to entries and exits
304  for (CrossSectionVectorConstIt crossSec1 = entries.begin(); crossSec1 != entries.end(); ++crossSec1) {
305  myEntryReminders.push_back(new MSE3EntryReminder(*crossSec1, *this));
306  }
307  for (CrossSectionVectorConstIt crossSec2 = exits.begin(); crossSec2 != exits.end(); ++crossSec2) {
308  myLeaveReminders.push_back(new MSE3LeaveReminder(*crossSec2, *this));
309  }
310  reset();
311 }
312 
313 
315  for (std::vector<MSE3EntryReminder*>::iterator i = myEntryReminders.begin(); i != myEntryReminders.end(); ++i) {
316  delete *i;
317  }
318  for (std::vector<MSE3LeaveReminder*>::iterator i = myLeaveReminders.begin(); i != myLeaveReminders.end(); ++i) {
319  delete *i;
320  }
321 }
322 
323 
324 void
326  myLeftContainer.clear();
327 }
328 
329 
330 
331 void
332 MSE3Collector::enter(const SUMOTrafficObject& veh, const double entryTimestep, const double fractionTimeOnDet, MSE3EntryReminder* entryReminder) {
333  if (!vehicleApplies(veh)) {
334  return;
335  }
336  if (myEnteredContainer.find(&veh) != myEnteredContainer.end()) {
337  WRITE_WARNING("Vehicle '" + veh.getID() + "' reentered " + toString(SUMO_TAG_E3DETECTOR) + " '" + getID() + "'.");
338  return;
339  }
340  const double speedFraction = veh.getSpeed() * fractionTimeOnDet;
341  E3Values v;
342  v.entryTime = entryTimestep;
343  v.frontLeaveTime = 0;
344  v.backLeaveTime = 0;
345  v.speedSum = speedFraction;
346  v.haltingBegin = veh.getSpeed() < myHaltingSpeedThreshold ? TIME2STEPS(entryTimestep) : -1;
347  v.intervalSpeedSum = entryTimestep >= STEPS2TIME(myLastResetTime) ? speedFraction : 0;
348  v.haltings = 0;
349  v.intervalHaltings = 0;
350  if (veh.getSpeed() < myHaltingSpeedThreshold) {
351  if (fractionTimeOnDet > myHaltingTimeThreshold) {
352  v.haltings++;
353  v.intervalHaltings++;
354  }
355  }
356  v.hadUpdate = false;
357  if (!MSGlobals::gUseMesoSim) {
358  v.timeLoss = static_cast<const MSVehicle&>(veh).getTimeLoss();
360  }
361  v.entryReminder = entryReminder;
362  myEnteredContainer[&veh] = v;
363 }
364 
365 
366 void
367 MSE3Collector::leaveFront(const SUMOTrafficObject& veh, const double leaveTimestep) {
368  if (!vehicleApplies(veh)) {
369  return;
370  }
371  if (myEnteredContainer.find(&veh) == myEnteredContainer.end()) {
372  if (!myOpenEntry) {
373  WRITE_WARNING("Vehicle '" + veh.getID() + "' left " + toString(SUMO_TAG_E3DETECTOR) + " '" + getID() + "' without entering it.");
374  }
375  } else {
376  myEnteredContainer[&veh].frontLeaveTime = leaveTimestep;
377  }
378 }
379 
380 
381 void
382 MSE3Collector::leave(const SUMOTrafficObject& veh, const double leaveTimestep, const double fractionTimeOnDet) {
383  if (!vehicleApplies(veh)) {
384  return;
385  }
386  if (myEnteredContainer.find(&veh) == myEnteredContainer.end()) {
387  if (!myOpenEntry) {
388  WRITE_WARNING("Vehicle '" + veh.getID() + "' left " + toString(SUMO_TAG_E3DETECTOR) + " '" + getID() + "' without entering it.");
389  }
390  } else {
391  E3Values values = myEnteredContainer[&veh];
392  values.backLeaveTime = leaveTimestep;
393  const double speedFraction = veh.getSpeed() * (TS - fractionTimeOnDet);
394  values.speedSum -= speedFraction;
395  values.intervalSpeedSum -= speedFraction;
397  // not yet supported
398  values.timeLoss = 0;
399  } else {
400  // timeLoss was initialized when entering
401  values.timeLoss = static_cast<const MSVehicle&>(veh).getTimeLoss() - values.timeLoss;
402  }
403  myEnteredContainer.erase(&veh);
404  myLeftContainer.push_back(values);
405  }
406 }
407 
408 
409 void
411  SUMOTime startTime, SUMOTime stopTime) {
412  dev << " <interval begin=\"" << time2string(startTime) << "\" end=\"" << time2string(stopTime) << "\" " << "id=\"" << myID << "\" ";
413  // collect values about vehicles that have left the area
414  const int vehicleSum = (int) myLeftContainer.size();
415  double meanTravelTime = 0.;
416  double meanOverlapTravelTime = 0.;
417  double meanSpeed = 0.;
418  double meanHaltsPerVehicle = 0.;
419  double meanTimeLoss = 0.;
420  for (const E3Values& values : myLeftContainer) {
421  meanHaltsPerVehicle += (double)values.haltings;
422  meanTravelTime += values.frontLeaveTime - values.entryTime;
423  const double steps = values.backLeaveTime - values.entryTime;
424  meanOverlapTravelTime += steps;
425  meanSpeed += (values.speedSum / steps);
426  meanTimeLoss += STEPS2TIME(values.timeLoss);
427  }
428  meanTravelTime = vehicleSum != 0 ? meanTravelTime / (double)vehicleSum : -1;
429  meanOverlapTravelTime = vehicleSum != 0 ? meanOverlapTravelTime / (double)vehicleSum : -1;
430  meanSpeed = vehicleSum != 0 ? meanSpeed / (double)vehicleSum : -1;
431  meanHaltsPerVehicle = vehicleSum != 0 ? meanHaltsPerVehicle / (double) vehicleSum : -1;
432  meanTimeLoss = vehicleSum != 0 ? meanTimeLoss / (double) vehicleSum : -1;
433  // clear container
434  myLeftContainer.clear();
435 
436  // collect values about vehicles within the container
437  const int vehicleSumWithin = (int) myEnteredContainer.size();
438  double meanSpeedWithin = 0.;
439  double meanDurationWithin = 0.;
440  double meanHaltsPerVehicleWithin = 0.;
441  double meanIntervalSpeedWithin = 0.;
442  double meanIntervalHaltsPerVehicleWithin = 0.;
443  double meanIntervalDurationWithin = 0.;
444  double meanTimeLossWithin = 0.;
445  for (std::map<const SUMOTrafficObject*, E3Values>::iterator i = myEnteredContainer.begin(); i != myEnteredContainer.end(); ++i) {
446  meanHaltsPerVehicleWithin += (double)(*i).second.haltings;
447  meanIntervalHaltsPerVehicleWithin += (double)(*i).second.intervalHaltings;
448  const double end = (*i).second.backLeaveTime == 0 ? STEPS2TIME(stopTime) : (*i).second.backLeaveTime;
449  const double time = end - (*i).second.entryTime;
450  const double timeWithin = MIN2(time, end - STEPS2TIME(startTime));
451  if (i->second.speedSum > 0.) {
452  meanSpeedWithin += i->second.speedSum / time;
453  }
454  if (i->second.intervalSpeedSum > 0.) {
455  meanIntervalSpeedWithin += i->second.intervalSpeedSum / timeWithin;
456  }
457  meanDurationWithin += time;
458  meanIntervalDurationWithin += timeWithin;
459  // reset interval values
460  (*i).second.intervalHaltings = 0;
461  (*i).second.intervalSpeedSum = 0;
462 
463  if (!MSGlobals::gUseMesoSim) {
464  const SUMOTime currentTimeLoss = static_cast<const MSVehicle*>(i->first)->getTimeLoss();
465  meanTimeLossWithin += STEPS2TIME(currentTimeLoss - (*i).second.intervalTimeLoss);
466  (*i).second.intervalTimeLoss = currentTimeLoss;
467  }
468  }
469  myLastResetTime = stopTime;
470  meanSpeedWithin = vehicleSumWithin != 0 ? meanSpeedWithin / (double) vehicleSumWithin : -1;
471  meanHaltsPerVehicleWithin = vehicleSumWithin != 0 ? meanHaltsPerVehicleWithin / (double) vehicleSumWithin : -1;
472  meanDurationWithin = vehicleSumWithin != 0 ? meanDurationWithin / (double) vehicleSumWithin : -1;
473  meanIntervalSpeedWithin = vehicleSumWithin != 0 ? meanIntervalSpeedWithin / (double) vehicleSumWithin : -1;
474  meanIntervalHaltsPerVehicleWithin = vehicleSumWithin != 0 ? meanIntervalHaltsPerVehicleWithin / (double) vehicleSumWithin : -1;
475  meanIntervalDurationWithin = vehicleSumWithin != 0 ? meanIntervalDurationWithin / (double) vehicleSumWithin : -1;
476  meanTimeLossWithin = vehicleSumWithin != 0 ? meanTimeLossWithin / (double) vehicleSumWithin : -1;
477 
478  // write values
479  dev << "meanTravelTime=\"" << meanTravelTime
480  << "\" meanOverlapTravelTime=\"" << meanOverlapTravelTime
481  << "\" meanSpeed=\"" << meanSpeed
482  << "\" meanHaltsPerVehicle=\"" << meanHaltsPerVehicle
483  << "\" meanTimeLoss=\"" << meanTimeLoss
484  << "\" vehicleSum=\"" << vehicleSum
485  << "\" meanSpeedWithin=\"" << meanSpeedWithin
486  << "\" meanHaltsPerVehicleWithin=\"" << meanHaltsPerVehicleWithin
487  << "\" meanDurationWithin=\"" << meanDurationWithin
488  << "\" vehicleSumWithin=\"" << vehicleSumWithin
489  << "\" meanIntervalSpeedWithin=\"" << meanIntervalSpeedWithin
490  << "\" meanIntervalHaltsPerVehicleWithin=\"" << meanIntervalHaltsPerVehicleWithin
491  << "\" meanIntervalDurationWithin=\"" << meanIntervalDurationWithin
492  << "\" meanTimeLossWithin=\"" << meanTimeLossWithin
493  << "\"/>\n";
494 }
495 
496 
497 void
499  dev.writeXMLHeader("e3Detector", "det_e3_file.xsd");
500 }
501 
502 
503 void
505  myCurrentMeanSpeed = 0;
507  for (std::map<const SUMOTrafficObject*, E3Values>::iterator pair = myEnteredContainer.begin(); pair != myEnteredContainer.end(); ++pair) {
508  const SUMOTrafficObject* veh = pair->first;
509 #ifdef DEBUG_E3_DETECTORUPDATE
510  //if (DEBUG_COND(*this) && DEBUG_COND_VEH(*veh)) {
511  if (DEBUG_COND(*this)) {
512  std::cout << SIMTIME << " vehPtr=" << veh << "\n";
513  std::cout << " veh=" << veh->getID() << "\n";
514  }
515 #endif
516  E3Values& values = pair->second;
517  myCurrentMeanSpeed += veh->getSpeed();
518  values.hadUpdate = true;
519  values.speedSum += veh->getSpeed() * TS;
520  values.intervalSpeedSum += veh->getSpeed() * TS;
521  if (veh->getSpeed() < myHaltingSpeedThreshold) {
522  if (values.haltingBegin == -1) {
523  values.haltingBegin = step;
524  }
525  SUMOTime haltingDuration = step - values.haltingBegin;
526  if (haltingDuration >= myHaltingTimeThreshold
527  && haltingDuration < (myHaltingTimeThreshold + DELTA_T)) {
528  values.haltings++;
529  values.intervalHaltings++;
531  }
532  } else {
533  values.haltingBegin = -1;
534  }
535  }
536  if (myEnteredContainer.size() == 0) {
537  myCurrentMeanSpeed = -1;
538  } else {
540  }
541 }
542 
543 
544 double
546  return myCurrentMeanSpeed;
547 }
548 
549 
550 int
553 }
554 
555 
556 int
558  return (int) myEnteredContainer.size();
559 }
560 
561 
562 std::vector<std::string>
564  std::vector<std::string> ret;
565  for (std::map<const SUMOTrafficObject*, E3Values>::const_iterator pair = myEnteredContainer.begin(); pair != myEnteredContainer.end(); ++pair) {
566  ret.push_back((*pair).first->getID());
567  }
568  std::sort(ret.begin(), ret.end());
569  return ret;
570 }
571 
572 void
574  myEnteredContainer.clear();
575 }
576 
577 /****************************************************************************/
CrossSectionVector::const_iterator CrossSectionVectorConstIt
std::vector< MSCrossSection > CrossSectionVector
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:276
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
std::string time2string(SUMOTime t)
convert SUMOTime to string
Definition: SUMOTime.cpp:68
#define STEPS2TIME(x)
Definition: SUMOTime.h:53
#define TS
Definition: SUMOTime.h:40
#define SIMTIME
Definition: SUMOTime.h:60
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
long long int SUMOTime
Definition: SUMOTime.h:31
@ SUMO_TAG_E3DETECTOR
an e3 detector
T MIN2(T a, T b)
Definition: StdDefs.h:73
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:44
A scoped lock which only triggers on condition.
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...
Definition: MSCFModel.cpp:595
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.
A place on the road net (at a certain lane and position on it) where the E3 area begins.
Definition: MSE3Collector.h:64
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.
Definition: MSE3Collector.h:58
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.
double myCurrentMeanSpeed
The current mean speed of known vehicles (inside)
virtual void clearState()
Remove all vehicles before quick-loading state.
void reset()
Resets all generated values to allow computation of next interval.
CrossSectionVector myExits
The detector's exits.
int myCurrentHaltingsNumber
The current number of haltings (inside)
void enter(const SUMOTrafficObject &veh, const double entryTimestep, const double fractionTimeOnDet, MSE3EntryReminder *entryReminder)
Called if a vehicle touches an entry-cross-section.
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
void leave(const SUMOTrafficObject &veh, const double leaveTimestep, const double fractionTimeOnDet)
Called if a vehicle back passes a leave-cross-section.
std::vector< MSE3LeaveReminder * > myLeaveReminders
The detector's built exit reminder.
std::vector< std::string > getCurrentVehicleIDs() const
Returns the number of vehicles within the area.
virtual ~MSE3Collector()
Destructor.
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.
MSE3Collector(const std::string &id, const CrossSectionVector &entries, const CrossSectionVector &exits, double haltingSpeedThreshold, SUMOTime haltingTimeThreshold, const std::string &vTypes, bool openEntry)
Constructor.
SUMOTime myHaltingTimeThreshold
CrossSectionVector myEntries
The detector's entries.
void writeXMLOutput(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Writes collected values into the given stream.
void leaveFront(const SUMOTrafficObject &veh, const double leaveTimestep)
Called if a vehicle front passes a leave-cross-section.
static bool gUseMesoSim
Definition: MSGlobals.h:88
static bool gSemiImplicitEulerUpdate
Definition: MSGlobals.h:53
static int gNumSimThreads
how many threads to use for simulation
Definition: MSGlobals.h:115
Representation of a lane in the micro simulation.
Definition: MSLane.h:82
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:673
Something on a lane to be noticed about vehicle movement.
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:171
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:124
const std::string & getID() const
Returns the id.
Definition: Named.h:73
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:60
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >())
Writes an XML header with optional configuration.
Representation of a vehicle, person, or container.
virtual double getPreviousSpeed() const =0
Returns the object's previous speed.
virtual double getSpeed() const =0
Returns the object's current speed.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual double getBackPositionOnLane(const MSLane *lane) const =0
Get the object's back position along the given lane.
#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.