View Javadoc
1   package org.opentrafficsim.road.gtu.lane.tactical.lmrs;
2   
3   import org.djunits.value.vdouble.scalar.Length;
4   import org.djunits.value.vdouble.scalar.Speed;
5   import org.djutils.exceptions.Try;
6   import org.opentrafficsim.base.parameters.ParameterException;
7   import org.opentrafficsim.base.parameters.ParameterTypeDouble;
8   import org.opentrafficsim.base.parameters.ParameterTypeLength;
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.perception.EgoPerception;
13  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
14  import org.opentrafficsim.core.network.LateralDirectionality;
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.PerceptionCollectable;
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.neighbors.NeighborsPerception;
21  import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGtu;
22  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
23  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Desire;
24  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
25  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Tailgating;
26  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
27  
28  /**
29   * Lane change incentive based on social pressure. Drivers may refrain from changing left to not hinder faster traffic, or
30   * drivers may change right to get out of the way. When drivers are on the left lane, this is considered 'overtaking', and
31   * related to this the desired speed could be increased by using {@code SocioDesiredSpeedModel}.
32   * <p>
33   * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
34   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
35   * </p>
36   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
37   * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
38   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
39   */
40  // TODO keep left or right rules
41  public class IncentiveSocioSpeed implements VoluntaryIncentive
42  {
43  
44      /** Social pressure applied to the leader. */
45      protected static final ParameterTypeDouble RHO = Tailgating.RHO;
46  
47      /** Hierarchy parameter. */
48      protected static final ParameterTypeDouble SOCIO = LmrsParameters.SOCIO;
49  
50      /** Speed threshold below which traffic is considered congested. */
51      protected static final ParameterTypeSpeed VCONG = ParameterTypes.VCONG;
52  
53      /** Vgain parameter; ego-speed sensitivity. */
54      protected static final ParameterTypeSpeed VGAIN = LmrsParameters.VGAIN;
55  
56      /** Look-ahead distance. */
57      protected static final ParameterTypeLength LOOKAHEAD = ParameterTypes.LOOKAHEAD;
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          double dLeft = 0;
66          double dRight = 0;
67          Speed vCong = parameters.getParameter(VCONG);
68          Speed ownSpeed = perception.getPerceptionCategoryOrNull(EgoPerception.class).getSpeed();
69          if (ownSpeed.gt(vCong))
70          {
71              double sigma = parameters.getParameter(SOCIO);
72              NeighborsPerception neighbors = perception.getPerceptionCategory(NeighborsPerception.class);
73              InfrastructurePerception infra = perception.getPerceptionCategory(InfrastructurePerception.class);
74              boolean leftLane = infra.getLegalLaneChangePossibility(RelativeLane.CURRENT, LateralDirectionality.LEFT).si > 0.0;
75              boolean rightLane = infra.getLegalLaneChangePossibility(RelativeLane.CURRENT, LateralDirectionality.RIGHT).si > 0.0;
76              // change right to get out of the way
77              if (rightLane && mandatoryDesire.right() >= 0.0)
78              {
79                  PerceptionCollectable<HeadwayGtu, LaneBasedGtu> followers = neighbors.getFollowers(RelativeLane.CURRENT);
80                  if (!followers.isEmpty())
81                  {
82                      double rho = parameters.getParameter(RHO);
83                      HeadwayGtu follower = followers.first();
84                      double rhoFollower = follower.getParameters().getParameter(RHO);
85                      if (rhoFollower * sigma > rho)
86                      {
87                          dRight = rhoFollower * sigma;
88                      }
89                  }
90              }
91              // stay right to keep out of the way
92              if (leftLane && mandatoryDesire.left() <= 0.0)
93              {
94                  PerceptionCollectable<HeadwayGtu, LaneBasedGtu> followers = neighbors.getFollowers(RelativeLane.LEFT);
95                  if (followers != null && !followers.isEmpty())
96                  {
97                      double rho;
98                      PerceptionCollectable<HeadwayGtu, LaneBasedGtu> leaders = neighbors.getLeaders(RelativeLane.LEFT);
99                      if (leaders != null && !leaders.isEmpty())
100                     {
101                         HeadwayGtu leader = leaders.first();
102                         Speed vDes = Try.assign(() -> perception.getGtu().getDesiredSpeed(),
103                                 "Could not obtain GTU from perception.");
104                         Speed vGain = parameters.getParameter(VGAIN);
105                         Length x0 = parameters.getParameter(LOOKAHEAD);
106                         rho = Tailgating.socialPressure(ownSpeed, vCong, vDes, leader.getSpeed(), vGain, leader.getDistance(),
107                                 x0);
108                     }
109                     else
110                     {
111                         rho = 0.0;
112                     }
113                     HeadwayGtu follower = followers.first();
114                     Speed vGainFollower = follower.getParameters().getParameter(VGAIN);
115                     Length x0Follower = follower.getParameters().getParameter(LOOKAHEAD);
116                     double rhoFollower = Tailgating.socialPressure(follower.getSpeed(), vCong, follower.getDesiredSpeed(),
117                             ownSpeed, vGainFollower, follower.getDistance(), x0Follower);
118                     if (rhoFollower * sigma > rho)
119                     {
120                         dLeft = -rhoFollower * sigma;
121                     }
122                 }
123             }
124         }
125         return new Desire(dLeft, dRight);
126     }
127 
128     /** {@inheritDoc} */
129     @Override
130     public final String toString()
131     {
132         return "IncentiveSocioSpeed";
133     }
134 
135 }