1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2013-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    MSDevice_SSM.h
11 /// @author  Daniel Krajzewicz
12 /// @author  Jakob Erdmann
13 /// @author  Leonhard Luecken
14 /// @date    11.06.2013
15 /// @version $Id$
16 ///
17 // An SSM-device logs encounters / conflicts of the carrying vehicle with other surrounding vehicles.
18 // XXX: Preliminary implementation. Use with care. Especially rerouting vehicles could be problematic.
19 /****************************************************************************/
20 #ifndef MSDevice_SSM_h
21 #define MSDevice_SSM_h
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #include <config.h>
28 
29 #include <queue>
30 #include "MSVehicleDevice.h"
31 #include <utils/common/SUMOTime.h>
32 #include <utils/iodevices/OutputDevice_File.h>
33 #include <utils/geom/Position.h>
34 
35 
36 // ===========================================================================
37 // class declarations
38 // ===========================================================================
39 class SUMOVehicle;
40 class SUMOTrafficObject;
41 
42 
43 // ===========================================================================
44 // class definitions
45 // ===========================================================================
46 /**
47  * @class MSDevice_SSM
48  * @brief A device which collects info on the vehicle trip (mainly on departure and arrival)
49  *
50  * Each device collects departure time, lane and speed and the same for arrival.
51  *
52  * @see MSDevice
53  */
54 
55 class MSCrossSection;
56 
57 class MSDevice_SSM : public MSVehicleDevice {
58 
59 private:
60     /// All currently existing SSM devices
61     static std::set<MSDevice_SSM*>* instances;
62 
63 public:
64     /// @brief Different types of encounters corresponding to relative positions of the vehicles.
65     ///        The name describes the type from the ego perspective
66     enum EncounterType {
67         // Other vehicle is closer than range, but not on a lane conflicting with the ego's route ahead
68         ENCOUNTER_TYPE_NOCONFLICT_AHEAD = 0,       //!< ENCOUNTER_TYPE_NOCONFLICT_AHEAD
69         // Ego and foe vehicles' edges form a part of a consecutive sequence of edges
70         // This type may be specified further by ENCOUNTER_TYPE_FOLLOWING_LEADER or ENCOUNTER_TYPE_FOLLOWING_FOLLOWER
71         ENCOUNTER_TYPE_FOLLOWING = 1,       //!< ENCOUNTER_TYPE_FOLLOWING
72         // Ego vehicle is on an edge that has a sequence of successors connected to the other vehicle's edge
73         ENCOUNTER_TYPE_FOLLOWING_FOLLOWER = 2,       //!< ENCOUNTER_TYPE_FOLLOWING_FOLLOWER
74         // Other vehicle is on an edge that has a sequence of successors connected to the ego vehicle's current edge
75         ENCOUNTER_TYPE_FOLLOWING_LEADER = 3,         //!< ENCOUNTER_TYPE_FOLLOWING_LEADER
76         // Other vehicle is on an edge that has a sequence of successors connected to the ego vehicle's current edge
77         ENCOUNTER_TYPE_ON_ADJACENT_LANES = 4,         //!< ENCOUNTER_TYPE_ON_ADJACENT_LANES
78         // Ego and foe share an upcoming edge of their routes while the merging point for the routes is still ahead
79         // This type may be specified further by ENCOUNTER_TYPE_MERGING_LEADER or ENCOUNTER_TYPE_MERGING_FOLLOWER
80         ENCOUNTER_TYPE_MERGING = 5,  //!< ENCOUNTER_TYPE_MERGING
81         // Other vehicle is on an edge that has a sequence of successors connected to an edge on the ego vehicle's route
82         // and the estimated arrival vehicle at the merge point is earlier for the ego than for the foe
83         ENCOUNTER_TYPE_MERGING_LEADER = 6,  //!< ENCOUNTER_TYPE_MERGING_LEADER
84         // Other vehicle is on an edge that has a sequence of successors connected to an edge on the ego vehicle's route
85         // and the estimated arrival vehicle at the merge point is earlier for the foe than for the ego
86         ENCOUNTER_TYPE_MERGING_FOLLOWER = 7,//!< ENCOUNTER_TYPE_MERGING_FOLLOWER
87         // Vehicles' bestlanes lead to the same edge but to adjacent lanes
88         ENCOUNTER_TYPE_MERGING_ADJACENT = 8,//!< ENCOUNTER_TYPE_MERGING_ADJACENT
89         // Ego's and foe's routes have crossing edges
90         // This type may be specified further by ENCOUNTER_TYPE_CROSSING_LEADER or ENCOUNTER_TYPE_CROSSING_FOLLOWER
91         ENCOUNTER_TYPE_CROSSING = 9,  //!< ENCOUNTER_TYPE_CROSSING
92         // Other vehicle is on an edge that has a sequence of successors leading to an internal edge that crosses the ego vehicle's edge at a junction
93         // and the estimated arrival vehicle at the merge point is earlier for the ego than for the foe
94         ENCOUNTER_TYPE_CROSSING_LEADER = 10, //!< ENCOUNTER_TYPE_CROSSING_LEADER
95         // Other vehicle is on an edge that has a sequence of successors leading to an internal edge that crosses the ego vehicle's edge at a junction
96         // and the estimated arrival vehicle at the merge point is earlier for the foe than for the ego
97         ENCOUNTER_TYPE_CROSSING_FOLLOWER = 11, //!< ENCOUNTER_TYPE_CROSSING_FOLLOWER
98         // The encounter is a possible crossing conflict, and the ego vehicle has entered the conflict area
99         ENCOUNTER_TYPE_EGO_ENTERED_CONFLICT_AREA = 12, //!< ENCOUNTER_TYPE_EGO_ENTERED_CONFLICT_AREA
100         // The encounter is a possible crossing conflict, and the foe vehicle has entered the conflict area
101         ENCOUNTER_TYPE_FOE_ENTERED_CONFLICT_AREA = 13, //!< ENCOUNTER_TYPE_FOE_ENTERED_CONFLICT_AREA
102         // The encounter has been a possible crossing conflict, but the ego vehicle has left the conflict area
103         ENCOUNTER_TYPE_EGO_LEFT_CONFLICT_AREA = 14, //!< ENCOUNTER_TYPE_EGO_LEFT_CONFLICT_AREA
104         // The encounter has been a possible crossing conflict, but the foe vehicle has left the conflict area
105         ENCOUNTER_TYPE_FOE_LEFT_CONFLICT_AREA = 15, //!< ENCOUNTER_TYPE_FOE_LEFT_CONFLICT_AREA
106         // The encounter has been a possible crossing conflict, and both vehicles have entered the conflict area (one must have already left, otherwise this must be a collision)
107         ENCOUNTER_TYPE_BOTH_ENTERED_CONFLICT_AREA = 16, //!< ENCOUNTER_TYPE_BOTH_ENTERED_CONFLICT_AREA
108         // The encounter has been a possible crossing conflict, but both vehicle have left the conflict area
109         ENCOUNTER_TYPE_BOTH_LEFT_CONFLICT_AREA = 17, //!< ENCOUNTER_TYPE_BOTH_LEFT_CONFLICT_AREA
110         // FOLLOWING_PASSED and MERGING_PASSED are reserved to achieve that these encounter types may be tracked longer (see updatePassedEncounter)
111         // The encounter has been a following situation, but is not active any more
112         ENCOUNTER_TYPE_FOLLOWING_PASSED = 18, //!< ENCOUNTER_TYPE_FOLLOWING_PASSED
113         // The encounter has been a merging situation, but is not active any more
114         ENCOUNTER_TYPE_MERGING_PASSED = 19, //!< ENCOUNTER_TYPE_FOLLOWING_PASSED
115         // Collision (currently unused, might be differentiated further)
116         ENCOUNTER_TYPE_COLLISION = 111 //!< ENCOUNTER_TYPE_COLLISION
117     };
118 
toString(EncounterType type)119     static std::string toString(EncounterType type) {
120         switch (type) {
121             case (ENCOUNTER_TYPE_NOCONFLICT_AHEAD):
122                 return ("NOCONFLICT_AHEAD");
123             case (ENCOUNTER_TYPE_FOLLOWING):
124                 return ("FOLLOWING");
125             case (ENCOUNTER_TYPE_FOLLOWING_FOLLOWER):
126                 return ("FOLLOWING_FOLLOWER");
127             case (ENCOUNTER_TYPE_FOLLOWING_LEADER):
128                 return ("FOLLOWING_LEADER");
129             case (ENCOUNTER_TYPE_ON_ADJACENT_LANES):
130                 return ("ON_ADJACENT_LANES");
131             case (ENCOUNTER_TYPE_MERGING):
132                 return ("MERGING");
133             case (ENCOUNTER_TYPE_MERGING_LEADER):
134                 return ("MERGING_LEADER");
135             case (ENCOUNTER_TYPE_MERGING_FOLLOWER):
136                 return ("MERGING_FOLLOWER");
137             case (ENCOUNTER_TYPE_MERGING_ADJACENT):
138                 return ("MERGING_ADJACENT");
139             case (ENCOUNTER_TYPE_CROSSING):
140                 return ("CROSSING");
141             case (ENCOUNTER_TYPE_CROSSING_LEADER):
142                 return ("CROSSING_LEADER");
143             case (ENCOUNTER_TYPE_CROSSING_FOLLOWER):
144                 return ("CROSSING_FOLLOWER");
145             case (ENCOUNTER_TYPE_EGO_ENTERED_CONFLICT_AREA):
146                 return ("EGO_ENTERED_CONFLICT_AREA");
147             case (ENCOUNTER_TYPE_FOE_ENTERED_CONFLICT_AREA):
148                 return ("FOE_ENTERED_CONFLICT_AREA");
149             case (ENCOUNTER_TYPE_EGO_LEFT_CONFLICT_AREA):
150                 return ("EGO_LEFT_CONFLICT_AREA");
151             case (ENCOUNTER_TYPE_FOE_LEFT_CONFLICT_AREA):
152                 return ("FOE_LEFT_CONFLICT_AREA");
153             case (ENCOUNTER_TYPE_BOTH_ENTERED_CONFLICT_AREA):
154                 return ("BOTH_ENTERED_CONFLICT_AREA");
155             case (ENCOUNTER_TYPE_BOTH_LEFT_CONFLICT_AREA):
156                 return ("BOTH_LEFT_CONFLICT_AREA");
157             case (ENCOUNTER_TYPE_FOLLOWING_PASSED):
158                 return ("FOLLOWING_PASSED");
159             case (ENCOUNTER_TYPE_MERGING_PASSED):
160                 return ("MERGING_PASSED");
161             case (ENCOUNTER_TYPE_COLLISION):
162                 return ("COLLISION");
163         }
164         return ("UNKNOWN");
165     };
166 
167 private:
168     /// @brief An encounter is an episode involving two vehicles,
169     ///        which are closer to each other than some specified distance.
170     class Encounter {
171     private:
172         /// @brief A trajectory encloses a series of positions x and speeds v for one vehicle
173         /// (the times are stored only once in the enclosing encounter)
174         struct Trajectory {
175             // positions
176             PositionVector x;
177             // momentary speeds
178             PositionVector v;
179         };
180         /// @brief ConflictPointInfo stores some information on a specific conflict point
181         ///        (used to store information on ssm-extremal values)
182         struct ConflictPointInfo {
183             /// @brief time point of the conflict
184             double time;
185             /// @brief Predicted location of the conflict:
186             /// In case of MERGING and CROSSING: entry point to conflict area for follower
187             /// In case of FOLLOWING: position of leader's back
188             Position pos;
189             /// @brief Type of the conflict
190             EncounterType type;
191             /// @brief value of the corresponding SSM
192             double value;
193 
ConflictPointInfoConflictPointInfo194             ConflictPointInfo(double time, Position x, EncounterType type, double ssmValue) :
195                 time(time), pos(x), type(type), value(ssmValue) {};
196         };
197 
198     public:
199         /// @brief Constructor
200         Encounter(const MSVehicle* _ego, const MSVehicle* const _foe, double _begin, double extraTime);
201         /// @brief Destructor
202         ~Encounter();
203 
204         /// @brief add a new data point and update encounter type
205         void add(double time, EncounterType type, Position egoX, Position egoV, Position foeX, Position foeV,
206                  Position conflictPoint, double egoDistToConflict, double foeDistToConflict, double ttc, double drac, std::pair<double, double> pet);
207 
208         /// @brief Returns the number of trajectory points stored
size()209         std::size_t size() const {
210             return timeSpan.size();
211         }
212 
213         /// @brief resets remainingExtraTime to the given value
214         void resetExtraTime(double value);
215         /// @brief decreases myRemaingExtraTime by given amount in seconds
216         void countDownExtraTime(double amount);
217         /// @brief returns the remaining extra time
218         double getRemainingExtraTime() const;
219 
220         /// @brief Compares encounters regarding to their start time
221         struct compare {
222             typedef bool value_type;
operatorcompare223             bool operator()(Encounter* e1, Encounter* e2) {
224                 return e1->begin >= e2->begin;
225             };
226         };
227 
228 
229 
230     public:
231         const MSVehicle* ego;
232         const MSVehicle* foe;
233         const std::string egoID;
234         const std::string foeID;
235         double begin, end;
236         EncounterType currentType;
237 
238         /// @brief Remaining extra time (decreases after an encounter ended)
239         double remainingExtraTime;
240 
241         /// @brief Times when the ego vehicle entered/left the conflict area. Currently only applies for crossing situations. Used for PET calculation. (May be defined for merge conflicts in the future)
242         double egoConflictEntryTime, egoConflictExitTime;
243         /// @brief Times when the foe vehicle entered/left the conflict area. Currently only applies for crossing situations. Used for PET calculation. (May be defined for merge conflicts in the future)
244         double foeConflictEntryTime, foeConflictExitTime;
245 
246         /// @brief time points corresponding to the trajectories
247         std::vector<double> timeSpan;
248         /// @brief Evolution of the encounter classification (@see EncounterType)
249         std::vector<int> typeSpan;
250         /// @brief Trajectory of the ego vehicle
251         Trajectory egoTrajectory;
252         /// @brief Trajectory of the foe vehicle
253         Trajectory foeTrajectory;
254         /// Evolution of the ego vehicle's distance to the conflict point
255         std::vector<double> egoDistsToConflict;
256         /// Evolution of the foe vehicle's distance to the conflict point
257         std::vector<double> foeDistsToConflict;
258 
259         /// @brief Predicted location of the conflict:
260         /// In case of MERGING and CROSSING: entry point to conflict area for follower
261         /// In case of FOLLOWING: position of leader's back
262         PositionVector conflictPointSpan;
263 
264         /// @brief All values for TTC
265         std::vector<double> TTCspan;
266         /// @brief All values for DRAC
267         std::vector<double> DRACspan;
268 
269 //        /// @brief Cross sections at which a PET shall be calculated for the corresponding vehicle
270 //        std::vector<std::pair<std::pair<const MSLane*, double>, double> > egoPETCrossSections;
271 //        std::vector<std::pair<std::pair<const MSLane*, double>, double> > foePETCrossSections;
272 
273         /// @name Extremal values for the SSMs
274         /// @{
275         ConflictPointInfo minTTC;
276         ConflictPointInfo maxDRAC;
277         ConflictPointInfo PET;
278         /// @}
279 
280         /// @brief this flag is set by updateEncounter() or directly in processEncounters(), where encounters are closed if it is true.
281         bool closingRequested;
282 
283     private:
284         /// @brief Invalidated Constructor.
285         Encounter(const Encounter&);
286         /// @brief Invalidated assignment operator.
287         Encounter& operator=(const Encounter&);
288         ///
289     };
290 
291 
292     /// @brief Structure to collect some info on the encounter needed during ssm calculation by various functions.
293     struct EncounterApproachInfo {
294         EncounterApproachInfo(Encounter* e);
295         Encounter* encounter;
296         EncounterType type;
297         Position conflictPoint;
298         double egoConflictEntryDist;
299         double foeConflictEntryDist;
300         double egoConflictExitDist;
301         double foeConflictExitDist;
302         double egoEstimatedConflictEntryTime;
303         double foeEstimatedConflictEntryTime;
304         double egoEstimatedConflictExitTime;
305         double foeEstimatedConflictExitTime;
306         double egoConflictAreaLength;
307         double foeConflictAreaLength;
308         bool egoLeftConflict;
309         bool foeLeftConflict;
310         double ttc;
311         double drac;
312         std::pair<double, double> pet;
313         std::pair<const MSLane*, double> egoConflictEntryCrossSection;
314         std::pair<const MSLane*, double> foeConflictEntryCrossSection;
315     };
316 
317 
318     /// A new FoeInfo is created during findSurroundingVehicles() to memorize, where the potential conflict
319     /// corresponding to the encounter might occur. Each FoeInfo ends up in a call to updateEncounter() and
320     /// is deleted there.
321     struct FoeInfo {
322         const MSLane* egoConflictLane;
323         double egoDistToConflictLane;
324     };
325     // TODO: consider introducing a class foeCollector, which holds the foe info content
326     //       plus a vehicle container to be used in findSurrounding vehicles.
327     //       findSurroundingVehicles() would then deliver a vector of such foeCollectors
328     //       (one for each possible egoConflictLane) instead of a map vehicle->foeInfo
329     //       This could be helpful to resolve the resolution for several different
330     //	 	 projected conflicts with the same foe.
331 
332 
333     typedef std::priority_queue<Encounter*, std::vector<Encounter*>, Encounter::compare> EncounterQueue;
334     typedef std::vector<Encounter*> EncounterVector;
335     typedef std::map<const MSVehicle*, FoeInfo*> FoeInfoMap;
336 public:
337 
338     /** @brief Inserts MSDevice_SSM-options
339      * @param[filled] oc The options container to add the options to
340      */
341     static void insertOptions(OptionsCont& oc);
342 
343 
344     /** @brief Build devices for the given vehicle, if needed
345      *
346      * The options are read and evaluated whether a example-device shall be built
347      *  for the given vehicle.
348      *
349      * The built device is stored in the given vector.
350      *
351      * @param[in] v The vehicle for which a device may be built
352      * @param[filled] into The vector to store the built device in
353      */
354     static void buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into);
355 
356 
357     /** @brief returns all currently existing SSM devices
358      */
359     static const std::set<MSDevice_SSM*>& getInstances();
360 
361     /** @brief This is called once per time step in MSNet::writeOutput() and
362      *         collects the surrounding vehicles, updates information on encounters
363      *         and flushes the encounters qualified as conflicts (@see thresholds)
364      *         to the output file.
365      */
366     void updateAndWriteOutput();
367 
368 private:
369     void update();
370     void writeOutConflict(Encounter* e);
371 
372     /// @brief convert SUMO-positions to geo coordinates (in place)
373     static void toGeo(Position& x);
374     /// @brief convert SUMO-positions to geo coordinates (in place)
375     static void toGeo(PositionVector& x);
376 
377 public:
378     /** @brief Clean up remaining devices instances
379      */
380     static void cleanup();
381 
382 
383 public:
384     /// @brief Destructor.
385     ~MSDevice_SSM();
386 
387 
388     /** @brief Returns all vehicles, which are within the given range of the given vehicle.
389      *  @note all vehicles behind and in front are collected,
390      *  including vehicles on confluent edges. For instance, if the range is 20 m. and
391      *  a junction lies 10 m. ahead, an upstream scan of 20 m. is performed
392      *  for all incoming edges.
393      *
394      * @param veh   The ego vehicle, that forms the origin for the scan
395      * @param range The range to be scanned.
396      * @param[in/out] foeCollector container for all collected vehicles
397      * @return All vehicles within range from veh
398      */
399     static void findSurroundingVehicles(const MSVehicle& veh, double range, FoeInfoMap& foeCollector);
400 
401     /** @brief Collects all vehicles within range 'range' upstream of the position 'pos' on the edge 'edge' into foeCollector
402      */
403     static void getUpstreamVehicles(const MSEdge* edge, double pos, double range, double egoDistToConflictLane, const MSLane* const egoConflictLane, FoeInfoMap& foeCollector, std::set<const MSJunction*>& seenJunctions);
404 
405     /** @brief Collects all vehicles on the junction into foeCollector
406      */
407     static void getVehiclesOnJunction(const MSJunction*, double egoDistToConflictLane, const MSLane* const egoConflictLane, FoeInfoMap& foeCollector);
408 
409 
410     /// @name Methods called on vehicle movement / state change, overwriting MSDevice
411     /// @{
412 
413     /** @brief Checks for waiting steps when the vehicle moves
414      *
415      * @param[in] veh Vehicle that notifies.
416      * @param[in] oldPos Position before move.
417      * @param[in] newPos Position after move with newSpeed.
418      * @param[in] newSpeed Moving speed.
419      *
420      * @return Always true to keep the device as it cannot be thrown away
421      */
422     bool notifyMove(SUMOTrafficObject& veh, double oldPos,
423                     double newPos, double newSpeed);
424 
425 
426     /** @brief Called whenever the holder enteres a lane
427      *
428      * @param[in] veh The entering vehicle.
429      * @param[in] reason Reason for leaving the lane
430      * @param[in] enteredLane The lane entered.
431      * @return Always true to keep the device as it cannot be thrown away
432      * @see MSMoveReminder::notifyEnter
433      * @see MSMoveReminder::Notification
434      */
435     bool notifyEnter(SUMOTrafficObject& veh, MSMoveReminder::Notification reason, const MSLane* enteredLane = 0);
436 
437 
438     /** @brief Called whenever the holder leaves a lane
439      *
440      * @param[in] veh The leaving vehicle.
441      * @param[in] lastPos Position on the lane when leaving.
442      * @param[in] reason Reason for leaving the lane
443      * @param[in] enteredLane The lane entered.
444      * @return True if it did not leave the net.
445      */
446     bool notifyLeave(SUMOTrafficObject& veh, double lastPos,
447                      MSMoveReminder::Notification reason, const MSLane* enteredLane = 0);
448     /// @}
449 
450 
451     /// @brief return the name for this type of device
deviceName()452     const std::string deviceName() const {
453         return "ssm";
454     }
455 
456     /** @brief Finalizes output. Called on vehicle removal
457      *
458      * @param[in] os The stream to write the information into
459      * @exception IOError not yet implemented
460      * @see MSDevice::generateOutput
461      */
462     void generateOutput() const;
463 
464 
465 
466 private:
467     /** @brief Constructor
468      *
469      * @param[in] holder The vehicle that holds this device
470      * @param[in] id The ID of the device
471      * @param measures Vector of Surrogate Safety Measure IDs
472      * @param thresholds Vector of corresponding thresholds
473      * @param trajectories Flag indicating whether complete trajectories should be saved for an encounter (if false only extremal values are logged)
474      * @param range Detection range. For vehicles closer than this distance from the ego vehicle, SSMs are traced
475      * @param extraTime Extra time in seconds to be logged after a conflict is over
476      * @param useGeoCoords Whether coordinates should be written out in the original coordinate reference system or as sumo's x,y values
477      */
478     MSDevice_SSM(SUMOVehicle& holder, const std::string& id, std::string outputFilename, std::map<std::string, double> thresholds,
479                  bool trajectories, double range, double extraTime, bool useGeoCoords);
480 
481     /** @brief Finds encounters for which the foe vehicle has disappeared from range.
482      *         remainingExtraTime is decreased until it reaches zero, which triggers closing the encounter.
483      *         If an ended encounter is qualified as a conflict, it is transferred to myPastConflicts
484      *         All vehicles for which an encounter instance already exists (vehicle is already tracked)
485      *         are removed from 'foes' during processing.
486      *  @param[in] foes Foe vehicles that have been found by findSurroundingVehicles()
487      *  @param[in] forceClose whether encounters for which the foe is not in range shall be closed immediately, disregarding the remaining extra time (is requested by resetEncounters()).
488      */
489     void processEncounters(FoeInfoMap& foes, bool forceClose = false);
490 
491 
492     /** @brief Closes encounters, whose duration exceeds the maximal encounter length. If it is classified as conflict, the encounter is saved.
493      *         In any case, a new active encounter is created holding the trailing part (of length myOverlapTime) of the original.
494      */
495     void storeEncountersExceedingMaxLength();
496 
497 
498 
499     /** @brief Makes new encounters for all given vehicles (these should be the ones entering the device's range in the current timestep)
500      */
501     void createEncounters(FoeInfoMap& foes);
502 
503 
504     /** @brief Stores measures, that are not associated to a specific encounter as headways and brake rates
505      *  @todo  Manage as episodes (BR -> braking episode, SGAP/TGAP -> car-following episode) with invariant leader, and filtering applying the
506      *  corresponding thresholds.
507      */
508     void computeGlobalMeasures();
509 
510     /** @brief Closes all current Encounters and moves conflicts to myPastConflicts, @see processEncounters
511      */
512     void resetEncounters();
513 
514     /** @brief Writes out all past conflicts that have begun earlier than the oldest active encounter
515      * @param[in] all Whether all conflicts should be flushed or only those for which no active encounters with earlier begin can exist
516      */
517     void flushConflicts(bool all = false);
518 
519     /** @brief Write out all non-encounter specific measures as headways and braking rates.
520      *  @todo  Adapt accordingly if episode structure is implemented, @see computeGlobalMeasures()
521      */
522     void flushGlobalMeasures();
523 
524     /** @brief Updates the encounter (adds a new trajectory point) and deletes the foeInfo.
525      *  @return Returns false for new encounters, which should not be kept (if one vehicle has
526      *          already left the conflict zone at encounter creation). True, otherwise.
527      */
528     bool updateEncounter(Encounter* e, FoeInfo* foeInfo);
529 
530     /** @brief Updates an encounter, which was classified as ENCOUNTER_TYPE_NOCONFLICT_AHEAD
531      *         this may be the case because the foe is out of the detection range but the encounter
532      *         is still in extra time (in this case foeInfo==0), or because the foe does not head for a lane conflicting with
533      *         the route of the ego vehicle.
534      *         It is also used for an ongoing crossing conflict, where only the covered distances are traced
535      *         until the situation is over. (A crossing conflict is ongoing, if one vehicle entered the conflict area)
536      *         Writes the type of encounter which is determined for the current state into eInfo. And if appropriate some
537      *         information concerning vehicles positions in relation to a crossed crossing point (for PET calculation).
538      */
539     void updatePassedEncounter(Encounter* e, FoeInfo* foeInfo, EncounterApproachInfo& eInfo);
540 
541 
542     /** @brief Classifies the current type of the encounter provided some information on the opponents
543      *  @param[in] foeInfo Info on distance to conflict point for the device holder.
544      *  @param[in/out] eInfo  Info structure for the current state of the encounter (provides a pointer to the encounter).
545      *  @return Returns an encounter type and writes a value to the relevant distances (egoEncounterDist, foeEncounterDist members of eInfo),
546      *          i.e. the distances to the entry points to the potential conflict.
547      *  @note: The encounter distance has a different meaning for different types of encounters:
548      *          1) For rear-end conflicts (lead/follow situations) the follower's encounter distance is the distance to the actual back position of the leader. The leaders's distance is undefined.
549      *          2) For merging encounters the encounter distance is the distance until the begin of the common target edge/lane.
550      *          3) For crossing encounters the encounter distance is the distance until crossing point of the conflicting lanes.
551      */
552     EncounterType classifyEncounter(const FoeInfo* foeInfo, EncounterApproachInfo& eInfo) const;
553 
554 
555     /** @brief Calculates the (x,y)-coordinate for the eventually predicted conflict point and stores the result in
556      *         eInfo.conflictPoint. In case of MERGING and CROSSING, this is the entry point to conflict area for follower
557      *         In case of FOLLOWING it is the position of leader's back.
558      *  @param[in/out] eInfo  Info structure for the current state of the encounter.
559      */
560     static void determineConflictPoint(EncounterApproachInfo& eInfo);
561 
562 
563     /** @brief Estimates the time until conflict for the vehicles based on the distance to the conflict entry points.
564      *         For acceleration profiles, we assume that the acceleration is <= 0 (that is, braking is extrapolated,
565      *         while for acceleration it is assumed that the vehicle will continue with its current speed)
566      *  @param[in/out] eInfo  Info structure for the current state of the encounter.
567      *  @note The '[in]'-part for eInfo are its members e->ego, e->foe (to access the vehicle parameters), egoConflictEntryDist, foeConflictEntryDist, i.e., distances to the conflict entry points.
568      *        The '[out]'-part for eInfo are its members type (type information may be refined) egoConflictEntryTime, foeConflictEntryTime (estimated times until the conflict entry point is reached)
569      *        and egoConflictExitTime, foeConflictExitTime (estimated time until the conflict exit point is reached).
570      *        Further the type of the encounter as determined by classifyEncounter(), is refined for the cases CROSSING and MERGING here.
571      */
572     static void estimateConflictTimes(EncounterApproachInfo& eInfo);
573 
574 
575     /** @brief Checks whether ego or foe have entered or left the conflict area in the last step and eventually writes
576      *         the corresponding entry or exit times to eInfo.encounter. For ongoing crossing conflicts, it also manages
577      *         the evolution of the conflict type.
578      *  @param[in/out] eInfo  Info structure for the current state of the encounter.
579      *  @note The times are to be used for SSM computation in computeSSMs(), e.g. in determinePET()
580      */
581     static void checkConflictEntryAndExit(EncounterApproachInfo& eInfo);
582 
583 
584     /** @brief Computes the conflict lane for the foe
585      *
586      * @param foe Foe vehicle
587      * @param egoConflictLane Lane, on which the ego would enter the possible conflict
588      * @param routeToConflict, Series of edges, that were traced back from egoConflictLane during findSurrounding Vehicles, when collecting the foe vehicle
589      * @param[out] distToConflictLane, distance to conflictlane entry link (may be negative if foe is already on the conflict lane)
590      * @return Lane, on which the foe would enter the possible conflict, if foe is not on conflict course, Null-pointer is returned.
591      */
592     const MSLane* findFoeConflictLane(const MSVehicle* foe, const MSLane* egoConflictLane, double& distToConflictLane) const;
593 
594     /** @brief Finalizes the encounter and calculates SSM values.
595      */
596     void closeEncounter(Encounter* e);
597 
598     /** @brief Tests if the SSM values exceed the threshold for qualification as conflict.
599      */
600     bool qualifiesAsConflict(Encounter* e);
601 
602     /** @brief Compute current values of the logged SSMs (myMeasures) for the given encounter 'e'
603      *  and update 'e' accordingly (add point to SSM time-series, update maximal/minimal value)
604      *  This is called just after adding the current vehicle positions and velocity vectors to the encounter.
605      */
606     void computeSSMs(EncounterApproachInfo& e) const;
607 
608 
609     /** @brief Discriminates between different encounter types and correspondingly determines the PET for those cases
610      *         and writes the result to eInfo.pet (after both vehicles have left the conflict area)
611      */
612     void determinePET(EncounterApproachInfo& eInfo) const;
613 
614 
615     /** @brief Discriminates between different encounter types and correspondingly determines TTC and DRAC for those cases
616      *         and writes the result to eInfo.ttc and eInfo.drac
617      */
618     void determineTTCandDRAC(EncounterApproachInfo& eInfo) const;
619 
620 
621     /** @brief Computes the time to collision (in seconds) for two vehicles with a given initial gap under the assumption
622      *         that both maintain their current speeds. Returns INVALID if no collision would occur under this assumption.
623      */
624     double computeTTC(double gap, double followerSpeed, double leaderSpeed) const;
625 
626 
627     /** @brief Computes the DRAC (deceleration to avoid a collision) for a lead/follow situation as defined,
628      *         e.g., in Guido et al. (2011, Safety performance measures:  a comparison between microsimulation and observational data)
629      *         for two vehicles with a given gap.
630      *         Returns 0.0 if no deceleration is required by the follower to avoid a crash, INVALID if collision is detected.
631      */
632     static double computeDRAC(double gap, double followerSpeed, double leaderSpeed);
633 
634     /** @brief Computes the DRAC a crossing situation, determining the minimal constant deceleration needed
635      *         for one of the vehicles to reach the conflict area after the other has left.
636      *         for estimated leaving times, current deceleration is extrapolated, and acceleration is neglected.
637      *         Returns 0.0 if no deceleration is required by the follower to avoid a crash, INVALID if collision is detected.
638      *  @param[in] eInfo infos on the encounter. Used variables:
639      *  			 dEntry1,dEntry2 The distances to the conflict area entry
640      *  			 dExit1,dExit2 The distances to the conflict area exit
641      *  			 v1,v2 The current speeds
642      *  			 tEntry1,tEntry2 The estimated conflict entry times (including extrapolation of current acceleration)
643      *  		     tExit1,tExit2 The estimated conflict exit times (including extrapolation of current acceleration)
644      */
645     static double computeDRAC(const EncounterApproachInfo& eInfo);
646 
647     /** @brief make a string of a double vector and treat a special value as invalid ("NA")
648      *
649      * @param v vector to be converted to string
650      * @param NA value to be treated as NA
651      * @param sep separator for values in string
652      * @return String concatenation of the vector entries
653      */
654     static std::string makeStringWithNAs(std::vector<double> v, double NA, std::string sep = " ");
655     static std::string makeStringWithNAs(std::vector<double> v, std::vector<double> NAs, std::string sep = " ");
656 
657     /// @name parameter load helpers (introduced for readability of buildVehicleDevices())
658     /// @{
659     static std::string getOutputFilename(const SUMOVehicle& v, std::string deviceID);
660     static double getDetectionRange(const SUMOVehicle& v);
661     static double getExtraTime(const SUMOVehicle& v);
662     static bool useGeoCoords(const SUMOVehicle& v);
663     static bool requestsTrajectories(const SUMOVehicle& v);
664     static bool getMeasuresAndThresholds(const SUMOVehicle& v, std::string deviceID,
665                                          std::map<std::string, double>& thresholds);
666     ///@}
667 
668 private:
669     /// @name Device parameters
670     /// @{
671     /// @brief thresholds for the ssms, i.e., critical values above or below which a value indicates that a conflict
672     ///        has occurred. These are used in qualifiesAsConflict() and decide whether an encounter is saved.
673     std::map<std::string, double> myThresholds;
674     /// @brief This determines whether the whole trajectories of the vehicles (position, speed, ssms) shall be saved in the ssm-output
675     ///        or only the most critical value shall be reported.
676     bool mySaveTrajectories;
677     /// Detection range. For vehicles closer than this distance from the ego vehicle, SSMs are traced
678     double myRange;
679     /// Extra time in seconds to be logged after a conflict is over
680     double myExtraTime;
681     /// Whether to use the original coordinate system for output
682     bool myUseGeoCoords;
683     /// Flags for switching on / off comutation of different SSMs, derived from myMeasures
684     bool myComputeTTC, myComputeDRAC, myComputePET, myComputeBR, myComputeSGAP, myComputeTGAP;
685     MSVehicle* myHolderMS;
686     /// @}
687 
688 
689     /// @name Internal storage for encounters/conflicts
690     /// @{
691     /// @brief Currently observed encounters/conflicts
692     EncounterVector myActiveEncounters;
693     /// @brief begin time of the oldest active encounter
694     double myOldestActiveEncounterBegin;
695     /// @brief Past encounters that where qualified as conflicts and are not yet flushed to the output file
696     EncounterQueue myPastConflicts;
697     /// @}
698 
699 
700 
701     /// @name Internal storage for global measures
702     /// @{
703     std::vector<double> myGlobalMeasuresTimeSpan;
704     /// @brief All values for brake rate
705     std::vector<double> myBRspan;
706     /// @brief All values for space gap
707     std::vector<double> mySGAPspan;
708     /// @brief All values for time gap
709     std::vector<double> myTGAPspan;
710     /// @brief Extremal values for the global measures (as <<<time, Position>, value>, [leaderID]>-pairs)
711     /// @{
712     std::pair<std::pair<double, Position>, double> myMaxBR;
713     std::pair<std::pair<std::pair<double, Position>, double>, std::string>  myMinSGAP;
714     std::pair<std::pair<std::pair<double, Position>, double>, std::string>  myMinTGAP;
715     /// @}
716     /// @}
717 
718     /// Output device
719     OutputDevice* myOutputFile;
720 
721     /// @brief remember which files were created already (don't duplicate xml root-elements)
722     static std::set<std::string> createdOutputFiles;
723 
724 
725     /// @brief bitset storing info whether warning has already been issued about unset parameter (warn only once!)
726     static int issuedParameterWarnFlags;
727     enum SSMParameterWarning {
728         SSM_WARN_MEASURES = 1,
729         SSM_WARN_THRESHOLDS = 1 << 1,
730         SSM_WARN_TRAJECTORIES = 1 << 2,
731         SSM_WARN_RANGE = 1 << 3,
732         SSM_WARN_EXTRATIME = 1 << 4,
733         SSM_WARN_FILE = 1 << 5,
734         SSM_WARN_GEO = 1 << 6
735     };
736 
737 
738 
739 private:
740     /// @brief Invalidated copy constructor.
741     MSDevice_SSM(const MSDevice_SSM&);
742 
743     /// @brief Invalidated assignment operator.
744     MSDevice_SSM& operator=(const MSDevice_SSM&);
745 
746 
747 };
748 
749 #endif
750 
751 /****************************************************************************/
752 
753