SUMO - Simulation of Urban MObility
MSE3Collector.cpp
Go to the documentation of this file.
1 /****************************************************************************/
11 // A detector of vehicles passing an area between entry/exit points
12 /****************************************************************************/
13 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
14 // Copyright (C) 2001-2017 DLR (http://www.dlr.de/) and contributors
15 /****************************************************************************/
16 //
17 // This file is part of SUMO.
18 // SUMO is free software: you can redistribute it and/or modify
19 // it under the terms of the GNU General Public License as published by
20 // the Free Software Foundation, either version 3 of the License, or
21 // (at your option) any later version.
22 //
23 /****************************************************************************/
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #include <algorithm>
35 
36 #include "MSE3Collector.h"
37 #include <microsim/MSNet.h>
38 #include <microsim/MSVehicle.h>
39 
40 
41 // ===========================================================================
42 // method definitions
43 // ===========================================================================
44 /* -------------------------------------------------------------------------
45  * MSE3Collector::MSE3EntryReminder - definitions
46  * ----------------------------------------------------------------------- */
48  const MSCrossSection& crossSection, MSE3Collector& collector) :
49  MSMoveReminder(collector.getID() + "_entry", crossSection.myLane),
50  myCollector(collector), myPosition(crossSection.myPosition) {}
51 
52 
53 bool
55  double newPos, double newSpeed) {
56  if (myCollector.myEnteredContainer.find(&veh) == myCollector.myEnteredContainer.end() && newPos > myPosition) {
57  if (oldPos > myPosition) {
58  // was behind the detector already in the last step
59  return false;
60  } else {
61  // entered in this step
62  const double oldSpeed = veh.getPreviousSpeed();
63  const double entryTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
64  assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the detector otherwise
65  const double timeBeforeEnter = MSCFModel::passingTime(oldPos, myPosition, newPos, oldSpeed, newSpeed);
66  const double fractionTimeOnDet = TS - timeBeforeEnter;
67  myCollector.enter(veh, entryTime - fractionTimeOnDet, fractionTimeOnDet);
68  }
69  }
70  return true;
71 }
72 
73 
74 bool
77  WRITE_WARNING("Vehicle '" + veh.getID() + "' arrived inside " + toString(SUMO_TAG_E3DETECTOR) + " '" + myCollector.getID() + "'.");
78  myCollector.myEnteredContainer.erase(&veh);
79  return false;
80  }
81  return true;
82 }
83 
84 
85 /* -------------------------------------------------------------------------
86  * MSE3Collector::MSE3LeaveReminder - definitions
87  * ----------------------------------------------------------------------- */
89  const MSCrossSection& crossSection, MSE3Collector& collector) :
90  MSMoveReminder(collector.getID() + "_exit", crossSection.myLane),
91  myCollector(collector), myPosition(crossSection.myPosition) {}
92 
93 
94 bool
96  double newPos, double newSpeed) {
97  if (newPos < myPosition) {
98  // crossSection not yet reached
99  return true;
100  }
101  const double oldSpeed = veh.getPreviousSpeed();
102  if (oldPos < myPosition) {
103  assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the detector otherwise
104  const double timeBeforeLeave = MSCFModel::passingTime(oldPos, myPosition, newPos, oldSpeed, newSpeed);
105 // const double leaveTimeFront = SIMTIME - TS + (myPosition - oldPos) / newSpeed;
106  const double leaveTimeFront = SIMTIME - TS + timeBeforeLeave;
107  myCollector.leaveFront(veh, leaveTimeFront);
108  }
109  const double backPos = newPos - veh.getVehicleType().getLength();
110  if (backPos < myPosition) {
111  // crossSection not yet left
112  return true;
113  }
114  // crossSection left
115  const double oldBackPos = oldPos - veh.getVehicleType().getLength();
116  const double leaveStep = SIMTIME;
117  assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the detector otherwise
118  const double timeBeforeLeave = MSCFModel::passingTime(oldBackPos, myPosition, backPos, oldSpeed, newSpeed);
119  myCollector.leave(veh, leaveStep - TS + timeBeforeLeave, timeBeforeLeave);
120  return false;
121 }
122 
123 
124 bool
125 MSE3Collector::MSE3LeaveReminder::notifyLeave(SUMOVehicle& veh , double /* lastPos */, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
127  return false;
128  }
130  WRITE_WARNING("Vehicle '" + veh.getID() + "' teleported from " + toString(SUMO_TAG_E3DETECTOR) + " '" + myCollector.getID() + "'.");
131  myCollector.myEnteredContainer.erase(&veh);
132  return false;
133  }
134  return true;
135 }
136 
137 /* -------------------------------------------------------------------------
138  * MSE3Collector - definitions
139  * ----------------------------------------------------------------------- */
140 MSE3Collector::MSE3Collector(const std::string& id,
141  const CrossSectionVector& entries,
142  const CrossSectionVector& exits,
143  double haltingSpeedThreshold,
144  SUMOTime haltingTimeThreshold,
145  const std::string& vTypes)
146  : MSDetectorFileOutput(id, vTypes), myEntries(entries), myExits(exits),
147  myHaltingTimeThreshold(haltingTimeThreshold), myHaltingSpeedThreshold(haltingSpeedThreshold),
149  // Set MoveReminders to entries and exits
150  for (CrossSectionVectorConstIt crossSec1 = entries.begin(); crossSec1 != entries.end(); ++crossSec1) {
151  myEntryReminders.push_back(new MSE3EntryReminder(*crossSec1, *this));
152  }
153  for (CrossSectionVectorConstIt crossSec2 = exits.begin(); crossSec2 != exits.end(); ++crossSec2) {
154  myLeaveReminders.push_back(new MSE3LeaveReminder(*crossSec2, *this));
155  }
156  reset();
157 }
158 
159 
161  for (std::vector<MSE3EntryReminder*>::iterator i = myEntryReminders.begin(); i != myEntryReminders.end(); ++i) {
162  delete *i;
163  }
164  for (std::vector<MSE3LeaveReminder*>::iterator i = myLeaveReminders.begin(); i != myLeaveReminders.end(); ++i) {
165  delete *i;
166  }
167 }
168 
169 
170 void
172  myLeftContainer.clear();
173 }
174 
175 
176 
177 void
178 MSE3Collector::enter(const SUMOVehicle& veh, const double entryTimestep, const double fractionTimeOnDet) {
179  if (myEnteredContainer.find(&veh) != myEnteredContainer.end()) {
180  WRITE_WARNING("Vehicle '" + veh.getID() + "' reentered " + toString(SUMO_TAG_E3DETECTOR) + " '" + getID() + "'.");
181  return;
182  }
183  const double speedFraction = veh.getSpeed() * fractionTimeOnDet;
184  E3Values v;
185  v.entryTime = entryTimestep;
186  v.frontLeaveTime = 0;
187  v.backLeaveTime = 0;
188  v.speedSum = speedFraction;
189  v.haltingBegin = veh.getSpeed() < myHaltingSpeedThreshold ? entryTimestep : -1;
190  v.intervalSpeedSum = entryTimestep >= STEPS2TIME(myLastResetTime) ? speedFraction : 0;
191  v.haltings = 0;
192  v.intervalHaltings = 0;
193  if (veh.getSpeed() < myHaltingSpeedThreshold) {
194  if (fractionTimeOnDet > myHaltingTimeThreshold) {
195  v.haltings++;
196  v.intervalHaltings++;
197  }
198  }
199  v.hadUpdate = false;
200  if (!MSGlobals::gUseMesoSim) {
201  v.timeLoss = static_cast<const MSVehicle&>(veh).getTimeLoss();
203  }
204 
205  myEnteredContainer[&veh] = v;
206 }
207 
208 
209 void
210 MSE3Collector::leaveFront(const SUMOVehicle& veh, const double leaveTimestep) {
211  if (myEnteredContainer.find(&veh) == myEnteredContainer.end()) {
212  WRITE_WARNING("Vehicle '" + veh.getID() + "' left " + toString(SUMO_TAG_E3DETECTOR) + " '" + getID() + "' without entering it.");
213  } else {
214  myEnteredContainer[&veh].frontLeaveTime = leaveTimestep;
215  }
216 }
217 
218 
219 void
220 MSE3Collector::leave(const SUMOVehicle& veh, const double leaveTimestep, const double fractionTimeOnDet) {
221  if (myEnteredContainer.find(&veh) == myEnteredContainer.end()) {
222  WRITE_WARNING("Vehicle '" + veh.getID() + "' left " + toString(SUMO_TAG_E3DETECTOR) + " '" + getID() + "' without entering it.");
223  } else {
224  E3Values values = myEnteredContainer[&veh];
225  values.backLeaveTime = leaveTimestep;
226  const double speedFraction = veh.getSpeed() * (TS - fractionTimeOnDet);
227  values.speedSum -= speedFraction;
228  values.intervalSpeedSum -= speedFraction;
230  // not yet supported
231  values.timeLoss = 0;
232  } else {
233  // timeLoss was initialized when entering
234  values.timeLoss = static_cast<const MSVehicle&>(veh).getTimeLoss() - values.timeLoss;
235  }
236  myEnteredContainer.erase(&veh);
237  myLeftContainer[&veh] = values;
238  }
239 }
240 
241 
242 void
244  SUMOTime startTime, SUMOTime stopTime) {
245  dev << " <interval begin=\"" << time2string(startTime) << "\" end=\"" << time2string(stopTime) << "\" " << "id=\"" << myID << "\" ";
246  // collect values about vehicles that have left the area
247  const int vehicleSum = (int) myLeftContainer.size();
248  double meanTravelTime = 0.;
249  double meanOverlapTravelTime = 0.;
250  double meanSpeed = 0.;
251  double meanHaltsPerVehicle = 0.;
252  double meanTimeLoss = 0.;
253  for (std::map<const SUMOVehicle*, E3Values>::iterator i = myLeftContainer.begin(); i != myLeftContainer.end(); ++i) {
254  meanHaltsPerVehicle += (double)(*i).second.haltings;
255  meanTravelTime += (*i).second.frontLeaveTime - (*i).second.entryTime;
256  const double steps = (*i).second.backLeaveTime - (*i).second.entryTime;
257  meanOverlapTravelTime += steps;
258  meanSpeed += ((*i).second.speedSum / steps);
259  meanTimeLoss += STEPS2TIME((*i).second.timeLoss);
260  }
261  meanTravelTime = vehicleSum != 0 ? meanTravelTime / (double)vehicleSum : -1;
262  meanOverlapTravelTime = vehicleSum != 0 ? meanOverlapTravelTime / (double)vehicleSum : -1;
263  meanSpeed = vehicleSum != 0 ? meanSpeed / (double)vehicleSum : -1;
264  meanHaltsPerVehicle = vehicleSum != 0 ? meanHaltsPerVehicle / (double) vehicleSum : -1;
265  meanTimeLoss = vehicleSum != 0 ? meanTimeLoss / (double) vehicleSum : -1;
266  // clear container
267  myLeftContainer.clear();
268 
269  // collect values about vehicles within the container
270  const int vehicleSumWithin = (int) myEnteredContainer.size();
271  double meanSpeedWithin = 0.;
272  double meanDurationWithin = 0.;
273  double meanHaltsPerVehicleWithin = 0.;
274  double meanIntervalSpeedWithin = 0.;
275  double meanIntervalHaltsPerVehicleWithin = 0.;
276  double meanIntervalDurationWithin = 0.;
277  double meanTimeLossWithin = 0.;
278  for (std::map<const SUMOVehicle*, E3Values>::iterator i = myEnteredContainer.begin(); i != myEnteredContainer.end(); ++i) {
279  meanHaltsPerVehicleWithin += (double)(*i).second.haltings;
280  meanIntervalHaltsPerVehicleWithin += (double)(*i).second.intervalHaltings;
281  const double end = (*i).second.backLeaveTime == 0 ? STEPS2TIME(stopTime) : (*i).second.backLeaveTime;
282  const double time = end - (*i).second.entryTime;
283  const double timeWithin = MIN2(time, end - STEPS2TIME(startTime));
284  if (i->second.speedSum > 0.) {
285  meanSpeedWithin += i->second.speedSum / time;
286  }
287  if (i->second.intervalSpeedSum > 0.) {
288  meanIntervalSpeedWithin += i->second.intervalSpeedSum / timeWithin;
289  }
290  meanDurationWithin += time;
291  meanIntervalDurationWithin += timeWithin;
292  // reset interval values
293  (*i).second.intervalHaltings = 0;
294  (*i).second.intervalSpeedSum = 0;
295 
296  if (!MSGlobals::gUseMesoSim) {
297  const SUMOTime currentTimeLoss = static_cast<const MSVehicle*>(i->first)->getTimeLoss();
298  meanTimeLossWithin += STEPS2TIME(currentTimeLoss - (*i).second.intervalTimeLoss);
299  (*i).second.intervalTimeLoss = currentTimeLoss;
300  }
301  }
302  myLastResetTime = stopTime;
303  meanSpeedWithin = vehicleSumWithin != 0 ? meanSpeedWithin / (double) vehicleSumWithin : -1;
304  meanHaltsPerVehicleWithin = vehicleSumWithin != 0 ? meanHaltsPerVehicleWithin / (double) vehicleSumWithin : -1;
305  meanDurationWithin = vehicleSumWithin != 0 ? meanDurationWithin / (double) vehicleSumWithin : -1;
306  meanIntervalSpeedWithin = vehicleSumWithin != 0 ? meanIntervalSpeedWithin / (double) vehicleSumWithin : -1;
307  meanIntervalHaltsPerVehicleWithin = vehicleSumWithin != 0 ? meanIntervalHaltsPerVehicleWithin / (double) vehicleSumWithin : -1;
308  meanIntervalDurationWithin = vehicleSumWithin != 0 ? meanIntervalDurationWithin / (double) vehicleSumWithin : -1;
309  meanTimeLossWithin = vehicleSumWithin != 0 ? meanTimeLossWithin / (double) vehicleSumWithin : -1;
310 
311  // write values
312  dev << "meanTravelTime=\"" << meanTravelTime
313  << "\" meanOverlapTravelTime=\"" << meanOverlapTravelTime
314  << "\" meanSpeed=\"" << meanSpeed
315  << "\" meanHaltsPerVehicle=\"" << meanHaltsPerVehicle
316  << "\" meanTimeLoss=\"" << meanTimeLoss
317  << "\" vehicleSum=\"" << vehicleSum
318  << "\" meanSpeedWithin=\"" << meanSpeedWithin
319  << "\" meanHaltsPerVehicleWithin=\"" << meanHaltsPerVehicleWithin
320  << "\" meanDurationWithin=\"" << meanDurationWithin
321  << "\" vehicleSumWithin=\"" << vehicleSumWithin
322  << "\" meanIntervalSpeedWithin=\"" << meanIntervalSpeedWithin
323  << "\" meanIntervalHaltsPerVehicleWithin=\"" << meanIntervalHaltsPerVehicleWithin
324  << "\" meanIntervalDurationWithin=\"" << meanIntervalDurationWithin
325  << "\" meanTimeLossWithin=\"" << meanTimeLossWithin
326  << "\"/>\n";
327 }
328 
329 
330 void
332  dev.writeXMLHeader("e3Detector", "det_e3_file.xsd");
333 }
334 
335 
336 void
338  myCurrentMeanSpeed = 0;
340  for (std::map<const SUMOVehicle*, E3Values>::iterator pair = myEnteredContainer.begin(); pair != myEnteredContainer.end(); ++pair) {
341  const SUMOVehicle* veh = pair->first;
342  E3Values& values = pair->second;
343  myCurrentMeanSpeed += veh->getSpeed();
344  values.hadUpdate = true;
345  values.speedSum += veh->getSpeed() * TS;
346  values.intervalSpeedSum += veh->getSpeed() * TS;
347  if (veh->getSpeed() < myHaltingSpeedThreshold) {
348  if (values.haltingBegin == -1) {
349  values.haltingBegin = STEPS2TIME(step);
350  }
351  if (step - values.haltingBegin > myHaltingTimeThreshold) {
352  values.haltings++;
353  values.intervalHaltings++;
355  }
356  } else {
357  values.haltingBegin = -1;
358  }
359  }
360  if (myEnteredContainer.size() == 0) {
361  myCurrentMeanSpeed = -1;
362  } else {
364  }
365 }
366 
367 
368 double
370  return myCurrentMeanSpeed;
371 }
372 
373 
374 int
377 }
378 
379 
380 int
382  return (int) myEnteredContainer.size();
383 }
384 
385 
386 std::vector<std::string>
388  std::vector<std::string> ret;
389  for (std::map<const SUMOVehicle*, E3Values>::const_iterator pair = myEnteredContainer.begin(); pair != myEnteredContainer.end(); ++pair) {
390  ret.push_back((*pair).first->getID());
391  }
392  std::sort(ret.begin(), ret.end());
393  return ret;
394 }
395 
396 
397 /****************************************************************************/
398 
double intervalSpeedSum
The sum of registered speeds the vehicle has/had inside the area during the current interval...
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:83
bool notifyMove(SUMOVehicle &veh, double, double newPos, double)
Checks whether the vehicle enters.
int haltings
The sum of haltings the vehicle has/had within the area.
int getCurrentHaltingNumber() const
Returns the number of current haltings within the area.
void enter(const SUMOVehicle &veh, const double entryTimestep, const double fractionTimeOnDet)
Called if a vehicle touches an entry-cross-section.
virtual ~MSE3Collector()
Destructor.
A simple description of a position on a lane (crossing of a lane)
std::vector< MSE3EntryReminder * > myEntryReminders
The detector&#39;s built entry reminder.
bool hadUpdate
An internal information whether the update step was performed.
A place on the road net (at a certain lane and position on it) where the E3 area ends.
MSE3EntryReminder(const MSCrossSection &crossSection, MSE3Collector &collector)
Constructor.
A place on the road net (at a certain lane and position on it) where the E3 area begins.
Definition: MSE3Collector.h:71
MSLane *const myLane
Lane on which the reminder works.
double myHaltingSpeedThreshold
Speed-threshold to determine if a vehicle is halting.
Notification
Definition of a vehicle state.
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:60
std::vector< MSCrossSection > CrossSectionVector
double frontLeaveTime
The time the vehicle&#39;s front was crossing the leave line.
double myCurrentMeanSpeed
The current mean speed of known vehicles (inside)
CrossSectionVector::const_iterator CrossSectionVectorConstIt
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:158
SUMOTime myLastResetTime
Information when the last reset has been done.
std::vector< std::string > getCurrentVehicleIDs() const
Returns the number of vehicles within the area.
MSE3Collector(const std::string &id, const CrossSectionVector &entries, const CrossSectionVector &exits, double haltingSpeedThreshold, SUMOTime haltingTimeThreshold, const std::string &vTypes)
Constructor.
const std::string & getID() const
Returns the id.
Definition: Named.h:66
std::vector< MSE3LeaveReminder * > myLeaveReminders
The detector&#39;s built exit reminder.
#define TS
Definition: SUMOTime.h:52
bool notifyLeave(SUMOVehicle &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Processes state changes of a vehicle.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
#define SIMTIME
Definition: SUMOTime.h:70
double backLeaveTime
The time the vehicle&#39;s back was crossing the leave line.
int myCurrentHaltingsNumber
The current number of haltings (inside)
The vehicle changes lanes (micro only)
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:56
Representation of a vehicle.
Definition: SUMOVehicle.h:67
std::map< const SUMOVehicle *, E3Values > myEnteredContainer
Container for vehicles that have entered the area.
Internal storage for values from a vehicle.
double entryTime
The vehicle&#39;s entry time.
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.
double getCurrentMeanSpeed() const
Returns the mean speed within the area.
SUMOTime myHaltingTimeThreshold
The vehicle arrived at its destination (is deleted)
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
T MIN2(T a, T b)
Definition: StdDefs.h:64
MSE3Collector & myCollector
The parent collector.
Something on a lane to be noticed about vehicle movement.
bool notifyMove(SUMOVehicle &veh, double oldPos, double newPos, double)
Checks whether the vehicle leaves.
MSE3LeaveReminder(const MSCrossSection &crossSection, MSE3Collector &collector)
Constructor.
void leaveFront(const SUMOVehicle &veh, const double leaveTimestep)
Called if a vehicle front passes a leave-cross-section.
void leave(const SUMOVehicle &veh, const double leaveTimestep, const double fractionTimeOnDet)
Called if a vehicle back passes a leave-cross-section.
SUMOTime intervalTimeLoss
The timeLoss of the vehicle when entering. Updated to the current timeLoss at interval write...
CrossSectionVector myEntries
The detector&#39;s entries.
double myPosition
The position on the lane.
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:372
std::string myID
The name of the object.
Definition: Named.h:136
double speedSum
The sum of registered speeds the vehicle has/had inside the area.
bool notifyLeave(SUMOVehicle &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Processes state changes of a vehicle.
double getLength() const
Get vehicle&#39;s length [m].
void reset()
Resets all generated values to allow computation of next interval.
A detector of vehicles passing an area between entry/exit points.
Definition: MSE3Collector.h:65
int intervalHaltings
The sum of haltings the vehicle has/had within the area during the current interval.
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:71
static bool gSemiImplicitEulerUpdate
Definition: MSGlobals.h:63
long long int SUMOTime
Definition: TraCIDefs.h:52
int getVehiclesWithin() const
Returns the number of vehicles within the area.
void detectorUpdate(const SUMOTime step)
Computes the detector values in each time step.
virtual double getSpeed() const =0
Returns the vehicle&#39;s current speed.
static bool gUseMesoSim
Definition: MSGlobals.h:98
Representation of a lane in the micro simulation.
Definition: MSLane.h:79
double haltingBegin
Begin time of last halt begin.
virtual double getPreviousSpeed() const =0
Returns the vehicle&#39;s previous speed.
virtual const std::string & getID() const =0
Get the vehicle&#39;s ID.
void writeXMLOutput(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Writes collected values into the given stream.
MSE3Collector & myCollector
The parent collector.
SUMOTime timeLoss
The timeLoss of the vehicle when entering. Updated to the actual time loss within the area when leavi...
Base of value-generating classes (detectors)
double myPosition
The position on the lane.
The vehicle is being teleported.
CrossSectionVector myExits
The detector&#39;s exits.
void writeXMLDetectorProlog(OutputDevice &dev) const
Opens the XML-output using "e3Detector" as root element.
virtual const MSVehicleType & getVehicleType() const =0
Returns the vehicle&#39;s type.
std::map< const SUMOVehicle *, E3Values > myLeftContainer
Container for vehicles that have left the area.