1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2003-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 /****************************************************************************/
10 /// @file    MSE3Collector.h
11 /// @author  Christian Roessel
12 /// @author  Daniel Krajzewicz
13 /// @author  Michael Behrisch
14 /// @author  Jakob Erdmann
15 /// @date    Tue Dec 02 2003 22:17 CET
16 /// @version $Id$
17 ///
18 // A detector of vehicles passing an area between entry/exit points
19 /****************************************************************************/
20 #ifndef MSE3Collector_h
21 #define MSE3Collector_h
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #include <config.h>
28 
29 #include <string>
30 #include <vector>
31 #include <limits>
32 #include <microsim/MSMoveReminder.h>
33 #include <microsim/output/MSDetectorFileOutput.h>
34 #include <utils/common/Named.h>
35 #include <microsim/output/MSCrossSection.h>
36 #include <utils/common/UtilExceptions.h>
37 
38 
39 // ===========================================================================
40 // class declarations
41 // ===========================================================================
42 class SUMOTrafficObject;
43 class OutputDevice;
44 
45 
46 // ===========================================================================
47 // class definitions
48 // ===========================================================================
49 /**
50  * @class MSE3Collector
51  * @brief A detector of vehicles passing an area between entry/exit points
52  *
53  * E3 detectors are defined by a set of in-cross-sections and out-cross-sections.
54  * Vehicles, that pass an in- and out-cross-section are detected when they pass the
55  *  out-cross-section. Vehicles passing the out-cross-section without having
56  *  passed the in-cross-section are not detected.
57  */
58 class MSE3Collector : public MSDetectorFileOutput {
59 public:
60     /**
61      * @class MSE3EntryReminder
62      * @brief A place on the road net (at a certain lane and position on it) where the E3 area begins
63      */
64     class MSE3EntryReminder : public MSMoveReminder {
65     public:
66         /** @brief Constructor
67          *
68          * @param[in] crossSection The position at which the entry lies
69          * @param[in] collector The detector the entry belongs to
70          */
71         MSE3EntryReminder(const MSCrossSection& crossSection, MSE3Collector& collector);
72 
73 
74         /// @name Methods inherited from MSMoveReminder.
75         /// @{
76         /** @brief Checks whether the reminder is activated by a vehicle entering the lane
77          *
78          * Lane change means in this case that the vehicle changes to the lane
79          *  the reminder is placed at.
80          *
81          * @param[in] veh The entering vehicle.
82          * @param[in] reason how the vehicle enters the lane
83          * @return True if vehicle enters the reminder.
84          * @see Notification
85          */
86         bool notifyEnter(SUMOTrafficObject& veh, Notification reason, const MSLane* enteredLane);
87 
88         /** @brief Checks whether the vehicle enters
89          *
90          * As soon as the reported vehicle enters the detector area (position>myPosition)
91          *  the entering time is computed and both are added to the parent detector using
92          *  "enter".
93          *
94          * @param[in] veh The vehicle in question.
95          * @param[in] oldPos Position before the move-micro-timestep.
96          * @param[in] newPos Position after the move-micro-timestep.
97          * @param[in] newSpeed Unused here.
98          * @return False, if vehicle passed the detector entierly, else true.
99          * @see MSMoveReminder
100          * @see MSMoveReminder::notifyMove
101          * @see MSE3Collector::enter
102          */
103         bool notifyMove(SUMOTrafficObject& veh, double, double newPos, double);
104 
105 
106         /** @brief Processes state changes of a vehicle
107         *
108         * If the reported vehicle is known, and the reason indicates a removal from the network
109         *  (permanent or temporary), the vehicle is removed from the list of vehicles to regard.
110         *
111         * @param[in] veh The leaving vehicle.
112         * @param[in] lastPos Position on the lane when leaving.
113         * @param[in] reason The reason for the state change
114         * @see MSMoveReminder::notifyLeave
115         */
116         bool notifyLeave(SUMOTrafficObject& veh, double lastPos, MSMoveReminder::Notification reason, const MSLane* enteredLane = 0);
117         /// @}
118 
119 
120     private:
121         /// @brief The parent collector
122         MSE3Collector& myCollector;
123 
124         /// @brief The position on the lane
125         double myPosition;
126 
127     private:
128         /// @brief Invalidated copy constructor.
129         MSE3EntryReminder(const MSE3EntryReminder&);
130 
131         /// @brief Invalidated assignment operator.
132         MSE3EntryReminder& operator=(const MSE3EntryReminder&);
133 
134     };
135 
136 
137 
138     /**
139      * @class MSE3LeaveReminder
140      * @brief A place on the road net (at a certain lane and position on it) where the E3 area ends
141      */
142     class MSE3LeaveReminder : public MSMoveReminder {
143     public:
144         /** @brief Constructor
145          *
146          * @param[in] crossSection The position at which the exit lies
147          * @param[in] collector The detector the exit belongs to
148          */
149         MSE3LeaveReminder(const MSCrossSection& crossSection, MSE3Collector& collector);
150 
151 
152         /// @name methods from MSMoveReminder
153         //@{
154         /** @brief Checks whether the reminder is activated by a vehicle entering the lane
155          *
156          * Lane change means in this case that the vehicle changes to the lane
157          *  the reminder is placed at.
158          *
159          * @param[in] veh The entering vehicle.
160          * @param[in] reason how the vehicle enters the lane
161          * @return True if vehicle enters the reminder.
162          * @see Notification
163          */
164         bool notifyEnter(SUMOTrafficObject& veh, Notification reason, const MSLane* enteredLane);
165 
166         /** @brief Checks whether the vehicle leaves
167          *
168          * As soon as the reported vehicle leaves the detector area (position-length>myPosition)
169          *  the leaving time is computed and both are made known to the parent detector using
170          *  "leave".
171          *
172          * @param[in] veh The vehicle in question.
173          * @param[in] oldPos Position before the move-micro-timestep.
174          * @param[in] newPos Position after the move-micro-timestep.
175          * @param[in] newSpeed Unused here.
176          * @return False, if vehicle passed the detector entirely, else true.
177          * @see MSMoveReminder
178          * @see MSMoveReminder::notifyMove
179          * @see MSE3Collector::leave
180          */
181         bool notifyMove(SUMOTrafficObject& veh, double oldPos, double newPos, double);
182 
183         /** @brief Processes state changes of a vehicle
184         *
185         * Checks whether the vehicle has changed lanes and this reminder needs to be removed
186         *
187         * @param[in] veh The leaving vehicle (unused).
188         * @param[in] lastPos Position on the lane when leaving (unused).
189         * @param[in] reason The reason for the state change
190         * @see MSMoveReminder::notifyLeave
191         */
192         bool notifyLeave(SUMOTrafficObject& veh, double lastPos, MSMoveReminder::Notification reason, const MSLane* enteredLane = 0);
193         //@}
194 
195 
196     private:
197         /// @brief The parent collector
198         MSE3Collector& myCollector;
199 
200         /// @brief The position on the lane
201         double myPosition;
202 
203     private:
204         /// @brief Invalidated copy constructor.
205         MSE3LeaveReminder(const MSE3LeaveReminder&);
206 
207         /// @brief Invalidated assignment operator.
208         MSE3LeaveReminder& operator=(const MSE3LeaveReminder&);
209 
210     };
211 
212 
213     /** @brief Constructor
214      *
215      * Sets reminder objects on entry- and leave-lanes
216      *
217      *  @param[in] id The detector's unique id.
218      *  @param[in] entries Entry-cross-sections.
219      *  @param[in] exits Leavey-cross-sections.
220      *  @param[in] haltingSpeedThreshold A vehicle must not drive a greater speed than haltingSpeedThreshold to be a "halting" vehicle.
221      *  @param[in] haltingTimeThreshold A vehicle must not drive a greater speed for more than haltingTimeThreshold to be a "halting" vehicle.
222      */
223     MSE3Collector(const std::string& id,
224                   const CrossSectionVector& entries, const CrossSectionVector& exits,
225                   double haltingSpeedThreshold,
226                   SUMOTime haltingTimeThreshold,
227                   const std::string& vTypes, bool openEntry);
228 
229 
230     /// @brief Destructor
231     virtual ~MSE3Collector();
232 
233 
234     /** @brief Resets all generated values to allow computation of next interval
235      */
236     void reset();
237 
238 
239     /** @brief Called if a vehicle touches an entry-cross-section.
240      *
241      * Inserts vehicle into internal containers.
242      *
243      *  @param[in] veh The vehicle that entered the area
244      *  @param[in] entryTimestep The time in seconds the vehicle entered the area
245      *  @param[in] fractionTimeOnDet The interpolated time in seconds the vehicle already spent on the detector
246      */
247     void enter(const SUMOTrafficObject& veh, const double entryTimestep, const double fractionTimeOnDet, MSE3EntryReminder* entryReminder);
248 
249 
250     /** @brief Called if a vehicle front passes a leave-cross-section.
251     *
252     *  @param[in] veh The vehicle that left the area
253     *  @param[in] leaveTimestep The time in seconds the vehicle started crossing the line
254     */
255     void leaveFront(const SUMOTrafficObject& veh, const double leaveTimestep);
256 
257 
258     /** @brief Called if a vehicle back passes a leave-cross-section.
259     *
260     * Removes vehicle from internal containers.
261     *
262     *  @param[in] veh The vehicle that left the area
263     *  @param[in] leaveTimestep The time in seconds the vehicle left the area
264     *  @param[in] fractionTimeOnDet The interpolated time in seconds the vehicle still spent on the detector
265     */
266     void leave(const SUMOTrafficObject& veh, const double leaveTimestep, const double fractionTimeOnDet);
267 
268 
269     /// @name Methods returning current values
270     /// @{
271 
272     /** @brief Returns the mean speed within the area
273      *
274      * If no vehicle is within the area, -1 is returned.
275      *
276      * @return The mean speed [m/s] of all vehicles within the area, -1 if there is none
277      */
278     double getCurrentMeanSpeed() const;
279 
280 
281     /** @brief Returns the number of current haltings within the area
282      *
283      * If no vehicle is within the area, 0 is returned.
284      *
285      * @return The mean number of haltings within the area
286      */
287     int getCurrentHaltingNumber() const;
288 
289 
290     /** @brief Returns the number of vehicles within the area
291      * @return The number of vehicles that passed the entry collector
292      */
293     int getVehiclesWithin() const;
294 
295 
296     /** @brief Returns the number of vehicles within the area
297      *
298      * @return The number of vehicles that have passed the entry, but not yet an exit point
299      */
300     std::vector<std::string> getCurrentVehicleIDs() const;
301     /// @}
302 
303 
304     /// @name Methods inherited from MSDetectorFileOutput.
305     /// @{
306 
307     /** @brief Writes collected values into the given stream
308      *
309      * @param[in] dev The output device to write the data into
310      * @param[in] startTime First time step the data were gathered
311      * @param[in] stopTime Last time step the data were gathered
312      * @see MSDetectorFileOutput::writeXMLOutput
313      * @exception IOError If an error on writing occurs (!!! not yet implemented)
314      */
315     void writeXMLOutput(OutputDevice& dev, SUMOTime startTime, SUMOTime stopTime);
316 
317 
318     /** @brief Opens the XML-output using "e3Detector" as root element
319      *
320      * The lists of entries/exists are written, too.
321      *
322      * @param[in] dev The output device to write the root into
323      * @see MSDetectorFileOutput::writeXMLDetectorProlog
324      * @exception IOError If an error on writing occurs (!!! not yet implemented)
325      */
326     void writeXMLDetectorProlog(OutputDevice& dev) const;
327     /// @}
328 
329 
330 
331     /** @brief Computes the detector values in each time step
332      *
333      * This method should be called at the end of a simulation step, when
334      *  all vehicles have moved. The current values are computed and
335      *  summed up with the previous.
336      *
337      * @param[in] currentTime The current simulation time (unused)
338      */
339     void detectorUpdate(const SUMOTime step);
340 
341 
342 protected:
343     /// @brief The detector's entries
344     CrossSectionVector myEntries;
345 
346     /// @brief The detector's exits
347     CrossSectionVector myExits;
348 
349     /// @brief The detector's built entry reminder
350     std::vector<MSE3EntryReminder*> myEntryReminders;
351 
352     /// @brief The detector's built exit reminder
353     std::vector<MSE3LeaveReminder*> myLeaveReminders;
354 
355 
356     // @brief Time-threshold to determine if a vehicle is halting.
357     SUMOTime myHaltingTimeThreshold;
358 
359     /// @brief Speed-threshold to determine if a vehicle is halting.
360     double myHaltingSpeedThreshold;
361 
362     /**
363      * @struct E3Values
364      * @brief Internal storage for values from a vehicle
365      *
366      * For each vehicle within the area (that entered through an entry point),
367      *  this structure is allocated. All values gathered from the vehicle are aggregated
368      *  within this structure.
369      */
370     struct E3Values {
371         /// @brief The vehicle's entry time
372         double entryTime;
373         /// @brief The time the vehicle's front was crossing the leave line
374         double frontLeaveTime;
375         /// @brief The time the vehicle's back was crossing the leave line
376         double backLeaveTime;
377         /// @brief The sum of registered speeds the vehicle has/had inside the area
378         double speedSum;
379         /// @brief The sum of haltings the vehicle has/had within the area
380         int haltings;
381         /// @brief Begin time of last halt begin
382         SUMOTime haltingBegin;
383         /// @brief The sum of registered speeds the vehicle has/had inside the area during the current interval
384         double intervalSpeedSum;
385         /// @brief The sum of haltings the vehicle has/had within the area during the current interval
386         int intervalHaltings;
387         /// @brief The timeLoss of the vehicle when entering. Updated to the actual time loss within the area when leaving
388         SUMOTime timeLoss;
389         /// @brief The timeLoss of the vehicle when entering. Updated to the current timeLoss at interval write
390         SUMOTime intervalTimeLoss;
391         /// @brief An internal information whether the update step was performed
392         bool hadUpdate;
393         /// @brief the reminder on which the vehicle entered the detector
394         MSE3EntryReminder* entryReminder;
395     };
396 
397     /// @brief Container for vehicles that have entered the area
398     std::map<const SUMOTrafficObject*, E3Values> myEnteredContainer;
399 
400     /// @brief Container for vehicles that have left the area
401     std::vector<E3Values> myLeftContainer;
402 
403 
404     /// @name Storages for current values
405     /// @{
406 
407     /// @brief The current mean speed of known vehicles (inside)
408     double myCurrentMeanSpeed;
409 
410     /// @brief The current number of haltings (inside)
411     int myCurrentHaltingsNumber;
412     /// @}
413 
414 
415     /// @brief Information when the last reset has been done
416     SUMOTime myLastResetTime;
417 
418     /// @brief whether this dector is declared as having incomplete entry detectors
419     const bool myOpenEntry;
420 
421 private:
422     /// @brief Invalidated copy constructor.
423     MSE3Collector(const MSE3Collector&);
424 
425     /// @brief Invalidated assignment operator.
426     MSE3Collector& operator=(const MSE3Collector&);
427 
428 
429 };
430 
431 
432 #endif
433 
434 /****************************************************************************/
435 
436