View Javadoc
1   package org.opentrafficsim.road.gtu.lane.tactical.toledo;
2   
3   import org.djunits.unit.AccelerationUnit;
4   import org.djunits.unit.DurationUnit;
5   import org.djunits.unit.LengthUnit;
6   import org.djunits.unit.SpeedUnit;
7   import org.djunits.value.vdouble.scalar.Acceleration;
8   import org.djunits.value.vdouble.scalar.Duration;
9   import org.djunits.value.vdouble.scalar.Length;
10  import org.djunits.value.vdouble.scalar.Speed;
11  import org.opentrafficsim.base.parameters.ParameterException;
12  import org.opentrafficsim.base.parameters.ParameterTypeDouble;
13  import org.opentrafficsim.base.parameters.ParameterTypeDuration;
14  import org.opentrafficsim.base.parameters.ParameterTypeSpeed;
15  import org.opentrafficsim.base.parameters.Parameters;
16  import org.opentrafficsim.base.parameters.constraint.ConstraintInterface;
17  import org.opentrafficsim.road.gtu.lane.perception.PerceptionIterable;
18  import org.opentrafficsim.road.gtu.lane.perception.headway.Headway;
19  import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractCarFollowingModel;
20  import org.opentrafficsim.road.gtu.lane.tactical.following.DesiredHeadwayModel;
21  import org.opentrafficsim.road.gtu.lane.tactical.following.DesiredSpeedModel;
22  import org.opentrafficsim.road.network.speed.SpeedLimitInfo;
23  
24  /**
25   * <p>
26   * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
27   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
28   * </p>
29   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
30   * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
31   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
32   */
33  public class ToledoCarFollowing extends AbstractCarFollowingModel
34  {
35  
36      /** */
37      public static final ParameterTypeSpeed CDS = new ParameterTypeSpeed("C_DS", "Constant in desired speed.",
38              new Speed(17.636, SpeedUnit.SI), ConstraintInterface.POSITIVE);
39  
40      /** */
41      public static final ParameterTypeSpeed BETADS = new ParameterTypeSpeed("BETA_DS", "Reduction of desired speed for trucks.",
42              new Speed(-1.458, SpeedUnit.SI), ConstraintInterface.NEGATIVE);
43  
44      /** */
45      public static final ParameterTypeSpeed ALPHADS =
46              new ParameterTypeSpeed("ALPHA_DS", "Factor on error term of desired speed.", new Speed(-0.105, SpeedUnit.SI));
47  
48      /** */
49      public static final ParameterTypeDuration HSTAR =
50              new ParameterTypeDuration("h*", "Desired time headway.", new Duration(2.579, DurationUnit.SI));
51  
52      /** */
53      public static final ParameterTypeDouble LAMBDAFF =
54              new ParameterTypeDouble("Lambda_ff", "Free flow acceleration sensitivity.", 0.0881, ConstraintInterface.POSITIVE);
55  
56      /** */
57      public static final ParameterTypeDouble SIGMAFF =
58              new ParameterTypeDouble("Sigma_ff", "Free flow acceleration standard deviation.", Math.exp(0.169));
59  
60      /** */
61      public static final ParameterTypeDouble CCFACC = new ParameterTypeDouble("C_CF_ACC",
62              "Constant for car following acceleration.", 0.0355, ConstraintInterface.POSITIVE);
63  
64      /** */
65      public static final ParameterTypeDouble BETAACC =
66              new ParameterTypeDouble("BETA_ACC", "Power on speed for acceleration.", 0.291, ConstraintInterface.POSITIVE);
67  
68      /** */
69      public static final ParameterTypeDouble GAMMAACC = new ParameterTypeDouble("GAMMA_ACC",
70              "Power on distance headway for acceleration.", -0.166, ConstraintInterface.NEGATIVE);
71  
72      /** */
73      public static final ParameterTypeDouble RHOACC =
74              new ParameterTypeDouble("RHO_ACC", "Power on density for acceleration.", 0.550, ConstraintInterface.POSITIVE);
75  
76      /** */
77      public static final ParameterTypeDouble LAMBDAACC = new ParameterTypeDouble("LAMBDA_ACC",
78              "Power on speed difference for acceleration.", 0.520, ConstraintInterface.POSITIVE);
79  
80      /** */
81      public static final ParameterTypeDouble SIGMAACC =
82              new ParameterTypeDouble("Sigma_acc", "Car-following acceleration standard deviation.", Math.exp(0.126));
83  
84      /** */
85      public static final ParameterTypeDouble CCFDEC = new ParameterTypeDouble("C_CF_DEC",
86              "Constant for car following deceleration.", -0.860, ConstraintInterface.NEGATIVE);
87  
88      /** */
89      public static final ParameterTypeDouble GAMMADEC = new ParameterTypeDouble("GAMMA_DEC",
90              "Power on distance headway for deceleration.", -0.565, ConstraintInterface.NEGATIVE);
91  
92      /** */
93      public static final ParameterTypeDouble RHODEC =
94              new ParameterTypeDouble("RHO_DEC", "Power on density for deceleration.", 0.143, ConstraintInterface.POSITIVE);
95  
96      /** */
97      public static final ParameterTypeDouble LAMBDADEC = new ParameterTypeDouble("LAMBDA_DEC",
98              "Power on speed difference for deceleration.", 0.834, ConstraintInterface.POSITIVE);
99  
100     /** */
101     public static final ParameterTypeDouble SIGMADEC =
102             new ParameterTypeDouble("Sigma_DEC", "Car-following deceleration standard deviation.", Math.exp(0.156));
103 
104     /** Toledo desired headway model. */
105     private static final DesiredHeadwayModel HEADWAY = new DesiredHeadwayModel()
106     {
107         @Override
108         public Length desiredHeadway(final Parameters parameters, final Speed speed) throws ParameterException
109         {
110             return parameters.getParameter(HSTAR).times(speed);
111         }
112     };
113 
114     /** Toledo desired speed model. */
115     private static final DesiredSpeedModel DESIRED_SPEED = new DesiredSpeedModel()
116     {
117         @Override
118         public Speed desiredSpeed(final Parameters parameters, final SpeedLimitInfo speedInfo) throws ParameterException
119         {
120             return parameters.getParameter(CDS).plus(parameters.getParameter(BETADS)).plus(
121                     parameters.getParameter(ALPHADS).times(parameters.getParameter(ToledoLaneChangeParameters.ERROR_TERM)));
122         }
123     };
124 
125     /**
126      * Constructor using Toledo models for desired headway ans speed.
127      */
128     public ToledoCarFollowing()
129     {
130         super(HEADWAY, DESIRED_SPEED);
131     }
132 
133     @Override
134     protected final Acceleration followingAcceleration(final Parameters parameters, final Speed speed, final Speed desiredSpeed,
135             final Length desiredHeadway, final PerceptionIterable<? extends Headway> leaders) throws ParameterException
136     {
137         if (leaders.isEmpty() || leaders.first().getDistance().gt(desiredHeadway))
138         {
139             // free
140             double eff = Toledo.RANDOM.nextGaussian() * parameters.getParameter(SIGMAFF) * parameters.getParameter(SIGMAFF);
141             return new Acceleration(parameters.getParameter(LAMBDAFF) * (desiredSpeed.si - speed.si) + eff,
142                     AccelerationUnit.SI);
143         }
144         // TODO speed difference with reaction time
145         if (leaders.first().getSpeed().ge(speed))
146         {
147             // accelerate
148             double eCfAcc =
149                     Toledo.RANDOM.nextGaussian() * parameters.getParameter(SIGMAACC) * parameters.getParameter(SIGMAACC);
150             // {@formatter:off}
151             return new Acceleration(
152                 parameters.getParameter(CCFACC) 
153                     * Math.pow(speed.si, parameters.getParameter(BETAACC))
154                     * Math.pow(leaders.first().getDistance().si, parameters.getParameter(GAMMAACC))
155                     * Math.pow(getDensity(leaders), parameters.getParameter(RHOACC))
156                     * Math.pow(leaders.first().getSpeed().si - speed.si, parameters.getParameter(LAMBDAACC))
157                     + eCfAcc,
158                 AccelerationUnit.SI);
159             // {@formatter:on}
160         }
161         // decelerate
162         double eCfDec = Toledo.RANDOM.nextGaussian() * parameters.getParameter(SIGMADEC) * parameters.getParameter(SIGMADEC);
163         // {@formatter:off}
164         return new Acceleration(
165             parameters.getParameter(CCFDEC) 
166                 * Math.pow(leaders.first().getDistance().si, parameters.getParameter(GAMMADEC))
167                 * Math.pow(getDensity(leaders), parameters.getParameter(RHODEC))
168                 * Math.pow(speed.si - leaders.first().getSpeed().si, parameters.getParameter(LAMBDADEC))
169                 + eCfDec,
170             AccelerationUnit.SI);
171         // {@formatter:on}
172     }
173 
174     @Override
175     public final String getName()
176     {
177         return "ToledoCFM";
178     }
179 
180     @Override
181     public final String getLongName()
182     {
183         return "Toledo car-following model";
184     }
185 
186     /**
187      * Returns the density based on the leaders in veh/km.
188      * @param leaders leading vehicles
189      * @return density based on the leaders in veh/km
190      */
191     private double getDensity(final PerceptionIterable<? extends Headway> leaders)
192     {
193         if (leaders.isEmpty())
194         {
195             return 0;
196         }
197         Headway last = null;
198         int n = 0;
199         for (Headway next : leaders)
200         {
201             n++;
202             last = next;
203         }
204         return last.getDistance().getInUnit(LengthUnit.KILOMETER) / n;
205     }
206 
207 }