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