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