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