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 /****************************************************************************/
13 // An areal (along a single lane) detector
14 /****************************************************************************/
15 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
16 // Copyright (C) 2014 DLR (http://www.dlr.de/) and contributors
17 /****************************************************************************/
18 //
19 // This file is part of SUMO.
20 // SUMO is free software: you can redistribute it and/or modify
21 // it under the terms of the GNU General Public License as published by
22 // the Free Software Foundation, either version 3 of the License, or
23 // (at your option) any later version.
24 //
25 /****************************************************************************/
26 
27 
28 // ===========================================================================
29 // included modules
30 // ===========================================================================
31 #ifdef _MSC_VER
32 #include <windows_config.h>
33 #else
34 #include <config.h>
35 #endif
36 
37 #include <cassert>
38 #include <algorithm>
39 #include "MSE2Collector.h"
40 #include <microsim/MSLane.h>
41 #include <microsim/MSVehicle.h>
42 #include <microsim/MSVehicleType.h>
43 
44 #ifdef CHECK_MEMORY_LEAKS
45 #include <foreign/nvwa/debug_new.h>
46 #endif // CHECK_MEMORY_LEAKS
47 
48 
49 // ===========================================================================
50 // method definitions
51 // ===========================================================================
52 MSE2Collector::MSE2Collector(const std::string& id, DetectorUsage usage,
53  MSLane* const lane, SUMOReal startPos, SUMOReal detLength,
54  SUMOTime haltingTimeThreshold,
55  SUMOReal haltingSpeedThreshold,
56  SUMOReal jamDistThreshold) :
57  MSMoveReminder(id, lane),
59  myJamHaltingSpeedThreshold(haltingSpeedThreshold),
60  myJamHaltingTimeThreshold(haltingTimeThreshold),
61  myJamDistanceThreshold(jamDistThreshold),
62  myStartPos(startPos), myEndPos(startPos + detLength),
63  myUsage(usage),
64  myCurrentOccupancy(0), myCurrentMeanSpeed(-1), myCurrentJamNo(0),
65  myCurrentMaxJamLengthInMeters(0), myCurrentMaxJamLengthInVehicles(0),
66  myCurrentJamLengthInMeters(0), myCurrentJamLengthInVehicles(0), myCurrentStartedHalts(0),
67  myCurrentHaltingsNumber(0)
68 
69 {
70  assert(myLane != 0);
71  assert(myStartPos >= 0 && myStartPos < myLane->getLength());
72  assert(myEndPos - myStartPos > 0 && myEndPos <= myLane->getLength());
73  reset();
74 }
75 
76 
78  myKnownVehicles.clear();
79 }
80 
81 
82 bool
84  SUMOReal newPos, SUMOReal) {
85  if (newPos < myStartPos) {
86  // detector not yet reached
87  return true;
88  }
89  if (newPos >= myStartPos && oldPos < myStartPos) {
90  if (find(myKnownVehicles.begin(), myKnownVehicles.end(), &veh) == myKnownVehicles.end()) {
91  myKnownVehicles.push_back(&veh);
92  }
93  }
94  if (newPos - veh.getVehicleType().getLength() > myEndPos) {
95  std::list<SUMOVehicle*>::iterator i = find(myKnownVehicles.begin(), myKnownVehicles.end(), &veh);
96  if (i != myKnownVehicles.end()) {
97  myKnownVehicles.erase(i);
98  }
99  return false;
100  }
101  return true;
102 }
103 
104 
105 bool
107  if (reason != MSMoveReminder::NOTIFICATION_JUNCTION || (lastPos >= myStartPos && lastPos - veh.getVehicleType().getLength() < myEndPos)) {
108  std::list<SUMOVehicle*>::iterator i = find(myKnownVehicles.begin(), myKnownVehicles.end(), &veh);
109  if (i != myKnownVehicles.end()) {
110  myKnownVehicles.erase(i);
111  }
112  return false;
113  }
114  return true;
115 }
116 
117 
118 bool
120  if (!veh.isOnRoad()) {
121  // vehicle is teleporting over the edge
122  return false;
123  }
125  // vehicle is on detector
126  myKnownVehicles.push_back(&veh);
127  return true;
128  }
129  if (veh.getPositionOnLane() - veh.getVehicleType().getLength() > myEndPos) {
130  // vehicle is beyond detector
131  return false;
132  }
133  // vehicle is in front of detector
134  return true;
135 }
136 
137 
138 void
140  mySpeedSum = 0;
141  myStartedHalts = 0;
144  myVehicleSamples = 0;
145  myOccupancySum = 0;
146  myMaxOccupancy = 0;
149  myMaxJamInVehicles = 0;
150  myMaxJamInMeters = 0;
151  myTimeSamples = 0;
153  myMaxVehicleNumber = 0;
154  for (std::map<const SUMOVehicle*, SUMOTime>::iterator i = myIntervalHaltingVehicleDurations.begin(); i != myIntervalHaltingVehicleDurations.end(); ++i) {
155  (*i).second = 0;
156  }
157  myPastStandingDurations.clear();
159 }
160 
161 
162 
163 void
165  JamInfo* currentJam = 0;
166  std::map<const SUMOVehicle*, SUMOTime> haltingVehicles;
167  std::map<const SUMOVehicle*, SUMOTime> intervalHaltingVehicles;
168  std::vector<JamInfo*> jams;
169 
170  SUMOReal lengthSum = 0;
171  myCurrentMeanSpeed = 0;
175 
176  // go through the (sorted) list of vehicles positioned on the detector
177  // sum up values and prepare the list of jams
179  for (std::list<SUMOVehicle*>::const_iterator i = myKnownVehicles.begin(); i != myKnownVehicles.end(); ++i) {
180  const MSVehicle* const veh = static_cast<MSVehicle*>(*i);
181 
182  SUMOReal length = veh->getVehicleType().getLength();
183  if (veh->getLane() == getLane()) {
184  if (veh->getPositionOnLane() - veh->getVehicleType().getLength() < myStartPos) {
185  // vehicle entered detector partially
186  length -= (veh->getVehicleType().getLength() - (veh->getPositionOnLane() - myStartPos));
187  }
188  if (veh->getPositionOnLane() > myEndPos && veh->getPositionOnLane() - veh->getVehicleType().getLength() <= myEndPos) {
189  // vehicle left detector partially
190  length -= (veh->getPositionOnLane() - myEndPos);
191  }
192  } else {
193  // ok, the vehicle is only partially still on the detector, has already moved to the
194  // next lane; still, we do not know how far away it is
195  assert(veh == myLane->getPartialOccupator());
196  length = myEndPos - myLane->getPartialOccupatorEnd();
197  }
198  assert(length >= 0);
199 
200  mySpeedSum += veh->getSpeed();
201  myCurrentMeanSpeed += veh->getSpeed();
202  lengthSum += length;
203  myCurrentMeanLength += length;
204 
205  // jam-checking begins
206  bool isInJam = false;
207  // first, check whether the vehicle is slow enough to be states as halting
208  if (veh->getSpeed() < myJamHaltingSpeedThreshold) {
210  // we have to track the time it was halting;
211  // so let's look up whether it was halting before and compute the overall halting time
212  bool wasHalting = myHaltingVehicleDurations.find(veh) != myHaltingVehicleDurations.end();
213  if (wasHalting) {
214  haltingVehicles[veh] = myHaltingVehicleDurations[veh] + DELTA_T;
215  intervalHaltingVehicles[veh] = myIntervalHaltingVehicleDurations[veh] + DELTA_T;
216  } else {
217  haltingVehicles[veh] = DELTA_T;
218  intervalHaltingVehicles[veh] = DELTA_T;
220  myStartedHalts++;
221  }
222  // we now check whether the halting time is large enough
223  if (haltingVehicles[veh] > myJamHaltingTimeThreshold) {
224  // yep --> the vehicle is a part of a jam
225  isInJam = true;
226  }
227  } else {
228  // is not standing anymore; keep duration information
229  std::map<const SUMOVehicle*, SUMOTime>::iterator v = myHaltingVehicleDurations.find(veh);
230  if (v != myHaltingVehicleDurations.end()) {
231  myPastStandingDurations.push_back((*v).second);
232  myHaltingVehicleDurations.erase(v);
233  }
234  v = myIntervalHaltingVehicleDurations.find(veh);
235  if (v != myIntervalHaltingVehicleDurations.end()) {
236  myPastIntervalStandingDurations.push_back((*v).second);
238  }
239  }
240 
241  // jam-building
242  if (isInJam) {
243  // the vehicle is in a jam;
244  // it may be a new one or already an existing one
245  if (currentJam == 0) {
246  // the vehicle is the first vehicle in a jam
247  currentJam = new JamInfo;
248  currentJam->firstStandingVehicle = i;
249  } else {
250  // ok, we have a jam already. But - maybe it is too far away
251  // ... honestly, I can hardly find a reason for doing this,
252  // but jams were defined this way in an earlier version...
253  if (veh->getPositionOnLane() - (*currentJam->lastStandingVehicle)->getPositionOnLane() > myJamDistanceThreshold) {
254  // yep, yep, yep - it's a new one...
255  // close the frist, build a new
256  jams.push_back(currentJam);
257  currentJam = new JamInfo;
258  currentJam->firstStandingVehicle = i;
259  }
260  }
261  currentJam->lastStandingVehicle = i;
262  } else {
263  // the vehicle is not part of a jam...
264  // maybe we have to close an already computed jam
265  if (currentJam != 0) {
266  jams.push_back(currentJam);
267  currentJam = 0;
268  }
269  }
270  }
271  if (currentJam != 0) {
272  jams.push_back(currentJam);
273  currentJam = 0;
274  }
275 
280  // process jam information
281  for (std::vector<JamInfo*>::iterator i = jams.begin(); i != jams.end(); ++i) {
282  // compute current jam's values
283  SUMOReal jamLengthInMeters =
284  (*(*i)->firstStandingVehicle)->getPositionOnLane()
285  - (*(*i)->lastStandingVehicle)->getPositionOnLane()
286  + (*(*i)->lastStandingVehicle)->getVehicleType().getLengthWithGap();
287  const MSVehicle* const occ = myLane->getPartialOccupator();
288  if (occ && occ == *(*i)->firstStandingVehicle && occ != *(*i)->lastStandingVehicle) {
289  jamLengthInMeters = myLane->getPartialOccupatorEnd() + occ->getVehicleType().getLengthWithGap()
290  - (*(*i)->lastStandingVehicle)->getPositionOnLane()
291  + (*(*i)->lastStandingVehicle)->getVehicleType().getLengthWithGap();
292  }
293  unsigned jamLengthInVehicles = (unsigned) distance((*i)->firstStandingVehicle, (*i)->lastStandingVehicle) + 1;
294  // apply them to the statistics
297  myJamLengthInMetersSum += jamLengthInMeters;
298  myJamLengthInVehiclesSum += jamLengthInVehicles;
299  myCurrentJamLengthInMeters += jamLengthInMeters;
300  myCurrentJamLengthInVehicles += jamLengthInVehicles;
301  }
302  myCurrentJamNo = (unsigned) jams.size();
303 
304  unsigned noVehicles = (unsigned) myKnownVehicles.size();
305  myVehicleSamples += noVehicles;
306  myTimeSamples += 1;
307  // compute occupancy values
308  SUMOReal currentOccupancy = lengthSum / (myEndPos - myStartPos) * (SUMOReal) 100.;
309  myCurrentOccupancy = currentOccupancy;
310  myOccupancySum += currentOccupancy;
311  myMaxOccupancy = MAX2(myMaxOccupancy, currentOccupancy);
312  // compute jam values
317  // save information about halting vehicles
318  myHaltingVehicleDurations = haltingVehicles;
319  myIntervalHaltingVehicleDurations = intervalHaltingVehicles;
320  // compute information about vehicle numbers
321  myMeanVehicleNumber += (unsigned) myKnownVehicles.size();
323  // norm current values
324  myCurrentMeanSpeed = noVehicles != 0 ? myCurrentMeanSpeed / (SUMOReal) noVehicles : -1;
325  myCurrentMeanLength = noVehicles != 0 ? myCurrentMeanLength / (SUMOReal) noVehicles : -1;
326 
327  // clean up
328  for (std::vector<JamInfo*>::iterator i = jams.begin(); i != jams.end(); ++i) {
329  delete *i;
330  }
331  jams.clear();
332 }
333 
334 
335 
336 void
338  dev << " <interval begin=\"" << time2string(startTime) << "\" end=\"" << time2string(stopTime) << "\" " << "id=\"" << getID() << "\" ";
339 
340  const SUMOReal meanSpeed = myVehicleSamples != 0 ? mySpeedSum / (SUMOReal) myVehicleSamples : -1;
341  const SUMOReal meanOccupancy = myTimeSamples != 0 ? myOccupancySum / (SUMOReal) myTimeSamples : 0;
342  const SUMOReal meanJamLengthInMeters = myTimeSamples != 0 ? myMeanMaxJamInMeters / (SUMOReal) myTimeSamples : 0;
343  const SUMOReal meanJamLengthInVehicles = myTimeSamples != 0 ? myMeanMaxJamInVehicles / (SUMOReal) myTimeSamples : 0;
344  const SUMOReal meanVehicleNumber = myTimeSamples != 0 ? (SUMOReal) myMeanVehicleNumber / (SUMOReal) myTimeSamples : 0;
345 
346  SUMOTime haltingDurationSum = 0;
347  SUMOTime maxHaltingDuration = 0;
348  unsigned haltingNo = 0;
349  for (std::vector<SUMOTime>::iterator i = myPastStandingDurations.begin(); i != myPastStandingDurations.end(); ++i) {
350  haltingDurationSum += (*i);
351  maxHaltingDuration = MAX2(maxHaltingDuration, (*i));
352  haltingNo++;
353  }
354  for (std::map<const SUMOVehicle*, SUMOTime> ::iterator i = myHaltingVehicleDurations.begin(); i != myHaltingVehicleDurations.end(); ++i) {
355  haltingDurationSum += (*i).second;
356  maxHaltingDuration = MAX2(maxHaltingDuration, (*i).second);
357  haltingNo++;
358  }
359  const SUMOTime meanHaltingDuration = haltingNo != 0 ? haltingDurationSum / haltingNo : 0;
360 
361  SUMOTime intervalHaltingDurationSum = 0;
362  SUMOTime intervalMaxHaltingDuration = 0;
363  unsigned intervalHaltingNo = 0;
364  for (std::vector<SUMOTime>::iterator i = myPastIntervalStandingDurations.begin(); i != myPastIntervalStandingDurations.end(); ++i) {
365  intervalHaltingDurationSum += (*i);
366  intervalMaxHaltingDuration = MAX2(intervalMaxHaltingDuration, (*i));
367  intervalHaltingNo++;
368  }
369  for (std::map<const SUMOVehicle*, SUMOTime> ::iterator i = myIntervalHaltingVehicleDurations.begin(); i != myIntervalHaltingVehicleDurations.end(); ++i) {
370  intervalHaltingDurationSum += (*i).second;
371  intervalMaxHaltingDuration = MAX2(intervalMaxHaltingDuration, (*i).second);
372  intervalHaltingNo++;
373  }
374  const SUMOTime intervalMeanHaltingDuration = intervalHaltingNo != 0 ? intervalHaltingDurationSum / intervalHaltingNo : 0;
375 
376  dev << "nSamples=\"" << myVehicleSamples << "\" "
377  << "meanSpeed=\"" << meanSpeed << "\" "
378  << "meanOccupancy=\"" << meanOccupancy << "\" "
379  << "maxOccupancy=\"" << myMaxOccupancy << "\" "
380  << "meanMaxJamLengthInVehicles=\"" << meanJamLengthInVehicles << "\" "
381  << "meanMaxJamLengthInMeters=\"" << meanJamLengthInMeters << "\" "
382  << "maxJamLengthInVehicles=\"" << myMaxJamInVehicles << "\" "
383  << "maxJamLengthInMeters=\"" << myMaxJamInMeters << "\" "
384  << "jamLengthInVehiclesSum=\"" << myJamLengthInVehiclesSum << "\" "
385  << "jamLengthInMetersSum=\"" << myJamLengthInMetersSum << "\" "
386  << "meanHaltingDuration=\"" << STEPS2TIME(meanHaltingDuration) << "\" "
387  << "maxHaltingDuration=\"" << STEPS2TIME(maxHaltingDuration) << "\" "
388  << "haltingDurationSum=\"" << STEPS2TIME(haltingDurationSum) << "\" "
389  << "meanIntervalHaltingDuration=\"" << STEPS2TIME(intervalMeanHaltingDuration) << "\" "
390  << "maxIntervalHaltingDuration=\"" << STEPS2TIME(intervalMaxHaltingDuration) << "\" "
391  << "intervalHaltingDurationSum=\"" << STEPS2TIME(intervalHaltingDurationSum) << "\" "
392  << "startedHalts=\"" << myStartedHalts << "\" "
393  << "meanVehicleNumber=\"" << meanVehicleNumber << "\" "
394  << "maxVehicleNumber=\"" << myMaxVehicleNumber << "\" "
395  << "/>\n";
396  reset();
397 }
398 
399 
400 void
402  dev.writeXMLHeader("detector", "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo-sim.org/xsd/det_e2_file.xsd\"");
403 }
404 
405 
406 unsigned
408  return (unsigned) myKnownVehicles.size();
409 }
410 
411 
412 SUMOReal
414  return myCurrentOccupancy * (SUMOReal) 100.;
415 }
416 
417 
418 SUMOReal
420  return myCurrentMeanSpeed;
421 }
422 
423 
424 SUMOReal
426  return myCurrentMeanLength;
427 }
428 
429 
430 unsigned
432  return myCurrentJamNo;
433 }
434 
435 
436 unsigned
439 }
440 
441 
442 SUMOReal
445 }
446 
447 
448 unsigned
451 }
452 
453 
454 SUMOReal
457 }
458 
459 
460 unsigned
462  return myCurrentStartedHalts;
463 }
464 
465 
466 int
468  const MSVehicle* const occ = myLane->getPartialOccupator();
469  if (v1 == occ) {
470  return true;
471  }
472  if (v2 == occ) {
473  return false;
474  }
475  return v1->getPositionOnLane() > v2->getPositionOnLane();
476 }
477 
478 SUMOReal
481 }
482 
483 
484 std::vector<std::string>
486  std::vector<std::string> ret;
487  for (std::list<SUMOVehicle*>::const_iterator i = myKnownVehicles.begin(); i != myKnownVehicles.end(); ++i) {
488  MSVehicle* veh = static_cast<MSVehicle*>(*i);
489  ret.push_back(veh->getID());
490  }
491  std::sort(ret.begin(), ret.end());
492  return ret;
493 }
494 
495 /****************************************************************************/
496