View Javadoc
1   package org.opentrafficsim.road.gtu.lane.tactical.lmrs;
2   
3   import org.djunits.unit.DimensionlessUnit;
4   import org.djunits.value.vdouble.scalar.Acceleration;
5   import org.djunits.value.vdouble.scalar.Dimensionless;
6   import org.djunits.value.vdouble.scalar.Speed;
7   import org.opentrafficsim.base.parameters.ParameterException;
8   import org.opentrafficsim.base.parameters.ParameterTypeAcceleration;
9   import org.opentrafficsim.base.parameters.ParameterTypeSpeed;
10  import org.opentrafficsim.base.parameters.ParameterTypes;
11  import org.opentrafficsim.base.parameters.Parameters;
12  import org.opentrafficsim.core.gtu.Try;
13  import org.opentrafficsim.core.gtu.perception.EgoPerception;
14  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
15  import org.opentrafficsim.core.network.LateralDirectionality;
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.InfrastructurePerception;
19  import org.opentrafficsim.road.gtu.lane.perception.categories.TrafficPerception;
20  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
21  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Desire;
22  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
23  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
24  
25  /**
26   * Determines lane change desire for speed. The anticipation speed in the current and adjacent lanes are compared. The larger
27   * the difference, the larger the lane change desire. For negative differences, negative desire results. Anticipation speed
28   * involves the the most critical vehicle considered to be in a lane. Vehicles are more critical if their speed is lower, and if
29   * they are closer. The set of vehicles considered to be on a lane includes drivers on adjacent lanes of the considered lane,
30   * with a lane change desire towards the considered lane above a certain certain threshold. If such vehicles have low speeds
31   * (i.e. vehicle accelerating to merge), this may result in a courtesy lane change, or in not changing lane out of courtesy from
32   * the 2nd lane of the mainline. Vehicle on the current lane of the driver, are not considered on adjacent lanes. This would
33   * maintain a large speed difference between the lanes where all drivers do not change lane as they consider leading vehicles to
34   * be on the adjacent lane, lowering the anticipation speed on the adjacent lane. The desire for speed is reduced as
35   * acceleration is larger, preventing over-assertive lane changes as acceleration out of congestion in the adjacent lane has
36   * progressed more.<br>
37   * <br>
38   * <b>Note:</b> This incentive includes speed, and a form of courtesy. It should therefore not be combined with incentives
39   * solely for speed, or solely for courtesy.
40   * <p>
41   * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
42   * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
43   * <p>
44   * @version $Revision$, $LastChangedDate$, by $Author$, initial version Apr 13, 2016 <br>
45   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
46   */
47  public class IncentiveSpeedWithCourtesy implements VoluntaryIncentive
48  {
49  
50      /** Acceleration parameter type. */
51      protected static final ParameterTypeAcceleration A = ParameterTypes.A;
52  
53      /** Anticipation speed difference parameter type. */
54      protected static final ParameterTypeSpeed VGAIN = LmrsParameters.VGAIN;
55  
56      /** Speed threshold below which traffic is considered congested. */
57      protected static final ParameterTypeSpeed VCONG = ParameterTypes.VCONG;
58  
59      /** {@inheritDoc} */
60      @Override
61      public final Desire determineDesire(final Parameters parameters, final LanePerception perception,
62              final CarFollowingModel carFollowingModel, final Desire mandatoryDesire, final Desire voluntaryDesire)
63              throws ParameterException, OperationalPlanException
64      {
65  
66          // zero if no lane change is possible
67          InfrastructurePerception infra = perception.getPerceptionCategory(InfrastructurePerception.class);
68          TrafficPerception traffic = perception.getPerceptionCategory(TrafficPerception.class);
69          EgoPerception ego = perception.getPerceptionCategory(EgoPerception.class);
70          double leftDist = infra.getLegalLaneChangePossibility(RelativeLane.CURRENT, LateralDirectionality.LEFT).si;
71          double rightDist = infra.getLegalLaneChangePossibility(RelativeLane.CURRENT, LateralDirectionality.RIGHT).si;
72  
73          // gather some info
74          Speed vCur = traffic.getSpeed(RelativeLane.CURRENT);
75          Speed vGain = parameters.getParameter(VGAIN);
76  
77          // calculate aGain (default 1; lower as acceleration is higher than 0)
78          Dimensionless aGain;
79          /*
80           * Instead of instantaneous car-following acceleration, use current acceleration; only then is the acceleration factor
81           * consistent with possible lane change incentives pertaining to speed (which used to be only vehicles in the original
82           * LMRS, but can be any number of reasons here. E.g. traffic lights, conflicts, etc.)
83           */
84          Acceleration aCur = ego.getAcceleration();
85          
86          /*
87           * The idea to let aCur simply be the current acceleration is wrong; aCur -should- only describe the car-following 
88           * relation, as this describes a sense of sticking to a lane as the leader is getting away.
89           */
90          aCur = Try.assign(() -> perception.getGtu().getCarFollowingAcceleration(), "Could not obtain the GTU.");
91          if (aCur.si > 0)
92          {
93              Acceleration a = parameters.getParameter(A);
94              aGain = a.minus(aCur).divideBy(a);
95          }
96          else
97          {
98              aGain = new Dimensionless(1, DimensionlessUnit.SI);
99          }
100 
101         // left desire
102         double dLeft;
103         if (leftDist > 0.0 && infra.getCrossSection().contains(RelativeLane.LEFT))
104         {
105             Speed vLeft = traffic.getSpeed(RelativeLane.LEFT);
106             dLeft = aGain.si * (vLeft.si - vCur.si) / vGain.si;
107         }
108         else
109         {
110             dLeft = 0.0;
111         }
112 
113         // right desire
114         double dRight;
115         if (rightDist > 0.0 && infra.getCrossSection().contains(RelativeLane.RIGHT))
116         {
117             Speed vRight = traffic.getSpeed(RelativeLane.RIGHT);
118             if (vCur.si >= parameters.getParameter(VCONG).si)
119             {
120                 dRight = aGain.si * Math.min(vRight.si - vCur.si, 0) / vGain.si;
121             }
122             else
123             {
124                 dRight = aGain.si * (vRight.si - vCur.si) / vGain.si;
125             }
126         }
127         else
128         {
129             dRight = 0.0;
130         }
131 
132         // return desire
133         return new Desire(dLeft, dRight);
134     }
135 
136     /** {@inheritDoc} */
137     @Override
138     public final String toString()
139     {
140         return "IncentiveSpeedWithCourtesy";
141     }
142 
143 }