1   package org.opentrafficsim.road.gtu.lane.plan.operational;
2   
3   import java.io.Serializable;
4   
5   import org.djunits.value.vdouble.scalar.Acceleration;
6   import org.djunits.value.vdouble.scalar.Duration;
7   import org.djunits.value.vdouble.scalar.Length;
8   import org.djutils.exceptions.Throw;
9   import org.opentrafficsim.core.gtu.GTUException;
10  import org.opentrafficsim.core.gtu.TurnIndicatorIntent;
11  import org.opentrafficsim.core.gtu.TurnIndicatorStatus;
12  import org.opentrafficsim.core.network.LateralDirectionality;
13  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
14  
15  import nl.tudelft.simulation.dsol.logger.SimLogger;
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  public class SimpleOperationalPlan implements Serializable
30  {
31  
32      
33      private static final long serialVersionUID = 20160811L;
34  
35      
36      private Acceleration acceleration;
37  
38      
39      private final LateralDirectionality laneChangeDirection;
40  
41      
42      private TurnIndicatorIntent indicatorIntent = TurnIndicatorIntent.NONE;
43  
44      
45      private Length indicatorObjectDistance = null;
46  
47      
48      private final Duration duration;
49  
50      
51  
52  
53  
54      public SimpleOperationalPlan(final Acceleration acceleration, final Duration duration)
55      {
56          this(acceleration, duration, LateralDirectionality.NONE);
57      }
58  
59      
60  
61  
62  
63  
64      public SimpleOperationalPlan(final Acceleration acceleration, final Duration duration,
65              final LateralDirectionality laneChangeDirection)
66      {
67          Throw.whenNull(acceleration, "Acceleration may not be null.");
68          Throw.whenNull(duration, "Duration may not be null.");
69          Throw.whenNull(laneChangeDirection, "Lane change direction may not be null.");
70          checkAcceleration(acceleration);
71          this.acceleration = Acceleration.max(Acceleration.createSI(-100.0), acceleration);
72          this.duration = duration;
73          this.laneChangeDirection = laneChangeDirection;
74      }
75  
76      
77  
78  
79      public final Acceleration getAcceleration()
80      {
81          return this.acceleration;
82      }
83  
84      
85  
86  
87      public Duration getDuration()
88      {
89          return this.duration;
90      }
91  
92      
93  
94  
95      public final boolean isLaneChange()
96      {
97          return this.laneChangeDirection != LateralDirectionality.NONE;
98      }
99  
100     
101 
102 
103     public final LateralDirectionality getLaneChangeDirection()
104     {
105         return this.laneChangeDirection;
106     }
107 
108     
109 
110 
111 
112     public final void minimizeAcceleration(final Acceleration a)
113     {
114         checkAcceleration(a);
115         this.acceleration = Acceleration.max(Acceleration.createSI(-100.0), Acceleration.min(this.acceleration, a)); 
116     }
117 
118     
119 
120 
121 
122     private void checkAcceleration(final Acceleration a)
123     {
124         if (a.equals(Acceleration.NEGATIVE_INFINITY) || a.equals(Acceleration.NEG_MAXVALUE))
125         {
126             SimLogger.always().error("Model has calculated a negative infinite or negative max value acceleration."); 
127         }
128     }
129 
130     
131 
132 
133     public final TurnIndicatorIntent getIndicatorIntent()
134     {
135         return this.indicatorIntent;
136     }
137 
138     
139 
140 
141     public final void setIndicatorIntentLeft()
142     {
143         if (this.indicatorObjectDistance != null)
144         {
145             return;
146         }
147         if (this.indicatorIntent.isRight())
148         {
149             this.indicatorIntent = TurnIndicatorIntent.CONFLICTING;
150         }
151         else
152         {
153             this.indicatorIntent = TurnIndicatorIntent.LEFT;
154         }
155     }
156 
157     
158 
159 
160     public final void setIndicatorIntentRight()
161     {
162         if (this.indicatorObjectDistance != null)
163         {
164             return;
165         }
166         if (this.indicatorIntent.isLeft())
167         {
168             this.indicatorIntent = TurnIndicatorIntent.CONFLICTING;
169         }
170         else
171         {
172             this.indicatorIntent = TurnIndicatorIntent.RIGHT;
173         }
174     }
175 
176     
177 
178 
179 
180     public final void setIndicatorIntentLeft(final Length distance)
181     {
182         if (compareAndIgnore(distance))
183         {
184             return;
185         }
186         if (this.indicatorIntent.isRight())
187         {
188             this.indicatorIntent = TurnIndicatorIntent.CONFLICTING;
189         }
190         else
191         {
192             this.indicatorIntent = TurnIndicatorIntent.LEFT;
193         }
194 
195     }
196 
197     
198 
199 
200 
201     public final void setIndicatorIntentRight(final Length distance)
202     {
203         if (compareAndIgnore(distance))
204         {
205             return;
206         }
207         if (this.indicatorIntent.isLeft())
208         {
209             this.indicatorIntent = TurnIndicatorIntent.CONFLICTING;
210         }
211         else
212         {
213             this.indicatorIntent = TurnIndicatorIntent.RIGHT;
214         }
215     }
216 
217     
218 
219 
220 
221 
222     private boolean compareAndIgnore(final Length distance)
223     {
224         if (this.indicatorObjectDistance != null)
225         {
226             if (this.indicatorObjectDistance.lt(distance))
227             {
228                 
229                 return true;
230             }
231             if (this.indicatorObjectDistance.gt(distance))
232             {
233                 
234                 this.indicatorIntent = TurnIndicatorIntent.NONE; 
235             }
236         }
237         else
238         {
239             
240             this.indicatorIntent = TurnIndicatorIntent.NONE; 
241         }
242         return false;
243     }
244 
245     
246     @Override
247     @SuppressWarnings("checkstyle:designforextension")
248     public String toString()
249     {
250         return "SimpleOperationalPlan [Acceleration=" + this.acceleration + ", change=" + this.laneChangeDirection
251                 + ", indicator intent=" + this.indicatorIntent + "]";
252     }
253 
254     
255 
256 
257 
258     public final void setTurnIndicator(final LaneBasedGTU gtu) throws GTUException
259     {
260         if (this.indicatorIntent.isLeft())
261         {
262             gtu.setTurnIndicatorStatus(TurnIndicatorStatus.LEFT);
263         }
264         else if (this.indicatorIntent.isRight())
265         {
266             gtu.setTurnIndicatorStatus(TurnIndicatorStatus.RIGHT);
267         }
268         else
269         {
270             gtu.setTurnIndicatorStatus(TurnIndicatorStatus.NONE);
271         }
272     }
273 
274 }