SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MSE2Collector.cpp
Go to the documentation of this file.
1 /****************************************************************************/
11 // An areal (along a single lane) detector
12 /****************************************************************************/
13 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
14 // Copyright (C) 2001-2013 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 // ===========================================================================
27 // included modules
28 // ===========================================================================
29 #ifdef _MSC_VER
30 #include <windows_config.h>
31 #else
32 #include <config.h>
33 #endif
34 
35 #include <cassert>
36 #include <algorithm>
37 #include "MSE2Collector.h"
38 #include <microsim/MSLane.h>
39 #include <microsim/MSVehicle.h>
40 #include <microsim/MSVehicleType.h>
41 
42 #ifdef CHECK_MEMORY_LEAKS
43 #include <foreign/nvwa/debug_new.h>
44 #endif // CHECK_MEMORY_LEAKS
45 
46 
47 // ===========================================================================
48 // method definitions
49 // ===========================================================================
50 MSE2Collector::MSE2Collector(const std::string& id, DetectorUsage usage,
51  MSLane* const lane, SUMOReal startPos, SUMOReal detLength,
52  SUMOTime haltingTimeThreshold,
53  SUMOReal haltingSpeedThreshold,
54  SUMOReal jamDistThreshold)
56  myJamHaltingSpeedThreshold(haltingSpeedThreshold),
57  myJamHaltingTimeThreshold(haltingTimeThreshold),
58  myJamDistanceThreshold(jamDistThreshold),
59  myStartPos(startPos), myEndPos(startPos + detLength),
60  myUsage(usage),
61  myCurrentOccupancy(0), myCurrentMeanSpeed(-1), myCurrentJamNo(0),
62  myCurrentMaxJamLengthInMeters(0), myCurrentMaxJamLengthInVehicles(0),
63  myCurrentJamLengthInMeters(0), myCurrentJamLengthInVehicles(0), myCurrentStartedHalts(0)
64 
65 {
66  assert(myLane != 0);
67  assert(myStartPos >= 0 && myStartPos < myLane->getLength());
68  assert(myEndPos - myStartPos > 0 && myEndPos <= myLane->getLength());
69  reset();
70 }
71 
72 
74  myKnownVehicles.clear();
75 }
76 
77 
78 bool
80  SUMOReal newPos, SUMOReal) {
81  if (newPos < myStartPos) {
82  // detector not yet reached
83  return true;
84  }
85  if (newPos >= myStartPos && oldPos < myStartPos) {
86  if (find(myKnownVehicles.begin(), myKnownVehicles.end(), &veh) == myKnownVehicles.end()) {
87  myKnownVehicles.push_back(&veh);
88  }
89  }
90  if (newPos - veh.getVehicleType().getLength() > myEndPos) {
91  std::list<SUMOVehicle*>::iterator i = find(myKnownVehicles.begin(), myKnownVehicles.end(), &veh);
92  if (i != myKnownVehicles.end()) {
93  myKnownVehicles.erase(i);
94  }
95  return false;
96  }
97  return true;
98 }
99 
100 
101 bool
103  if (reason != MSMoveReminder::NOTIFICATION_JUNCTION || (lastPos >= myStartPos && lastPos - veh.getVehicleType().getLength() < myEndPos)) {
104  std::list<SUMOVehicle*>::iterator i = find(myKnownVehicles.begin(), myKnownVehicles.end(), &veh);
105  if (i != myKnownVehicles.end()) {
106  myKnownVehicles.erase(i);
107  }
108  return false;
109  }
110  return true;
111 }
112 
113 
114 bool
117  // vehicle is on detector
118  myKnownVehicles.push_back(&veh);
119  return true;
120  }
121  if (veh.getPositionOnLane() - veh.getVehicleType().getLength() > myEndPos) {
122  // vehicle is beyond detector
123  return false;
124  }
125  // vehicle is in front of detector
126  return true;
127 }
128 
129 
130 void
132  mySpeedSum = 0;
133  myStartedHalts = 0;
136  myVehicleSamples = 0;
137  myOccupancySum = 0;
138  myMaxOccupancy = 0;
141  myMaxJamInVehicles = 0;
142  myMaxJamInMeters = 0;
143  myTimeSamples = 0;
145  myMaxVehicleNumber = 0;
146  for (std::map<SUMOVehicle*, SUMOTime>::iterator i = myIntervalHaltingVehicleDurations.begin(); i != myIntervalHaltingVehicleDurations.end(); ++i) {
147  (*i).second = 0;
148  }
149  myPastStandingDurations.clear();
151 }
152 
153 
154 
155 void
157  JamInfo* currentJam = 0;
158  std::map<SUMOVehicle*, SUMOTime> haltingVehicles;
159  std::map<SUMOVehicle*, SUMOTime> intervalHaltingVehicles;
160  std::vector<JamInfo*> jams;
161 
162  SUMOReal lengthSum = 0;
163  myCurrentMeanSpeed = 0;
166 
167  // go through the (sorted) list of vehicles positioned on the detector
168  // sum up values and prepare the list of jams
170  for (std::list<SUMOVehicle*>::const_iterator i = myKnownVehicles.begin(); i != myKnownVehicles.end(); ++i) {
171  MSVehicle* veh = static_cast<MSVehicle*>(*i);
172 
173  SUMOReal length = veh->getVehicleType().getLength();
174  if (veh->getLane() == getLane()) {
175  if (veh->getPositionOnLane() - veh->getVehicleType().getLength() < myStartPos) {
176  // vehicle entered detector partially
177  length -= (veh->getVehicleType().getLength() - (veh->getPositionOnLane() - myStartPos));
178  }
179  if (veh->getPositionOnLane() > myEndPos && veh->getPositionOnLane() - veh->getVehicleType().getLength() <= myEndPos) {
180  // vehicle left detector partially
181  length -= (veh->getPositionOnLane() - myEndPos);
182  }
183  } else {
184  // ok, the vehicle is only partially still on the detector, has already moved to the
185  // next lane; still, we do not know how far away it is
186  assert(veh == myLane->getPartialOccupator());
187  length = myEndPos - myLane->getPartialOccupatorEnd();
188  }
189  assert(length >= 0);
190 
191  mySpeedSum += veh->getSpeed();
192  myCurrentMeanSpeed += veh->getSpeed();
193  lengthSum += length;
194  myCurrentMeanLength += length;
195 
196  // jam-checking begins
197  bool isInJam = false;
198  // first, check whether the vehicle is slow enough to be states as halting
199  if (veh->getSpeed() < myJamHaltingSpeedThreshold) {
200  // we have to track the time it was halting;
201  // so let's look up whether it was halting before and compute the overall halting time
202  bool wasHalting = myHaltingVehicleDurations.find(veh) != myHaltingVehicleDurations.end();
203  if (wasHalting) {
204  haltingVehicles[veh] = myHaltingVehicleDurations[veh] + DELTA_T;
205  intervalHaltingVehicles[veh] = myIntervalHaltingVehicleDurations[veh] + DELTA_T;
206  } else {
207  haltingVehicles[veh] = DELTA_T;
208  intervalHaltingVehicles[veh] = DELTA_T;
210  myStartedHalts++;
211  }
212  // we now check whether the halting time is large enough
213  if (haltingVehicles[veh] > myJamHaltingTimeThreshold) {
214  // yep --> the vehicle is a part of a jam
215  isInJam = true;
216  }
217  } else {
218  // is not standing anymore; keep duration information
219  std::map<SUMOVehicle*, SUMOTime>::iterator v = myHaltingVehicleDurations.find(veh);
220  if (v != myHaltingVehicleDurations.end()) {
221  myPastStandingDurations.push_back((*v).second);
222  myHaltingVehicleDurations.erase(v);
223  }
224  v = myIntervalHaltingVehicleDurations.find(veh);
225  if (v != myIntervalHaltingVehicleDurations.end()) {
226  myPastIntervalStandingDurations.push_back((*v).second);
228  }
229  }
230 
231  // jam-building
232  if (isInJam) {
233  // the vehicle is in a jam;
234  // it may be a new one or already an existing one
235  if (currentJam == 0) {
236  // the vehicle is the first vehicle in a jam
237  currentJam = new JamInfo;
238  currentJam->firstStandingVehicle = i;
239  } else {
240  // ok, we have a jam already. But - maybe it is too far away
241  // ... honestly, I can hardly find a reason for doing this,
242  // but jams were defined this way in an earlier version...
243  if (veh->getPositionOnLane() - (*currentJam->lastStandingVehicle)->getPositionOnLane() > myJamDistanceThreshold) {
244  // yep, yep, yep - it's a new one...
245  // close the frist, build a new
246  jams.push_back(currentJam);
247  currentJam = new JamInfo;
248  currentJam->firstStandingVehicle = i;
249  }
250  }
251  currentJam->lastStandingVehicle = i;
252  } else {
253  // the vehicle is not part of a jam...
254  // maybe we have to close an already computed jam
255  if (currentJam != 0) {
256  jams.push_back(currentJam);
257  currentJam = 0;
258  }
259  }
260  }
261  if (currentJam != 0) {
262  jams.push_back(currentJam);
263  currentJam = 0;
264  }
265 
270  // process jam information
271  for (std::vector<JamInfo*>::iterator i = jams.begin(); i != jams.end(); ++i) {
272  // compute current jam's values
273  SUMOReal jamLengthInMeters =
274  (*(*i)->firstStandingVehicle)->getPositionOnLane()
275  - (*(*i)->lastStandingVehicle)->getPositionOnLane()
276  + (*(*i)->lastStandingVehicle)->getVehicleType().getLengthWithGap();
277  const MSVehicle* const occ = myLane->getPartialOccupator();
278  if (occ && occ == *(*i)->firstStandingVehicle && occ != *(*i)->lastStandingVehicle) {
279  jamLengthInMeters = myLane->getPartialOccupatorEnd() + occ->getVehicleType().getLengthWithGap()
280  - (*(*i)->lastStandingVehicle)->getPositionOnLane()
281  + (*(*i)->lastStandingVehicle)->getVehicleType().getLengthWithGap();
282  }
283  unsigned jamLengthInVehicles = (unsigned) distance((*i)->firstStandingVehicle, (*i)->lastStandingVehicle) + 1;
284  // apply them to the statistics
287  myJamLengthInMetersSum += jamLengthInMeters;
288  myJamLengthInVehiclesSum += jamLengthInVehicles;
289  myCurrentJamLengthInMeters += jamLengthInMeters;
290  myCurrentJamLengthInVehicles += jamLengthInVehicles;
291  }
292  myCurrentJamNo = (unsigned) jams.size();
293 
294  unsigned noVehicles = (unsigned) myKnownVehicles.size();
295  myVehicleSamples += noVehicles;
296  myTimeSamples += 1;
297  // compute occupancy values
298  SUMOReal currentOccupancy = lengthSum / (myEndPos - myStartPos) * (SUMOReal) 100.;
299  myCurrentOccupancy = currentOccupancy;
300  myOccupancySum += currentOccupancy;
301  myMaxOccupancy = MAX2(myMaxOccupancy, currentOccupancy);
302  // compute jam values
307  // save information about halting vehicles
308  myHaltingVehicleDurations = haltingVehicles;
309  myIntervalHaltingVehicleDurations = intervalHaltingVehicles;
310  // compute information about vehicle numbers
311  myMeanVehicleNumber += (unsigned) myKnownVehicles.size();
313  // norm current values
314  myCurrentMeanSpeed = noVehicles != 0 ? myCurrentMeanSpeed / (SUMOReal) noVehicles : -1;
315  myCurrentMeanLength = noVehicles != 0 ? myCurrentMeanLength / (SUMOReal) noVehicles : -1;
316 
317  // clean up
318  for (std::vector<JamInfo*>::iterator i = jams.begin(); i != jams.end(); ++i) {
319  delete *i;
320  }
321  jams.clear();
322 }
323 
324 
325 
326 void
328  dev << " <interval begin=\"" << time2string(startTime) << "\" end=\"" << time2string(stopTime) << "\" " << "id=\"" << getID() << "\" ";
329 
330  const SUMOReal meanSpeed = myVehicleSamples != 0 ? mySpeedSum / (SUMOReal) myVehicleSamples : -1;
331  const SUMOReal meanOccupancy = myTimeSamples != 0 ? myOccupancySum / (SUMOReal) myTimeSamples : 0;
332  const SUMOReal meanJamLengthInMeters = myTimeSamples != 0 ? myMeanMaxJamInMeters / (SUMOReal) myTimeSamples : 0;
333  const SUMOReal meanJamLengthInVehicles = myTimeSamples != 0 ? myMeanMaxJamInVehicles / (SUMOReal) myTimeSamples : 0;
334  const SUMOReal meanVehicleNumber = myTimeSamples != 0 ? (SUMOReal) myMeanVehicleNumber / (SUMOReal) myTimeSamples : 0;
335 
336  SUMOTime haltingDurationSum = 0;
337  SUMOTime maxHaltingDuration = 0;
338  unsigned haltingNo = 0;
339  for (std::vector<SUMOTime>::iterator i = myPastStandingDurations.begin(); i != myPastStandingDurations.end(); ++i) {
340  haltingDurationSum += (*i);
341  maxHaltingDuration = MAX2(maxHaltingDuration, (*i));
342  haltingNo++;
343  }
344  for (std::map<SUMOVehicle*, SUMOTime> ::iterator i = myHaltingVehicleDurations.begin(); i != myHaltingVehicleDurations.end(); ++i) {
345  haltingDurationSum += (*i).second;
346  maxHaltingDuration = MAX2(maxHaltingDuration, (*i).second);
347  haltingNo++;
348  }
349  const SUMOTime meanHaltingDuration = haltingNo != 0 ? haltingDurationSum / haltingNo : 0;
350 
351  SUMOTime intervalHaltingDurationSum = 0;
352  SUMOTime intervalMaxHaltingDuration = 0;
353  unsigned intervalHaltingNo = 0;
354  for (std::vector<SUMOTime>::iterator i = myPastIntervalStandingDurations.begin(); i != myPastIntervalStandingDurations.end(); ++i) {
355  intervalHaltingDurationSum += (*i);
356  intervalMaxHaltingDuration = MAX2(intervalMaxHaltingDuration, (*i));
357  intervalHaltingNo++;
358  }
359  for (std::map<SUMOVehicle*, SUMOTime> ::iterator i = myIntervalHaltingVehicleDurations.begin(); i != myIntervalHaltingVehicleDurations.end(); ++i) {
360  intervalHaltingDurationSum += (*i).second;
361  intervalMaxHaltingDuration = MAX2(intervalMaxHaltingDuration, (*i).second);
362  intervalHaltingNo++;
363  }
364  const SUMOTime intervalMeanHaltingDuration = intervalHaltingNo != 0 ? intervalHaltingDurationSum / intervalHaltingNo : 0;
365 
366  dev << "nSamples=\"" << myVehicleSamples << "\" "
367  << "meanSpeed=\"" << meanSpeed << "\" "
368  << "meanOccupancy=\"" << meanOccupancy << "\" "
369  << "maxOccupancy=\"" << myMaxOccupancy << "\" "
370  << "meanMaxJamLengthInVehicles=\"" << meanJamLengthInVehicles << "\" "
371  << "meanMaxJamLengthInMeters=\"" << meanJamLengthInMeters << "\" "
372  << "maxJamLengthInVehicles=\"" << myMaxJamInVehicles << "\" "
373  << "maxJamLengthInMeters=\"" << myMaxJamInMeters << "\" "
374  << "jamLengthInVehiclesSum=\"" << myJamLengthInVehiclesSum << "\" "
375  << "jamLengthInMetersSum=\"" << myJamLengthInMetersSum << "\" "
376  << "meanHaltingDuration=\"" << STEPS2TIME(meanHaltingDuration) << "\" "
377  << "maxHaltingDuration=\"" << STEPS2TIME(maxHaltingDuration) << "\" "
378  << "haltingDurationSum=\"" << STEPS2TIME(haltingDurationSum) << "\" "
379  << "meanIntervalHaltingDuration=\"" << STEPS2TIME(intervalMeanHaltingDuration) << "\" "
380  << "maxIntervalHaltingDuration=\"" << STEPS2TIME(intervalMaxHaltingDuration) << "\" "
381  << "intervalHaltingDurationSum=\"" << STEPS2TIME(intervalHaltingDurationSum) << "\" "
382  << "startedHalts=\"" << myStartedHalts << "\" "
383  << "meanVehicleNumber=\"" << meanVehicleNumber << "\" "
384  << "maxVehicleNumber=\"" << myMaxVehicleNumber << "\" "
385  << "/>\n";
386  reset();
387 }
388 
389 
390 void
392  dev.writeXMLHeader("detector", "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.sf.net/xsd/det_e2_file.xsd\"");
393 }
394 
395 
396 unsigned
398  return (unsigned) myKnownVehicles.size();
399 }
400 
401 
402 SUMOReal
404  return myCurrentOccupancy * (SUMOReal) 100.;
405 }
406 
407 
408 SUMOReal
410  return myCurrentMeanSpeed;
411 }
412 
413 
414 SUMOReal
416  return myCurrentMeanLength;
417 }
418 
419 
420 unsigned
422  return myCurrentJamNo;
423 }
424 
425 
426 unsigned
429 }
430 
431 
432 SUMOReal
435 }
436 
437 
438 unsigned
441 }
442 
443 
444 SUMOReal
447 }
448 
449 
450 unsigned
452  return myCurrentStartedHalts;
453 }
454 
455 
456 int
458  const MSVehicle* const occ = myLane->getPartialOccupator();
459  if (v1 == occ) {
460  return true;
461  }
462  if (v2 == occ) {
463  return false;
464  }
465  return v1->getPositionOnLane() > v2->getPositionOnLane();
466 }
467 
468 /****************************************************************************/
469