Eclipse SUMO - Simulation of Urban MObility
MSE2Collector.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
21 // An areal detector covering a sequence of consecutive lanes
22 /****************************************************************************/
23 
24 
25 /* TODO:
26  * tests:
27  * - subsecond variant, ballistic variant
28  * allow omitting jam processing (?)
29  *
30  * Meso-compatibility? (esp. enteredLane-argument for MSBaseVehicle::notifyEnter() is not treated)
31  * Compatibility without internal lanes?
32  * Include leftVehicles into output?
33  */
34 
35 // ===========================================================================
36 // included modules
37 // ===========================================================================
38 #include <config.h>
39 
40 #include <cassert>
41 #include <algorithm>
42 #include "MSE2Collector.h"
43 #include <microsim/MSLane.h>
44 #include <microsim/MSNet.h>
45 #include <microsim/MSVehicle.h>
46 #include <microsim/MSVehicleType.h>
47 
48 //#define DEBUG_E2_CONSTRUCTOR
49 //#define DEBUG_E2_NOTIFY_ENTER_AND_LEAVE
50 //#define DEBUG_E2_NOTIFY_MOVE
51 //#define DEBUG_E2_MAKE_VEHINFO
52 //#define DEBUG_E2_DETECTOR_UPDATE
53 //#define DEBUG_E2_TIME_ON_DETECTOR
54 //#define DEBUG_E2_JAMS
55 //#define DEBUG_E2_XML_OUT
56 //#define DEBUG_COND (true)
57 //#define DEBUG_COND (getID()=="e2Detector_e5.601A_1_SAa")
58 //#define DEBUG_COND (getID()=="702057")
59 //#define DEBUG_COND (getID()=="det0")
60 
61 MSE2Collector::MSE2Collector(const std::string& id,
62  DetectorUsage usage, MSLane* lane, double startPos, double endPos, double length,
63  SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
64  const std::string& vTypes) :
65  MSMoveReminder(id, lane, false),
66  MSDetectorFileOutput(id, vTypes),
67  myUsage(usage),
68  myJamHaltingSpeedThreshold(haltingSpeedThreshold),
69  myJamHaltingTimeThreshold(haltingTimeThreshold),
70  myJamDistanceThreshold(jamDistThreshold),
71  myNumberOfEnteredVehicles(0),
72  myNumberOfSeenVehicles(0),
73  myNumberOfLeftVehicles(0) {
74  reset();
75 
76 #ifdef DEBUG_E2_CONSTRUCTOR
77  if (DEBUG_COND) {
78  std::cout << "\n" << "Creating MSE2Collector " << id
79  << " with lane = " << lane->getID()
80  << " startPos = " << startPos
81  << " endPos = " << endPos
82  << " length = " << length
83  << " haltingTimeThreshold = " << haltingTimeThreshold
84  << " haltingSpeedThreshold = " << haltingSpeedThreshold
85  << " jamDistThreshold = " << jamDistThreshold
86  << std::endl;
87  }
88 #endif
89 
90  assert(lane != 0);
91 
92  // check that exactly one of length, startPos, endPos is invalid
93  bool lengthInvalid = length == std::numeric_limits<double>::max() || length <= 0;
94  bool endPosInvalid = endPos == std::numeric_limits<double>::max();
95  bool posInvalid = startPos == std::numeric_limits<double>::max();
96 
97  // check and normalize positions (assure positive values for pos and endPos, snap to lane-ends)
98  if (lengthInvalid) {
99  // assume that the detector is only located on a single lane
100  if (posInvalid) {
101  WRITE_WARNING("No valid detector length and start position given. Assuming startPos = 0 and length = end position");
102  startPos = 0;
103  }
104  if (endPosInvalid) {
105  WRITE_WARNING("No valid detector length and end position given. Assuming endPos = lane length and length = endPos-startPos");
106  endPos = lane->getLength();
107  }
108  endPos = endPos < 0 ? lane->getLength() + endPos : endPos;
109  startPos = startPos < 0 ? lane->getLength() + startPos : startPos;
110  bool valid = endPos <= lane->getLength() && 0 <= startPos && startPos < endPos;
111  if (!valid) {
112  throw InvalidArgument("Error in specification for E2Detector '" + id + "'. Positional argument is malformed. 0 <= pos < endPos <= lane.getLength() is required.");
113  }
114  // snap detector ends to lane ends
115  endPos = snap(endPos, lane->getLength(), POSITION_EPS);
116  startPos = snap(startPos, 0., POSITION_EPS);
117  length = endPos - startPos;
118  } else if (posInvalid) {
119  // endPosInvalid == false
120  endPos = endPos < 0 ? lane->getLength() + endPos : endPos;
121  endPos = snap(endPos, lane->getLength(), POSITION_EPS);
122  } else {
123  // posInvalid == false
124  startPos = startPos < 0 ? lane->getLength() + startPos : startPos;
125  startPos = snap(startPos, 0., POSITION_EPS);
126  }
127 
128  myStartPos = startPos;
129  myEndPos = endPos;
130 
131  std::vector<MSLane*> lanes;
132  if (posInvalid) {
133  lanes = selectLanes(lane, length, "bw");
134  } else if (endPosInvalid) {
135  lanes = selectLanes(lane, length, "fw");
136  } else {
137  // assuming detector is only located at a single lane
138  lanes.push_back(lane);
139  }
140 
141  initAuxiliaries(lanes);
142  checkPositioning(endPosInvalid, length);
143  addDetectorToLanes(lanes);
144 }
145 
146 
147 MSE2Collector::MSE2Collector(const std::string& id,
148  DetectorUsage usage, std::vector<MSLane*> lanes, double startPos, double endPos,
149  SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
150  const std::string& vTypes) :
151  MSMoveReminder(id, lanes[lanes.size() - 1], false), // assure that lanes.size() > 0 at caller side!!!
152  MSDetectorFileOutput(id, vTypes),
153  myUsage(usage),
154  myFirstLane(lanes[0]),
155  myLastLane(lanes[lanes.size() - 1]),
156  myStartPos(startPos),
157  myEndPos(endPos),
158  myJamHaltingSpeedThreshold(haltingSpeedThreshold),
159  myJamHaltingTimeThreshold(haltingTimeThreshold),
160  myJamDistanceThreshold(jamDistThreshold),
161  myNumberOfEnteredVehicles(0),
162  myNumberOfSeenVehicles(0),
163  myNumberOfLeftVehicles(0) {
164  reset();
165 
166  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
167  assert((*i) != 0);
168  }
169 
170 #ifdef DEBUG_E2_CONSTRUCTOR
171  if (DEBUG_COND) {
172  std::cout << "\n" << "Creating MSE2Collector " << id
173  << " with endLane = " << myLastLane->getID()
174  << " endPos = " << endPos
175  << " startLane = " << myFirstLane->getID()
176  << " startPos = " << startPos
177  << " haltingTimeThreshold = " << haltingTimeThreshold
178  << " haltingSpeedThreshold = " << haltingSpeedThreshold
179  << " jamDistThreshold = " << jamDistThreshold
180  << std::endl;
181  }
182 #endif
183 
184  myStartPos = myStartPos < 0 ? lanes[0]->getLength() + myStartPos : myStartPos;
185  myEndPos = myEndPos < 0 ? lanes[lanes.size() - 1]->getLength() + myEndPos : myEndPos;
186 
187  if (myStartPos < POSITION_EPS) {
188  myStartPos = 0;
189  }
190  if (myEndPos > lanes[lanes.size() - 1]->getLength() - POSITION_EPS) {
191  myEndPos = lanes[lanes.size() - 1]->getLength();
192  }
193 
194 
195  initAuxiliaries(lanes);
197  addDetectorToLanes(lanes);
198 }
199 
200 
201 void
202 MSE2Collector::checkPositioning(bool posGiven, double desiredLength) {
203  // check if detector was truncated
204  if (desiredLength > 0 && myDetectorLength < desiredLength - NUMERICAL_EPS) {
205  std::stringstream ss;
206  ss << "Cannot build detector of length " << desiredLength
207  << " because no further continuation lane was found for lane '" << (posGiven ? myLastLane->getID() : myFirstLane->getID())
208  << "'! Truncated detector at length " << myDetectorLength << ".";
209  WRITE_WARNING(ss.str());
210  }
211 
212  if (myDetectorLength < POSITION_EPS && (myStartPos > 0. || myEndPos < myLastLane->getLength())) {
213  // assure minimal detector length
214  double prolong = POSITION_EPS - myDetectorLength;
215  double startPos = MAX2(0., myStartPos - prolong); // new startPos
216  prolong -= myStartPos - startPos;
217  myStartPos = startPos;
218  if (prolong > 0.) {
219  myEndPos = MIN2(myEndPos + prolong, myLastLane->getLength());
220  }
221  WRITE_WARNING("Adjusted detector positioning to meet requirement length >= " + toString(POSITION_EPS)
222  + ". New position is [" + toString(myStartPos) + "," + toString(myEndPos) + "]");
223  }
224 
225  // do some regularization snapping...
233 
234 #ifdef DEBUG_E2_CONSTRUCTOR
235  if (DEBUG_COND) {
236  std::stringstream ss;
237  // ss << std::setprecision(32) << myEndPos << " : " << POSITION_EPS;
238  // std::cout << ss.str() << std::endl;
239  std::cout << "myStartPos = " << myStartPos << std::endl;
240  std::cout << "myEndPos = " << myEndPos << std::endl;
241  std::cout << "myLastLane->getLength() = " << myLastLane->getLength() << std::endl;
242  }
243 #endif
244 
245 
246  assert((myStartPos >= POSITION_EPS || myStartPos == 0) && myStartPos < myFirstLane->getLength());
247  assert(myEndPos <= myLastLane->getLength() - POSITION_EPS || myEndPos == myLastLane->getLength());
248  assert(myFirstLane != myLastLane || myEndPos - myStartPos > 0);
249 }
250 
251 
252 double
253 MSE2Collector::snap(double value, double snapPoint, double snapDist) {
254  if (fabs(value - snapPoint) < snapDist) {
255  return snapPoint;
256  } else {
257  return value;
258  }
259 }
260 
261 
262 void
264  std::vector<std::string>::const_iterator i;
265  std::vector<MSLane*> lanes;
266  // get real lanes
267  for (i = myLanes.begin(); i != myLanes.end(); ++i) {
268  MSLane* lane = MSLane::dictionary(*i);
269  lanes.push_back(lane);
270  }
271 
272  // sum up their lengths
273  std::vector<MSLane*>::const_iterator j;
274  MSLane* previous = nullptr;
275  myDetectorLength = 0;
276  for (j = lanes.begin(); j != lanes.end(); ++j) {
277  // lane length
278  myDetectorLength += (*j)->getLength();
279  if (previous != nullptr && !MSGlobals::gUsingInternalLanes) {
280  // eventually link length
281  myDetectorLength += previous->getLinkTo(*j)->getLength();
282  }
283  previous = *j;
284  }
285  // substract uncovered area on first and last lane
288 
289 #ifdef DEBUG_E2_CONSTRUCTOR
290  if (DEBUG_COND) {
291  std::cout << "Total detector length after recalculation = " << myDetectorLength << std::endl;
292  }
293 #endif
294 }
295 
296 
298  // clear move notifications
299  for (std::vector<MoveNotificationInfo*>::iterator j = myMoveNotifications.begin(); j != myMoveNotifications.end(); ++j) {
300  delete *j;
301  }
302  myMoveNotifications.clear();
303 
304  // clear vehicle infos
305  for (VehicleInfoMap::iterator j = myVehicleInfos.begin(); j != myVehicleInfos.end(); ++j) {
306  delete j->second;
307  }
308  myVehicleInfos.clear();
309 }
310 
311 
312 std::vector<MSLane*>
313 MSE2Collector::selectLanes(MSLane* lane, double length, std::string dir) {
314  // direction of detector extension
315  assert(dir == "fw" || dir == "bw");
316  bool fw = dir == "fw";
317  double linkLength = 0; // linkLength (used if no internal lanes are present)
318  bool substractedLinkLength = false; // whether linkLength was substracted during the last iteration.
319 
320 #ifdef DEBUG_E2_CONSTRUCTOR
321  if (DEBUG_COND) {
322  std::cout << "\n" << "selectLanes()" << (fw ? "(forward)" : "(backward)") << std::endl;
323  }
324 #endif
325  std::vector<MSLane*> lanes;
326  // Selected lanes are stacked into vector 'lanes'. If dir == "bw" lanes will be reversed after this is done.
327  // The length is reduced while adding lanes to the detector
328  // First we adjust the starting value for length (in the first iteration, the whole length of the first considered lane is substracted,
329  // while it might only be partially covered by the detector)
330  if (fw) {
331  assert(myStartPos != std::numeric_limits<double>::max());
332  length += myStartPos;
333  } else {
334  assert(myEndPos != std::numeric_limits<double>::max());
335  length += lane->getLength() - myEndPos;
336  }
337  length = MAX2(POSITION_EPS, length); // this assures to add at least one lane to lanes
338  while (length >= POSITION_EPS && lane != nullptr) {
339  // Break loop for length <= NUMERICAL_EPS to avoid placement of very small
340  // detector piece on the end or beginning of one lane due to numerical rounding errors.
341  lanes.push_back(lane);
342 #ifdef DEBUG_E2_CONSTRUCTOR
343  if (DEBUG_COND) {
344  std::cout << "Added lane " << lane->getID()
345  << " (length: " << lane->getLength() << ")" << std::endl;
346  }
347 #endif
348 
349  length -= lane->getLength();
350 
351  // proceed to upstream predecessor
352  if (fw) {
353  lane = lane->getCanonicalSuccessorLane();
354  } else {
355  lane = lane->getCanonicalPredecessorLane();
356  }
357 
358 
359  substractedLinkLength = false;
360  if (lane != nullptr && !MSGlobals::gUsingInternalLanes && length > POSITION_EPS) {
361  // In case wher no internal lanes are used,
362  // take into account the link length for the detector range
363  linkLength = 0;
364  if (fw) {
365  linkLength = lanes.back()->getLinkTo(lane)->getLength();
366  } else {
367  linkLength = lane->getLinkTo(lanes.back())->getLength();
368  }
369  length -= linkLength;
370  substractedLinkLength = true;
371  }
372 
373 
374 #ifdef DEBUG_E2_CONSTRUCTOR
375  if (DEBUG_COND) {
376  if (lane != 0) {
377  std::cout << (fw ? "Successor lane: " : "Predecessor lane: ") << "'" << lane->getID() << "'";
378  }
379  std::cout << std::endl;
380  }
381 #endif
382  }
383 
384  if (substractedLinkLength) {
385  // if the link's length was substracted during the last step,
386  // the start/endPos would lie on a non-existing internal lane,
387  // therefore revert and truncate detector part on the non-existing internal lane.
388  length += linkLength;
389  }
390 
391 
392  // 1) At this point a negative <length> means that not the whole last stored lane lanes[lanes.size()-1]
393  // should be added to the detector, but the detector should spare out a part with length = -<length>
394  // If this part is too small (of length < POSITION_EPS) we take the whole lane
395  // 2) The whole lane is also taken for the case that <length> is positive. This corresponds to on
396  // of three situations: i) <length> < POSITION_EPS (break condition -> don't take too small pieces on the next lane)
397  // ii&iii) <length> >= POS_EPSILON may arise either if no continuation lane was found (lane==0), or
398  // in case of not using internal lanes if the detector end/start falls on a link.
399  // In all cases we take the whole last lane.
400  if (fw) {
401  if (length > -POSITION_EPS) {
402  myEndPos = lanes[lanes.size() - 1]->getLength();
403  } else if (length < 0) {
404  myEndPos = lanes[lanes.size() - 1]->getLength() + length;
405  }
406  } else {
407  if (length > -POSITION_EPS) {
408  myStartPos = 0;
409  } else if (length < 0) {
410  myStartPos = -length;
411  }
412  }
413 
414  // reverse lanes if lane selection was backwards
415  if (!fw) {
416  std::reverse(lanes.begin(), lanes.end());
417  }
418 
419  return lanes;
420 }
421 
422 void
423 MSE2Collector::addDetectorToLanes(std::vector<MSLane*>& lanes) {
424 #ifdef DEBUG_E2_CONSTRUCTOR
425  if (DEBUG_COND) {
426  std::cout << "\n" << "Adding detector " << myID << " to lanes:" << std::endl;
427  }
428 #endif
429  for (std::vector<MSLane*>::iterator l = lanes.begin(); l != lanes.end(); ++l) {
430  (*l)->addMoveReminder(this);
431 #ifdef DEBUG_E2_CONSTRUCTOR
432  if (DEBUG_COND) {
433  std::cout << (*l)->getID() << std::endl;
434  }
435 #endif
436  }
437 }
438 
439 void
440 MSE2Collector::initAuxiliaries(std::vector<MSLane*>& lanes) {
441  // Checks integrity of myLanes, adds internal-lane information, inits myLength, myFirstLane, myLastLane, myOffsets, myEndPos/myStartPos
442  myFirstLane = lanes[0];
443  myLastLane = lanes[lanes.size() - 1];
444 
445 #ifdef DEBUG_E2_CONSTRUCTOR
446  if (DEBUG_COND) {
447  std::cout << "\n" << "Initializing auxiliaries:"
448  << "\nFirst lane: " << myFirstLane->getID() << " (startPos = " << myStartPos << ")"
449  << "\nLast lane: " << myLastLane->getID() << " (endPos = " << myEndPos << ")"
450  << std::endl;
451  }
452 #endif
453 
454  // Init myOffsets and myDetectorLength.
455  // The loop below runs through the given lanes assuming the possibility that only non-internal lanes are given
456  // or at least not all relevant internal lanes are considered. During this a new, complete list of lane ids is
457  // built into myLanes.
458  myLanes.clear();
459 
460  // myDetectorLength will be increased in the loop below, always giving
461  // the offset of the currently considered lane to the detector start
463  myOffsets.clear();
464 
465  // loop over detector lanes and accumulate offsets with respect to the first lane's begin
466  // (these will be corrected afterwards by substracting the start position.)
467  std::vector<MSLane*>::iterator il = lanes.begin();
468 
469  // start on an internal lane?
470  // (This may happen if specifying the detector by its upstream
471  // length starting from a given end position)
472  const MSLane* internal = (*il)->isInternal() ? *il : nullptr;
473 
474 #ifdef DEBUG_E2_CONSTRUCTOR
475  if (DEBUG_COND) {
476  std::cout << "\n" << "Initializing offsets:" << std::endl;
477  }
478 #endif
479 
480 #ifdef _MSC_VER
481 #pragma warning(push)
482 #pragma warning(disable: 4127) // do not warn about constant conditional expression
483 #endif
484  while (true) {
485 #ifdef _MSC_VER
486 #pragma warning(pop)
487 #endif
488  // Consider the next internal lanes
489  while (internal != nullptr) {
490  myLanes.push_back(internal->getID());
491  myOffsets.push_back(myDetectorLength);
492 
493 #ifdef DEBUG_E2_CONSTRUCTOR
494  if (DEBUG_COND) {
495  std::cout << "Offset for lane " << internal->getID() << " = " << myDetectorLength
496  << std::endl;
497  }
498 #endif
499 
500  myDetectorLength += internal->getLength();
501  if (internal->getID() == myLastLane->getID()) {
502  break;
503  }
504 
505  // There should be a unique continuation for each internal lane
506  assert(internal->getLinkCont().size() == 1);
507 
508  internal = internal->getLinkCont()[0]->getViaLaneOrLane();
509  if (!internal->isInternal()) {
510  // passed the junction
511  internal = nullptr;
512  break;
513  }
514  }
515 
516  // Consider the next non-internal lane
517  // This is the first lane in the first iteration, if it is non-internal
518  // However, it can equal myLanes.end() if the myLastLane is internal. In that case we break.
519 
520  // Move il to next non-internal
521  while (il != lanes.end() && (*il)->isInternal()) {
522  il++;
523  }
524  if (il == lanes.end()) {
525  break;
526  }
527 
528  // There is still a non-internal lane to consider
529  MSLane* lane = *il;
530  myLanes.push_back(lane->getID());
531 
532 #ifdef DEBUG_E2_CONSTRUCTOR
533  if (DEBUG_COND) {
534  std::cout << "Offset for lane " << lane->getID() << " = " << myDetectorLength
535  << std::endl;
536  }
537 #endif
538 
539  // Offset to detector start for this lane
540  myOffsets.push_back(myDetectorLength);
541 
542  // Add the lanes length to the detector offset
543  myDetectorLength += lane->getLength();
544 
545  // Get the next lane if this lane isn't the last one
546  if (++il == lanes.end()) {
547  break;
548  }
549 
550  if ((*il)->isInternal()) {
551  // next lane in myLanes is internal
552  internal = *il;
553  continue;
554  }
555 
556  // find the connection to next
557  const MSLink* link = lane->getLinkTo(*il);
558  if (link == nullptr) {
559  throw InvalidArgument("Lanes '" + lane->getID() + "' and '" + (*il)->getID() + "' are not consecutive in defintion of e2Detector '" + getID() + "'");
560  }
561 
563  myDetectorLength += link->getLength();
564  } else {
565  internal = link->getViaLane();
566  }
567  }
568 
569  // Substract distance not covered on the last considered lane
570  bool fw = myEndPos == std::numeric_limits<double>::max();
571  if (fw) {
573  } else {
575  }
576 
577 #ifdef DEBUG_E2_CONSTRUCTOR
578  if (DEBUG_COND) {
579  std::cout << "Total detector length after initAuxiliaries() = " << myDetectorLength << std::endl;
580  }
581 #endif
582 
583 // make lanes a complete list including internal lanes
584  lanes = getLanes();
585 }
586 
587 
588 std::vector<MSLane*>
590  std::vector<MSLane*> res;
591  for (std::vector<std::string>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
592  res.push_back(MSLane::dictionary(*i));
593  }
594  return res;
595 }
596 
597 
598 bool
600  double newPos, double newSpeed) {
601  if (!tObject.isVehicle()) {
602  return false;
603  }
604  SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
605  VehicleInfoMap::iterator vi = myVehicleInfos.find(veh.getID());
606  assert(vi != myVehicleInfos.end()); // all vehicles calling notifyMove() should have called notifyEnter() before
607 
608  const std::string& vehID = veh.getID();
609  VehicleInfo& vehInfo = *(vi->second);
610 
611  // position relative to the detector start
612  double relPos = vehInfo.entryOffset + newPos;
613 
614  // update current distance to the detector end
615  vehInfo.distToDetectorEnd = myDetectorLength - relPos;
616 
617 #ifdef DEBUG_E2_NOTIFY_MOVE
618  if (DEBUG_COND) {
619  std::cout << "\n" << SIMTIME
620  << " MSE2Collector::notifyMove() (detID = " << myID << "on lane '" << myLane->getID() << "')"
621  << " called by vehicle '" << vehID << "'"
622  << " at relative position " << relPos
623  << ", distToDetectorEnd = " << vehInfo.distToDetectorEnd << std::endl;
624  }
625 #endif
626 
627  // Check whether vehicle has reached the detector begin
628  if (relPos <= 0) {
629  // detector not yet reached, request being informed further
630 #ifdef DEBUG_E2_NOTIFY_MOVE
631  if (DEBUG_COND) {
632  std::cout << "Vehicle has not yet reached the detector start position." << std::endl;
633  }
634 #endif
635  return true;
636  } else if (!vehInfo.hasEntered) {
637  vehInfo.hasEntered = true;
640  }
641 
642 
643  // determine whether vehicle has moved beyond the detector's end
644  bool vehPassedDetectorEnd = - vehInfo.exitOffset <= newPos - veh.getVehicleType().getLength();
645 
646  // determine whether vehicle has been on the detector at all
647  bool vehicleEnteredLaneAfterDetector = vehPassedDetectorEnd && (-vehInfo.exitOffset <= oldPos - veh.getVehicleType().getLength());
648  // ... if not, dont create any notification at all
649  if (vehicleEnteredLaneAfterDetector) {
650 #ifdef DEBUG_E2_NOTIFY_MOVE
651  if (DEBUG_COND) {
652  std::cout << "Vehicle entered lane behind detector." << std::endl;
653  }
654 #endif
655  } else {
656  myMoveNotifications.push_back(makeMoveNotification(veh, oldPos, newPos, newSpeed, vehInfo));
657  }
658 
659 
660  if (vehPassedDetectorEnd) {
661 #ifdef DEBUG_E2_NOTIFY_MOVE
662  if (DEBUG_COND) {
663  std::cout << "Vehicle has left the detector longitudinally." << std::endl;
664  }
665 #endif
666  // Vehicle is beyond the detector, unsubscribe and register removal from myVehicleInfos
667  myLeftVehicles.insert(vehID);
668  return false;
669  } else {
670  // Receive further notifications
671  return true;
672  }
673 }
674 
675 bool
676 MSE2Collector::notifyLeave(SUMOTrafficObject& tObject, double /* lastPos */, MSMoveReminder::Notification reason, const MSLane* enteredLane) {
677  if (!tObject.isVehicle()) {
678  return false;
679  }
680  SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
681 #ifdef DEBUG_E2_NOTIFY_ENTER_AND_LEAVE
682  if (DEBUG_COND) {
683  std::cout << "\n" << SIMTIME << " notifyLeave() (detID = " << myID << "on lane '" << myLane->getID() << "')"
684  << "called by vehicle '" << veh.getID() << "'" << std::endl;
685  }
686 #endif
687 
689  // vehicle left lane via junction, unsubscription and registering in myLeftVehicles when
690  // moving beyond the detector end is controlled in notifyMove.
691 #ifdef DEBUG_E2_NOTIFY_ENTER_AND_LEAVE
692  if (DEBUG_COND) {
693  std::cout << SIMTIME << " Left longitudinally (along junction) -> keep subscription [handle exit in notifyMove()]" << std::endl;
694  }
695 #endif
696 
697  if (std::find(myLanes.begin(), myLanes.end(), enteredLane->getID()) == myLanes.end()) {
698  // Entered lane is not part of the detector
699  VehicleInfoMap::iterator vi = myVehicleInfos.find(veh.getID());
700  // Determine exit offset, where vehicle left the detector
701  double exitOffset = vi->second->entryOffset - myOffsets[vi->second->currentOffsetIndex] - vi->second->currentLane->getLength();
702  vi->second->exitOffset = MAX2(vi->second->exitOffset, exitOffset);
703 #ifdef DEBUG_E2_NOTIFY_ENTER_AND_LEAVE
704  if (DEBUG_COND) {
705  std::cout << SIMTIME << " Vehicle '" << veh.getID() << "' leaves the detector. Exit offset = " << vi->second->exitOffset << std::endl;
706  }
707 #endif
708  }
709 
710  return true;
711  } else {
712  VehicleInfoMap::iterator vi = myVehicleInfos.find(veh.getID());
713  // erase vehicle, which leaves in a non-longitudinal way, immediately
714  if (vi->second->hasEntered) {
716  }
717  delete vi->second;
718  myVehicleInfos.erase(vi);
719 #ifdef DEBUG_E2_NOTIFY_ENTER_AND_LEAVE
720  if (DEBUG_COND) {
721  std::cout << SIMTIME << " Left non-longitudinally (lanechange, teleport, parking, etc) -> discard subscription" << std::endl;
722  }
723 #endif
724  return false;
725  }
726 }
727 
728 
729 bool
731  if (!tObject.isVehicle()) {
732  return false;
733  }
734  SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
735 #ifdef DEBUG_E2_NOTIFY_ENTER_AND_LEAVE
736  if (DEBUG_COND) {
737  std::cout << std::endl << SIMTIME << " notifyEnter() (detID = " << myID << " on lane '" << myLane->getID() << "')"
738  << " called by vehicle '" << veh.getID()
739  << "' entering lane '" << (enteredLane != 0 ? enteredLane->getID() : "NULL") << "'" << std::endl;
740  }
741 #endif
742  // notifyEnter() should only be called for lanes of the detector
743  assert(std::find(myLanes.begin(), myLanes.end(), enteredLane->getID()) != myLanes.end());
744  assert(veh.getLane() == enteredLane);
745 
746  if (!vehicleApplies(veh)) {
747  // That's not my type...
748  return false;
749  }
750 
751  // determine whether the vehicle entered the lane behind the detector end
752  // e.g. due to lane change manoeuver
753  if (reason != NOTIFICATION_JUNCTION) {
754  const double vehBackPos = veh.getBackPositionOnLane(enteredLane);
755  bool vehEnteredBehindDetectorEnd = (enteredLane == myLastLane) && myEndPos <= vehBackPos;
756  if (vehEnteredBehindDetectorEnd) {
757  // this vehicle cannot influence detector readings, do not subscribe
758  // to move notifications
759 #ifdef DEBUG_E2_NOTIFY_ENTER_AND_LEAVE
760  if (DEBUG_COND) {
761  std::cout << "Vehicle entered the lane behind the detector, ignoring it." << std::endl;
762  std::cout << "(myEndPos = " << this->myEndPos << ", veh.getBackPositionOnLane() = " << vehBackPos << ")" << std::endl;
763  }
764 #endif
765  return false;
766  }
767  }
768 
769 #ifdef DEBUG_E2_NOTIFY_ENTER_AND_LEAVE
770  if (DEBUG_COND) {
771  if (!veh.isOnRoad()) {
772  // Vehicle is teleporting over the edge
773  std::cout << "Vehicle is off road (teleporting over edge)..." << std::endl;
774  }
775  }
776 #endif
777 
778  const std::string& vehID = veh.getID();
779  VehicleInfoMap::iterator vi = myVehicleInfos.find(vehID);
780  if (vi != myVehicleInfos.end()) {
781  // Register move current offset to the next lane
782  if (vi->second->currentLane != enteredLane) {
783  vi->second->currentOffsetIndex++;
784  vi->second->currentLane = enteredLane;
785  }
786 
787 #ifdef DEBUG_E2_NOTIFY_ENTER_AND_LEAVE
788  if (DEBUG_COND) {
789  std::cout << SIMTIME << " Vehicle '" << veh.getID() << "' on lane '" << veh.getLane()->getID()
790  << "' already known. No new VehicleInfo is created.\n"
791  << "enteredLane = " << enteredLane->getID() << "\nmyLanes[vi->offset] = " << myLanes[vi->second->currentOffsetIndex]
792  << std::endl;
793  }
794 #endif
795  assert(myLanes[vi->second->currentOffsetIndex] == enteredLane->getID());
796 
797  // but don't add a second subscription for another lane
798  return false;
799  }
800 
801 
802 
803 #ifdef DEBUG_E2_NOTIFY_ENTER_AND_LEAVE
804  if (DEBUG_COND) {
805  std::cout << SIMTIME << " Adding VehicleInfo for vehicle '" << veh.getID() << "'." << std::endl;
806  }
807 #endif
808 
809  // Add vehicle info
810  myVehicleInfos.insert(std::make_pair(vehID, makeVehicleInfo(veh, enteredLane)));
811  // Subscribe to vehicle's movement notifications
812  return true;
813 }
814 
816 MSE2Collector::makeVehicleInfo(const SUMOVehicle& veh, const MSLane* enteredLane) const {
817  // The vehicle's distance to the detector end
818  int j = (int)(std::find(myLanes.begin(), myLanes.end(), enteredLane->getID()) - myLanes.begin());
819  assert(j >= 0 && j < (int)myLanes.size());
820  double entryOffset = myOffsets[j];
821  double distToDetectorEnd = myDetectorLength - (entryOffset + veh.getPositionOnLane());
822  bool onDetector = -entryOffset < veh.getPositionOnLane() && distToDetectorEnd > -veh.getVehicleType().getLength();
823 
824 #ifdef DEBUG_E2_MAKE_VEHINFO
825  if (DEBUG_COND) {
826  std::cout << SIMTIME << " Making VehicleInfo for vehicle '" << veh.getID() << "'."
827  << "\ndistToDetectorEnd = " << distToDetectorEnd
828  << "\nveh.getPositionOnLane() = " << veh.getPositionOnLane()
829  << "\nentry lane offset (lane begin from detector begin) = " << entryOffset
830  << std::endl;
831  }
832 #endif
833  return new VehicleInfo(veh.getID(), veh.getVehicleType().getID(), veh.getVehicleType().getLength(), veh.getVehicleType().getMinGap(), enteredLane, entryOffset, j,
834  myOffsets[j] - myDetectorLength, distToDetectorEnd, onDetector);
835 }
836 
837 void
839 
840 #ifdef DEBUG_E2_DETECTOR_UPDATE
841  if (DEBUG_COND) {
842  std::cout << "\n" << SIMTIME << " detectorUpdate() for detector '" << myID << "'"
843  << "\nmyCurrentMeanSpeed = " << myCurrentMeanSpeed
844  << "\nmyCurrentMeanLength = " << myCurrentMeanLength
845  << "\nmyNumberOfEnteredVehicles = " << myNumberOfEnteredVehicles
846  << "\nmyNumberOfLeftVehicles = " << myNumberOfLeftVehicles
847  << "\nmyNumberOfSeenVehicles = " << myNumberOfSeenVehicles
848  << std::endl;
849  }
850 #endif
851 
852 // sort myMoveNotifications (required for jam processing) ascendingly according to vehicle's distance to the detector end
853 // (min = myMoveNotifications[0].distToDetectorEnd)
855 
856  // reset values concerning current time step (these are updated in integrateMoveNotification() and aggregateOutputValues())
857  myCurrentMeanSpeed = 0;
861 
862  JamInfo* currentJam = nullptr;
863  std::vector<JamInfo*> jams;
864  std::map<std::string, SUMOTime> haltingVehicles;
865  std::map<std::string, SUMOTime> intervalHaltingVehicles;
866 
867  // go through the list of vehicles positioned on the detector
868  for (std::vector<MoveNotificationInfo*>::iterator i = myMoveNotifications.begin(); i != myMoveNotifications.end(); ++i) {
869  // The ID of the vehicle that has sent this notification in the last step
870  const std::string& vehID = (*i)->id;
871  VehicleInfoMap::iterator vi = myVehicleInfos.find(vehID);
872 
873  if (vi == myVehicleInfos.end()) {
874  // The vehicle has already left the detector by lanechange, teleport, etc. (not longitudinal)
875  integrateMoveNotification(nullptr, *i);
876  } else {
877  // Add move notification infos to detector values and VehicleInfo
878  integrateMoveNotification(vi->second, *i);
879  }
880  // construct jam structure
881  bool isInJam = checkJam(i, haltingVehicles, intervalHaltingVehicles);
882  buildJam(isInJam, i, currentJam, jams);
883  }
884 
885  // extract some aggregated values from the jam structure
886  processJams(jams, currentJam);
887 
888  // Aggregate and normalize values for the detector output
890 
891  // save information about halting vehicles
892  myHaltingVehicleDurations = haltingVehicles;
893  myIntervalHaltingVehicleDurations = intervalHaltingVehicles;
894 
895 #ifdef DEBUG_E2_DETECTOR_UPDATE
896  if (DEBUG_COND) {
897  std::cout << "\n" << SIMTIME << " Current lanes for vehicles still on or approaching the detector:" << std::endl;
898  }
899 #endif
900 // update current and entered lanes for remaining vehicles
901  VehicleInfoMap::iterator iv;
902  for (iv = myVehicleInfos.begin(); iv != myVehicleInfos.end(); ++iv) {
903 #ifdef DEBUG_E2_DETECTOR_UPDATE
904  if (DEBUG_COND) {
905  std::cout << " Vehicle '" << iv->second->id << "'" << ": '"
906  << iv->second->currentLane->getID() << "'"
907  << std::endl;
908  }
909 #endif
910  }
911 
912 #ifdef DEBUG_E2_DETECTOR_UPDATE
913  if (DEBUG_COND) {
914  std::cout << SIMTIME << " Discarding vehicles that have left the detector:" << std::endl;
915  }
916 #endif
917 // Remove the vehicles that have left the detector
918  std::set<std::string>::const_iterator i;
919  for (i = myLeftVehicles.begin(); i != myLeftVehicles.end(); ++i) {
920  VehicleInfoMap::iterator j = myVehicleInfos.find(*i);
921  delete j->second;
922  myVehicleInfos.erase(*i);
924 #ifdef DEBUG_E2_DETECTOR_UPDATE
925  if (DEBUG_COND) {
926  std::cout << "Erased vehicle '" << *i << "'" << std::endl;
927  }
928 #endif
929  }
930  myLeftVehicles.clear();
931 
932  // reset move notifications
933  for (std::vector<MoveNotificationInfo*>::iterator j = myMoveNotifications.begin(); j != myMoveNotifications.end(); ++j) {
934  delete *j;
935  }
936  myMoveNotifications.clear();
937 }
938 
939 
940 void
942  myTimeSamples += 1;
943  // compute occupancy values (note myCurrentMeanLength is still not normalized here, but holds the sum of all vehicle lengths)
944  const double currentOccupancy = myCurrentMeanLength / myDetectorLength * (double) 100.;
945  myCurrentOccupancy = currentOccupancy;
946  myOccupancySum += currentOccupancy;
947  myMaxOccupancy = MAX2(myMaxOccupancy, currentOccupancy);
948  // compute jam values
953  // compute information about vehicle numbers
954  const int numVehicles = (int)myMoveNotifications.size();
955  myMeanVehicleNumber += numVehicles;
957  // norm current values
958  myCurrentMeanSpeed = numVehicles != 0 ? myCurrentMeanSpeed / (double) numVehicles : -1;
959  myCurrentMeanLength = numVehicles != 0 ? myCurrentMeanLength / (double) numVehicles : -1;
960 }
961 
962 
963 
964 void
966 
967 #ifdef DEBUG_E2_DETECTOR_UPDATE
968  if (DEBUG_COND) {
969  std::cout << SIMTIME << " integrateMoveNotification() for vehicle '" << mni->id << "'"
970  << "\ntimeOnDetector = " << mni->timeOnDetector
971  << "\nlengthOnDetector = " << mni->lengthOnDetector
972  << "\ntimeLoss = " << mni->timeLoss
973  << "\nspeed = " << mni->speed
974  << std::endl;
975  }
976 #endif
977 
978 // Accumulate detector values
980  myTotalTimeLoss += mni->timeLoss;
981  mySpeedSum += mni->speed * mni->timeOnDetector;
982  myCurrentMeanSpeed += mni->speed * mni->timeOnDetector;
984 
985  if (vi != nullptr) {
986  // Accumulate individual values for the vehicle.
987  // @note vi==0 occurs, if the vehicle info has been erased at
988  // notifyLeave() in case of a non-longitudinal exit (lanechange, teleport, etc.)
990  vi->accumulatedTimeLoss += mni->timeLoss;
991  vi->lastAccel = mni->accel;
992  vi->lastSpeed = mni->speed;
993  vi->lastPos = myStartPos + vi->entryOffset + mni->newPos;
994  vi->onDetector = mni->onDetector;
995  }
996 }
997 
998 
999 
1001 MSE2Collector::makeMoveNotification(const SUMOVehicle& veh, double oldPos, double newPos, double newSpeed, const VehicleInfo& vehInfo) const {
1002 #ifdef DEBUG_E2_NOTIFY_MOVE
1003  if (DEBUG_COND) {
1004  std::cout << SIMTIME << " makeMoveNotification() for vehicle '" << veh.getID() << "'"
1005  << " oldPos = " << oldPos << " newPos = " << newPos << " newSpeed = " << newSpeed
1006  << std::endl;
1007  }
1008 #endif
1009 
1010  // Timefraction in [0,TS] the vehicle has spend on the detector in the last step
1011  double timeOnDetector;
1012  // Note that at this point, vehInfo.currentLane points to the lane at the beginning of the last timestep,
1013  // and vehInfo.enteredLanes is a list of lanes entered in the last timestep
1014  double timeLoss;
1015  calculateTimeLossAndTimeOnDetector(veh, oldPos, newPos, vehInfo, timeOnDetector, timeLoss);
1016 
1017  // The length of the part of the vehicle on the detector at the end of the last time step
1018  // may be shorter than vehicle's length if its back reaches out
1019  double lengthOnDetector = MAX2(MIN2(vehInfo.length, newPos + vehInfo.entryOffset), 0.);
1020 
1021  // XXX: Fulfulling the specifications of the documentation (lengthOnDetector = time integral
1022  // over length of the vehicle's part on the detector) would be much more cumbersome.
1023  double distToExit = -vehInfo.exitOffset - newPos;
1024  // Eventually decrease further to account for the front reaching out
1025  lengthOnDetector = MAX2(0., lengthOnDetector + MIN2(0., distToExit));
1026 
1027  // whether the vehicle is still on the detector at the end of the time step
1028  bool stillOnDetector = -distToExit < vehInfo.length;
1029 
1030 #ifdef DEBUG_E2_NOTIFY_MOVE
1031  if (DEBUG_COND) {
1032  std::cout << SIMTIME << " lengthOnDetector = " << lengthOnDetector
1033  << "\nvehInfo.exitOffset = " << vehInfo.exitOffset
1034  << " vehInfo.entryOffset = " << vehInfo.entryOffset
1035  << " distToExit = " << distToExit
1036  << std::endl;
1037  }
1038 #endif
1039 
1040  /* Store new infos */
1041  return new MoveNotificationInfo(veh.getID(), oldPos, newPos, newSpeed, veh.getAcceleration(),
1042  myDetectorLength - (vehInfo.entryOffset + newPos),
1043  timeOnDetector, lengthOnDetector, timeLoss, stillOnDetector);
1044 }
1045 
1046 void
1047 MSE2Collector::buildJam(bool isInJam, std::vector<MoveNotificationInfo*>::const_iterator mni, JamInfo*& currentJam, std::vector<JamInfo*>& jams) {
1048 #ifdef DEBUG_E2_JAMS
1049  if (DEBUG_COND) {
1050  std::cout << SIMTIME << " buildJam() for vehicle '" << (*mni)->id << "'" << std::endl;
1051  }
1052 #endif
1053  if (isInJam) {
1054  // The vehicle is in a jam;
1055  // it may be a new one or already an existing one
1056  if (currentJam == nullptr) {
1057 #ifdef DEBUG_E2_JAMS
1058  if (DEBUG_COND) {
1059  std::cout << SIMTIME << " vehicle '" << (*mni)->id << "' forms the start of the first jam" << std::endl;
1060  }
1061 #endif
1062  // the vehicle is the first vehicle in a jam
1063  currentJam = new JamInfo();
1064  currentJam->firstStandingVehicle = mni;
1065  } else {
1066  // ok, we have a jam already. But - maybe it is too far away
1067  // ... honestly, I can hardly find a reason for doing this,
1068  // but jams were defined this way in an earlier version...
1069  MoveNotificationInfo* lastVeh = *currentJam->lastStandingVehicle;
1070  MoveNotificationInfo* currVeh = *mni;
1071  if (lastVeh->distToDetectorEnd - currVeh->distToDetectorEnd > myJamDistanceThreshold) {
1072 #ifdef DEBUG_E2_JAMS
1073  if (DEBUG_COND) {
1074  std::cout << SIMTIME << " vehicle '" << (*mni)->id << "' forms the start of a new jam" << std::endl;
1075  }
1076 #endif
1077  // yep, yep, yep - it's a new one...
1078  // close the frist, build a new
1079  jams.push_back(currentJam);
1080  currentJam = new JamInfo();
1081  currentJam->firstStandingVehicle = mni;
1082  }
1083  }
1084  currentJam->lastStandingVehicle = mni;
1085  } else {
1086  // the vehicle is not part of a jam...
1087  // maybe we have to close an already computed jam
1088  if (currentJam != nullptr) {
1089 #ifdef DEBUG_E2_JAMS
1090  if (DEBUG_COND) {
1091  std::cout << SIMTIME << " Closing current jam." << std::endl;
1092  }
1093 #endif
1094  jams.push_back(currentJam);
1095  currentJam = nullptr;
1096  }
1097  }
1098 }
1099 
1100 
1101 bool
1102 MSE2Collector::checkJam(std::vector<MoveNotificationInfo*>::const_iterator mni, std::map<std::string, SUMOTime>& haltingVehicles, std::map<std::string, SUMOTime>& intervalHaltingVehicles) {
1103 #ifdef DEBUG_E2_JAMS
1104  if (DEBUG_COND) {
1105  std::cout << SIMTIME << " CheckJam() for vehicle '" << (*mni)->id << "'" << std::endl;
1106  }
1107 #endif
1108  // jam-checking begins
1109  bool isInJam = false;
1110  // first, check whether the vehicle is slow enough to be counted as halting
1111  if ((*mni)->speed < myJamHaltingSpeedThreshold) {
1113  // we have to track the time it was halting;
1114  // so let's look up whether it was halting before and compute the overall halting time
1115  bool wasHalting = myHaltingVehicleDurations.count((*mni)->id) > 0;
1116  if (wasHalting) {
1117  haltingVehicles[(*mni)->id] = myHaltingVehicleDurations[(*mni)->id] + DELTA_T;
1118  intervalHaltingVehicles[(*mni)->id] = myIntervalHaltingVehicleDurations[(*mni)->id] + DELTA_T;
1119  } else {
1120 #ifdef DEBUG_E2_JAMS
1121  if (DEBUG_COND) {
1122  std::cout << SIMTIME << " vehicle '" << (*mni)->id << "' starts halting." << std::endl;
1123  }
1124 #endif
1125  haltingVehicles[(*mni)->id] = DELTA_T;
1126  intervalHaltingVehicles[(*mni)->id] = DELTA_T;
1128  myStartedHalts++;
1129  }
1130  // we now check whether the halting time is large enough
1131  if (haltingVehicles[(*mni)->id] > myJamHaltingTimeThreshold) {
1132  // yep --> the vehicle is a part of a jam
1133  isInJam = true;
1134  }
1135  } else {
1136  // is not standing anymore; keep duration information
1137  std::map<std::string, SUMOTime>::iterator v = myHaltingVehicleDurations.find((*mni)->id);
1138  if (v != myHaltingVehicleDurations.end()) {
1139  myPastStandingDurations.push_back(v->second);
1140  myHaltingVehicleDurations.erase(v);
1141  }
1142  v = myIntervalHaltingVehicleDurations.find((*mni)->id);
1143  if (v != myIntervalHaltingVehicleDurations.end()) {
1144  myPastIntervalStandingDurations.push_back((*v).second);
1146  }
1147  }
1148 #ifdef DEBUG_E2_JAMS
1149  if (DEBUG_COND) {
1150  std::cout << SIMTIME << " vehicle '" << (*mni)->id << "'" << (isInJam ? "is jammed." : "is not jammed.") << std::endl;
1151  }
1152 #endif
1153  return isInJam;
1154 }
1155 
1156 
1157 void
1158 MSE2Collector::processJams(std::vector<JamInfo*>& jams, JamInfo* currentJam) {
1159  // push last jam
1160  if (currentJam != nullptr) {
1161  jams.push_back(currentJam);
1162  currentJam = nullptr;
1163  }
1164 
1165 #ifdef DEBUG_E2_JAMS
1166  if (DEBUG_COND) {
1167  std::cout << "\n" << SIMTIME << " processJams()"
1168  << "\nNumber of jams: " << jams.size() << std::endl;
1169  }
1170 #endif
1171 
1172  // process jam information
1177  for (std::vector<JamInfo*>::const_iterator i = jams.begin(); i != jams.end(); ++i) {
1178  // compute current jam's values
1179  MoveNotificationInfo* lastVeh = *((*i)->lastStandingVehicle);
1180  MoveNotificationInfo* firstVeh = *((*i)->firstStandingVehicle);
1181  const double jamLengthInMeters = lastVeh->distToDetectorEnd
1182  - firstVeh->distToDetectorEnd
1183  + lastVeh->lengthOnDetector;
1184  const int jamLengthInVehicles = (int) distance((*i)->firstStandingVehicle, (*i)->lastStandingVehicle) + 1;
1185  // apply them to the statistics
1188  myJamLengthInMetersSum += jamLengthInMeters;
1189  myJamLengthInVehiclesSum += jamLengthInVehicles;
1190  myCurrentJamLengthInMeters += jamLengthInMeters;
1191  myCurrentJamLengthInVehicles += jamLengthInVehicles;
1192 #ifdef DEBUG_E2_JAMS
1193  if (DEBUG_COND) {
1194  std::cout << SIMTIME << " processing jam nr." << ((int) distance((std::vector<JamInfo*>::const_iterator) jams.begin(), i) + 1)
1195  << "\njamLengthInMeters = " << jamLengthInMeters
1196  << " jamLengthInVehicles = " << jamLengthInVehicles
1197  << std::endl;
1198  }
1199 #endif
1200  }
1201  myCurrentJamNo = (int) jams.size();
1202 
1203  // clean up jam structure
1204  for (std::vector<JamInfo*>::iterator i = jams.begin(); i != jams.end(); ++i) {
1205  delete *i;
1206  }
1207 }
1208 
1209 void
1210 MSE2Collector::calculateTimeLossAndTimeOnDetector(const SUMOVehicle& veh, double oldPos, double newPos, const VehicleInfo& vi, double& timeOnDetector, double& timeLoss) const {
1211  assert(veh.getID() == vi.id);
1212  assert(newPos + vi.entryOffset >= 0);
1213 
1214  if (oldPos == newPos) {
1215  // vehicle is stopped
1216  timeLoss = TS;
1217  timeOnDetector = TS;
1218  return;
1219  }
1220 
1221  // Eventual positional offset of the detector start from the lane's start
1222  double entryPos = MAX2(-vi.entryOffset, 0.);
1223  // Time of this vehicle entering the detector in the last time step
1224  double entryTime = 0;
1225  // Take into account the time before entering the detector, if there is.
1226  if (oldPos < entryPos) {
1227  // Vehicle entered the detector in the last step, either traversing the detector start or somewhere in the middle.
1228  entryTime = MSCFModel::passingTime(oldPos, entryPos, newPos, veh.getPreviousSpeed(), veh.getSpeed());
1229  }
1230  // speed at detector entry
1231  double entrySpeed = MSCFModel::speedAfterTime(entryTime, veh.getPreviousSpeed(), newPos - oldPos);
1232  // Calculate time spent on detector until reaching newPos or a detector exit
1233  double exitPos = MIN2(newPos, -vi.exitOffset + vi.length);
1234  assert(entryPos < exitPos);
1235 
1236  // calculate vehicle's time spent on the detector
1237  double exitTime;
1238  if (exitPos == newPos) {
1239  exitTime = TS;
1240  } else {
1241  exitTime = MSCFModel::passingTime(oldPos, exitPos, newPos, veh.getPreviousSpeed(), veh.getSpeed());
1242  }
1243 
1244  // Vehicle's Speed when leaving the detector
1245  double exitSpeed = MSCFModel::speedAfterTime(exitTime, veh.getPreviousSpeed(), newPos - oldPos);
1246 
1247  // Maximal speed on vehicle's current lane (== lane before last time step)
1248  // Note: this disregards the possibility of different maximal speeds on different traversed lanes.
1249  // (we accept this as discretization error)
1250  double vmax = MAX2(veh.getLane()->getVehicleMaxSpeed(&veh), NUMERICAL_EPS);
1251 
1252  // Time loss suffered on the detector
1253  timeOnDetector = exitTime - entryTime;
1254  timeLoss = MAX2(0., timeOnDetector * (vmax - (entrySpeed + exitSpeed) / 2) / vmax);
1255 
1256 #ifdef DEBUG_E2_TIME_ON_DETECTOR
1257  if (DEBUG_COND) {
1258  std::cout << SIMTIME << " calculateTimeLoss() for vehicle '" << veh.getID() << "'"
1259  << " oldPos = " << oldPos << " newPos = " << newPos
1260  << " entryPos = " << entryPos << " exitPos = " << exitPos
1261  << " timeOnDetector = " << timeOnDetector
1262  << " timeLoss = " << timeLoss
1263  << std::endl;
1264  }
1265 #endif
1266 }
1267 
1268 
1269 void
1271  dev.writeXMLHeader("detector", "det_e2_file.xsd");
1272 }
1273 
1274 void
1276  dev << " <interval begin=\"" << time2string(startTime) << "\" end=\"" << time2string(stopTime) << "\" " << "id=\"" << getID() << "\" ";
1277 
1278  const double meanSpeed = myVehicleSamples != 0 ? mySpeedSum / myVehicleSamples : -1;
1279  const double meanOccupancy = myTimeSamples != 0 ? myOccupancySum / (double) myTimeSamples : 0;
1280  const double meanJamLengthInMeters = myTimeSamples != 0 ? myMeanMaxJamInMeters / (double) myTimeSamples : 0;
1281  const double meanJamLengthInVehicles = myTimeSamples != 0 ? myMeanMaxJamInVehicles / (double) myTimeSamples : 0;
1282  const double meanVehicleNumber = myTimeSamples != 0 ? (double) myMeanVehicleNumber / (double) myTimeSamples : 0;
1283  const double meanTimeLoss = myNumberOfSeenVehicles != 0 ? myTotalTimeLoss / myNumberOfSeenVehicles : -1;
1284 
1285  SUMOTime haltingDurationSum = 0;
1286  SUMOTime maxHaltingDuration = 0;
1287  int haltingNo = 0;
1288  for (std::vector<SUMOTime>::iterator i = myPastStandingDurations.begin(); i != myPastStandingDurations.end(); ++i) {
1289  haltingDurationSum += (*i);
1290  maxHaltingDuration = MAX2(maxHaltingDuration, (*i));
1291  haltingNo++;
1292  }
1293  for (std::map<std::string, SUMOTime> ::iterator i = myHaltingVehicleDurations.begin(); i != myHaltingVehicleDurations.end(); ++i) {
1294  haltingDurationSum += (*i).second;
1295  maxHaltingDuration = MAX2(maxHaltingDuration, (*i).second);
1296  haltingNo++;
1297  }
1298  const SUMOTime meanHaltingDuration = haltingNo != 0 ? haltingDurationSum / haltingNo : 0;
1299 
1300  SUMOTime intervalHaltingDurationSum = 0;
1301  SUMOTime intervalMaxHaltingDuration = 0;
1302  int intervalHaltingNo = 0;
1303  for (std::vector<SUMOTime>::iterator i = myPastIntervalStandingDurations.begin(); i != myPastIntervalStandingDurations.end(); ++i) {
1304  intervalHaltingDurationSum += (*i);
1305  intervalMaxHaltingDuration = MAX2(intervalMaxHaltingDuration, (*i));
1306  intervalHaltingNo++;
1307  }
1308  for (std::map<std::string, SUMOTime> ::iterator i = myIntervalHaltingVehicleDurations.begin(); i != myIntervalHaltingVehicleDurations.end(); ++i) {
1309  intervalHaltingDurationSum += (*i).second;
1310  intervalMaxHaltingDuration = MAX2(intervalMaxHaltingDuration, (*i).second);
1311  intervalHaltingNo++;
1312  }
1313  const SUMOTime intervalMeanHaltingDuration = intervalHaltingNo != 0 ? intervalHaltingDurationSum / intervalHaltingNo : 0;
1314 
1315 #ifdef DEBUG_E2_XML_OUT
1316  if (DEBUG_COND) {
1317  std::stringstream ss;
1318  ss << "sampledSeconds=\"" << myVehicleSamples << "\" "
1319  << "myTimeSamples=\"" << myTimeSamples << "\" "
1320  << "myOccupancySum=\"" << myOccupancySum << "\" "
1321  << "myMeanVehicleNumber=\"" << myMeanVehicleNumber << "\" "
1322  << "nVehEntered=\"" << myNumberOfEnteredVehicles << "\" "
1323  << "meanSpeed=\"" << meanSpeed << "\"";
1324  std::cout << ss.str() << std::endl;
1325  }
1326 #endif
1327 
1328 
1329  dev << "sampledSeconds=\"" << myVehicleSamples << "\" "
1330  << "nVehEntered=\"" << myNumberOfEnteredVehicles << "\" "
1331  << "nVehLeft=\"" << myNumberOfLeftVehicles << "\" "
1332  << "nVehSeen=\"" << myNumberOfSeenVehicles << "\" "
1333  << "meanSpeed=\"" << meanSpeed << "\" "
1334  << "meanTimeLoss=\"" << meanTimeLoss << "\" "
1335  << "meanOccupancy=\"" << meanOccupancy << "\" "
1336  << "maxOccupancy=\"" << myMaxOccupancy << "\" "
1337  << "meanMaxJamLengthInVehicles=\"" << meanJamLengthInVehicles << "\" "
1338  << "meanMaxJamLengthInMeters=\"" << meanJamLengthInMeters << "\" "
1339  << "maxJamLengthInVehicles=\"" << myMaxJamInVehicles << "\" "
1340  << "maxJamLengthInMeters=\"" << myMaxJamInMeters << "\" "
1341  << "jamLengthInVehiclesSum=\"" << myJamLengthInVehiclesSum << "\" "
1342  << "jamLengthInMetersSum=\"" << myJamLengthInMetersSum << "\" "
1343  << "meanHaltingDuration=\"" << STEPS2TIME(meanHaltingDuration) << "\" "
1344  << "maxHaltingDuration=\"" << STEPS2TIME(maxHaltingDuration) << "\" "
1345  << "haltingDurationSum=\"" << STEPS2TIME(haltingDurationSum) << "\" "
1346  << "meanIntervalHaltingDuration=\"" << STEPS2TIME(intervalMeanHaltingDuration) << "\" "
1347  << "maxIntervalHaltingDuration=\"" << STEPS2TIME(intervalMaxHaltingDuration) << "\" "
1348  << "intervalHaltingDurationSum=\"" << STEPS2TIME(intervalHaltingDurationSum) << "\" "
1349  << "startedHalts=\"" << myStartedHalts << "\" "
1350  << "meanVehicleNumber=\"" << meanVehicleNumber << "\" "
1351  << "maxVehicleNumber=\"" << myMaxVehicleNumber << "\" "
1352  << "/>\n";
1353  reset();
1354 
1355 }
1356 
1357 void
1359  myVehicleSamples = 0;
1360  myTotalTimeLoss = 0.;
1364  myMaxVehicleNumber = 0;
1365 
1366  mySpeedSum = 0;
1367  myStartedHalts = 0;
1370  myOccupancySum = 0;
1371  myMaxOccupancy = 0;
1374  myMaxJamInVehicles = 0;
1375  myMaxJamInMeters = 0;
1376  myTimeSamples = 0;
1377  myMeanVehicleNumber = 0;
1378  for (std::map<std::string, SUMOTime>::iterator i = myIntervalHaltingVehicleDurations.begin(); i != myIntervalHaltingVehicleDurations.end(); ++i) {
1379  (*i).second = 0;
1380  }
1381  myPastStandingDurations.clear();
1383 }
1384 
1385 
1386 int
1388  int result = 0;
1389  for (VehicleInfoMap::const_iterator it = myVehicleInfos.begin(); it != myVehicleInfos.end(); it++) {
1390  if (it->second->onDetector) {
1391  result++;
1392  }
1393  }
1394  return result;
1395 }
1396 
1397 
1398 
1399 std::vector<std::string>
1401  std::vector<std::string> ret;
1402  for (VehicleInfoMap::const_iterator i = myVehicleInfos.begin(); i != myVehicleInfos.end(); ++i) {
1403  if (i->second->onDetector) {
1404  ret.push_back(i->second->id);
1405  }
1406  }
1407  std::sort(ret.begin(), ret.end());
1408  return ret;
1409 }
1410 
1411 
1412 std::vector<MSE2Collector::VehicleInfo*>
1414  std::vector<VehicleInfo*> res;
1415  VehicleInfoMap::const_iterator i;
1416  for (i = myVehicleInfos.begin(); i != myVehicleInfos.end(); ++i) {
1417  if (i->second->onDetector) {
1418  res.push_back(i->second);
1419  }
1420  }
1421  return res;
1422 }
1423 
1424 
1425 
1426 int
1428 
1429  // double distance = std::numeric_limits<double>::max();
1430  double thresholdSpeed = myLane->getSpeedLimit() / speedThreshold;
1431 
1432  int count = 0;
1433  for (VehicleInfoMap::const_iterator it = myVehicleInfos.begin();
1434  it != myVehicleInfos.end(); it++) {
1435  if (it->second->onDetector) {
1436  // if (it->position < distance) {
1437  // distance = it->position;
1438  // }
1439  // const double realDistance = myLane->getLength() - distance; // the closer vehicle get to the light the greater is the distance
1440  const double realDistance = it->second->distToDetectorEnd;
1441  if (it->second->lastSpeed <= thresholdSpeed || it->second->lastAccel > 0) { //TODO speed less half of the maximum speed for the lane NEED TUNING
1442  count = (int)(realDistance / (it->second->length + it->second->minGap)) + 1;
1443  }
1444  }
1445  }
1446 
1447  return count;
1448 }
1449 
1450 double
1452 
1453  if (myVehicleInfos.empty()) {
1454  return -1;
1455  }
1456 
1457  double distance = std::numeric_limits<double>::max();
1458  double realDistance = 0;
1459  bool flowing = true;
1460  for (VehicleInfoMap::const_iterator it = myVehicleInfos.begin();
1461  it != myVehicleInfos.end(); it++) {
1462  if (it->second->onDetector) {
1463  distance = MIN2(it->second->lastPos, distance);
1464  // double distanceTemp = myLane->getLength() - distance;
1465  if (it->second->lastSpeed <= 0.5) {
1466  realDistance = distance - it->second->length + it->second->minGap;
1467  flowing = false;
1468  }
1469  // DBG(
1470  // std::ostringstream str;
1471  // str << time2string(MSNet::getInstance()->getCurrentTimeStep())
1472  // << " MSE2Collector::getEstimateQueueLength::"
1473  // << " lane " << myLane->getID()
1474  // << " vehicle " << it->second.id
1475  // << " positionOnLane " << it->second.position
1476  // << " vel " << it->second.speed
1477  // << " realDistance " << realDistance;
1478  // WRITE_MESSAGE(str.str());
1479  // )
1480  }
1481  }
1482  if (flowing) {
1483  return 0;
1484  } else {
1485  return myLane->getLength() - realDistance;
1486  }
1487 }
1488 
1489 /****************************************************************************/
1490 
MSE2Collector::MSE2Collector
MSE2Collector(const std::string &id, DetectorUsage usage, MSLane *lane, double startPos, double endPos, double length, SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold, const std::string &vTypes)
Constructor with given end position and detector length.
Definition: MSE2Collector.cpp:61
SUMOTrafficObject
Representation of a vehicle or person.
Definition: SUMOTrafficObject.h:48
MSE2Collector::getEstimateQueueLength
double getEstimateQueueLength() const
Returns an estimate of the lenght of the queue of vehicles currently stopped on the detector.
Definition: MSE2Collector.cpp:1451
MSLane::dictionary
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition: MSLane.cpp:1855
MSVehicleType::getID
const std::string & getID() const
Returns the name of the vehicle type.
Definition: MSVehicleType.h:94
MSE2Collector::MoveNotificationInfo::newPos
double newPos
Position after the last integration step (relative to the vehicle's entry lane on the detector)
Definition: MSE2Collector.h:181
MSE2Collector::myMaxOccupancy
double myMaxOccupancy
The maximum occupancy [%].
Definition: MSE2Collector.h:723
MIN2
T MIN2(T a, T b)
Definition: StdDefs.h:74
MSE2Collector::myTotalTimeLoss
double myTotalTimeLoss
The total amount of all time losses [time x vehicle] since the last reset.
Definition: MSE2Collector.h:709
MSE2Collector::myVehicleSamples
double myVehicleSamples
Definition: MSE2Collector.h:707
WRITE_WARNING
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:239
MSE2Collector::JamInfo
Internal representation of a jam.
Definition: MSE2Collector.h:205
MSNet.h
MSDetectorFileOutput
Base of value-generating classes (detectors)
Definition: MSDetectorFileOutput.h:64
MSE2Collector::checkJam
bool checkJam(std::vector< MoveNotificationInfo * >::const_iterator mni, std::map< std::string, SUMOTime > &haltingVehicles, std::map< std::string, SUMOTime > &intervalHaltingVehicles)
checks whether the vehicle stands in a jam
Definition: MSE2Collector.cpp:1102
MSLane
Representation of a lane in the micro simulation.
Definition: MSLane.h:83
MSE2Collector::MoveNotificationInfo::onDetector
bool onDetector
whether the vehicle is on the detector at the end of the current timestep
Definition: MSE2Collector.h:195
SUMOTrafficObject::getAcceleration
virtual double getAcceleration() const =0
Returns the vehicle's acceleration.
OutputDevice
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:64
MSE2Collector::VehicleInfo::lastAccel
double lastAccel
Last value of the acceleration.
Definition: MSE2Collector.h:145
MSE2Collector::myNumberOfEnteredVehicles
int myNumberOfEnteredVehicles
Definition: MSE2Collector.h:740
DELTA_T
SUMOTime DELTA_T
Definition: SUMOTime.cpp:35
MSE2Collector::myMeanVehicleNumber
int myMeanVehicleNumber
The mean number of vehicles [#veh].
Definition: MSE2Collector.h:733
NUMERICAL_EPS
#define NUMERICAL_EPS
Definition: config.h:145
MSLane::getCanonicalSuccessorLane
MSLane * getCanonicalSuccessorLane() const
Definition: MSLane.cpp:2598
MSE2Collector::JamInfo::lastStandingVehicle
std::vector< MoveNotificationInfo * >::const_iterator lastStandingVehicle
The last standing vehicle.
Definition: MSE2Collector.h:210
MSE2Collector::myCurrentStartedHalts
int myCurrentStartedHalts
The number of started halts in the last step.
Definition: MSE2Collector.h:765
SUMOTrafficObject::getVehicleType
virtual const MSVehicleType & getVehicleType() const =0
Returns the vehicle's type.
SUMOTrafficObject::isVehicle
virtual bool isVehicle() const =0
Get the vehicle's ID.
MSE2Collector::myMoveNotifications
std::vector< MoveNotificationInfo * > myMoveNotifications
Temporal storage for notifications from vehicles that did call the detector's notifyMove() in the las...
Definition: MSE2Collector.h:682
SUMOTrafficObject::getID
virtual const std::string & getID() const =0
Get the vehicle's ID.
MSE2Collector::notifyLeave
virtual bool notifyLeave(SUMOTrafficObject &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Removes a known vehicle due to its lane-change.
Definition: MSE2Collector.cpp:676
MSE2Collector::MoveNotificationInfo
Values collected in notifyMove and needed in detectorUpdate() to calculate the accumulated quantities...
Definition: MSE2Collector.h:161
MSE2Collector::myMeanMaxJamInVehicles
int myMeanMaxJamInVehicles
The mean jam length [#veh].
Definition: MSE2Collector.h:725
SUMOTime
long long int SUMOTime
Definition: SUMOTime.h:35
SUMOVehicle
Representation of a vehicle.
Definition: SUMOVehicle.h:61
MSE2Collector::MoveNotificationInfo::id
std::string id
Vehicle's id.
Definition: MSE2Collector.h:174
MSE2Collector::VehicleInfo::totalTimeOnDetector
double totalTimeOnDetector
Accumulated time that this vehicle has spent on the detector since its last entry.
Definition: MSE2Collector.h:136
SUMOVehicle::isOnRoad
virtual bool isOnRoad() const =0
Returns the information whether the vehicle is on a road (is simulated)
MSE2Collector::checkPositioning
void checkPositioning(bool posGiven=false, double desiredLength=0.)
Adjusts positioning if the detector length is less than POSITION_EPS and tests some assertions.
Definition: MSE2Collector.cpp:202
MSE2Collector::VehicleInfo::lastSpeed
double lastSpeed
Last value of the speed.
Definition: MSE2Collector.h:147
MSE2Collector::recalculateDetectorLength
void recalculateDetectorLength()
Updates the detector length after myStartPos and myEndPos have been modified.
Definition: MSE2Collector.cpp:263
MSE2Collector::myTimeSamples
int myTimeSamples
The current aggregation duration [#steps].
Definition: MSE2Collector.h:719
MSE2Collector::compareMoveNotification
static bool compareMoveNotification(MoveNotificationInfo *mni1, MoveNotificationInfo *mni2)
Definition: MSE2Collector.h:639
MSE2Collector::getCurrentVehicles
std::vector< VehicleInfo * > getCurrentVehicles() const
Returns the VehicleInfos for the vehicles currently on the detector.
Definition: MSE2Collector.cpp:1413
MSE2Collector::~MSE2Collector
virtual ~MSE2Collector()
Destructor.
Definition: MSE2Collector.cpp:297
MSE2Collector::myCurrentMeanLength
double myCurrentMeanLength
The current mean length.
Definition: MSE2Collector.h:753
MSE2Collector::JamInfo::firstStandingVehicle
std::vector< MoveNotificationInfo * >::const_iterator firstStandingVehicle
The first standing vehicle.
Definition: MSE2Collector.h:207
MSE2Collector::getLength
double getLength() const
Returns the length of the detector.
Definition: MSE2Collector.h:386
MSE2Collector::snap
static double snap(double value, double snapPoint, double snapDist)
Snaps value to snpPoint if they are closer than snapDist.
Definition: MSE2Collector.cpp:253
MSE2Collector::myCurrentJamLengthInVehicles
int myCurrentJamLengthInVehicles
The overall jam length in vehicles.
Definition: MSE2Collector.h:763
MSE2Collector::myJamHaltingSpeedThreshold
double myJamHaltingSpeedThreshold
A vehicle must driver slower than this to be counted as a part of a jam.
Definition: MSE2Collector.h:667
MSE2Collector.h
MSE2Collector::writeXMLDetectorProlog
virtual void writeXMLDetectorProlog(OutputDevice &dev) const
Open the XML-output.
Definition: MSE2Collector.cpp:1270
MSE2Collector::myPastStandingDurations
std::vector< SUMOTime > myPastStandingDurations
Halting durations of ended halts [s].
Definition: MSE2Collector.h:696
MSE2Collector::makeVehicleInfo
VehicleInfo * makeVehicleInfo(const SUMOVehicle &veh, const MSLane *enteredLane) const
Creates and returns a VehicleInfo (called at the vehicle's entry)
Definition: MSE2Collector.cpp:816
MSE2Collector::myLanes
std::vector< std::string > myLanes
Definition: MSE2Collector.h:652
MSE2Collector::mySpeedSum
double mySpeedSum
The sum of collected vehicle speeds [m/s].
Definition: MSE2Collector.h:711
MSE2Collector::myCurrentMaxJamLengthInVehicles
int myCurrentMaxJamLengthInVehicles
The current maximum jam length in vehicles.
Definition: MSE2Collector.h:759
SUMOTrafficObject::getBackPositionOnLane
virtual double getBackPositionOnLane(const MSLane *lane) const =0
Get the vehicle's back position along the given lane.
MSVehicle.h
MSMoveReminder
Something on a lane to be noticed about vehicle movement.
Definition: MSMoveReminder.h:64
MSE2Collector::MoveNotificationInfo::lengthOnDetector
double lengthOnDetector
The length of the part of the vehicle on the detector at the end of the last time step.
Definition: MSE2Collector.h:191
MSVehicleType.h
MAX2
T MAX2(T a, T b)
Definition: StdDefs.h:80
MSE2Collector::MoveNotificationInfo::timeOnDetector
double timeOnDetector
Time spent on the detector during the last integration step.
Definition: MSE2Collector.h:189
MSE2Collector::VehicleInfo::id
std::string id
vehicle's ID
Definition: MSE2Collector.h:111
MSE2Collector::myCurrentMeanSpeed
double myCurrentMeanSpeed
The current mean speed.
Definition: MSE2Collector.h:751
MSE2Collector::processJams
void processJams(std::vector< JamInfo * > &jams, JamInfo *currentJam)
Calculates aggregated values from the given jam structure, deletes all jam-pointers.
Definition: MSE2Collector.cpp:1158
MSE2Collector::aggregateOutputValues
void aggregateOutputValues()
Aggregates and normalize some values for the detector output during detectorUpdate()
Definition: MSE2Collector.cpp:941
SIMTIME
#define SIMTIME
Definition: SUMOTime.h:64
MSE2Collector::myNumberOfSeenVehicles
int myNumberOfSeenVehicles
The number of vehicles, present on the detector at the last reset.
Definition: MSE2Collector.h:742
MSE2Collector::myJamLengthInVehiclesSum
int myJamLengthInVehiclesSum
The sum of jam lengths [#veh].
Definition: MSE2Collector.h:717
MSE2Collector::myJamDistanceThreshold
double myJamDistanceThreshold
Two standing vehicles must be closer than this to be counted into the same jam.
Definition: MSE2Collector.h:671
TS
#define TS
Definition: SUMOTime.h:44
MSE2Collector::myMaxJamInMeters
double myMaxJamInMeters
The max jam length [m].
Definition: MSE2Collector.h:731
MSE2Collector::myDetectorLength
double myDetectorLength
The total detector length.
Definition: MSE2Collector.h:664
MSE2Collector::VehicleInfo
A VehicleInfo stores values that are tracked for the individual vehicles on the detector,...
Definition: MSE2Collector.h:87
MSE2Collector::initAuxiliaries
void initAuxiliaries(std::vector< MSLane * > &lanes)
Checks integrity of myLanes, adds internal-lane information, inits myLength, myFirstLane,...
Definition: MSE2Collector.cpp:440
STEPS2TIME
#define STEPS2TIME(x)
Definition: SUMOTime.h:57
SUMOVehicle::getLane
virtual MSLane * getLane() const =0
Returns the lane the vehicle is on.
MSLane::getLength
double getLength() const
Returns the lane's length.
Definition: MSLane.h:541
MSE2Collector::VehicleInfo::lastPos
double lastPos
Definition: MSE2Collector.h:150
MSE2Collector::VehicleInfo::exitOffset
double exitOffset
Definition: MSE2Collector.h:132
MSE2Collector::myStartedHalts
double myStartedHalts
The number of started halts [#].
Definition: MSE2Collector.h:713
MSE2Collector::myStartPos
double myStartPos
The position the detector starts at on the first lane.
Definition: MSE2Collector.h:660
time2string
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:65
MSE2Collector::notifyMove
virtual bool notifyMove(SUMOTrafficObject &veh, double oldPos, double newPos, double newSpeed)
Adds/removes vehicles from the list of vehicles to regard.
Definition: MSE2Collector.cpp:599
MSE2Collector::selectLanes
std::vector< MSLane * > selectLanes(MSLane *endLane, double length, std::string dir)
This is called if no lane sequence is given to the constructor. Builds myLanes from the given informa...
Definition: MSE2Collector.cpp:313
MSVehicleType::getMinGap
double getMinGap() const
Get the free space in front of vehicles of this class.
Definition: MSVehicleType.h:126
MSE2Collector::myJamLengthInMetersSum
double myJamLengthInMetersSum
The sum of jam lengths [m].
Definition: MSE2Collector.h:715
MSE2Collector::VehicleInfo::hasEntered
bool hasEntered
Whether the vehicle has already entered the detector (don't count twice!)
Definition: MSE2Collector.h:143
MSE2Collector::MoveNotificationInfo::timeLoss
double timeLoss
timeloss during the last integration step
Definition: MSE2Collector.h:193
MSE2Collector::VehicleInfo::accumulatedTimeLoss
double accumulatedTimeLoss
Accumulated time loss that this vehicle suffered since it entered the detector.
Definition: MSE2Collector.h:138
DEBUG_COND
#define DEBUG_COND
Definition: Vehicle.cpp:55
MSE2Collector::VehicleInfo::distToDetectorEnd
double distToDetectorEnd
Distance left till the detector end after the last integration step (may become negative if the vehic...
Definition: MSE2Collector.h:134
MSLane::getCanonicalPredecessorLane
MSLane * getCanonicalPredecessorLane() const
Definition: MSLane.cpp:2578
MSCFModel::speedAfterTime
static double speedAfterTime(const double t, const double oldSpeed, const double dist)
Calculates the speed after a time t \in [0,TS] given the initial speed and the distance traveled in a...
Definition: MSCFModel.cpp:674
MSE2Collector::buildJam
void buildJam(bool isInJam, std::vector< MoveNotificationInfo * >::const_iterator mni, JamInfo *&currentJam, std::vector< JamInfo * > &jams)
Either adds the vehicle to the end of an existing jam, or closes the last jam, and/or creates a new j...
Definition: MSE2Collector.cpp:1047
MSE2Collector::myCurrentJamNo
int myCurrentJamNo
The current jam number.
Definition: MSE2Collector.h:755
MSE2Collector::reset
virtual void reset()
Resets all values.
Definition: MSE2Collector.cpp:1358
MSE2Collector::calculateTimeLossAndTimeOnDetector
void calculateTimeLossAndTimeOnDetector(const SUMOVehicle &veh, double oldPos, double newPos, const VehicleInfo &vi, double &timeOnDetector, double &timeLoss) const
Calculates the time spent on the detector in the last step and the timeloss suffered in the last step...
Definition: MSE2Collector.cpp:1210
MSE2Collector::myHaltingVehicleDurations
std::map< std::string, SUMOTime > myHaltingVehicleDurations
Storage for halting durations of known vehicles (for halting vehicles)
Definition: MSE2Collector.h:690
MSE2Collector::myVehicleInfos
VehicleInfoMap myVehicleInfos
Definition: MSE2Collector.h:678
MSE2Collector::myNumberOfLeftVehicles
int myNumberOfLeftVehicles
The number of vehicles, which have left the detector since the last reset.
Definition: MSE2Collector.h:744
MSGlobals::gUsingInternalLanes
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:69
DetectorUsage
DetectorUsage
Definition: MSDetectorFileOutput.h:51
MSE2Collector::myCurrentMaxJamLengthInMeters
double myCurrentMaxJamLengthInMeters
the current maximum jam length in meters
Definition: MSE2Collector.h:757
MSE2Collector::myFirstLane
MSLane * myFirstLane
The first lane of the detector's lane sequence.
Definition: MSE2Collector.h:656
MSE2Collector::myEndPos
double myEndPos
The position the detector ends at on the last lane.
Definition: MSE2Collector.h:662
MSE2Collector::myLastLane
MSLane * myLastLane
The last lane of the detector's lane sequence.
Definition: MSE2Collector.h:658
MSE2Collector::getLanes
std::vector< MSLane * > getLanes()
Returns a vector containing pointers to the lanes covered by the detector ordered from its first to i...
Definition: MSE2Collector.cpp:589
toString
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:48
MSE2Collector::MoveNotificationInfo::speed
double speed
Speed after the last integration step.
Definition: MSE2Collector.h:183
MSE2Collector::integrateMoveNotification
void integrateMoveNotification(VehicleInfo *vi, const MoveNotificationInfo *mni)
This updates the detector values and the VehicleInfo of a vehicle on the detector with the given Move...
Definition: MSE2Collector.cpp:965
MSE2Collector::myCurrentHaltingsNumber
int myCurrentHaltingsNumber
The number of halted vehicles [#].
Definition: MSE2Collector.h:767
MSE2Collector::addDetectorToLanes
void addDetectorToLanes(std::vector< MSLane * > &lanes)
This adds the detector as a MoveReminder to the associated lanes.
Definition: MSE2Collector.cpp:423
MSE2Collector::writeXMLOutput
virtual void writeXMLOutput(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Write the generated output to the given device.
Definition: MSE2Collector.cpp:1275
SUMOTrafficObject::getPreviousSpeed
virtual double getPreviousSpeed() const =0
Returns the vehicle's previous speed.
MSVehicleType::getLength
double getLength() const
Get vehicle's length [m].
Definition: MSVehicleType.h:110
InvalidArgument
Definition: UtilExceptions.h:57
MSE2Collector::myIntervalHaltingVehicleDurations
std::map< std::string, SUMOTime > myIntervalHaltingVehicleDurations
Storage for halting durations of known vehicles (current interval)
Definition: MSE2Collector.h:693
MSLane::getLinkTo
MSLink * getLinkTo(const MSLane *) const
returns the link to the given lane or 0, if it is not connected
Definition: MSLane.cpp:2106
MSE2Collector::myJamHaltingTimeThreshold
SUMOTime myJamHaltingTimeThreshold
A vehicle must be that long beyond myJamHaltingSpeedThreshold to be counted as a part of a jam.
Definition: MSE2Collector.h:669
MSDetectorFileOutput::vehicleApplies
bool vehicleApplies(const SUMOTrafficObject &veh) const
Checks whether the detector measures vehicles of the given type.
Definition: MSDetectorFileOutput.h:142
config.h
MSCFModel::passingTime
static double passingTime(const double lastPos, const double passedPos, const double currentPos, const double lastSpeed, const double currentSpeed)
Calculates the time at which the position passedPosition has been passed In case of a ballistic updat...
Definition: MSCFModel.cpp:597
MSLane::isInternal
bool isInternal() const
Definition: MSLane.cpp:1999
MSE2Collector::MoveNotificationInfo::accel
double accel
Acceleration in the last integration step.
Definition: MSE2Collector.h:185
MSE2Collector::getCurrentVehicleNumber
int getCurrentVehicleNumber() const
Returns the number of vehicles currently on the detector.
Definition: MSE2Collector.cpp:1387
MSE2Collector::detectorUpdate
virtual void detectorUpdate(const SUMOTime step)
Computes the detector values in each time step.
Definition: MSE2Collector.cpp:838
MSE2Collector::myOffsets
std::vector< double > myOffsets
The distances of the lane-beginnings from the detector start-point.
Definition: MSE2Collector.h:654
MSE2Collector::makeMoveNotification
MoveNotificationInfo * makeMoveNotification(const SUMOVehicle &veh, double oldPos, double newPos, double newSpeed, const VehicleInfo &vehInfo) const
Creates and returns a MoveNotificationInfo containing detector specific information on the vehicle's ...
Definition: MSE2Collector.cpp:1001
MSLane.h
MSE2Collector::getEstimatedCurrentVehicleNumber
int getEstimatedCurrentVehicleNumber(double speedThreshold) const
Returns an estimate of the number of vehicles currently on the detector.
Definition: MSE2Collector.cpp:1427
OutputDevice::writeXMLHeader
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >())
Writes an XML header with optional configuration.
Definition: OutputDevice.cpp:228
MSE2Collector::VehicleInfo::length
double length
vehicle's length
Definition: MSE2Collector.h:117
MSLane::getVehicleMaxSpeed
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Definition: MSLane.h:519
MSE2Collector::myPastIntervalStandingDurations
std::vector< SUMOTime > myPastIntervalStandingDurations
Halting durations of ended halts for the current interval [s].
Definition: MSE2Collector.h:699
SUMOTrafficObject::getPositionOnLane
virtual double getPositionOnLane() const =0
Get the vehicle's position along the lane.
MSLane::getSpeedLimit
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition: MSLane.h:533
MSE2Collector::myMeanMaxJamInMeters
double myMeanMaxJamInMeters
The mean jam length [m].
Definition: MSE2Collector.h:727
Named::myID
std::string myID
The name of the object.
Definition: Named.h:134
MSE2Collector::MoveNotificationInfo::distToDetectorEnd
double distToDetectorEnd
Distance left till the detector end after the last integration step (may become negative if the vehic...
Definition: MSE2Collector.h:187
Named::getID
const std::string & getID() const
Returns the id.
Definition: Named.h:77
MSMoveReminder::Notification
Notification
Definition of a vehicle state.
Definition: MSMoveReminder.h:89
POSITION_EPS
#define POSITION_EPS
Definition: config.h:169
MSMoveReminder::NOTIFICATION_JUNCTION
The vehicle arrived at a junction.
Definition: MSMoveReminder.h:93
MSE2Collector::getCurrentVehicleIDs
std::vector< std::string > getCurrentVehicleIDs() const
Returns the IDs of the vehicles within the area.
Definition: MSE2Collector.cpp:1400
MSE2Collector::myMaxJamInVehicles
int myMaxJamInVehicles
The max jam length [#veh].
Definition: MSE2Collector.h:729
MSE2Collector::myCurrentOccupancy
double myCurrentOccupancy
The current occupancy.
Definition: MSE2Collector.h:749
MSE2Collector::VehicleInfo::entryOffset
double entryOffset
Definition: MSE2Collector.h:125
MSE2Collector::myMaxVehicleNumber
int myMaxVehicleNumber
The maximal number of vehicles located on the detector simultaneously since the last reset.
Definition: MSE2Collector.h:746
MSMoveReminder::myLane
MSLane *const myLane
Lane on which the reminder works.
Definition: MSMoveReminder.h:238
MSE2Collector::VehicleInfo::onDetector
bool onDetector
whether the vehicle is on the detector at the end of the current timestep
Definition: MSE2Collector.h:141
MSE2Collector::notifyEnter
virtual bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane)
Adds the vehicle to known vehicles if not beyond the dector.
Definition: MSE2Collector.cpp:730
SUMOTrafficObject::getSpeed
virtual double getSpeed() const =0
Returns the vehicle's current speed.
MSE2Collector::myLeftVehicles
std::set< std::string > myLeftVehicles
Keep track of vehicles that left the detector by a regular move along a junction (not lanechange,...
Definition: MSE2Collector.h:687
MSE2Collector::myOccupancySum
double myOccupancySum
The sum of occupancies [%].
Definition: MSE2Collector.h:721
MSE2Collector::myCurrentJamLengthInMeters
double myCurrentJamLengthInMeters
The overall jam length in meters.
Definition: MSE2Collector.h:761