View Javadoc
1   package org.opentrafficsim.road.gtu.lane.tactical.lmrs;
2   
3   import org.djunits.unit.DimensionlessUnit;
4   import org.djunits.unit.SpeedUnit;
5   import org.djunits.value.vdouble.scalar.Acceleration;
6   import org.djunits.value.vdouble.scalar.Dimensionless;
7   import org.djunits.value.vdouble.scalar.Length;
8   import org.djunits.value.vdouble.scalar.Speed;
9   import org.opentrafficsim.core.gtu.behavioralcharacteristics.AbstractParameterType;
10  import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
11  import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException;
12  import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterTypeSpeed;
13  import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterTypes;
14  import org.opentrafficsim.core.gtu.perception.EgoPerception;
15  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
16  import org.opentrafficsim.core.network.LateralDirectionality;
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.perception.categories.NeighborsPerception;
21  import org.opentrafficsim.road.gtu.lane.perception.headway.AbstractHeadwayGTU;
22  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
23  import org.opentrafficsim.road.gtu.lane.tactical.util.CarFollowingUtil;
24  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Desire;
25  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
26  
27  /**
28   * Determines lane change desire for speed. The anticipation speed in the current and adjacent lanes are compared. The larger
29   * the difference, the larger the lane change desire. For negative differences, negative desire results. Anticipation speed
30   * involves the the most critical vehicle considered to be in a lane. Vehicles are more critical if their speed is lower, and if
31   * they are closer. The set of vehicles considered to be on a lane includes drivers on adjacent lanes of the considered lane,
32   * with a lane change desire towards the considered lane above a certain certain threshold. If such vehicles have low speeds
33   * (i.e. vehicle accelerating to merge), this may result in a courtesy lane change, or in not changing lane out of courtesy from
34   * the 2nd lane of the mainline. Vehicle on the current lane of the driver, are not considered on adjacent lanes. This would
35   * maintain a large speed difference between the lanes where all drivers do not change lane as they consider leading vehicles to
36   * be on the adjacent lane, lowering the anticipation speed on the adjacent lane. The desire for speed is reduced as
37   * acceleration is larger, preventing over-assertive lane changes as acceleration out of congestion in the adjacent lane has
38   * progressed more.<br>
39   * <br>
40   * <b>Note:</b> This incentive includes speed, and a form of courtesy. It should therefore not be combined with incentives
41   * solely for speed, or solely for courtesy.
42   * <p>
43   * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
44   * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
45   * <p>
46   * @version $Revision$, $LastChangedDate$, by $Author$, initial version Apr 13, 2016 <br>
47   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
48   */
49  public class IncentiveSpeedWithCourtesy implements VoluntaryIncentive
50  {
51  
52      /** Anticipation speed difference at full lane change desired. */
53      public static final ParameterTypeSpeed VGAIN = new ParameterTypeSpeed("vGain", "Anticipation speed difference at "
54          + "full lane change desired.", new Speed(69.6, SpeedUnit.KM_PER_HOUR), AbstractParameterType.Check.POSITIVE);
55  
56      /** {@inheritDoc} */
57      @Override
58      public final Desire determineDesire(final BehavioralCharacteristics behavioralCharacteristics,
59          final LanePerception perception, final CarFollowingModel carFollowingModel, final Desire mandatoryDesire,
60          final Desire voluntaryDesire) throws ParameterException, OperationalPlanException
61      {
62  
63          // zero if no lane change is possible
64          if (perception.getPerceptionCategory(InfrastructurePerception.class).getLegalLaneChangePossibility(
65              RelativeLane.CURRENT, LateralDirectionality.LEFT).si == 0
66              && perception.getPerceptionCategory(InfrastructurePerception.class).getLegalLaneChangePossibility(
67                  RelativeLane.CURRENT, LateralDirectionality.RIGHT).si == 0)
68          {
69              return new Desire(0, 0);
70          }
71  
72          // gather some info
73          Speed vCur = anticipationSpeed(RelativeLane.CURRENT, behavioralCharacteristics, perception, carFollowingModel);
74          Speed vGain = behavioralCharacteristics.getParameter(VGAIN);
75  
76          // calculate aGain (default 1; lower as acceleration is higher than 0)
77          Dimensionless aGain;
78          Acceleration aCur =
79              CarFollowingUtil.followLeaders(carFollowingModel, behavioralCharacteristics, perception.getPerceptionCategory(
80                  EgoPerception.class).getSpeed(), perception.getPerceptionCategory(InfrastructurePerception.class)
81                  .getSpeedLimitProspect(RelativeLane.CURRENT).getSpeedLimitInfo(Length.ZERO), perception
82                  .getPerceptionCategory(NeighborsPerception.class).getLeaders(RelativeLane.CURRENT));
83          if (aCur.si > 0)
84          {
85              Acceleration a = behavioralCharacteristics.getParameter(ParameterTypes.A);
86              aGain = a.minus(aCur).divideBy(a);
87          }
88          else
89          {
90              aGain = new Dimensionless(1, DimensionlessUnit.SI);
91          }
92  
93          // left desire
94          Dimensionless dLeft;
95          if (perception.getPerceptionCategory(InfrastructurePerception.class).getCrossSection().contains(RelativeLane.LEFT))
96          {
97              Speed vLeft = anticipationSpeed(RelativeLane.LEFT, behavioralCharacteristics, perception, carFollowingModel);
98              dLeft = aGain.multiplyBy(vLeft.minus(vCur)).divideBy(vGain);
99          }
100         else
101         {
102             dLeft = Dimensionless.ZERO;
103         }
104 
105         // right desire
106         Dimensionless dRight;
107         if (perception.getPerceptionCategory(InfrastructurePerception.class).getCrossSection().contains(RelativeLane.RIGHT))
108         {
109             Speed vRight = anticipationSpeed(RelativeLane.RIGHT, behavioralCharacteristics, perception, carFollowingModel);
110             dRight = aGain.multiplyBy(vRight.minus(vCur)).divideBy(vGain);
111         }
112         else
113         {
114             dRight = Dimensionless.ZERO;
115         }
116 
117         // return desire
118         return new Desire(dLeft, dRight);
119     }
120 
121     /**
122      * Determine the anticipation speed on the given lane.
123      * @param lane lane to anticipate the speed on
124      * @param bc behavioral characteristics
125      * @param perception perception
126      * @param cfm car-following model, used for the desired speed
127      * @return anticipation speed on lane
128      * @throws ParameterException if a parameter is not defined
129      * @throws OperationalPlanException perception exception
130      */
131     private Speed anticipationSpeed(final RelativeLane lane, final BehavioralCharacteristics bc,
132         final LanePerception perception, final CarFollowingModel cfm) throws ParameterException, OperationalPlanException
133     {
134 
135         Speed anticipationSpeed =
136             cfm.desiredSpeed(bc, perception.getPerceptionCategory(InfrastructurePerception.class).getSpeedLimitProspect(lane)
137                 .getSpeedLimitInfo(Length.ZERO));
138         Speed desiredSpeed = new Speed(anticipationSpeed);
139         Length x0 = bc.getParameter(ParameterTypes.LOOKAHEAD);
140 
141         // leaders with right indicators on left lane of considered lane
142         if (perception.getPerceptionCategory(InfrastructurePerception.class).getCrossSection().contains(lane.getLeft()))
143         {
144             for (AbstractHeadwayGTU headwayGTU : perception.getPerceptionCategory(NeighborsPerception.class).getLeaders(
145                 lane.getLeft()))
146             {
147                 // leaders on the current lane with indicator to an adjacent lane are not considered
148                 if (headwayGTU.isRightTurnIndicatorOn() && !lane.getLeft().equals(RelativeLane.CURRENT))
149                 {
150                     anticipationSpeed = anticipateSingle(anticipationSpeed, desiredSpeed, x0, headwayGTU);
151                 }
152             }
153         }
154 
155         // leaders with left indicators on right lane of considered lane
156         if (perception.getPerceptionCategory(InfrastructurePerception.class).getCrossSection().contains(lane.getRight()))
157         {
158             for (AbstractHeadwayGTU headwayGTU : perception.getPerceptionCategory(NeighborsPerception.class).getLeaders(
159                 lane.getRight()))
160             {
161                 // leaders on the current lane with indicator to an adjacent lane are not considered
162                 if (headwayGTU.isLeftTurnIndicatorOn() && !lane.getRight().equals(RelativeLane.CURRENT))
163                 {
164                     anticipationSpeed = anticipateSingle(anticipationSpeed, desiredSpeed, x0, headwayGTU);
165                 }
166             }
167         }
168 
169         // leaders in the considered lane
170         for (AbstractHeadwayGTU headwayGTU : perception.getPerceptionCategory(NeighborsPerception.class).getLeaders(lane))
171         {
172             anticipationSpeed = anticipateSingle(anticipationSpeed, desiredSpeed, x0, headwayGTU);
173         }
174 
175         return anticipationSpeed;
176     }
177 
178     /**
179      * Anticipate a single leader by possibly lowering the anticipation speed.
180      * @param anticipationSpeed anticipation speed
181      * @param desiredSpeed desired speed on anticipated lane
182      * @param x0 look-ahead distance
183      * @param headwayGTU leader to anticipate
184      * @return possibly lowered anticipation speed
185      */
186     private Speed anticipateSingle(final Speed anticipationSpeed, final Speed desiredSpeed, final Length x0,
187         final AbstractHeadwayGTU headwayGTU)
188     {
189         if (headwayGTU.getSpeed().gt(anticipationSpeed) || headwayGTU.getDistance().gt(x0))
190         {
191             return anticipationSpeed;
192         }
193         Speed vSingle = Speed.interpolate(headwayGTU.getSpeed(), desiredSpeed, headwayGTU.getDistance().si / x0.si);
194         return anticipationSpeed.lt(vSingle) ? anticipationSpeed : vSingle;
195     }
196 
197     /** {@inheritDoc} */
198     @Override
199     public final String toString()
200     {
201         return "IncentiveSpeedWithCourtesy";
202     }
203 
204 }