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://tudelft.nl/staff/p.knoppers-1">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     /** {@inheritDoc} */
134     @Override
135     protected final Acceleration followingAcceleration(final Parameters parameters, final Speed speed, final Speed desiredSpeed,
136             final Length desiredHeadway, final PerceptionIterable<? extends Headway> leaders) throws ParameterException
137     {
138         if (leaders.isEmpty() || leaders.first().getDistance().gt(desiredHeadway))
139         {
140             // free
141             double eff = Toledo.RANDOM.nextGaussian() * parameters.getParameter(SIGMAFF) * parameters.getParameter(SIGMAFF);
142             return new Acceleration(parameters.getParameter(LAMBDAFF) * (desiredSpeed.si - speed.si) + eff,
143                     AccelerationUnit.SI);
144         }
145         // TODO speed difference with reaction time
146         if (leaders.first().getSpeed().ge(speed))
147         {
148             // accelerate
149             double eCfAcc =
150                     Toledo.RANDOM.nextGaussian() * parameters.getParameter(SIGMAACC) * parameters.getParameter(SIGMAACC);
151             // {@formatter:off}
152             return new Acceleration(
153                 parameters.getParameter(CCFACC) 
154                     * Math.pow(speed.si, parameters.getParameter(BETAACC))
155                     * Math.pow(leaders.first().getDistance().si, parameters.getParameter(GAMMAACC))
156                     * Math.pow(getDensity(leaders), parameters.getParameter(RHOACC))
157                     * Math.pow(leaders.first().getSpeed().si - speed.si, parameters.getParameter(LAMBDAACC))
158                     + eCfAcc,
159                 AccelerationUnit.SI);
160             // {@formatter:on}
161         }
162         // decelerate
163         double eCfDec = Toledo.RANDOM.nextGaussian() * parameters.getParameter(SIGMADEC) * parameters.getParameter(SIGMADEC);
164         // {@formatter:off}
165         return new Acceleration(
166             parameters.getParameter(CCFDEC) 
167                 * Math.pow(leaders.first().getDistance().si, parameters.getParameter(GAMMADEC))
168                 * Math.pow(getDensity(leaders), parameters.getParameter(RHODEC))
169                 * Math.pow(speed.si - leaders.first().getSpeed().si, parameters.getParameter(LAMBDADEC))
170                 + eCfDec,
171             AccelerationUnit.SI);
172         // {@formatter:on}
173     }
174 
175     /** {@inheritDoc} */
176     @Override
177     public final String getName()
178     {
179         return "ToledoCFM";
180     }
181 
182     /** {@inheritDoc} */
183     @Override
184     public final String getLongName()
185     {
186         return "Toledo car-following model";
187     }
188 
189     /**
190      * Returns the density based on the leaders in veh/km.
191      * @param leaders PerceptionIterable&lt;? extends Headway&gt;; leading vehicles
192      * @return density based on the leaders in veh/km
193      */
194     private double getDensity(final PerceptionIterable<? extends Headway> leaders)
195     {
196         if (leaders.isEmpty())
197         {
198             return 0;
199         }
200         Headway last = null;
201         int n = 0;
202         for (Headway next : leaders)
203         {
204             n++;
205             last = next;
206         }
207         return last.getDistance().getInUnit(LengthUnit.KILOMETER) / n;
208     }
209 
210 }