View Javadoc
1   package org.opentrafficsim.road.gtu.lane.tactical.lmrs;
2   
3   import java.util.Optional;
4   
5   import org.djunits.value.vdouble.scalar.Duration;
6   import org.djunits.value.vdouble.scalar.Length;
7   import org.djunits.value.vdouble.scalar.Speed;
8   import org.djutils.draw.point.DirectedPoint2d;
9   import org.opentrafficsim.base.parameters.ParameterException;
10  import org.opentrafficsim.base.parameters.ParameterTypes;
11  import org.opentrafficsim.base.parameters.Parameters;
12  import org.opentrafficsim.core.gtu.GtuException;
13  import org.opentrafficsim.core.gtu.perception.EgoPerception;
14  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlan;
15  import org.opentrafficsim.core.network.NetworkException;
16  import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
17  import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
18  import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
19  import org.opentrafficsim.road.gtu.lane.perception.categories.InfrastructurePerception;
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  /**
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-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
47   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
48   * </p>
49   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
50   */
51  public class Lmrs extends AbstractIncentivesTacticalPlanner implements DesireBased, Synchronizable, Blockable
52  {
53  
54      /** LMRS data. */
55      private final LmrsData lmrsData;
56  
57      /**
58       * Constructor setting the car-following model.
59       * @param carFollowingModel car-following model
60       * @param gtu GTU
61       * @param lanePerception perception
62       * @param synchronization type of synchronization
63       * @param cooperation type of cooperation
64       * @param gapAcceptance gap-acceptance
65       * @param tailgating tailgating
66       */
67      public Lmrs(final CarFollowingModel carFollowingModel, final LaneBasedGtu gtu, final LanePerception lanePerception,
68              final Synchronization synchronization, final Cooperation cooperation, final GapAcceptance gapAcceptance,
69              final Tailgating tailgating)
70      {
71          super(carFollowingModel, gtu, lanePerception);
72          this.lmrsData = new LmrsData(synchronization, cooperation, gapAcceptance, tailgating);
73      }
74  
75      @Override
76      public final OperationalPlan generateOperationalPlan(final Duration startTime, final DirectedPoint2d locationAtStartTime)
77              throws GtuException, NetworkException, ParameterException
78      {
79          // obtain objects to get info
80          SpeedLimitProspect slp = getPerception().getPerceptionCategory(InfrastructurePerception.class)
81                  .getSpeedLimitProspect(RelativeLane.CURRENT);
82          SpeedLimitInfo sli = slp.getSpeedLimitInfo(Length.ZERO);
83          Parameters params = getGtu().getParameters();
84  
85          // LMRS
86          SimpleOperationalPlan simplePlan = LmrsUtil.determinePlan(getGtu(), getCarFollowingModel(), this.lmrsData,
87                  getPerception(), getMandatoryIncentives(), getVoluntaryIncentives());
88  
89          // Lower acceleration from additional sources, consider adjacent lane when changing lane or synchronizing
90          Speed speed = getPerception().getPerceptionCategory(EgoPerception.class).getSpeed();
91          RelativeLane[] lanes;
92          double dLeft = params.getParameter(LmrsParameters.DLEFT);
93          double dRight = params.getParameter(LmrsParameters.DRIGHT);
94          double dSync = params.getParameter(LmrsParameters.DSYNC);
95          if (dLeft >= dSync && dLeft >= dRight)
96          {
97              lanes = new RelativeLane[] {RelativeLane.CURRENT, RelativeLane.LEFT};
98          }
99          else if (dRight >= dSync)
100         {
101             lanes = new RelativeLane[] {RelativeLane.CURRENT, RelativeLane.RIGHT};
102         }
103         else
104         {
105             lanes = new RelativeLane[] {RelativeLane.CURRENT};
106         }
107         for (RelativeLane lane : lanes)
108         {
109             if (getPerception().getLaneStructure().getRootCrossSection().contains(lane))
110             {
111                 // On the current lane, consider all incentives. On adjacent lanes only consider incentives beyond the distance
112                 // over
113                 // which a lane change is not yet possible, i.e. the merge distance.
114                 // TODO: consider route in incentives (only if not on current lane?)
115                 Length mergeDistance = lane.isCurrent() ? Length.ZERO
116                         : Synchronization.getMergeDistance(getPerception(), lane.getLateralDirectionality());
117                 for (AccelerationIncentive incentive : getAccelerationIncentives())
118                 {
119                     incentive.accelerate(simplePlan, lane, mergeDistance, getGtu(), getPerception(), getCarFollowingModel(),
120                             speed, params, sli);
121                 }
122             }
123         }
124 
125         // set turn indicator
126         simplePlan.setTurnIndicator(getGtu());
127 
128         // create plan
129         return LaneOperationalPlanBuilder.buildPlanFromSimplePlan(getGtu(), simplePlan,
130                 getGtu().getParameters().getParameter(ParameterTypes.LCDUR));
131 
132     }
133 
134     @Override
135     public final Optional<Desire> getLatestDesire(final Class<? extends Incentive> incentiveClass)
136     {
137         return this.lmrsData.getLatestDesire(incentiveClass);
138     }
139 
140     @Override
141     public Synchronizable.State getSynchronizationState()
142     {
143         return this.lmrsData.getSynchronizationState();
144     }
145 
146     @Override
147     public boolean isBlocking()
148     {
149         for (AccelerationIncentive acc : getAccelerationIncentives())
150         {
151             if (acc instanceof AccelerationConflicts)
152             {
153                 return ((AccelerationConflicts) acc).isBlocking();
154             }
155         }
156         return false;
157     }
158 
159     @Override
160     public final String toString()
161     {
162         return "LMRS [mandatoryIncentives=" + getMandatoryIncentives() + ", voluntaryIncentives=" + getVoluntaryIncentives()
163                 + ", accelerationIncentives = " + getAccelerationIncentives() + "]";
164     }
165 
166 }