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-2017 German Aerospace Center (DLR) and others.
4 /****************************************************************************/
5 //
6 // This program and the accompanying materials
7 // are made available under the terms of the Eclipse Public License v2.0
8 // which accompanies this distribution, and is available at
9 // http://www.eclipse.org/legal/epl-v20.html
10 //
11 /****************************************************************************/
21 // A detector of vehicles passing an area between entry/exit points
22 /****************************************************************************/
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <algorithm>
34 
35 #include "MSE3Collector.h"
36 #include <microsim/MSNet.h>
37 #include <microsim/MSVehicle.h>
38 
39 
40 // ===========================================================================
41 // method definitions
42 // ===========================================================================
43 /* -------------------------------------------------------------------------
44  * MSE3Collector::MSE3EntryReminder - definitions
45  * ----------------------------------------------------------------------- */
47  const MSCrossSection& crossSection, MSE3Collector& collector) :
48  MSMoveReminder(collector.getID() + "_entry", crossSection.myLane),
49  myCollector(collector), myPosition(crossSection.myPosition) {}
50 
51 
52 bool
54  double newPos, double newSpeed) {
55  if (myCollector.myEnteredContainer.find(&veh) == myCollector.myEnteredContainer.end() && newPos > myPosition) {
56  if (oldPos > myPosition) {
57  // was behind the detector already in the last step
58  return false;
59  } else {
60  // entered in this step
61  const double oldSpeed = veh.getPreviousSpeed();
62  const double entryTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
63  assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the detector otherwise
64  const double timeBeforeEnter = MSCFModel::passingTime(oldPos, myPosition, newPos, oldSpeed, newSpeed);
65  const double fractionTimeOnDet = TS - timeBeforeEnter;
66  myCollector.enter(veh, entryTime - fractionTimeOnDet, fractionTimeOnDet);
67  }
68  }
69  return true;
70 }
71 
72 
73 bool
76  WRITE_WARNING("Vehicle '" + veh.getID() + "' arrived inside " + toString(SUMO_TAG_E3DETECTOR) + " '" + myCollector.getID() + "'.");
77  myCollector.myEnteredContainer.erase(&veh);
78  return false;
79  }
80  return true;
81 }
82 
83 
84 /* -------------------------------------------------------------------------
85  * MSE3Collector::MSE3LeaveReminder - definitions
86  * ----------------------------------------------------------------------- */
88  const MSCrossSection& crossSection, MSE3Collector& collector) :
89  MSMoveReminder(collector.getID() + "_exit", crossSection.myLane),
90  myCollector(collector), myPosition(crossSection.myPosition) {}
91 
92 
93 bool
95  double newPos, double newSpeed) {
96  if (newPos < myPosition) {
97  // crossSection not yet reached
98  return true;
99  }
100  const double oldSpeed = veh.getPreviousSpeed();
101  if (oldPos < myPosition) {
102  assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the detector otherwise
103  const double timeBeforeLeave = MSCFModel::passingTime(oldPos, myPosition, newPos, oldSpeed, newSpeed);
104 // const double leaveTimeFront = SIMTIME - TS + (myPosition - oldPos) / newSpeed;
105  const double leaveTimeFront = SIMTIME - TS + timeBeforeLeave;
106  myCollector.leaveFront(veh, leaveTimeFront);
107  }
108  const double backPos = newPos - veh.getVehicleType().getLength();
109  if (backPos < myPosition) {
110  // crossSection not yet left
111  return true;
112  }
113  // crossSection left
114  const double oldBackPos = oldPos - veh.getVehicleType().getLength();
115  const double leaveStep = SIMTIME;
116  assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the detector otherwise
117  const double timeBeforeLeave = MSCFModel::passingTime(oldBackPos, myPosition, backPos, oldSpeed, newSpeed);
118  myCollector.leave(veh, leaveStep - TS + timeBeforeLeave, timeBeforeLeave);
119  return false;
120 }
121 
122 
123 bool
124 MSE3Collector::MSE3LeaveReminder::notifyLeave(SUMOVehicle& veh , double /* lastPos */, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
126  return false;
127  }
129  WRITE_WARNING("Vehicle '" + veh.getID() + "' teleported from " + toString(SUMO_TAG_E3DETECTOR) + " '" + myCollector.getID() + "'.");
130  myCollector.myEnteredContainer.erase(&veh);
131  return false;
132  }
133  return true;
134 }
135 
136 /* -------------------------------------------------------------------------
137  * MSE3Collector - definitions
138  * ----------------------------------------------------------------------- */
139 MSE3Collector::MSE3Collector(const std::string& id,
140  const CrossSectionVector& entries,
141  const CrossSectionVector& exits,
142  double haltingSpeedThreshold,
143  SUMOTime haltingTimeThreshold,
144  const std::string& vTypes)
145  : MSDetectorFileOutput(id, vTypes), myEntries(entries), myExits(exits),
146  myHaltingTimeThreshold(haltingTimeThreshold), myHaltingSpeedThreshold(haltingSpeedThreshold),
148  // Set MoveReminders to entries and exits
149  for (CrossSectionVectorConstIt crossSec1 = entries.begin(); crossSec1 != entries.end(); ++crossSec1) {
150  myEntryReminders.push_back(new MSE3EntryReminder(*crossSec1, *this));
151  }
152  for (CrossSectionVectorConstIt crossSec2 = exits.begin(); crossSec2 != exits.end(); ++crossSec2) {
153  myLeaveReminders.push_back(new MSE3LeaveReminder(*crossSec2, *this));
154  }
155  reset();
156 }
157 
158 
160  for (std::vector<MSE3EntryReminder*>::iterator i = myEntryReminders.begin(); i != myEntryReminders.end(); ++i) {
161  delete *i;
162  }
163  for (std::vector<MSE3LeaveReminder*>::iterator i = myLeaveReminders.begin(); i != myLeaveReminders.end(); ++i) {
164  delete *i;
165  }
166 }
167 
168 
169 void
171  myLeftContainer.clear();
172 }
173 
174 
175 
176 void
177 MSE3Collector::enter(const SUMOVehicle& veh, const double entryTimestep, const double fractionTimeOnDet) {
178  if (myEnteredContainer.find(&veh) != myEnteredContainer.end()) {
179  WRITE_WARNING("Vehicle '" + veh.getID() + "' reentered " + toString(SUMO_TAG_E3DETECTOR) + " '" + getID() + "'.");
180  return;
181  }
182  const double speedFraction = veh.getSpeed() * fractionTimeOnDet;
183  E3Values v;
184  v.entryTime = entryTimestep;
185  v.frontLeaveTime = 0;
186  v.backLeaveTime = 0;
187  v.speedSum = speedFraction;
188  v.haltingBegin = veh.getSpeed() < myHaltingSpeedThreshold ? entryTimestep : -1;
189  v.intervalSpeedSum = entryTimestep >= STEPS2TIME(myLastResetTime) ? speedFraction : 0;
190  v.haltings = 0;
191  v.intervalHaltings = 0;
192  if (veh.getSpeed() < myHaltingSpeedThreshold) {
193  if (fractionTimeOnDet > myHaltingTimeThreshold) {
194  v.haltings++;
195  v.intervalHaltings++;
196  }
197  }
198  v.hadUpdate = false;
199  if (!MSGlobals::gUseMesoSim) {
200  v.timeLoss = static_cast<const MSVehicle&>(veh).getTimeLoss();
202  }
203 
204  myEnteredContainer[&veh] = v;
205 }
206 
207 
208 void
209 MSE3Collector::leaveFront(const SUMOVehicle& veh, const double leaveTimestep) {
210  if (myEnteredContainer.find(&veh) == myEnteredContainer.end()) {
211  WRITE_WARNING("Vehicle '" + veh.getID() + "' left " + toString(SUMO_TAG_E3DETECTOR) + " '" + getID() + "' without entering it.");
212  } else {
213  myEnteredContainer[&veh].frontLeaveTime = leaveTimestep;
214  }
215 }
216 
217 
218 void
219 MSE3Collector::leave(const SUMOVehicle& veh, const double leaveTimestep, const double fractionTimeOnDet) {
220  if (myEnteredContainer.find(&veh) == myEnteredContainer.end()) {
221  WRITE_WARNING("Vehicle '" + veh.getID() + "' left " + toString(SUMO_TAG_E3DETECTOR) + " '" + getID() + "' without entering it.");
222  } else {
223  E3Values values = myEnteredContainer[&veh];
224  values.backLeaveTime = leaveTimestep;
225  const double speedFraction = veh.getSpeed() * (TS - fractionTimeOnDet);
226  values.speedSum -= speedFraction;
227  values.intervalSpeedSum -= speedFraction;
229  // not yet supported
230  values.timeLoss = 0;
231  } else {
232  // timeLoss was initialized when entering
233  values.timeLoss = static_cast<const MSVehicle&>(veh).getTimeLoss() - values.timeLoss;
234  }
235  myEnteredContainer.erase(&veh);
236  myLeftContainer[&veh] = values;
237  }
238 }
239 
240 
241 void
243  SUMOTime startTime, SUMOTime stopTime) {
244  dev << " <interval begin=\"" << time2string(startTime) << "\" end=\"" << time2string(stopTime) << "\" " << "id=\"" << myID << "\" ";
245  // collect values about vehicles that have left the area
246  const int vehicleSum = (int) myLeftContainer.size();
247  double meanTravelTime = 0.;
248  double meanOverlapTravelTime = 0.;
249  double meanSpeed = 0.;
250  double meanHaltsPerVehicle = 0.;
251  double meanTimeLoss = 0.;
252  for (std::map<const SUMOVehicle*, E3Values>::iterator i = myLeftContainer.begin(); i != myLeftContainer.end(); ++i) {
253  meanHaltsPerVehicle += (double)(*i).second.haltings;
254  meanTravelTime += (*i).second.frontLeaveTime - (*i).second.entryTime;
255  const double steps = (*i).second.backLeaveTime - (*i).second.entryTime;
256  meanOverlapTravelTime += steps;
257  meanSpeed += ((*i).second.speedSum / steps);
258  meanTimeLoss += STEPS2TIME((*i).second.timeLoss);
259  }
260  meanTravelTime = vehicleSum != 0 ? meanTravelTime / (double)vehicleSum : -1;
261  meanOverlapTravelTime = vehicleSum != 0 ? meanOverlapTravelTime / (double)vehicleSum : -1;
262  meanSpeed = vehicleSum != 0 ? meanSpeed / (double)vehicleSum : -1;
263  meanHaltsPerVehicle = vehicleSum != 0 ? meanHaltsPerVehicle / (double) vehicleSum : -1;
264  meanTimeLoss = vehicleSum != 0 ? meanTimeLoss / (double) vehicleSum : -1;
265  // clear container
266  myLeftContainer.clear();
267 
268  // collect values about vehicles within the container
269  const int vehicleSumWithin = (int) myEnteredContainer.size();
270  double meanSpeedWithin = 0.;
271  double meanDurationWithin = 0.;
272  double meanHaltsPerVehicleWithin = 0.;
273  double meanIntervalSpeedWithin = 0.;
274  double meanIntervalHaltsPerVehicleWithin = 0.;
275  double meanIntervalDurationWithin = 0.;
276  double meanTimeLossWithin = 0.;
277  for (std::map<const SUMOVehicle*, E3Values>::iterator i = myEnteredContainer.begin(); i != myEnteredContainer.end(); ++i) {
278  meanHaltsPerVehicleWithin += (double)(*i).second.haltings;
279  meanIntervalHaltsPerVehicleWithin += (double)(*i).second.intervalHaltings;
280  const double end = (*i).second.backLeaveTime == 0 ? STEPS2TIME(stopTime) : (*i).second.backLeaveTime;
281  const double time = end - (*i).second.entryTime;
282  const double timeWithin = MIN2(time, end - STEPS2TIME(startTime));
283  if (i->second.speedSum > 0.) {
284  meanSpeedWithin += i->second.speedSum / time;
285  }
286  if (i->second.intervalSpeedSum > 0.) {
287  meanIntervalSpeedWithin += i->second.intervalSpeedSum / timeWithin;
288  }
289  meanDurationWithin += time;
290  meanIntervalDurationWithin += timeWithin;
291  // reset interval values
292  (*i).second.intervalHaltings = 0;
293  (*i).second.intervalSpeedSum = 0;
294 
295  if (!MSGlobals::gUseMesoSim) {
296  const SUMOTime currentTimeLoss = static_cast<const MSVehicle*>(i->first)->getTimeLoss();
297  meanTimeLossWithin += STEPS2TIME(currentTimeLoss - (*i).second.intervalTimeLoss);
298  (*i).second.intervalTimeLoss = currentTimeLoss;
299  }
300  }
301  myLastResetTime = stopTime;
302  meanSpeedWithin = vehicleSumWithin != 0 ? meanSpeedWithin / (double) vehicleSumWithin : -1;
303  meanHaltsPerVehicleWithin = vehicleSumWithin != 0 ? meanHaltsPerVehicleWithin / (double) vehicleSumWithin : -1;
304  meanDurationWithin = vehicleSumWithin != 0 ? meanDurationWithin / (double) vehicleSumWithin : -1;
305  meanIntervalSpeedWithin = vehicleSumWithin != 0 ? meanIntervalSpeedWithin / (double) vehicleSumWithin : -1;
306  meanIntervalHaltsPerVehicleWithin = vehicleSumWithin != 0 ? meanIntervalHaltsPerVehicleWithin / (double) vehicleSumWithin : -1;
307  meanIntervalDurationWithin = vehicleSumWithin != 0 ? meanIntervalDurationWithin / (double) vehicleSumWithin : -1;
308  meanTimeLossWithin = vehicleSumWithin != 0 ? meanTimeLossWithin / (double) vehicleSumWithin : -1;
309 
310  // write values
311  dev << "meanTravelTime=\"" << meanTravelTime
312  << "\" meanOverlapTravelTime=\"" << meanOverlapTravelTime
313  << "\" meanSpeed=\"" << meanSpeed
314  << "\" meanHaltsPerVehicle=\"" << meanHaltsPerVehicle
315  << "\" meanTimeLoss=\"" << meanTimeLoss
316  << "\" vehicleSum=\"" << vehicleSum
317  << "\" meanSpeedWithin=\"" << meanSpeedWithin
318  << "\" meanHaltsPerVehicleWithin=\"" << meanHaltsPerVehicleWithin
319  << "\" meanDurationWithin=\"" << meanDurationWithin
320  << "\" vehicleSumWithin=\"" << vehicleSumWithin
321  << "\" meanIntervalSpeedWithin=\"" << meanIntervalSpeedWithin
322  << "\" meanIntervalHaltsPerVehicleWithin=\"" << meanIntervalHaltsPerVehicleWithin
323  << "\" meanIntervalDurationWithin=\"" << meanIntervalDurationWithin
324  << "\" meanTimeLossWithin=\"" << meanTimeLossWithin
325  << "\"/>\n";
326 }
327 
328 
329 void
331  dev.writeXMLHeader("e3Detector", "det_e3_file.xsd");
332 }
333 
334 
335 void
337  myCurrentMeanSpeed = 0;
339  for (std::map<const SUMOVehicle*, E3Values>::iterator pair = myEnteredContainer.begin(); pair != myEnteredContainer.end(); ++pair) {
340  const SUMOVehicle* veh = pair->first;
341  E3Values& values = pair->second;
342  myCurrentMeanSpeed += veh->getSpeed();
343  values.hadUpdate = true;
344  values.speedSum += veh->getSpeed() * TS;
345  values.intervalSpeedSum += veh->getSpeed() * TS;
346  if (veh->getSpeed() < myHaltingSpeedThreshold) {
347  if (values.haltingBegin == -1) {
348  values.haltingBegin = STEPS2TIME(step);
349  }
350  if (step - values.haltingBegin > myHaltingTimeThreshold) {
351  values.haltings++;
352  values.intervalHaltings++;
354  }
355  } else {
356  values.haltingBegin = -1;
357  }
358  }
359  if (myEnteredContainer.size() == 0) {
360  myCurrentMeanSpeed = -1;
361  } else {
363  }
364 }
365 
366 
367 double
369  return myCurrentMeanSpeed;
370 }
371 
372 
373 int
376 }
377 
378 
379 int
381  return (int) myEnteredContainer.size();
382 }
383 
384 
385 std::vector<std::string>
387  std::vector<std::string> ret;
388  for (std::map<const SUMOVehicle*, E3Values>::const_iterator pair = myEnteredContainer.begin(); pair != myEnteredContainer.end(); ++pair) {
389  ret.push_back((*pair).first->getID());
390  }
391  std::sort(ret.begin(), ret.end());
392  return ret;
393 }
394 
395 
396 /****************************************************************************/
397 
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:70
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:59
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:167
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:65
std::vector< MSE3LeaveReminder * > myLeaveReminders
The detector&#39;s built exit reminder.
#define TS
Definition: SUMOTime.h:51
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:199
#define SIMTIME
Definition: SUMOTime.h:71
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:55
Representation of a vehicle.
Definition: SUMOVehicle.h:66
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:64
T MIN2(T a, T b)
Definition: StdDefs.h:67
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:552
std::string myID
The name of the object.
Definition: Named.h:135
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:64
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:70
static bool gSemiImplicitEulerUpdate
Definition: MSGlobals.h:62
long long int SUMOTime
Definition: TraCIDefs.h:51
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:97
Representation of a lane in the micro simulation.
Definition: MSLane.h:77
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.