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