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