1   package org.opentrafficsim.road.gtu.lane.tactical.lmrs;
2   
3   import org.djunits.value.vdouble.scalar.Length;
4   import org.djunits.value.vdouble.scalar.Speed;
5   import org.djunits.value.vdouble.scalar.Time;
6   import org.djutils.exceptions.Try;
7   import org.opentrafficsim.base.parameters.ParameterException;
8   import org.opentrafficsim.base.parameters.ParameterTypes;
9   import org.opentrafficsim.base.parameters.Parameters;
10  import org.opentrafficsim.core.gtu.GTUException;
11  import org.opentrafficsim.core.gtu.perception.EgoPerception;
12  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlan;
13  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
14  import org.opentrafficsim.core.network.NetworkException;
15  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
16  import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
17  import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
18  import org.opentrafficsim.road.gtu.lane.perception.categories.InfrastructurePerception;
19  import org.opentrafficsim.road.gtu.lane.plan.operational.LaneChange;
20  import org.opentrafficsim.road.gtu.lane.plan.operational.LaneOperationalPlanBuilder;
21  import org.opentrafficsim.road.gtu.lane.plan.operational.SimpleOperationalPlan;
22  import org.opentrafficsim.road.gtu.lane.tactical.Blockable;
23  import org.opentrafficsim.road.gtu.lane.tactical.DesireBased;
24  import org.opentrafficsim.road.gtu.lane.tactical.Synchronizable;
25  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
26  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Cooperation;
27  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Desire;
28  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.GapAcceptance;
29  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Incentive;
30  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsData;
31  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
32  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsUtil;
33  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
34  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Tailgating;
35  import org.opentrafficsim.road.network.speed.SpeedLimitInfo;
36  import org.opentrafficsim.road.network.speed.SpeedLimitProspect;
37  
38  import nl.tudelft.simulation.language.d3.DirectedPoint;
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  public class LMRS extends AbstractIncentivesTacticalPlanner implements DesireBased, Synchronizable, Blockable
55  {
56  
57      
58      private static final long serialVersionUID = 20160300L;
59  
60      
61      private final LaneChange laneChange;
62  
63      
64      private final LmrsData lmrsData;
65  
66      
67  
68  
69  
70  
71  
72  
73  
74  
75  
76      public LMRS(final CarFollowingModel carFollowingModel, final LaneBasedGTU gtu, final LanePerception lanePerception,
77              final Synchronization synchronization, final Cooperation cooperation, final GapAcceptance gapAcceptance,
78              final Tailgating tailgating)
79      {
80          super(carFollowingModel, gtu, lanePerception);
81          this.laneChange = Try.assign(() -> new LaneChange(gtu), "Parameter LCDUR is required.", GTUException.class);
82          this.lmrsData = new LmrsData(synchronization, cooperation, gapAcceptance, tailgating);
83      }
84  
85      
86      @Override
87      public final OperationalPlan generateOperationalPlan(final Time startTime, final DirectedPoint locationAtStartTime)
88              throws OperationalPlanException, GTUException, NetworkException, ParameterException
89      {
90          
91          SpeedLimitProspect slp = getPerception().getPerceptionCategory(InfrastructurePerception.class)
92                  .getSpeedLimitProspect(RelativeLane.CURRENT);
93          SpeedLimitInfo sli = slp.getSpeedLimitInfo(Length.ZERO);
94          Parameters params = getGtu().getParameters();
95  
96          
97          SimpleOperationalPlan simplePlan = LmrsUtil.determinePlan(getGtu(), startTime, getCarFollowingModel(), this.laneChange,
98                  this.lmrsData, getPerception(), getMandatoryIncentives(), getVoluntaryIncentives());
99  
100         
101         Speed speed = getPerception().getPerceptionCategory(EgoPerception.class).getSpeed();
102         RelativeLane[] lanes;
103         double dLeft = params.getParameterOrNull(LmrsParameters.DLEFT);
104         double dRight = params.getParameterOrNull(LmrsParameters.DRIGHT);
105         double dSync = params.getParameterOrNull(LmrsParameters.DSYNC);
106         if (this.laneChange.isChangingLane())
107         {
108             lanes = new RelativeLane[] { RelativeLane.CURRENT, this.laneChange.getSecondLane(getGtu()) };
109         }
110         else if (dLeft >= dSync && dLeft >= dRight)
111         {
112             lanes = new RelativeLane[] { RelativeLane.CURRENT, RelativeLane.LEFT };
113         }
114         else if (dRight >= dSync)
115         {
116             lanes = new RelativeLane[] { RelativeLane.CURRENT, RelativeLane.RIGHT };
117         }
118         else
119         {
120             lanes = new RelativeLane[] { RelativeLane.CURRENT };
121         }
122         for (RelativeLane lane : lanes)
123         {
124             
125             
126             
127             Length mergeDistance = lane.isCurrent() ? Length.ZERO
128                     : Synchronization.getMergeDistance(getPerception(), lane.getLateralDirectionality());
129             for (AccelerationIncentive incentive : getAccelerationIncentives())
130             {
131                 incentive.accelerate(simplePlan, lane, mergeDistance, getGtu(), getPerception(), getCarFollowingModel(), speed,
132                         params, sli);
133             }
134         }
135 
136         if (simplePlan.isLaneChange())
137         {
138             this.laneChange.setDesiredLaneChangeDuration(getGtu().getParameters().getParameter(ParameterTypes.LCDUR));
139             
140         }
141 
142         
143         simplePlan.setTurnIndicator(getGtu());
144 
145         
146         return LaneOperationalPlanBuilder.buildPlanFromSimplePlan(getGtu(), startTime, simplePlan, this.laneChange);
147 
148     }
149 
150     
151     @Override
152     public final Desire getLatestDesire(final Class<? extends Incentive> incentiveClass)
153     {
154         return this.lmrsData.getLatestDesire(incentiveClass);
155     }
156 
157     
158     @Override
159     public Synchronizable.State getSynchronizationState()
160     {
161         return this.lmrsData.getSynchronizationState();
162     }
163 
164     
165     @Override
166     public boolean isBlocking()
167     {
168         for (AccelerationIncentive acc : getAccelerationIncentives())
169         {
170             if (acc instanceof AccelerationConflicts)
171             {
172                 return ((AccelerationConflicts) acc).isBlocking();
173             }
174         }
175         return false;
176     }
177 
178     
179     @Override
180     public final String toString()
181     {
182         return "LMRS [mandatoryIncentives=" + getMandatoryIncentives() + ", voluntaryIncentives=" + getVoluntaryIncentives()
183                 + ", accelerationIncentives = " + getAccelerationIncentives() + "]";
184     }
185 
186 }