SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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.sourceforge.net/
14 // Copyright (C) 2001-2012 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 #ifdef CHECK_MEMORY_LEAKS
41 #include <foreign/nvwa/debug_new.h>
42 #endif // CHECK_MEMORY_LEAKS
43 
44 
45 // ===========================================================================
46 // method definitions
47 // ===========================================================================
48 /* -------------------------------------------------------------------------
49  * MSE3Collector::MSE3EntryReminder - definitions
50  * ----------------------------------------------------------------------- */
52  const MSCrossSection& crossSection, MSE3Collector& collector)
53  : MSMoveReminder(crossSection.myLane),
54  myCollector(collector), myPosition(crossSection.myPosition) {}
55 
56 
57 bool
59  SUMOReal newPos, SUMOReal newSpeed) {
60  if (newPos < myPosition/* && static_cast<MSVehicle&>(veh).getLane() == myLane*/) {
61  return true;
62  }
63  if (newPos >= myPosition && oldPos <= myPosition/* && static_cast<MSVehicle&>(veh).getLane() == myLane*/) {
64  SUMOReal entryTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
65  if (newSpeed != 0) {
66  if (myPosition > oldPos) {
67  entryTime += (myPosition - oldPos) / newSpeed;
68  }
69  }
70  myCollector.enter(veh, entryTime);
71  }
72  return myCollector.myEnteredContainer.find(&veh) != myCollector.myEnteredContainer.end();
73 }
74 
75 
76 bool
79  myCollector.myEnteredContainer.erase(&veh);
80  return false;
81  }
82  return myCollector.myEnteredContainer.find(&veh) != myCollector.myEnteredContainer.end();
83 }
84 
85 
86 /* -------------------------------------------------------------------------
87  * MSE3Collector::MSE3LeaveReminder - definitions
88  * ----------------------------------------------------------------------- */
90  const MSCrossSection& crossSection, MSE3Collector& collector)
91  : MSMoveReminder(crossSection.myLane),
92  myCollector(collector), myPosition(crossSection.myPosition) {}
93 
94 
95 bool
97  SUMOReal newPos, SUMOReal newSpeed) {
98  if (newPos <= myPosition) {
99  // crossSection not yet reached
100  return true;
101  }
102  if (oldPos > myPosition) {
103  // crossSection was not passed
104  return false;
105  }
106  // crossSection left
107  SUMOReal leaveTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
108  if (myPosition > oldPos) {
109  leaveTime += (myPosition - oldPos) / newSpeed;
110  }
111  myCollector.leave(veh, leaveTime);
112  return false;
113 }
114 
115 
116 /* -------------------------------------------------------------------------
117  * MSE3Collector - definitions
118  * ----------------------------------------------------------------------- */
119 MSE3Collector::MSE3Collector(const std::string& id,
120  const CrossSectionVector& entries,
121  const CrossSectionVector& exits,
122  SUMOReal haltingSpeedThreshold,
123  SUMOTime haltingTimeThreshold)
124  : MSDetectorFileOutput(id), myEntries(entries), myExits(exits),
125  myHaltingTimeThreshold(haltingTimeThreshold), myHaltingSpeedThreshold(haltingSpeedThreshold),
127  myLastResetTime(-1) {
128  // Set MoveReminders to entries and exits
129  for (CrossSectionVectorConstIt crossSec1 = entries.begin(); crossSec1 != entries.end(); ++crossSec1) {
130  myEntryReminders.push_back(new MSE3EntryReminder(*crossSec1, *this));
131  }
132  for (CrossSectionVectorConstIt crossSec2 = exits.begin(); crossSec2 != exits.end(); ++crossSec2) {
133  myLeaveReminders.push_back(new MSE3LeaveReminder(*crossSec2, *this));
134  }
135  reset();
136 }
137 
138 
140  for (std::vector<MSE3EntryReminder*>::iterator i = myEntryReminders.begin(); i != myEntryReminders.end(); ++i) {
141  delete *i;
142  }
143  for (std::vector<MSE3LeaveReminder*>::iterator i = myLeaveReminders.begin(); i != myLeaveReminders.end(); ++i) {
144  delete *i;
145  }
146 }
147 
148 
149 void
151  myLeftContainer.clear();
152 }
153 
154 
155 
156 void
158  if (myEnteredContainer.find(&veh) != myEnteredContainer.end()) {
159  WRITE_WARNING("Vehicle '" + veh.getID() + "' reentered " + toString(SUMO_TAG_E3DETECTOR) + " '" + getID() + "'.");
160  return;
161  }
162  SUMOReal entryTimestepFraction = ((SUMOReal) DELTA_T - fmod(entryTimestep * 1000., 1000.)) / (SUMOReal) DELTA_T;
163  SUMOReal speedFraction = (veh.getSpeed() * entryTimestepFraction);
164  E3Values v;
165  v.entryTime = entryTimestep;
166  v.leaveTime = 0;
167  v.speedSum = speedFraction / (1000. / (SUMOReal) DELTA_T);
168  v.haltingBegin = veh.getSpeed() < myHaltingSpeedThreshold ? entryTimestep : -1;
169  v.intervalSpeedSum = speedFraction / (1000. / (SUMOReal) DELTA_T);
170  v.haltings = 0;
171  v.intervalHaltings = 0;
172  if (veh.getSpeed() < myHaltingSpeedThreshold) {
173  if (1. - entryTimestepFraction > myHaltingTimeThreshold) {
174  v.haltings++;
175  v.intervalHaltings++;
176  }
177  }
178  v.hadUpdate = false;
179  myEnteredContainer[&veh] = v;
180 }
181 
182 
183 void
185  if (myEnteredContainer.find(&veh) == myEnteredContainer.end()) {
186  WRITE_WARNING("Vehicle '" + veh.getID() + "' left " + toString(SUMO_TAG_E3DETECTOR) + " '" + getID() + "' before entering it.");
187  } else {
188  E3Values values = myEnteredContainer[&veh];
189  values.leaveTime = leaveTimestep;
190  SUMOReal leaveTimestepFraction = leaveTimestep - (SUMOReal)((int) leaveTimestep);
191  leaveTimestepFraction = fmod(leaveTimestep * 1000., 1000.) / (SUMOReal) DELTA_T;
192  if (values.hadUpdate) {
193  SUMOReal speedFraction = (veh.getSpeed() * leaveTimestepFraction);
194  values.speedSum += speedFraction / (1000. / (SUMOReal) DELTA_T);
195  values.intervalSpeedSum += speedFraction / (1000. / (SUMOReal) DELTA_T);
196  if (veh.getSpeed() < myHaltingSpeedThreshold && values.haltingBegin != -1 && leaveTimestep - values.haltingBegin > myHaltingTimeThreshold) {
197  values.haltings++;
198  values.intervalHaltings++;
199  }
200  } else {
201  SUMOReal speedFraction = (veh.getSpeed() * SUMOReal(1. - leaveTimestepFraction));
202  values.speedSum -= speedFraction / (1000. / (SUMOReal) DELTA_T);
203  values.intervalSpeedSum -= speedFraction / (1000. / (SUMOReal) DELTA_T);
204  }
205  myEnteredContainer.erase(&veh);
206  myLeftContainer[&veh] = values;
207  }
208 }
209 
210 
211 void
213  SUMOTime startTime, SUMOTime stopTime) {
214  dev << " <interval begin=\"" << time2string(startTime) << "\" end=\"" << time2string(stopTime) << "\" " << "id=\"" << myID << "\" ";
215  // collect values about vehicles that have left the area
216  unsigned vehicleSum = (unsigned) myLeftContainer.size();
217  SUMOReal meanTravelTime = 0.;
218  SUMOReal meanSpeed = 0.;
219  SUMOReal meanHaltsPerVehicle = 0.;
220  for (std::map<SUMOVehicle*, E3Values>::iterator i = myLeftContainer.begin(); i != myLeftContainer.end(); ++i) {
221  meanHaltsPerVehicle += (SUMOReal)(*i).second.haltings;
222  SUMOReal steps = (*i).second.leaveTime - (*i).second.entryTime;
223  meanTravelTime += steps;
224  meanSpeed += ((*i).second.speedSum / steps);
225  }
226  meanTravelTime = vehicleSum != 0 ? meanTravelTime / (SUMOReal) vehicleSum : -1;
227  meanSpeed = vehicleSum != 0 ? meanSpeed / (SUMOReal) vehicleSum : -1;
228  meanHaltsPerVehicle = vehicleSum != 0 ? meanHaltsPerVehicle / (SUMOReal) vehicleSum : -1;
229  // clear container
230  myLeftContainer.clear();
231 
232  // collect values about vehicles within the container
233  unsigned vehicleSumWithin = (unsigned) myEnteredContainer.size();
234  SUMOReal meanSpeedWithin = 0.;
235  SUMOReal meanDurationWithin = 0.;
236  SUMOReal meanHaltsPerVehicleWithin = 0.;
237  SUMOReal meanIntervalSpeedWithin = 0.;
238  SUMOReal meanIntervalHaltsPerVehicleWithin = 0.;
239  SUMOReal meanIntervalDurationWithin = 0.;
240  for (std::map<SUMOVehicle*, E3Values>::iterator i = myEnteredContainer.begin(); i != myEnteredContainer.end(); ++i) {
241  meanHaltsPerVehicleWithin += (SUMOReal)(*i).second.haltings;
242  meanIntervalHaltsPerVehicleWithin += (SUMOReal)(*i).second.intervalHaltings;
243  SUMOReal time = (SUMOReal)stopTime / 1000. - (*i).second.entryTime;
244  SUMOReal intLength = (SUMOReal)(stopTime - startTime) / 1000.;
245  SUMOReal timeWithin = MIN2(time, intLength);
246  meanSpeedWithin += ((*i).second.speedSum / time);
247  meanIntervalSpeedWithin += ((*i).second.intervalSpeedSum / timeWithin);
248  meanDurationWithin += time;
249  meanIntervalDurationWithin += timeWithin;
250  // reset interval values
251  (*i).second.intervalHaltings = 0;
252  (*i).second.intervalSpeedSum = 0;
253  }
254  myLastResetTime = stopTime;
255  meanSpeedWithin = vehicleSumWithin != 0 ? meanSpeedWithin / (SUMOReal) vehicleSumWithin : -1;
256  meanHaltsPerVehicleWithin = vehicleSumWithin != 0 ? meanHaltsPerVehicleWithin / (SUMOReal) vehicleSumWithin : -1;
257  meanDurationWithin = vehicleSumWithin != 0 ? meanDurationWithin / (SUMOReal) vehicleSumWithin : -1;
258  meanIntervalSpeedWithin = vehicleSumWithin != 0 ? meanIntervalSpeedWithin / (SUMOReal) vehicleSumWithin : -1;
259  meanIntervalHaltsPerVehicleWithin = vehicleSumWithin != 0 ? meanIntervalHaltsPerVehicleWithin / (SUMOReal) vehicleSumWithin : -1;
260  meanIntervalDurationWithin = vehicleSumWithin != 0 ? meanIntervalDurationWithin / (SUMOReal) vehicleSumWithin : -1;
261 
262  // write values
263  dev << "meanTravelTime=\"" << meanTravelTime
264  << "\" meanSpeed=\"" << meanSpeed
265  << "\" meanHaltsPerVehicle=\"" << meanHaltsPerVehicle
266  << "\" vehicleSum=\"" << vehicleSum
267  << "\" meanSpeedWithin=\"" << meanSpeedWithin
268  << "\" meanHaltsPerVehicleWithin=\"" << meanHaltsPerVehicleWithin
269  << "\" meanDurationWithin=\"" << meanDurationWithin
270  << "\" vehicleSumWithin=\"" << vehicleSumWithin
271  << "\" meanIntervalSpeedWithin=\"" << meanIntervalSpeedWithin
272  << "\" meanIntervalHaltsPerVehicleWithin=\"" << meanIntervalHaltsPerVehicleWithin
273  << "\" meanIntervalDurationWithin=\"" << meanIntervalDurationWithin
274  << "\"/>\n";
275 }
276 
277 
278 void
280  dev.writeXMLHeader("e3Detector");
281 }
282 
283 
284 void
286  myCurrentMeanSpeed = 0;
289  for (std::map<SUMOVehicle*, E3Values>::iterator pair = myEnteredContainer.begin(); pair != myEnteredContainer.end(); ++pair) {
290  SUMOVehicle* veh = pair->first;
291  E3Values& values = pair->second;
292  values.hadUpdate = true;
293  if (values.entryTime * 1000. >= step) {
294  // vehicle entered at this time step
295  SUMOReal fraction = step + 1. - values.entryTime;
296  myCurrentMeanSpeed += fraction * veh->getSpeed();
297  myCurrentTouchedVehicles += fraction;
298  if (values.haltingBegin >= 0) {
300  }
301  continue;
302  }
303  values.speedSum += veh->getSpeed() * TS;
304  values.intervalSpeedSum += veh->getSpeed() * TS;
305  myCurrentMeanSpeed += veh->getSpeed();
307  if (veh->getSpeed() < myHaltingSpeedThreshold) {
308  if (values.haltingBegin == -1) {
309  values.haltingBegin = step;
310  }
311  if (step - values.haltingBegin > myHaltingTimeThreshold) {
312  values.haltings++;
313  values.intervalHaltings++;
315  }
316  } else {
317  values.haltingBegin = -1;
318  }
320  }
321 }
322 
323 
324 SUMOReal
326  SUMOReal ret = 0;
327  if (myEnteredContainer.size() == 0) {
328  return -1;
329  }
330  for (std::map<SUMOVehicle*, E3Values>::const_iterator pair = myEnteredContainer.begin(); pair != myEnteredContainer.end(); ++pair) {
331  ret += (*pair).first->getSpeed();
332  }
333  return ret / SUMOReal(myEnteredContainer.size());
334 }
335 
336 
337 SUMOReal
340 }
341 
342 
343 SUMOReal
345  return (SUMOReal) myEnteredContainer.size();
346 }
347 
348 
349 std::vector<std::string>
351  std::vector<std::string> ret;
352  for (std::map<SUMOVehicle*, E3Values>::const_iterator pair = myEnteredContainer.begin(); pair != myEnteredContainer.end(); ++pair) {
353  ret.push_back((*pair).first->getID());
354  }
355  std::sort(ret.begin(), ret.end());
356  return ret;
357 }
358 
359 
360 /****************************************************************************/
361