View Javadoc
1   package org.opentrafficsim.road.gtu.lane.tactical.util.lmrs;
2   
3   import java.util.LinkedHashMap;
4   import java.util.LinkedHashSet;
5   import java.util.Map;
6   import java.util.Optional;
7   import java.util.Set;
8   
9   import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
10  import org.opentrafficsim.road.gtu.lane.perception.PerceptionCollectable;
11  import org.opentrafficsim.road.gtu.lane.perception.object.PerceivedGtu;
12  import org.opentrafficsim.road.gtu.lane.tactical.DesireBased;
13  import org.opentrafficsim.road.gtu.lane.tactical.Synchronizable;
14  
15  /**
16   * Keeps data for LMRS for a specific GTU.
17   * <p>
18   * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
19   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
20   * </p>
21   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
22   * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
23   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
24   */
25  public final class LmrsData implements DesireBased, Synchronizable
26  {
27  
28      /** Form of synchronization. */
29      private final Synchronization synchronization;
30  
31      /** Form of cooperation. */
32      private final Cooperation cooperation;
33  
34      /** Form of gap-acceptance. */
35      private final GapAcceptance gapAcceptance;
36  
37      /** Form of tail gating. */
38      private final Tailgating tailgating;
39  
40      /** Most recent leaders. */
41      private final Set<String> leaders = new LinkedHashSet<>();
42  
43      /** Current leaders. */
44      private final Set<String> tempLeaders = new LinkedHashSet<>();
45  
46      /** Latest desire value for visualization. */
47      private final Map<Class<? extends Incentive>, Desire> desireMap = new LinkedHashMap<>();
48  
49      /** Synchronization state. */
50      private Synchronizable.State synchronizationState = Synchronizable.State.NONE;
51  
52      /** Vehicle that is being synchronized to. */
53      private String syncVehicle;
54  
55      /** Whether the longitudinal control is human. */
56      private boolean humanLongitudinalControl = true;
57  
58      /**
59       * Constructor.
60       * @param synchronization synchronization
61       * @param cooperation cooperation
62       * @param gapAcceptance gap-acceptance
63       * @param tailgating tail gating
64       */
65      public LmrsData(final Synchronization synchronization, final Cooperation cooperation, final GapAcceptance gapAcceptance,
66              final Tailgating tailgating)
67      {
68          this.synchronization = synchronization;
69          this.cooperation = cooperation;
70          this.gapAcceptance = gapAcceptance;
71          this.tailgating = tailgating;
72      }
73  
74      /**
75       * Checks if the given leader is a new leader.
76       * @param gtu gtu to check
77       * @return whether the gtu is a new leader
78       */
79      boolean isNewLeader(final PerceivedGtu gtu)
80      {
81          this.tempLeaders.add(gtu.getId());
82          return !this.leaders.contains(gtu.getId());
83      }
84  
85      /**
86       * Remembers the leaders of the current time step (those forwarded to isNewLeader()) for the next time step.
87       */
88      void finalizeStep()
89      {
90          this.leaders.clear();
91          this.leaders.addAll(this.tempLeaders);
92          this.tempLeaders.clear();
93      }
94  
95      /**
96       * Remembers the gtu that is synchronized to.
97       * @param gtu gtu that is synchronized to
98       */
99      void setSyncVehicle(final PerceivedGtu gtu)
100     {
101         this.syncVehicle = gtu == null ? null : gtu.getId();
102     }
103 
104     /**
105      * Returns whether the provided gtu is the gtu that is synchronized to.
106      * @param gtu gtu to inquiry
107      * @return whether the provided gtu is the gtu that is synchronized to
108      */
109     boolean isSyncVehicle(final PerceivedGtu gtu)
110     {
111         return this.syncVehicle == null ? false : gtu.getId().equals(this.syncVehicle);
112     }
113 
114     /**
115      * Returns the gtu from the set that is the current sync vehicle, or {@code null} of there is no sync vehicle or it is not
116      * in the set.
117      * @param adjLeaders leaders in adjacent lane
118      * @return gtu from the set that is the current sync vehicle
119      */
120     PerceivedGtu getSyncVehicle(final PerceptionCollectable<PerceivedGtu, LaneBasedGtu> adjLeaders)
121     {
122         if (this.syncVehicle == null)
123         {
124             return null;
125         }
126         for (PerceivedGtu leader : adjLeaders)
127         {
128             if (leader.getId().equals(this.syncVehicle))
129             {
130                 return leader;
131             }
132         }
133         return null;
134     }
135 
136     /**
137      * Returns the synchronization.
138      * @return synchronization
139      */
140     Synchronization getSynchronization()
141     {
142         return this.synchronization;
143     }
144 
145     /**
146      * Returns the cooperation.
147      * @return cooperation
148      */
149     Cooperation getCooperation()
150     {
151         return this.cooperation;
152     }
153 
154     /**
155      * Return the gap-acceptance.
156      * @return gap-acceptance
157      */
158     GapAcceptance getGapAcceptance()
159     {
160         return this.gapAcceptance;
161     }
162 
163     /**
164      * Return the tail gating.
165      * @return gap-acceptance
166      */
167     Tailgating getTailgating()
168     {
169         return this.tailgating;
170     }
171 
172     @Override
173     public Optional<Desire> getLatestDesire(final Class<? extends Incentive> incentiveClass)
174     {
175         return Optional.ofNullable(this.desireMap.get(incentiveClass));
176     }
177 
178     /**
179      * Returns the desire map.
180      * @return desire map
181      */
182     Map<Class<? extends Incentive>, Desire> getDesireMap()
183     {
184         return this.desireMap;
185     }
186 
187     /**
188      * Sets the synchronization state.
189      * @param synchronizationState Synchronizable.State; synchronization step
190      */
191     void setSynchronizationState(final Synchronizable.State synchronizationState)
192     {
193         this.synchronizationState = synchronizationState;
194     }
195 
196     @Override
197     public Synchronizable.State getSynchronizationState()
198     {
199         return this.synchronizationState;
200     }
201 
202     /**
203      * Return whether control is human.
204      * @return humanLongitudinalControl.
205      */
206     boolean isHumanLongitudinalControl()
207     {
208         return this.humanLongitudinalControl;
209     }
210 
211     /**
212      * Set human longitudinal control.
213      * @param humanLongitudinalControl set humanLongitudinalControl.
214      */
215     public void setHumanLongitudinalControl(final boolean humanLongitudinalControl)
216     {
217         this.humanLongitudinalControl = humanLongitudinalControl;
218     }
219 
220     @Override
221     public String toString()
222     {
223         return "LmrsData [synchronization=" + this.synchronization + ", leaders=" + this.leaders + ", tempLeaders="
224                 + this.tempLeaders + ", syncVehicle=" + this.syncVehicle + "]";
225     }
226 
227 }