View Javadoc
1   package org.opentrafficsim.road.gtu.lane.tactical.lmrs;
2   
3   import java.util.HashMap;
4   import java.util.LinkedHashSet;
5   import java.util.Map;
6   
7   import org.djunits.value.vdouble.scalar.Length;
8   import org.djunits.value.vdouble.scalar.Speed;
9   import org.djunits.value.vdouble.scalar.Time;
10  import org.opentrafficsim.core.gtu.GTUException;
11  import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
12  import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException;
13  import org.opentrafficsim.core.gtu.perception.EgoPerception;
14  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlan;
15  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
16  import org.opentrafficsim.core.network.NetworkException;
17  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
18  import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
19  import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
20  import org.opentrafficsim.road.gtu.lane.perception.categories.DelayedNeighborsPerception;
21  import org.opentrafficsim.road.gtu.lane.perception.categories.InfrastructurePerception;
22  import org.opentrafficsim.road.gtu.lane.plan.operational.LaneOperationalPlanBuilder.LaneChange;
23  import org.opentrafficsim.road.gtu.lane.plan.operational.SimpleOperationalPlan;
24  import org.opentrafficsim.road.gtu.lane.tactical.AbstractLaneBasedTacticalPlanner;
25  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
26  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Desire;
27  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Incentive;
28  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsData;
29  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsUtil;
30  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.MandatoryIncentive;
31  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
32  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
33  import org.opentrafficsim.road.network.speed.SpeedLimitInfo;
34  import org.opentrafficsim.road.network.speed.SpeedLimitProspect;
35  
36  import nl.tudelft.simulation.language.d3.DirectedPoint;
37  
38  /**
39   * Implementation of the LMRS (Lane change Model with Relaxation and Synchronization). See Schakel, W.J., Knoop, V.L., and Van
40   * Arem, B. (2012), <a href="http://victorknoop.eu/research/papers/TRB2012_LMRS_reviewed.pdf">LMRS: Integrated Lane Change Model
41   * with Relaxation and Synchronization</a>, Transportation Research Records: Journal of the Transportation Research Board, No.
42   * 2316, pp. 47-57. Note in the official versions of TRB and TRR some errors appeared due to the typesetting of the papers (not
43   * in the preprint provided here). A list of errata for the official versions is found
44   * <a href="http://victorknoop.eu/research/papers/Erratum_LMRS.pdf">here</a>.
45   * <p>
46   * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
47   * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
48   * <p>
49   * @version $Revision$, $LastChangedDate$, by $Author$, initial version Apr 13, 2016 <br>
50   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
51   */
52  public class LMRS extends AbstractLaneBasedTacticalPlanner
53  {
54  
55      /** Serialization id. */
56      private static final long serialVersionUID = 20160300L;
57  
58      /** Lane change status. */
59      private final LaneChange laneChange = new LaneChange();
60  
61      /** LMRS data. */
62      private final LmrsData lmrsData;
63  
64      /** Set of mandatory lane change incentives. */
65      private final LinkedHashSet<MandatoryIncentive> mandatoryIncentives = new LinkedHashSet<>();
66  
67      /** Set of voluntary lane change incentives. */
68      private final LinkedHashSet<VoluntaryIncentive> voluntaryIncentives = new LinkedHashSet<>();
69  
70      /** Latest desire value for visualization. */
71      private final Map<Class<? extends Incentive>, Desire> desireMap = new HashMap<>();
72  
73      /** Set of acceleration incentives. */
74      private final LinkedHashSet<AccelerationIncentive> accelerationIncentives = new LinkedHashSet<>();
75  
76      /**
77       * Constructor setting the car-following model.
78       * @param carFollowingModel Car-following model.
79       * @param gtu GTU
80       * @param lanePerception perception
81       * @param synchronization type of synchronization
82       */
83      public LMRS(final CarFollowingModel carFollowingModel, final LaneBasedGTU gtu, final LanePerception lanePerception,
84              final Synchronization synchronization)
85      {
86          super(carFollowingModel, gtu, lanePerception);
87          this.lmrsData = new LmrsData(synchronization);
88      }
89  
90      /**
91       * Adds a mandatory incentive. Ignores {@code null}.
92       * @param incentive Incentive to add.
93       */
94      public final void addMandatoryIncentive(final MandatoryIncentive incentive)
95      {
96          if (incentive != null)
97          {
98              this.mandatoryIncentives.add(incentive);
99          }
100     }
101 
102     /**
103      * Adds a voluntary incentive. Ignores {@code null}.
104      * @param incentive Incentive to add.
105      */
106     public final void addVoluntaryIncentive(final VoluntaryIncentive incentive)
107     {
108         if (incentive != null)
109         {
110             this.voluntaryIncentives.add(incentive);
111         }
112     }
113 
114     /**
115      * Adds an acceleration incentive. Ignores {@code null}.
116      * @param incentive Incentive to add.
117      */
118     public final void addAccelerationIncentive(final AccelerationIncentive incentive)
119     {
120         if (incentive != null)
121         {
122             this.accelerationIncentives.add(incentive);
123         }
124     }
125 
126     /**
127      * Sets the default lane change incentives.
128      */
129     public final void setDefaultIncentives()
130     {
131         this.mandatoryIncentives.clear();
132         this.voluntaryIncentives.clear();
133         this.accelerationIncentives.clear();
134         this.mandatoryIncentives.add(new IncentiveRoute());
135         this.mandatoryIncentives.add(new IncentiveGetInLane());
136         this.voluntaryIncentives.add(new IncentiveSpeedWithCourtesy());
137         this.voluntaryIncentives.add(new IncentiveKeep());
138         this.accelerationIncentives.add(new AccelerationSpeedLimitTransition());
139         this.accelerationIncentives.add(new AccelerationTrafficLights());
140         this.accelerationIncentives.add(new AccelerationConflicts());
141     }
142 
143     /** {@inheritDoc} */
144     @Override
145     public final OperationalPlan generateOperationalPlan(final Time startTime, final DirectedPoint locationAtStartTime)
146             throws OperationalPlanException, GTUException, NetworkException, ParameterException
147     {
148 
149         // obtain objects to get info
150         getPerception().perceive();
151         SpeedLimitProspect slp = getPerception().getPerceptionCategory(InfrastructurePerception.class)
152                 .getSpeedLimitProspect(RelativeLane.CURRENT);
153         SpeedLimitInfo sli = slp.getSpeedLimitInfo(Length.ZERO);
154         BehavioralCharacteristics bc = getGtu().getBehavioralCharacteristics();
155 
156         // LMRS
157         SimpleOperationalPlan simplePlan = LmrsUtil.determinePlan(getGtu(), startTime, getCarFollowingModel(), this.laneChange,
158                 this.lmrsData, getPerception(), this.mandatoryIncentives, this.voluntaryIncentives, this.desireMap);
159 
160         // Lower acceleration from additional sources
161         Speed speed = getPerception().getPerceptionCategory(EgoPerception.class).getSpeed();
162         RelativeLane[] lanes = this.laneChange.isChangingLane()
163                 ? new RelativeLane[] { RelativeLane.CURRENT, this.laneChange.getSecondLane(getGtu()) }
164                 : new RelativeLane[] { RelativeLane.CURRENT };
165         for (AccelerationIncentive incentive : this.accelerationIncentives)
166         {
167             for (RelativeLane lane : lanes)
168             {
169                 incentive.accelerate(simplePlan, lane, getGtu(), getPerception(), getCarFollowingModel(), speed, bc, sli);
170             }
171         }
172 
173         // adjust lane based data in perception
174         // TODO make this automatic within the perception itself, e.g. by a lane change event from the tactical planner
175         if (simplePlan.isLaneChange())
176         {
177             if (getPerception().contains(DelayedNeighborsPerception.class))
178             {
179                 getPerception().getPerceptionCategory(DelayedNeighborsPerception.class)
180                         .changeLane(simplePlan.getLaneChangeDirection());
181             }
182         }
183 
184         // set turn indicator
185         simplePlan.setTurnIndicator(getGtu());
186 
187         // create plan
188         return buildPlanFromSimplePlan(getGtu(), startTime, bc, simplePlan, this.laneChange);
189 
190     }
191 
192     /**
193      * Returns the desire of the given incentive.
194      * @param incentiveClass class of incentive
195      * @return desire of the given incentive
196      */
197     public Desire getLatestDesire(final Class<? extends Incentive> incentiveClass)
198     {
199         return this.desireMap.get(incentiveClass);
200     }
201 
202     /** {@inheritDoc} */
203     @Override
204     public final String toString()
205     {
206         String mandatory;
207         mandatory = "mandatoryIncentives=" + this.mandatoryIncentives + ", ";
208         String voluntary;
209         if (!this.voluntaryIncentives.isEmpty())
210         {
211             voluntary = "voluntaryIncentives=" + this.voluntaryIncentives;
212         }
213         else
214         {
215             voluntary = "voluntaryIncentives=[]";
216         }
217         return "LMRS [" + mandatory + voluntary + "]";
218     }
219 
220 }