View Javadoc
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   * Implementation of the LMRS (Lane change Model with Relaxation and Synchronization). See Schakel, W.J., Knoop, V.L., and Van
49   * Arem, B. (2012), <a href="http://victorknoop.eu/research/papers/TRB2012_LMRS_reviewed.pdf">LMRS: Integrated Lane Change Model
50   * with Relaxation and Synchronization</a>, Transportation Research Records: Journal of the Transportation Research Board, No.
51   * 2316, pp. 47-57. Note in the official versions of TRB and TRR some errors appeared due to the typesetting of the papers (not
52   * in the preprint provided here). A list of errata for the official versions is found
53   * <a href="http://victorknoop.eu/research/papers/Erratum_LMRS.pdf">here</a>.
54   * <p>
55   * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
56   * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
57   * <p>
58   * @version $Revision$, $LastChangedDate$, by $Author$, initial version Apr 13, 2016 <br>
59   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
60   */
61  public class LMRS extends AbstractLaneBasedTacticalPlanner implements DesireBased, Synchronizable, Blockable
62  {
63  
64      /** Parameter type for mandatory lane change incentives. */
65      public static final ParameterTypeClassList<MandatoryIncentive> MANDATORY = new ParameterTypeClassList<>("man.incent.",
66              "Mandatory lane-change incentives.", ParameterTypeClassList.getValueClass(MandatoryIncentive.class));
67  
68      /** Parameter type for voluntary lane change incentives. */
69      public static final ParameterTypeClassList<VoluntaryIncentive> VOLUNTARY = new ParameterTypeClassList<>("vol.incent.",
70              "Voluntary lane-change incentives.", ParameterTypeClassList.getValueClass(VoluntaryIncentive.class));
71  
72      /** Parameter type for acceleration incentives. */
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      /** Serialization id. */
78      private static final long serialVersionUID = 20160300L;
79  
80      /** Lane change status. */
81      private final LaneChange laneChange = new LaneChange();
82  
83      /** LMRS data. */
84      private final LmrsData lmrsData;
85  
86      /** Set of mandatory lane change incentives. */
87      private final LinkedHashSet<MandatoryIncentive> mandatoryIncentives = new LinkedHashSet<>();
88  
89      /** Set of voluntary lane change incentives. */
90      private final LinkedHashSet<VoluntaryIncentive> voluntaryIncentives = new LinkedHashSet<>();
91  
92      /** Set of acceleration incentives. */
93      private final LinkedHashSet<AccelerationIncentive> accelerationIncentives = new LinkedHashSet<>();
94  
95      /**
96       * Constructor setting the car-following model.
97       * @param carFollowingModel CarFollowingModel; Car-following model.
98       * @param gtu LaneBasedGTU; GTU
99       * @param lanePerception LanePerception; perception
100      * @param synchronization Synchronization; type of synchronization
101      * @param cooperation Cooperation; type of cooperation
102      * @param gapAcceptance GapAcceptance; gap-acceptance
103      * @param tailGating Tailgating; tail gating
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      * Adds a mandatory incentive. Ignores {@code null}.
115      * @param incentive MandatoryIncentive; Incentive to add.
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      * Adds a voluntary incentive. Ignores {@code null}.
127      * @param incentive VoluntaryIncentive; Incentive to add.
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      * Adds an acceleration incentive. Ignores {@code null}.
139      * @param incentive AccelerationIncentive; Incentive to add.
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      * Sets the default lane change incentives.
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         // this.mandatoryIncentives.add(new IncentiveGetInLane());
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     /** {@inheritDoc} */
167     @Override
168     public final OperationalPlan generateOperationalPlan(final Time startTime, final DirectedPoint locationAtStartTime)
169             throws OperationalPlanException, GTUException, NetworkException, ParameterException
170     {
171         // obtain objects to get info
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         // LMRS
179         SimpleOperationalPlan simplePlan = LmrsUtil.determinePlan(getGtu(), startTime, getCarFollowingModel(), this.laneChange,
180                 this.lmrsData, getPerception(), this.mandatoryIncentives, this.voluntaryIncentives);
181 
182         // Lower acceleration from additional sources, consider adjacent lane when changing lane or synchronizing
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             // adjust lane based data in perception
216             // TODO make this automatic within the perception itself, e.g. by a lane change event from the tactical planner
217             if (getPerception().contains(DelayedNeighborsPerception.class))
218             {
219                 getPerception().getPerceptionCategory(DelayedNeighborsPerception.class)
220                         .changeLane(simplePlan.getLaneChangeDirection());
221             }
222         }
223 
224         // set turn indicator
225         simplePlan.setTurnIndicator(getGtu());
226 
227         // create plan
228         return LaneOperationalPlanBuilder.buildPlanFromSimplePlan(getGtu(), startTime, simplePlan, this.laneChange);
229 
230     }
231 
232     /** {@inheritDoc} */
233     @Override
234     public final Desire getLatestDesire(final Class<? extends Incentive> incentiveClass)
235     {
236         return this.lmrsData.getLatestDesire(incentiveClass);
237     }
238 
239     /** {@inheritDoc} */
240     @Override
241     public Synchronizable.State getSynchronizationState()
242     {
243         return this.lmrsData.getSynchronizationState();
244     }
245 
246     /** {@inheritDoc} */
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     /** {@inheritDoc} */
261     @Override
262     public final String toString()
263     {
264         return "LMRS [mandatoryIncentives=" + this.mandatoryIncentives + ", voluntaryIncentives=" + this.voluntaryIncentives
265                 + ", accelerationIncentives = " + this.accelerationIncentives + "]";
266     }
267 
268 }