1   package org.opentrafficsim.road.gtu.lane.tactical.lmrs;
2   
3   import java.util.LinkedHashSet;
4   
5   import org.djunits.value.vdouble.scalar.Length;
6   import org.djunits.value.vdouble.scalar.Speed;
7   import org.djunits.value.vdouble.scalar.Time;
8   import org.opentrafficsim.base.parameters.ParameterException;
9   import org.opentrafficsim.base.parameters.ParameterTypeClassList;
10  import org.opentrafficsim.base.parameters.ParameterTypes;
11  import org.opentrafficsim.base.parameters.Parameters;
12  import org.opentrafficsim.base.parameters.constraint.ClassCollectionConstraint;
13  import org.opentrafficsim.core.gtu.GTUException;
14  import org.opentrafficsim.core.gtu.perception.EgoPerception;
15  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlan;
16  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
17  import org.opentrafficsim.core.network.NetworkException;
18  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
19  import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
20  import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
21  import org.opentrafficsim.road.gtu.lane.perception.categories.InfrastructurePerception;
22  import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.DelayedNeighborsPerception;
23  import org.opentrafficsim.road.gtu.lane.plan.operational.LaneChange;
24  import org.opentrafficsim.road.gtu.lane.plan.operational.LaneOperationalPlanBuilder;
25  import org.opentrafficsim.road.gtu.lane.plan.operational.SimpleOperationalPlan;
26  import org.opentrafficsim.road.gtu.lane.tactical.AbstractLaneBasedTacticalPlanner;
27  import org.opentrafficsim.road.gtu.lane.tactical.Blockable;
28  import org.opentrafficsim.road.gtu.lane.tactical.DesireBased;
29  import org.opentrafficsim.road.gtu.lane.tactical.Synchronizable;
30  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
31  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Cooperation;
32  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Desire;
33  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.GapAcceptance;
34  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Incentive;
35  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsData;
36  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
37  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsUtil;
38  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.MandatoryIncentive;
39  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
40  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Tailgating;
41  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
42  import org.opentrafficsim.road.network.speed.SpeedLimitInfo;
43  import org.opentrafficsim.road.network.speed.SpeedLimitProspect;
44  
45  import nl.tudelft.simulation.language.d3.DirectedPoint;
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  public class LMRS extends AbstractLaneBasedTacticalPlanner implements DesireBased, Synchronizable, Blockable
62  {
63  
64      
65      public static final ParameterTypeClassList<MandatoryIncentive> MANDATORY = new ParameterTypeClassList<>("man.incent.",
66              "Mandatory lane-change incentives.", ParameterTypeClassList.getValueClass(MandatoryIncentive.class));
67  
68      
69      public static final ParameterTypeClassList<VoluntaryIncentive> VOLUNTARY = new ParameterTypeClassList<>("vol.incent.",
70              "Voluntary lane-change incentives.", ParameterTypeClassList.getValueClass(VoluntaryIncentive.class));
71  
72      
73      public static final ParameterTypeClassList<AccelerationIncentive> ACCELERATION = new ParameterTypeClassList<>("acc.incent.",
74              "Acceleration incentives.", ParameterTypeClassList.getValueClass(AccelerationIncentive.class),
75              ClassCollectionConstraint.newInstance(AccelerationBusStop.class));
76  
77      
78      private static final long serialVersionUID = 20160300L;
79  
80      
81      private final LaneChange laneChange = new LaneChange();
82  
83      
84      private final LmrsData lmrsData;
85  
86      
87      private final LinkedHashSet<MandatoryIncentive> mandatoryIncentives = new LinkedHashSet<>();
88  
89      
90      private final LinkedHashSet<VoluntaryIncentive> voluntaryIncentives = new LinkedHashSet<>();
91  
92      
93      private final LinkedHashSet<AccelerationIncentive> accelerationIncentives = new LinkedHashSet<>();
94  
95      
96  
97  
98  
99  
100 
101 
102 
103 
104 
105     public LMRS(final CarFollowingModel carFollowingModel, final LaneBasedGTU gtu, final LanePerception lanePerception,
106             final Synchronization synchronization, final Cooperation cooperation, final GapAcceptance gapAcceptance,
107             final Tailgating tailGating)
108     {
109         super(carFollowingModel, gtu, lanePerception);
110         this.lmrsData = new LmrsData(synchronization, cooperation, gapAcceptance, tailGating);
111     }
112 
113     
114 
115 
116 
117     public final void addMandatoryIncentive(final MandatoryIncentive incentive)
118     {
119         if (incentive != null)
120         {
121             this.mandatoryIncentives.add(incentive);
122         }
123     }
124 
125     
126 
127 
128 
129     public final void addVoluntaryIncentive(final VoluntaryIncentive incentive)
130     {
131         if (incentive != null)
132         {
133             this.voluntaryIncentives.add(incentive);
134         }
135     }
136 
137     
138 
139 
140 
141     public final void addAccelerationIncentive(final AccelerationIncentive incentive)
142     {
143         if (incentive != null)
144         {
145             this.accelerationIncentives.add(incentive);
146         }
147     }
148 
149     
150 
151 
152     public final void setDefaultIncentives()
153     {
154         this.mandatoryIncentives.clear();
155         this.voluntaryIncentives.clear();
156         this.accelerationIncentives.clear();
157         this.mandatoryIncentives.add(new IncentiveRoute());
158         
159         this.voluntaryIncentives.add(new IncentiveSpeedWithCourtesy());
160         this.voluntaryIncentives.add(new IncentiveKeep());
161         this.accelerationIncentives.add(new AccelerationSpeedLimitTransition());
162         this.accelerationIncentives.add(new AccelerationTrafficLights());
163         this.accelerationIncentives.add(new AccelerationConflicts());
164     }
165 
166     
167     @Override
168     public final OperationalPlan generateOperationalPlan(final Time startTime, final DirectedPoint locationAtStartTime)
169             throws OperationalPlanException, GTUException, NetworkException, ParameterException
170     {
171         
172         getPerception().perceive();
173         SpeedLimitProspect slp = getPerception().getPerceptionCategory(InfrastructurePerception.class)
174                 .getSpeedLimitProspect(RelativeLane.CURRENT);
175         SpeedLimitInfo sli = slp.getSpeedLimitInfo(Length.ZERO);
176         Parameters params = getGtu().getParameters();
177 
178         
179         SimpleOperationalPlan simplePlan = LmrsUtil.determinePlan(getGtu(), startTime, getCarFollowingModel(), this.laneChange,
180                 this.lmrsData, getPerception(), this.mandatoryIncentives, this.voluntaryIncentives);
181 
182         
183         Speed speed = getPerception().getPerceptionCategory(EgoPerception.class).getSpeed();
184         RelativeLane[] lanes;
185         double dLeft = params.getParameterOrNull(LmrsParameters.DLEFT);
186         double dRight = params.getParameterOrNull(LmrsParameters.DRIGHT);
187         double dSync = params.getParameterOrNull(LmrsParameters.DSYNC);
188         if (this.laneChange.isChangingLane())
189         {
190             lanes = new RelativeLane[] { RelativeLane.CURRENT, this.laneChange.getSecondLane(getGtu()) };
191         }
192         else if (dLeft >= dSync && dLeft >= dRight)
193         {
194             lanes = new RelativeLane[] { RelativeLane.CURRENT, RelativeLane.LEFT };
195         }
196         else if (dRight >= dSync)
197         {
198             lanes = new RelativeLane[] { RelativeLane.CURRENT, RelativeLane.RIGHT };
199         }
200         else
201         {
202             lanes = new RelativeLane[] { RelativeLane.CURRENT };
203         }
204         for (AccelerationIncentive incentive : this.accelerationIncentives)
205         {
206             for (RelativeLane lane : lanes)
207             {
208                 incentive.accelerate(simplePlan, lane, getGtu(), getPerception(), getCarFollowingModel(), speed, params, sli);
209             }
210         }
211 
212         if (simplePlan.isLaneChange())
213         {
214             this.laneChange.setDesiredLaneChangeDuration(getGtu().getParameters().getParameter(ParameterTypes.LCDUR));
215             
216             
217             if (getPerception().contains(DelayedNeighborsPerception.class))
218             {
219                 getPerception().getPerceptionCategory(DelayedNeighborsPerception.class)
220                         .changeLane(simplePlan.getLaneChangeDirection());
221             }
222         }
223 
224         
225         simplePlan.setTurnIndicator(getGtu());
226 
227         
228         return LaneOperationalPlanBuilder.buildPlanFromSimplePlan(getGtu(), startTime, simplePlan, this.laneChange);
229 
230     }
231 
232     
233     @Override
234     public final Desire getLatestDesire(final Class<? extends Incentive> incentiveClass)
235     {
236         return this.lmrsData.getLatestDesire(incentiveClass);
237     }
238 
239     
240     @Override
241     public Synchronizable.State getSynchronizationState()
242     {
243         return this.lmrsData.getSynchronizationState();
244     }
245 
246     
247     @Override
248     public boolean isBlocking()
249     {
250         for (AccelerationIncentive acc : this.accelerationIncentives)
251         {
252             if (acc instanceof AccelerationConflicts)
253             {
254                 return ((AccelerationConflicts) acc).isBlocking();
255             }
256         }
257         return false;
258     }
259 
260     
261     @Override
262     public final String toString()
263     {
264         return "LMRS [mandatoryIncentives=" + this.mandatoryIncentives + ", voluntaryIncentives=" + this.voluntaryIncentives
265                 + ", accelerationIncentives = " + this.accelerationIncentives + "]";
266     }
267 
268 }