View Javadoc
1   package org.opentrafficsim.ahfe;
2   
3   import java.util.LinkedHashMap;
4   import java.util.LinkedHashSet;
5   import java.util.Map;
6   import java.util.Set;
7   import java.util.SortedSet;
8   
9   import org.djunits.value.vdouble.scalar.Duration;
10  import org.djunits.value.vdouble.scalar.Length;
11  import org.djunits.value.vdouble.scalar.Time;
12  import org.opentrafficsim.base.TimeStampedObject;
13  import org.opentrafficsim.base.parameters.ParameterException;
14  import org.opentrafficsim.base.parameters.ParameterTypeDuration;
15  import org.opentrafficsim.base.parameters.ParameterTypes;
16  import org.opentrafficsim.base.parameters.Parameters;
17  import org.opentrafficsim.core.gtu.GTUException;
18  import org.opentrafficsim.core.gtu.perception.PerceptionException;
19  import org.opentrafficsim.core.network.LateralDirectionality;
20  import org.opentrafficsim.core.network.NetworkException;
21  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
22  import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
23  import org.opentrafficsim.road.gtu.lane.perception.PerceptionCollectable;
24  import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
25  import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.DirectNeighborsPerception;
26  import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.HeadwayGtuType;
27  import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.NeighborsPerception;
28  import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGTU;
29  
30  import nl.tudelft.simulation.dsol.SimRuntimeException;
31  
32  /**
33   * <p>
34   * Copyright (c) 2013-2022 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
35   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
36   * <p>
37   * @version $Revision$, $LastChangedDate$, by $Author$, initial version 17 feb. 2017 <br>
38   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
39   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
40   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
41   */
42  @Deprecated
43  public abstract class AbstractDelayedNeighborsPerception extends AbstractDelayedPerceptionCategory
44          implements NeighborsPerception
45  {
46  
47      /** */
48      private static final long serialVersionUID = 20170217L;
49  
50      /** Reaction time parameter type. */
51      protected static final ParameterTypeDuration TR = ParameterTypes.TR;
52  
53      /** Time step parameter type. */
54      protected static final ParameterTypeDuration DT = ParameterTypes.DT;
55  
56      /** First update time. */
57      private Time initialTime = null;
58  
59      /** Wrapped direct perception. */
60      private final DirectNeighborsPerception direct;
61  
62      /** Reaction time. */
63      private Duration reactionTime = null;
64  
65      /** Time step of planner. */
66      private Duration plannerTimeStep = null;
67  
68      /** Remainder between reaction time and planner time step. */
69      private Duration remainder = null;
70  
71      /** Info type id base for first leaders. */
72      public static final String FIRSTLEADERS = "firstLeaders";
73  
74      /** Info type id base for first followers. */
75      public static final String FIRSTFOLLOWERS = "firstFollower";
76  
77      /** Info type id base for gtu alongside. */
78      public static final String GTUALONGSIDE = "gtuAlongside";
79  
80      /** Info type id base for leaders. */
81      public static final String LEADERS = "leaders";
82  
83      /** Info type id base for followers. */
84      public static final String FOLLOWERS = "followers";
85  
86      /** Info type id for cross-section. */
87      public static final NeighborsInfoType<SortedSet<RelativeLane>> CROSSSECTION = new NeighborsInfoType<>("cross-section");
88  
89      /** Id for odometer info type. */
90      public static final NeighborsInfoType<Length> ODOMETER = new NeighborsInfoType<>("odometer");
91  
92      /** Override for left lane change. */
93      private boolean gtuAlongsideLeftOverride = false;
94  
95      /** Override for right lane change. */
96      private boolean gtuAlongsideRightOverride = false;
97  
98      /**
99       * Constructor.
100      * @param perception LanePerception; perception
101      */
102     public AbstractDelayedNeighborsPerception(final LanePerception perception)
103     {
104         super(perception);
105         this.direct = new DirectNeighborsPerception(perception, HeadwayGtuType.COPY);
106     }
107 
108     /** {@inheritDoc} */
109     @Override
110     public final void updateAll() throws GTUException, NetworkException, ParameterException
111     {
112 
113         if (this.remainder == null)
114         {
115             try
116             {
117                 // TODO The reaction time may differ between observed objects and vary over time
118                 Parameters params = getPerception().getGtu().getParameters();
119                 this.reactionTime = params.getParameter(TR);
120                 this.plannerTimeStep = params.getParameter(DT);
121                 double rem;
122                 if (this.reactionTime.eq0())
123                 {
124                     rem = 0;
125                 }
126                 else if (this.reactionTime.gt(this.plannerTimeStep))
127                 {
128                     rem = this.reactionTime.si % this.plannerTimeStep.si;
129                 }
130                 else
131                 {
132                     rem = this.plannerTimeStep.si - this.reactionTime.si;
133                 }
134                 this.remainder = Duration.instantiateSI(rem);
135             }
136             catch (ParameterException | GTUException exception)
137             {
138                 throw new RuntimeException("Exception while setting up delayed neighors perception.", exception);
139             }
140         }
141 
142         // direct perception in first few time steps; build up history
143         Time now = getPerception().getGtu().getSimulator().getSimulatorAbsTime();
144         if (this.initialTime == null)
145         {
146             this.initialTime = now;
147         }
148         if (now.minus(this.initialTime).le(this.reactionTime))
149         {
150             updateAllDelayed();
151             return;
152         }
153 
154         if (this.remainder.eq0())
155         {
156             // reaction time is multiple of time step, just do it now
157             updateAllDelayed();
158         }
159         else
160         {
161             // schedule actual update slightly in the future: this will be the snapshot for a future time step
162             Time scheduledTime = now.plus(this.remainder);
163             try
164             {
165                 getPerception().getGtu().getSimulator().scheduleEventAbsTime(scheduledTime, this, this, "updateAllDelayed",
166                         null);
167             }
168             catch (SimRuntimeException exception)
169             {
170                 throw new RuntimeException("Scheduling perception update in the past.", exception);
171             }
172         }
173 
174         /*
175          * During the reaction time, an instantaneous lane change by a neighbor may be performed, which may cause an
176          * unreasonable lane change of the subject vehicle if it is not considered. Therefore, the 'gtuAlongSide' information is
177          * amended with a current snapshot of the surroundings. If the current first leaders/followers contains a GTU that the
178          * delayed leaders/followers do not contain, and that is within 50m, 'gtuAlongSide' is overruled with 'true', preventing
179          * a lane change.
180          */
181         if (getPerception().getLaneStructure().getExtendedCrossSection().contains(RelativeLane.LEFT))
182         {
183             this.gtuAlongsideLeftOverride = newFirstLeaderOrFollower(getFollowers(RelativeLane.LEFT),
184                     this.direct.getFirstFollowers(LateralDirectionality.LEFT))
185                     || newFirstLeaderOrFollower(getLeaders(RelativeLane.LEFT),
186                             this.direct.getFirstLeaders(LateralDirectionality.LEFT))
187                     || this.direct.isGtuAlongside(LateralDirectionality.LEFT);
188         }
189         if (getPerception().getLaneStructure().getExtendedCrossSection().contains(RelativeLane.RIGHT))
190         {
191             this.gtuAlongsideRightOverride = newFirstLeaderOrFollower(getFollowers(RelativeLane.RIGHT),
192                     this.direct.getFirstFollowers(LateralDirectionality.RIGHT))
193                     || newFirstLeaderOrFollower(getLeaders(RelativeLane.RIGHT),
194                             this.direct.getFirstLeaders(LateralDirectionality.RIGHT))
195                     || this.direct.isGtuAlongside(LateralDirectionality.RIGHT);
196         }
197 
198     }
199 
200     /**
201      * Returns whether there is a gtu in the current set that is not present in the delayed set.
202      * @param delayedSet Iterable&lt;? extends HeadwayGTU&gt;; delayed set
203      * @param currentSet Set&lt;? extends HeadwayGTU&gt;; current set
204      * @return whether there is a gtu in the current set that is not present in the delayed set
205      */
206     private boolean newFirstLeaderOrFollower(final Iterable<? extends HeadwayGTU> delayedSet,
207             final Set<? extends HeadwayGTU> currentSet)
208     {
209         Set<String> set = new LinkedHashSet<>();
210         for (HeadwayGTU gtu : delayedSet)
211         {
212             set.add(gtu.getId());
213         }
214         for (HeadwayGTU gtu : currentSet)
215         {
216             if (!set.contains(gtu.getId()) && gtu.getDistance().si < 50)
217             {
218                 return true;
219             }
220         }
221         return false;
222     }
223 
224     /**
225      * Returns whether to override the gtu alongside boolean as true.
226      * @param lat LateralDirectionality; lateral direction
227      * @return whether to override the gtu alongside boolean as true
228      */
229     public final boolean isGtuAlongsideOverride(final LateralDirectionality lat)
230     {
231         return lat.isLeft() ? this.gtuAlongsideLeftOverride : this.gtuAlongsideRightOverride;
232     }
233 
234     /**
235      * Performs actual update.
236      * @throws ParameterException if parameter is not present or is given a wrong value
237      * @throws NetworkException on error in the network
238      * @throws GTUException if not initialized
239      */
240     // TODO private when DSOL allows
241     protected void updateAllDelayed() throws GTUException, NetworkException, ParameterException
242     {
243 
244         try
245         {
246             getGtu().getReferencePosition();
247         }
248         catch (GTUException exception)
249         {
250             // GTU was destroyed
251             return;
252         }
253 
254         this.direct.updateAll();
255         // below code is a copy of the updateAll() method in the direct perception TODO structure better
256         setInfo(CROSSSECTION,
257                 new TimeStampedObject<>(getPerception().getLaneStructure().getExtendedCrossSection(), getTimestamp()));
258         setInfo(ODOMETER, new TimeStampedObject<>(getGtu().getOdometer(), getTimestamp()));
259     }
260 
261     /**
262      * Returns the cross-section on which the most recent observed neighbors were determined.
263      * @return cross-section on which the most recent observed neighbors were determined
264      */
265     public final SortedSet<RelativeLane> getDelayedCrossSection()
266     {
267         try
268         {
269             return getInfo(CROSSSECTION).getObject();
270         }
271         catch (PerceptionException exception)
272         {
273             throw new RuntimeException("Crosssection was not perceived.", exception);
274         }
275     }
276 
277     /**
278      * Delayed information about the type of the neighbors. <br>
279      * @param <T> data type of info
280      */
281     public static final class NeighborsInfoType<T> extends DelayedInfoType<T>
282     {
283 
284         /** Map of id's and lane info types. */
285         private static final Map<String, NeighborsInfoType<?>> LANEINFOTYPES = new LinkedHashMap<>();
286 
287         /**
288          * Construct new info.
289          * @param id String; id
290          */
291         public NeighborsInfoType(final String id)
292         {
293             super(id, TR);
294         }
295 
296         /**
297          * Returns a (cached) info type for a sorted set of GTU's.
298          * @param id String; id
299          * @return info type
300          */
301         @SuppressWarnings("unchecked")
302         public static NeighborsInfoType<SortedSet<HeadwayGTU>> getSortedSetType(final String id)
303         {
304             if (!LANEINFOTYPES.containsKey(id))
305             {
306                 LANEINFOTYPES.put(id, new NeighborsInfoType<SortedSet<HeadwayGTU>>(id));
307             }
308             return (NeighborsInfoType<SortedSet<HeadwayGTU>>) LANEINFOTYPES.get(id);
309         }
310 
311         /**
312          * Returns a (cached) info type for a sorted set of GTU's.
313          * @param id String; id
314          * @return info type
315          */
316         @SuppressWarnings("unchecked")
317         public static NeighborsInfoType<PerceptionCollectable<HeadwayGTU, LaneBasedGTU>> getIterableType(final String id)
318         {
319             if (!LANEINFOTYPES.containsKey(id))
320             {
321                 LANEINFOTYPES.put(id, new NeighborsInfoType<SortedSet<HeadwayGTU>>(id));
322             }
323             return (NeighborsInfoType<PerceptionCollectable<HeadwayGTU, LaneBasedGTU>>) LANEINFOTYPES.get(id);
324         }
325 
326         /**
327          * Returns a (cached) info type for a sorted set of GTU's.
328          * @param id String; id
329          * @return info type
330          */
331         @SuppressWarnings("unchecked")
332         public static NeighborsInfoType<Boolean> getBooleanType(final String id)
333         {
334             if (!LANEINFOTYPES.containsKey(id))
335             {
336                 LANEINFOTYPES.put(id, new NeighborsInfoType<SortedSet<HeadwayGTU>>(id));
337             }
338             return (NeighborsInfoType<Boolean>) LANEINFOTYPES.get(id);
339         }
340 
341         /** {@inheritDoc} */
342         @Override
343         public String toString()
344         {
345             return "NeighborsInfoType []";
346         }
347 
348     }
349 
350 }