Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file MSE2Collector.h
15 : /// @author Christian Roessel
16 : /// @author Daniel Krajzewicz
17 : /// @author Sascha Krieg
18 : /// @author Michael Behrisch
19 : /// @author Robbin Blokpoel
20 : /// @author Jakob Erdmann
21 : /// @author Leonhard Luecken
22 : /// @date Mon Feb 03 2014 14:13 CET
23 : ///
24 : // An areal detector covering to a sequence of consecutive lanes
25 : /****************************************************************************/
26 : #pragma once
27 : #include <config.h>
28 :
29 : #include <vector>
30 : #include <list>
31 : #include <microsim/MSLane.h>
32 : #include <microsim/MSNet.h>
33 : #include <microsim/MSMoveReminder.h>
34 : #include <microsim/output/MSDetectorFileOutput.h>
35 : #include <utils/common/UtilExceptions.h>
36 : #include <cassert>
37 :
38 :
39 : // ===========================================================================
40 : // class declarations
41 : // ===========================================================================
42 : class OutputDevice;
43 : class SUMOVehicle;
44 : class SUMOTrafficObject;
45 :
46 :
47 : // ===========================================================================
48 : // class definitions
49 : // ===========================================================================
50 : /**
51 : * @class MSE2Collector
52 : * @brief An areal detector corresponding to a sequence of consecutive lanes
53 : *
54 : * This detector traces vehicles which are on a sequence of consecutive lanes. A
55 : * vehicle that enters the detector is stored and the stored vehicles' speeds
56 : * are used within each timestep to compute the detector values. As soon as the
57 : * vehicle leaves the detector, it is no longer tracked.
58 : *
59 : * Determining entering and leaving vehicles is done via the MSMoveReminder
60 : * interface. The values are computed by an event-callback (at the end of
61 : * a time step).
62 : *
63 : * @note As soon as a vehicle enters the detector, a VehicleInfo object is created
64 : * and stored in myVehicleInfos. This is constantly updated as long as the
65 : * vehicle stays on the detector (i.e. calls notifyMove()). All movement
66 : * notifications sent by vehicles on the detector are temporarily stored
67 : * in myMoveNotifications, see notifyMove(). Finally they are integrated
68 : * into myVehicleInfos when updateDetector is called.
69 : * @note When subclassing this detector, it is probably sufficient to adapt the
70 : * definition of the structs VehicleInfo and the MoveNotification, as well as
71 : * the methods that define and create those structs, i.e., makeVehicleInfo()
72 : * and makeMoveNotification(). Further the integration of new movement
73 : * notifications of the last time step into the vehicle infos is done
74 : * in updateVehicleInfos().
75 : *
76 : */
77 :
78 :
79 : class MSE2Collector : public MSMoveReminder, public MSDetectorFileOutput {
80 : public:
81 : /** @brief A VehicleInfo stores values that are tracked for the individual vehicles on the detector,
82 : * e.g., accumulated timeloss. These infos are stored in myVehicles. If a vehicle leaves the detector
83 : * (may it be temporarily), the entry in myVehicles is discarded, i.e. all information on the vehicle is reset.
84 : */
85 : struct VehicleInfo {
86 : /** @note Constructor expects an entryLane argument corresponding to a lane, which is part of the detector.
87 : */
88 600644 : VehicleInfo(std::string id, std::string type, double length, double minGap, const MSLane* entryLane, double entryOffset,
89 600644 : std::size_t currentOffsetIndex, double exitOffset, double distToDetectorEnd, bool onDetector) :
90 600644 : id(id),
91 600644 : type(type),
92 600644 : length(length),
93 600644 : minGap(minGap),
94 600644 : entryLaneID(entryLane->getID()),
95 600644 : entryOffset(entryOffset),
96 600644 : currentLane(entryLane),
97 600644 : currentOffsetIndex(currentOffsetIndex),
98 600644 : exitOffset(exitOffset),
99 600644 : distToDetectorEnd(distToDetectorEnd),
100 600644 : totalTimeOnDetector(0.),
101 600644 : accumulatedTimeLoss(0.),
102 600644 : onDetector(onDetector),
103 600644 : hasEntered(false),
104 600644 : lastAccel(0),
105 600644 : lastSpeed(0),
106 600644 : lastPos(0) {
107 : assert(exitOffset < 0);
108 600644 : }
109 1201288 : virtual ~VehicleInfo() {};
110 : /// vehicle's ID
111 : std::string id;
112 : /// vehicle's type
113 : std::string type;
114 : /// vehicle's length
115 : double length;
116 : /// vehicle's minGap
117 : double minGap;
118 : /// ID of the lane, on which the vehicle entered the detector
119 : std::string entryLaneID;
120 : /// Distance of the vehicle's entry lane's beginning to the detector start (can be negative for the first lane)
121 : /// In notifyMove(), the positional input arguments are relative to that position (since the vehicle picks up the MoveReminder
122 : /// on the entry lane)
123 : double entryOffset;
124 : /// Lane, on which the vehicle currently resides (always the one for which the last notifyEnter was received)
125 : const MSLane* currentLane;
126 : /// Index of currentLane in the detector's myLanes vector.
127 : std::size_t currentOffsetIndex;
128 : /// Offset from the detector start, where the vehicle has leaves the detector (defaults to detector length and is updated
129 : /// if the vehicle leaves the detector via a junction before reaching its end, i.e. enters a lane not part of the detector)
130 : double exitOffset;
131 : /// Distance left till the detector end after the last integration step (may become negative if the vehicle passes beyond the detector end)
132 : double distToDetectorEnd;
133 : /// Accumulated time that this vehicle has spent on the detector since its last entry
134 : double totalTimeOnDetector;
135 : /// Accumulated time loss that this vehicle suffered since it entered the detector
136 : double accumulatedTimeLoss;
137 :
138 : /// whether the vehicle is on the detector at the end of the current timestep
139 : bool onDetector;
140 : /// Whether the vehicle has already entered the detector (don't count twice!)
141 : bool hasEntered;
142 : /// Last value of the acceleration
143 : double lastAccel;
144 : /// Last value of the speed
145 : double lastSpeed;
146 : /// Last value of the vehicle position in reference to the start lane
147 : /// @note NOT in reference to the entry lane as newPos argument in notifyMove()!
148 : double lastPos;
149 : };
150 :
151 : typedef std::map<std::string, VehicleInfo*> VehicleInfoMap;
152 :
153 :
154 : private:
155 : /** @brief Values collected in notifyMove and needed in detectorUpdate() to
156 : * calculate the accumulated quantities for the detector. These are
157 : * temporarily stored in myMoveNotifications for each step.
158 : */
159 : struct MoveNotificationInfo {
160 47370516 : MoveNotificationInfo(std::string _vehID, double _oldPos, double _newPos, double _speed, double _accel, double _distToDetectorEnd, double _timeOnDetector, double _lengthOnDetector, double _timeLoss, double _waitingTime, bool _onDetector) :
161 47370516 : id(_vehID),
162 47370516 : oldPos(_oldPos),
163 47370516 : newPos(_newPos),
164 47370516 : speed(_speed),
165 47370516 : accel(_accel),
166 47370516 : distToDetectorEnd(_distToDetectorEnd),
167 47370516 : timeOnDetector(_timeOnDetector),
168 47370516 : lengthOnDetector(_lengthOnDetector),
169 47370516 : timeLoss(_timeLoss),
170 47370516 : waitingTime(_waitingTime),
171 47370516 : onDetector(_onDetector) {}
172 :
173 47370516 : virtual ~MoveNotificationInfo() {};
174 :
175 : /// Vehicle's id
176 : std::string id;
177 : /// Position before the last integration step (relative to the vehicle's entry lane on the detector)
178 : double oldPos;
179 : /// Position after the last integration step (relative to the vehicle's entry lane on the detector)
180 : double newPos;
181 : /// Speed after the last integration step
182 : double speed;
183 : /// Acceleration in the last integration step
184 : double accel;
185 : /// Distance left till the detector end after the last integration step (may become negative if the vehicle passes beyond the detector end)
186 : double distToDetectorEnd;
187 : /// Time spent on the detector during the last integration step
188 : double timeOnDetector;
189 : /// The length of the part of the vehicle on the detector at the end of the last time step
190 : double lengthOnDetector;
191 : /// timeloss during the last integration step
192 : double timeLoss;
193 : /// the current (consecutive) waitingTime on the detector in s
194 : double waitingTime;
195 : /// whether the vehicle is on the detector at the end of the current timestep
196 : bool onDetector;
197 : };
198 :
199 :
200 :
201 : /** @brief Internal representation of a jam
202 : *
203 : * Used in execute, instances of this structure are used to track
204 : * begin and end positions (as vehicles) of a jam.
205 : */
206 : struct JamInfo {
207 : /// @brief The first standing vehicle
208 : std::vector<MoveNotificationInfo*>::const_iterator firstStandingVehicle;
209 :
210 : /// @brief The last standing vehicle
211 : std::vector<MoveNotificationInfo*>::const_iterator lastStandingVehicle;
212 : };
213 :
214 :
215 : public:
216 :
217 : /** @brief Constructor with given end position and detector length
218 : *
219 : * @param[in] id The detector's unique id.
220 : * @param[in] usage Information how the detector is used
221 : * @param[in] lane The lane the detector ends
222 : * @param[in] startPos The start position on the lane the detector is placed at
223 : * @param[in] endPos The end position on the lane the detector is placed at
224 : * @param[in] length The length the detector has (heuristic lane selection is done if the continuation is not unique)
225 : * @param[in] haltingTimeThreshold The time a vehicle's speed must be below haltingSpeedThreshold to be assigned as jammed
226 : * @param[in] haltingSpeedThreshold The speed a vehicle's speed must be below to be assigned as jammed
227 : * @param[in] jamDistThreshold The distance between two vehicles in order to not count them to one jam
228 : * @param[in] vTypes Vehicle types, that the detector takes into account
229 : *
230 : * @note Exactly one of the arguments startPos, endPos and length should be invalid (i.e. equal to std::numeric_limits<double>::max()).
231 : * If length is invalid, it is required that 0 <= startPos < endPos <= lane->length
232 : * If endPos is invalid, the detector may span over several lanes downstream of the lane
233 : * If pos is invalid, the detector may span over several lanes upstream of the lane
234 : */
235 : MSE2Collector(const std::string& id,
236 : DetectorUsage usage, MSLane* lane, double startPos, double endPos, double length,
237 : SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
238 : const std::string name, const std::string& vTypes,
239 : const std::string& nextEdges,
240 : int detectPersons);
241 :
242 :
243 : /** @brief Constructor with a sequence of lanes and given start and end position on the first and last lanes
244 : *
245 : * @param[in] id The detector's unique id.
246 : * @param[in] usage Information how the detector is used
247 : * @param[in] lanes A sequence of lanes the detector covers (must form a continuous piece)
248 : * @param[in] startPos The position of the detector start on the first lane the detector is placed at
249 : * @param[in] endPos The position of the detector end on the last lane the detector is placed at
250 : * @param[in] haltingTimeThreshold The time a vehicle's speed must be below haltingSpeedThreshold to be assigned as jammed
251 : * @param[in] haltingSpeedThreshold The speed a vehicle's speed must be below to be assigned as jammed
252 : * @param[in] jamDistThreshold The distance between two vehicles in order to not count them to one jam
253 : * @param[in] vTypes Vehicle types, that the detector takes into account
254 : */
255 : MSE2Collector(const std::string& id,
256 : DetectorUsage usage, std::vector<MSLane*> lanes, double startPos, double endPos,
257 : SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
258 : const std::string name, const std::string& vTypes,
259 : const std::string& nextEdges,
260 : int detectPersons);
261 :
262 :
263 : /// @brief Destructor
264 : virtual ~MSE2Collector();
265 :
266 : /** @brief Returns the detector's usage type
267 : *
268 : * @see DetectorUsage
269 : * @return How the detector is used.
270 : */
271 10420 : virtual DetectorUsage getUsageType() const {
272 10420 : return myUsage;
273 : }
274 :
275 :
276 :
277 : /// @name Methods inherited from MSMoveReminder
278 : /// @{
279 :
280 : /** @brief Adds/removes vehicles from the list of vehicles to regard
281 : *
282 : * As soon as the reported vehicle enters the detector area (position>myStartPos)
283 : * it is added to the list of vehicles to regard (myKnownVehicles). It
284 : * is removed from this list if it leaves the detector (position<length>myEndPos).
285 : * The method returns true as long as the vehicle is not beyond the detector.
286 : *
287 : * @param[in] veh The vehicle in question.
288 : * @param[in] oldPos Position before the move-micro-timestep.
289 : * @param[in] newPos Position after the move-micro-timestep.
290 : * Note that this position is given in reference
291 : * to the begin of the entry lane of the vehicle.
292 : * @param[in] newSpeed Unused here.
293 : * @return False, if vehicle passed the detector entirely, else true.
294 : * @see MSMoveReminder
295 : * @see MSMoveReminder::notifyMove
296 : */
297 : virtual bool notifyMove(SUMOTrafficObject& veh, double oldPos, double newPos,
298 : double newSpeed);
299 :
300 :
301 : /** @brief Removes a known vehicle due to its lane-change
302 : *
303 : * If the reported vehicle is known, it is removed from the list of
304 : * vehicles to regard (myKnownVehicles).
305 : *
306 : * @param[in] veh The leaving vehicle.
307 : * @param[in] lastPos Position on the lane when leaving.
308 : * @param[in] isArrival whether the vehicle arrived at its destination
309 : * @param[in] isLaneChange whether the vehicle changed from the lane
310 : * @see MSMoveReminder::notifyLeave
311 : */
312 : virtual bool notifyLeave(SUMOTrafficObject& veh, double lastPos, MSMoveReminder::Notification reason, const MSLane* enteredLane = 0);
313 :
314 :
315 : /** @brief Adds the vehicle to known vehicles if not beyond the dector
316 : *
317 : * If the vehicles is within the detector are, it is added to the list
318 : * of known vehicles.
319 : * The method returns true as long as the vehicle is not beyond the detector.
320 : *
321 : * @param[in] veh The entering vehicle.
322 : * @param[in] reason how the vehicle enters the lane
323 : * @return False, if vehicle passed the detector entirely, else true.
324 : * @see MSMoveReminder::notifyEnter
325 : * @see MSMoveReminder::Notification
326 : */
327 : virtual bool notifyEnter(SUMOTrafficObject& veh, MSMoveReminder::Notification reason, const MSLane* enteredLane);
328 : /// @}
329 :
330 :
331 :
332 :
333 :
334 : /// @name Methods inherited from MSDetectorFileOutput.
335 : /// @{
336 :
337 : /** @brief Computes the detector values in each time step
338 : *
339 : * This method should be called at the end of a simulation step, when
340 : * all vehicles have moved. The current values are computed and
341 : * summed up with the previous.
342 : *
343 : * @param[in] currentTime The current simulation time
344 : */
345 : virtual void detectorUpdate(const SUMOTime step);
346 :
347 :
348 : /** @brief Write the generated output to the given device
349 : * @param[in] dev The output device to write the data into
350 : * @param[in] startTime First time step the data were gathered
351 : * @param[in] stopTime Last time step the data were gathered
352 : * @exception IOError If an error on writing occurs
353 : */
354 : virtual void writeXMLOutput(OutputDevice& dev, SUMOTime startTime, SUMOTime stopTime);
355 :
356 :
357 : /** @brief Open the XML-output
358 : *
359 : * The implementing function should open an xml element using
360 : * OutputDevice::writeXMLHeader.
361 : *
362 : * @param[in] dev The output device to write the root into
363 : * @exception IOError If an error on writing occurs
364 : */
365 : virtual void writeXMLDetectorProlog(OutputDevice& dev) const;
366 :
367 : /// @}
368 :
369 : /// @brief get name
370 : const std::string& getName() {
371 : return myName;
372 : }
373 :
374 : /** @brief Returns the begin position of the detector
375 : *
376 : * @return The detector's begin position
377 : */
378 : double getStartPos() const {
379 593 : return myStartPos;
380 : }
381 :
382 :
383 : /** @brief Returns the end position of the detector
384 : *
385 : * @return The detector's end position
386 : */
387 : double getEndPos() const {
388 593 : return myEndPos;
389 : }
390 :
391 : /** @brief Returns the length of the detector
392 : *
393 : * @return The detector's length
394 : */
395 : double getLength() const {
396 429 : return myDetectorLength;
397 : }
398 :
399 :
400 : /** @brief Returns the id of the detector's last lane
401 : *
402 : * @return The detector's end position
403 : */
404 : MSLane* getLastLane() const {
405 8 : return myLastLane;
406 : }
407 :
408 :
409 : /** @brief Returns a vector containing pointers to the lanes covered by the detector ordered from its first to its last lane
410 : */
411 : std::vector<MSLane*> getLanes();
412 :
413 : /** @brief Resets all values
414 : *
415 : * This method is called on initialisation and as soon as the values
416 : * were written. Values for the next interval may be collected, then.
417 : * The list of known vehicles stays untouched.
418 : */
419 : virtual void reset();
420 :
421 :
422 : /// @name Methods returning current values
423 : /// @{
424 :
425 : /** @brief Returns the number of vehicles currently on the detector */
426 : int getCurrentVehicleNumber() const;
427 :
428 : /** @brief Returns the current detector occupancy */
429 0 : double getCurrentOccupancy() const {
430 428 : return myCurrentOccupancy;
431 : }
432 :
433 : /** @brief Returns the mean vehicle speed of vehicles currently on the detector*/
434 0 : double getCurrentMeanSpeed() const {
435 128236 : return myCurrentMeanSpeed;
436 : }
437 :
438 : /** @brief Returns the mean vehicle length of vehicles currently on the detector*/
439 0 : double getCurrentMeanLength() const {
440 0 : return myCurrentMeanLength;
441 : }
442 :
443 : /** @brief Returns the current number of jams */
444 0 : int getCurrentJamNumber() const {
445 0 : return myCurrentJamNo;
446 : }
447 :
448 : /** @brief Returns the length in vehicles of the currently largest jam */
449 0 : int getCurrentMaxJamLengthInVehicles() const {
450 0 : return myCurrentMaxJamLengthInVehicles;
451 : }
452 :
453 : /** @brief Returns the length in meters of the currently largest jam */
454 0 : double getCurrentMaxJamLengthInMeters() const {
455 0 : return myCurrentMaxJamLengthInMeters;
456 : }
457 :
458 : /** @brief Returns the length of all jams in vehicles */
459 0 : int getCurrentJamLengthInVehicles() const {
460 428 : return myCurrentJamLengthInVehicles;
461 : }
462 :
463 : /** @brief Returns the length of all jams in meters */
464 0 : double getCurrentJamLengthInMeters() const {
465 428 : return myCurrentJamLengthInMeters;
466 : }
467 :
468 : /** @brief Returns the length of the longest-duration jam in s */
469 : double getCurrentJamDuration() const {
470 1092 : return myCurrentJamDuration;
471 : }
472 :
473 : /** @brief Returns the length of all jams in meters */
474 0 : int getCurrentStartedHalts() const {
475 0 : return myCurrentStartedHalts;
476 : }
477 :
478 : /** @brief Returns the number of current haltings within the area
479 : *
480 : * If no vehicle is within the area, 0 is returned.
481 : *
482 : * @return The mean number of haltings within the area
483 : */
484 : int getCurrentHaltingNumber() const {
485 428 : return myCurrentHaltingsNumber;
486 : }
487 :
488 : /** @brief Returns the IDs of the vehicles within the area
489 : *
490 : * @return The IDs of the vehicles that have passed the entry, but not yet an exit point
491 : */
492 : std::vector<std::string> getCurrentVehicleIDs() const;
493 :
494 : /** @brief Returns the VehicleInfos for the vehicles currently on the detector
495 : */
496 : std::vector<VehicleInfo*> getCurrentVehicles() const;
497 :
498 : /** \brief Returns the number of vehicles passed over the sensor (i.e. entered the sensor)
499 : *
500 : * @return number of cars passed over the sensor
501 : */
502 0 : int getPassedVeh() {
503 0 : return myNumberOfEnteredVehicles;
504 : }
505 :
506 : /** \brief Subtract the number of vehicles indicated from passed from the sensor count.
507 : *
508 : * @param[in] passed - int that indicates the number of vehicles to subtract
509 : */
510 : void subtractPassedVeh(int passed) {
511 0 : myNumberOfEnteredVehicles -= passed;
512 0 : }
513 :
514 : /// @}
515 :
516 :
517 : /// @name Methods returning aggregated values
518 : /// @{
519 :
520 0 : double getIntervalOccupancy() const {
521 318871 : return myTimeSamples != 0 ? myOccupancySum / (double) myTimeSamples : 0;
522 : }
523 0 : double getIntervalMeanSpeed() const {
524 318871 : return myVehicleSamples != 0 ? mySpeedSum / myVehicleSamples : -1;
525 : }
526 : double getIntervalMeanTimeLoss() const {
527 318871 : return myNumberOfSeenVehicles != 0 ? myTotalTimeLoss / myNumberOfSeenVehicles : -1;
528 : }
529 0 : double getIntervalMaxJamLengthInMeters() const {
530 608 : return myMaxJamInMeters;
531 : }
532 0 : int getIntervalVehicleNumber() const {
533 608 : return myNumberOfSeenVehicles;
534 : }
535 :
536 0 : double getLastIntervalOccupancy() const {
537 608 : return myPreviousMeanOccupancy;
538 : }
539 0 : double getLastIntervalMeanSpeed() const {
540 608 : return myPreviousMeanSpeed;
541 : }
542 : double getLastIntervalMeanTimeLoss() const {
543 608 : return myPreviousMeanTimeLoss;
544 : }
545 0 : double getLastIntervalMaxJamLengthInMeters() const {
546 608 : return myPreviousMaxJamLengthInMeters;
547 : }
548 0 : int getLastIntervalVehicleNumber() const {
549 608 : return myPreviousNumberOfSeenVehicles;
550 : }
551 :
552 : /// @}
553 :
554 :
555 : /// @name Estimation methods
556 : /// TODO: Need documentation, used for tls control in MSSOTLE2Sensors (->Daniel?)
557 : /// @{
558 : /** @brief Returns an estimate of the number of vehicles currently on the detector */
559 : int getEstimatedCurrentVehicleNumber(double speedThreshold) const;
560 :
561 : /** @brief Returns an estimate of the length of the queue of vehicles currently stopped on the detector */
562 : double getEstimateQueueLength() const;
563 : /// @}
564 :
565 :
566 67 : virtual void setVisible(bool /*show*/) {};
567 :
568 : /** @brief Remove all vehicles before quick-loading state */
569 : virtual void clearState(SUMOTime step);
570 :
571 : /** @brief Persistently overrides the number of vehicles on top of the detector
572 : * Setting a negative value removes the override
573 : */
574 : void overrideVehicleNumber(int num);
575 :
576 : double getOverrideVehNumber() const {
577 5210 : return myOverrideVehNumber;
578 : }
579 : private:
580 :
581 : /** @brief checks whether the vehicle stands in a jam
582 : *
583 : * @param[in] mni
584 : * @param[in/out] haltingVehicles
585 : * @param[in/out] intervalHaltingVehicles
586 : * @return Whether vehicle is in a jam.
587 : */
588 : bool checkJam(std::vector<MoveNotificationInfo*>::const_iterator mni, std::map<std::string, SUMOTime>& haltingVehicles, std::map<std::string, SUMOTime>& intervalHaltingVehicles);
589 :
590 :
591 : /** @brief Either adds the vehicle to the end of an existing jam, or closes the last jam, and/or creates a new jam
592 : *
593 : * @param isInJam
594 : * @param mni
595 : * @param[in/out] currentJam
596 : * @param[in/out] jams
597 : */
598 : void buildJam(bool isInJam, std::vector<MoveNotificationInfo*>::const_iterator mni, JamInfo*& currentJam, std::vector<JamInfo*>& jams);
599 :
600 :
601 : /** @brief Calculates aggregated values from the given jam structure, deletes all jam-pointers
602 : *
603 : * @param jams
604 : */
605 : void processJams(std::vector<JamInfo*>& jams, JamInfo* currentJam);
606 :
607 : /** @brief Calculates the time spent on the detector in the last step and the timeloss suffered in the last step for the given vehicle
608 : *
609 : * @param[in] veh Vehicle for which the values are to be calculated
610 : * @param[in] oldPos Last position (before the last timestep) of the vehicle relative to the beginning of its entry lane
611 : * @param[in] newPos Current position of the vehicle
612 : * @param[in] vi VehicleInfo corresponding to the vehicle
613 : * @param[in/out] timeOnDetector Total time spent on the detector during the last step
614 : * @param[in/out] timeLoss Total time loss suffered during the last integration step
615 : */
616 : void calculateTimeLossAndTimeOnDetector(const SUMOTrafficObject& veh, double oldPos, double newPos, const VehicleInfo& vi, double& timeOnDetector, double& timeLoss) const;
617 :
618 : /** @brief Checks integrity of myLanes, adds internal-lane information, inits myLength, myFirstLane, myLastLane, myOffsets
619 : * Called once at construction.
620 : * @requires myLanes should form a continuous sequence.
621 : */
622 : void initAuxiliaries(std::vector<MSLane*>& lanes);
623 :
624 : /** @brief Adjusts positioning if the detector length is less than POSITION_EPS and tests some assertions
625 : */
626 : void checkPositioning(bool posGiven = false, double desiredLength = 0.);
627 :
628 : /** @brief Snaps value to snpPoint if they are closer than snapDist
629 : */
630 : static double snap(double value, double snapPoint, double snapDist);
631 :
632 : /** @brief Updates the detector length after myStartPos and myEndPos have been modified
633 : */
634 : void recalculateDetectorLength();
635 :
636 :
637 :
638 : /** @brief This is called if no lane sequence is given to the constructor. Builds myLanes from the given information.
639 : * Also inits startPos (case dir=="bw") / endPos (case dir=="fw").
640 : * Selects lanes heuristically if no unambiguous continuation exists.
641 : *
642 : * @param[in] lane Lane, where the detector starts/ends
643 : * @param[in] length Length of the detector
644 : * @param[in] dir Direction of detector extension with value in {"fw", "bw"} (forward / backward)
645 : * If dir == "fw" lane is interpreted as corresponding to the start lane of the detector,
646 : * otherwise the lane is interpreted as the end lane.
647 : */
648 : std::vector<MSLane*> selectLanes(MSLane* endLane, double length, std::string dir);
649 :
650 :
651 : /** @brief This adds the detector as a MoveReminder to the associated lanes.
652 : */
653 : void addDetectorToLanes(std::vector<MSLane*>& lanes);
654 :
655 :
656 : /** @brief Aggregates and normalize some values for the detector output during detectorUpdate()
657 : */
658 : void aggregateOutputValues();
659 :
660 :
661 : /** @brief This updates the detector values and the VehicleInfo of a vehicle on the detector
662 : * with the given MoveNotificationInfo generated by the vehicle during the last time step.
663 : *
664 : * @param[in/out] vi VehicleInfo corresponding to the notifying vehicle
665 : * @param[in] mni MoveNotification for the vehicle
666 : */
667 : void integrateMoveNotification(VehicleInfo* vi, const MoveNotificationInfo* mni);
668 :
669 : /** @brief Creates and returns a MoveNotificationInfo containing detector specific information on the vehicle's last movement
670 : *
671 : * @param veh The vehicle sending the notification
672 : * @param oldPos The vehicle's position before the last integration step
673 : * @param newPos The vehicle's position after the last integration step
674 : * @param newSpeed The vehicle's speed after the last integration step
675 : * @param vehInfo Info on the detector's memory of the vehicle
676 : * @return A MoveNotificationInfo containing quantities of interest for the detector
677 : */
678 : MoveNotificationInfo* makeMoveNotification(const SUMOTrafficObject& veh, double oldPos, double newPos, double newSpeed, const VehicleInfo& vehInfo) const;
679 :
680 : /** @brief Creates and returns a VehicleInfo (called at the vehicle's entry)
681 : *
682 : * @param veh The entering vehicle
683 : * @param enteredLane The entry lane
684 : * @return A vehicle info which can be used to store information about the vehicle's stay on the detector
685 : */
686 : VehicleInfo* makeVehicleInfo(const SUMOTrafficObject& veh, const MSLane* enteredLane) const;
687 :
688 : /** @brief Calculates the time loss for a segment with constant vmax
689 : *
690 : * @param timespan time needed to cover the segment
691 : * @param initialSpeed speed at segment entry
692 : * @param accel constant acceleration assumed during movement on the segment
693 : * @param vmax Maximal possible speed for the considered vehicle on the segment
694 : * @return Time loss (== MAX(timespan*(vmax - (initialSpeed + accel/2))/vmax), 0)
695 : */
696 : static double calculateSegmentTimeLoss(double timespan, double initialSpeed, double accel, double vmax);
697 :
698 : /** brief returns true if the vehicle corresponding to mni1 is closer to the detector end than the vehicle corresponding to mni2
699 : */
700 215218530 : static bool compareMoveNotification(MoveNotificationInfo* mni1, MoveNotificationInfo* mni2) {
701 215218530 : return mni1->distToDetectorEnd < mni2->distToDetectorEnd;
702 : }
703 :
704 : void notifyMovePerson(MSTransportable* p, int dir, double pos);
705 :
706 : private:
707 :
708 : /// @brief Information about how this detector is used
709 : DetectorUsage myUsage;
710 :
711 : /// @name Detector parameter
712 : /// @{
713 : /// @brief name
714 : const std::string myName;
715 : /// @brief The detector's lane sequence
716 : std::vector<std::string> myLanes;
717 : /// @brief The distances of the lane-beginnings from the detector start-point
718 : std::vector<double> myOffsets;
719 : /// @brief The first lane of the detector's lane sequence
720 : MSLane* myFirstLane;
721 : /// @brief The last lane of the detector's lane sequence
722 : MSLane* myLastLane;
723 : /// @brief The position the detector starts at on the first lane
724 : double myStartPos;
725 : /// @brief The position the detector ends at on the last lane
726 : double myEndPos;
727 : /// @brief The total detector length
728 : double myDetectorLength;
729 :
730 : /// @brief A vehicle must driver slower than this to be counted as a part of a jam
731 : double myJamHaltingSpeedThreshold;
732 : /// @brief A vehicle must be that long beyond myJamHaltingSpeedThreshold to be counted as a part of a jam
733 : SUMOTime myJamHaltingTimeThreshold;
734 : /// @brief Two standing vehicles must be closer than this to be counted into the same jam
735 : double myJamDistanceThreshold;
736 : /// @}
737 :
738 :
739 : /// @name Container
740 : /// @{
741 : /// @brief List of informations about the vehicles currently on the detector
742 : VehicleInfoMap myVehicleInfos;
743 :
744 : /// @brief Temporal storage for notifications from vehicles that did call the
745 : /// detector's notifyMove() in the last time step.
746 : std::vector<MoveNotificationInfo*> myMoveNotifications;
747 :
748 : /// @brief Keep track of vehicles that left the detector by a regular move along a junction (not lanechange, teleport, etc.)
749 : /// and should be removed from myVehicleInfos after taking into account their movement. Non-longitudinal exits
750 : /// are processed immediately in notifyLeave()
751 : std::set<std::string> myLeftVehicles;
752 :
753 : /// @brief Storage for halting durations of known vehicles (for halting vehicles)
754 : std::map<std::string, SUMOTime> myHaltingVehicleDurations;
755 :
756 : /// @brief Storage for halting durations of known vehicles (current interval)
757 : std::map<std::string, SUMOTime> myIntervalHaltingVehicleDurations;
758 :
759 : /// @brief Halting durations of ended halts [s]
760 : std::vector<SUMOTime> myPastStandingDurations;
761 :
762 : /// @brief Halting durations of ended halts for the current interval [s]
763 : std::vector<SUMOTime> myPastIntervalStandingDurations;
764 : /// @}
765 :
766 :
767 :
768 : /// @name Values generated for aggregated file output
769 : /// @{
770 : /// @brief The number of collected samples [time x vehicle] since the last reset
771 : double myVehicleSamples;
772 : /// @brief The total amount of all time losses [time x vehicle] since the last reset
773 : double myTotalTimeLoss;
774 : /// @brief The sum of collected vehicle speeds [m/s]
775 : double mySpeedSum;
776 : /// @brief The number of started halts [#]
777 : double myStartedHalts;
778 : /// @brief The sum of jam lengths [m]
779 : double myJamLengthInMetersSum;
780 : /// @brief The sum of jam lengths [#veh]
781 : int myJamLengthInVehiclesSum;
782 : /// @brief The current aggregation duration [#steps]
783 : int myTimeSamples;
784 : /// @brief The sum of occupancies [%]
785 : double myOccupancySum;
786 : /// @brief The maximum occupancy [%]
787 : double myMaxOccupancy;
788 : /// @brief The mean jam length [#veh]
789 : int myMeanMaxJamInVehicles;
790 : /// @brief The mean jam length [m]
791 : double myMeanMaxJamInMeters;
792 : /// @brief The max jam length [#veh]
793 : int myMaxJamInVehicles;
794 : /// @brief The max jam length [m]
795 : double myMaxJamInMeters;
796 : /// @brief The mean number of vehicles [#veh]
797 : int myMeanVehicleNumber;
798 : /// @}
799 :
800 :
801 : /// @name Values generated describing the current state
802 : /// @{
803 : /// @brief The number of vehicles, which have entered the detector since the last reset
804 : int myNumberOfEnteredVehicles;
805 : /// @brief The number of vehicles, present on the detector at the last reset
806 : int myNumberOfSeenVehicles;
807 : /// @brief The number of vehicles, which have left the detector since the last reset
808 : int myNumberOfLeftVehicles;
809 : /// @brief The maximal number of vehicles located on the detector simultaneously since the last reset
810 : int myMaxVehicleNumber;
811 :
812 : /// @brief The current vehicle samples
813 : double myCurrentVehicleSamples;
814 : /// @brief The current occupancy
815 : double myCurrentOccupancy;
816 : /// @brief The current mean speed
817 : double myCurrentMeanSpeed;
818 : /// @brief The current mean timeLoss
819 : double myCurrentMeanTimeLoss;
820 : /// @brief The current mean length
821 : double myCurrentMeanLength;
822 : /// @brief The current jam number
823 : int myCurrentJamNo;
824 : /// @brief the current maximum jam length in meters
825 : double myCurrentMaxJamLengthInMeters;
826 : /// @brief The current maximum jam length in vehicles
827 : int myCurrentMaxJamLengthInVehicles;
828 : /// @brief The overall jam length in meters
829 : double myCurrentJamLengthInMeters;
830 : /// @brief The overall jam length in vehicles
831 : int myCurrentJamLengthInVehicles;
832 : /// @brief The overall jam duration in s
833 : double myCurrentJamDuration;
834 : /// @brief The number of started halts in the last step
835 : int myCurrentStartedHalts;
836 : /// @brief The number of halted vehicles [#]
837 : int myCurrentHaltingsNumber;
838 : /// @}
839 :
840 : /// @name Values generated describing the previous interval state
841 : /// @{
842 : double myPreviousMeanOccupancy;
843 : double myPreviousMeanSpeed;
844 : double myPreviousMeanTimeLoss;
845 : double myPreviousMaxJamLengthInMeters;
846 : int myPreviousNumberOfSeenVehicles;
847 : /// @}
848 :
849 : /// @brief stores the overriden (via Traci) number of vehicles on detector
850 : int myOverrideVehNumber;
851 :
852 : private:
853 : /// @brief Invalidated copy constructor.
854 : MSE2Collector(const MSE2Collector&);
855 :
856 : /// @brief Invalidated assignment operator.
857 : MSE2Collector& operator=(const MSE2Collector&);
858 : };
|