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