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