View Javadoc
1   package org.opentrafficsim.road.gtu.lane.tactical.lmrs;
2   
3   import java.util.LinkedHashSet;
4   
5   import nl.tudelft.simulation.language.d3.DirectedPoint;
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.plan.operational.OperationalPlan;
14  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
15  import org.opentrafficsim.core.network.NetworkException;
16  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
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.perception.categories.IntersectionPerception;
20  import org.opentrafficsim.road.gtu.lane.perception.categories.NeighborsPerception;
21  import org.opentrafficsim.road.gtu.lane.plan.operational.SimpleOperationalPlan;
22  import org.opentrafficsim.road.gtu.lane.plan.operational.LaneOperationalPlanBuilder.LaneChange;
23  import org.opentrafficsim.road.gtu.lane.tactical.AbstractLaneBasedTacticalPlanner;
24  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
25  import org.opentrafficsim.road.gtu.lane.tactical.util.ConflictUtil;
26  import org.opentrafficsim.road.gtu.lane.tactical.util.ConflictUtil.ConflictPlans;
27  import org.opentrafficsim.road.gtu.lane.tactical.util.SpeedLimitUtil;
28  import org.opentrafficsim.road.gtu.lane.tactical.util.TrafficLightUtil;
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.VoluntaryIncentive;
32  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsUtil.LmrsStatus;
33  import org.opentrafficsim.road.network.speed.SpeedLimitInfo;
34  import org.opentrafficsim.road.network.speed.SpeedLimitProspect;
35  
36  /**
37   * Implementation of the LMRS (Lane change Model with Relaxation and Synchronization). See Schakel, W.J., Knoop, V.L., and Van
38   * Arem, B. (2012), <a href="http://victorknoop.eu/research/papers/TRB2012_LMRS_reviewed.pdf">LMRS: Integrated Lane Change Model
39   * with Relaxation and Synchronization</a>, Transportation Research Records: Journal of the Transportation Research Board, No.
40   * 2316, pp. 47-57. Note in the official versions of TRB and TRR some errors appeared due to the typesetting of the papers (not
41   * in the preprint provided here). A list of errata for the official versions is found <a
42   * href="http://victorknoop.eu/research/papers/Erratum_LMRS.pdf">here</a>.
43   * <p>
44   * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
45   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
46   * <p>
47   * @version $Revision$, $LastChangedDate$, by $Author$, initial version Apr 13, 2016 <br>
48   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
49   */
50  public class LMRS extends AbstractLaneBasedTacticalPlanner
51  {
52  
53      /** Serialization id. */
54      private static final long serialVersionUID = 20160300L;
55  
56      /** Set of yield plans at conflicts with priority. Remembering for static model. */
57      private final ConflictPlans yieldPlans = new ConflictPlans();
58  
59      /** Lane change status. */
60      private final LaneChange laneChange = new LaneChange();
61  
62      /** LMRS status. */
63      private final LmrsStatus lmrsStatus = new LmrsStatus();
64  
65      /** Set of mandatory lane change incentives. */
66      private final LinkedHashSet<MandatoryIncentive> mandatoryIncentives = new LinkedHashSet<>();
67  
68      /** Set of voluntary lane change incentives. */
69      private final LinkedHashSet<VoluntaryIncentive> voluntaryIncentives = new LinkedHashSet<>();
70  
71      /**
72       * Constructor setting the car-following model.
73       * @param carFollowingModel Car-following model.
74       * @param gtu GTU
75       */
76      public LMRS(final CarFollowingModel carFollowingModel, final LaneBasedGTU gtu)
77      {
78          super(carFollowingModel, gtu);
79      }
80  
81      /**
82       * Adds a mandatory incentive. Ignores <tt>null</tt>.
83       * @param incentive Incentive to add.
84       */
85      public final void addMandatoryIncentive(final MandatoryIncentive incentive)
86      {
87          if (incentive != null)
88          {
89              this.mandatoryIncentives.add(incentive);
90          }
91      }
92  
93      /**
94       * Adds a voluntary incentive. Ignores <tt>null</tt>.
95       * @param incentive Incentive to add.
96       */
97      public final void addVoluntaryIncentive(final VoluntaryIncentive incentive)
98      {
99          if (incentive != null)
100         {
101             this.voluntaryIncentives.add(incentive);
102         }
103     }
104 
105     /**
106      * Sets the default lane change incentives.
107      */
108     public final void setDefaultIncentives()
109     {
110         this.mandatoryIncentives.clear();
111         this.voluntaryIncentives.clear();
112         this.mandatoryIncentives.add(new IncentiveRoute());
113         this.voluntaryIncentives.add(new IncentiveSpeedWithCourtesy());
114         this.voluntaryIncentives.add(new IncentiveKeep());
115     }
116 
117     /** {@inheritDoc} */
118     @Override
119     public final OperationalPlan generateOperationalPlan(final Time startTime, final DirectedPoint locationAtStartTime)
120         throws OperationalPlanException, GTUException, NetworkException, ParameterException
121     {
122         // obtain objects to get info
123         getPerception().perceive();
124         SpeedLimitProspect slp =
125             getPerception().getPerceptionCategory(InfrastructurePerception.class).getSpeedLimitProspect(RelativeLane.CURRENT);
126         SpeedLimitInfo sli = slp.getSpeedLimitInfo(Length.ZERO);
127         BehavioralCharacteristics bc = getGtu().getBehavioralCharacteristics();
128 
129         // LMRS
130         SimpleOperationalPlan simplePlan =
131             LmrsUtil.determinePlan(getGtu(), startTime, this.lmrsStatus, getCarFollowingModel(), this.laneChange,
132                 getPerception(), this.mandatoryIncentives, this.voluntaryIncentives);
133 
134         // speed limits
135         Speed speed = getGtu().getSpeed();
136         simplePlan.minimumAcceleration(SpeedLimitUtil.considerSpeedLimitTransitions(bc, speed, slp, getCarFollowingModel()));
137 
138         // traffic lights
139         // TODO traffic lights on route, possible on different lane (and possibly close)
140         simplePlan.minimumAcceleration(TrafficLightUtil.respondToTrafficLights(bc, getPerception().getPerceptionCategory(
141             IntersectionPerception.class).getTrafficLights(RelativeLane.CURRENT), getCarFollowingModel(), speed, sli));
142 
143         // conflicts
144         simplePlan.minimumAcceleration(ConflictUtil.approachConflicts(bc, getPerception().getPerceptionCategory(
145             IntersectionPerception.class).getConflicts(RelativeLane.CURRENT), getPerception().getPerceptionCategory(
146             NeighborsPerception.class).getLeaders(RelativeLane.CURRENT), getCarFollowingModel(), getGtu().getLength(), speed,
147             sli, this.yieldPlans));
148 
149         // create plan
150         return buildPlanFromSimplePlan(getGtu(), startTime, bc, simplePlan, this.laneChange);
151 
152     }
153 
154     /** {@inheritDoc} */
155     @Override
156     public final String toString()
157     {
158         String mandatory;
159         mandatory = "mandatoryIncentives=" + this.mandatoryIncentives + ", ";
160         String voluntary;
161         if (!this.voluntaryIncentives.isEmpty())
162         {
163             voluntary = "voluntaryIncentives=" + this.voluntaryIncentives;
164         }
165         else
166         {
167             voluntary = "voluntaryIncentives=[]";
168         }
169         return "LMRS [" + mandatory + voluntary + "]";
170     }
171 
172 }