View Javadoc
1   package org.opentrafficsim.road.gtu.lane.tactical.util;
2   
3   import java.io.Serializable;
4   
5   import org.djunits.unit.LengthUnit;
6   import org.djunits.unit.SpeedUnit;
7   import org.djunits.unit.TimeUnit;
8   import org.djunits.value.vdouble.scalar.Acceleration;
9   import org.djunits.value.vdouble.scalar.Duration;
10  import org.djunits.value.vdouble.scalar.Length;
11  import org.djunits.value.vdouble.scalar.Speed;
12  import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
13  import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException;
14  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
15  import org.opentrafficsim.road.network.speed.SpeedLimitInfo;
16  
17  /**
18   * Utility class that stores duration and end-speed for a given anticipated movement.
19   * <p>
20   * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
21   * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
22   * <p>
23   * @version $Revision$, $LastChangedDate$, by $Author$, initial version Jun 7, 2016 <br>
24   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
25   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
26   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
27   */
28  public final class AnticipationInfo implements Serializable
29  {
30  
31      /** */
32      private static final long serialVersionUID = 20160811L;
33  
34      /** Duration of movement. */
35      private final Duration duration;
36      
37      /** End speed of movement. */
38      private final Speed endSpeed;
39      
40      /**
41       * @param duration duration of movement
42       * @param endSpeed end speed of movement
43       */
44      public AnticipationInfo(final Duration duration, final Speed endSpeed)
45      {
46          this.duration = duration;
47          this.endSpeed = endSpeed;
48      }
49  
50      /**
51       * @return duration.
52       */
53      public Duration getDuration()
54      {
55          return this.duration;
56      }
57  
58      /**
59       * @return endSpeed.
60       */
61      public Speed getEndSpeed()
62      {
63          return this.endSpeed;
64      }
65      
66      /**
67       * Returns info of the anticipation assuming constant acceleration.
68       * @param distance distance to cover
69       * @param initialSpeed initial speed
70       * @param acceleration (assumed) acceleration
71       * @return duration to cover given distance with given initial speed and acceleration
72       */
73      public static AnticipationInfo anticipateMovement(final Length distance, final Speed initialSpeed,
74          final Acceleration acceleration)
75      {
76          return anticipateMovementSpeedLimited(distance, initialSpeed, acceleration, new Speed(Double.POSITIVE_INFINITY,
77              SpeedUnit.SI));
78      }
79      
80      /**
81       * Returns info of the anticipation assuming constant acceleration, without exceeding maximum speed.
82       * @param distance distance to cover
83       * @param initialSpeed initial speed
84       * @param acceleration (assumed) acceleration
85       * @param maxSpeed maximum speed
86       * @return duration to cover given distance with given initial speed and acceleration, without exceeding maximum speed
87       */
88      public static AnticipationInfo anticipateMovementSpeedLimited(final Length distance, final Speed initialSpeed,
89          final Acceleration acceleration, final Speed maxSpeed)
90      {
91          // solve constant speed movement
92          if (acceleration.eq(Acceleration.ZERO))
93          {
94              if (initialSpeed.gt(Speed.ZERO))
95              {
96                  return new AnticipationInfo(distance.divideBy(initialSpeed), initialSpeed);
97              }
98              // stand-still, so infinite
99              return new AnticipationInfo(new Duration(Double.POSITIVE_INFINITY, TimeUnit.SI), Speed.ZERO);
100         }
101         // solve parabolic movement
102         double tmp = initialSpeed.si * initialSpeed.si + 2.0 * acceleration.si * distance.si;
103         if (tmp < 0)
104         {
105             // will never cover distance due to deceleration
106             return new AnticipationInfo(new Duration(Double.POSITIVE_INFINITY, TimeUnit.SI), Speed.ZERO);
107         }
108         // parabolic solution
109         Duration d = new Duration((Math.sqrt(tmp) - initialSpeed.si) / acceleration.si, TimeUnit.SI);
110         // check max speed
111         Speed endSpeed = initialSpeed.plus(acceleration.multiplyBy(d));
112         if (endSpeed.le(maxSpeed))
113         {
114             return new AnticipationInfo(d, endSpeed);
115         }
116         // maximum speed exceeded, calculate in two steps
117         Duration d1 = maxSpeed.minus(initialSpeed).divideBy(acceleration);
118         Length x2 = new Length(distance.si - initialSpeed.si * d1.si - .5 * acceleration.si * d1.si * d1.si, LengthUnit.SI);
119         return new AnticipationInfo(d1.plus(x2.divideBy(maxSpeed)), maxSpeed);
120     }
121     
122     /**
123      * Returns info of the anticipation using free acceleration from car-following model.
124      * @param distance distance to cover
125      * @param initialSpeed initial speed
126      * @param behavioralCharacteristics behavioral characteristics of the anticipated GTU
127      * @param carFollowingModel car-following model of the anticipated GTU
128      * @param speedLimitInfo speed limit info of the anticipated GTU
129      * @param timeStep time step to use
130      * @return info regarding anticipation of movement
131      * @throws ParameterException if parameter is not defined
132      */
133     public static AnticipationInfo anticipateMovementFreeAcceleration(final Length distance, final Speed initialSpeed,
134         final BehavioralCharacteristics behavioralCharacteristics, final CarFollowingModel carFollowingModel,
135         final SpeedLimitInfo speedLimitInfo, final Duration timeStep) throws ParameterException
136     {
137         Duration out = Duration.ZERO;
138         Length xCumul = Length.ZERO;
139         Speed speed = initialSpeed;
140         while (xCumul.lt(distance))
141         {
142             Acceleration a =
143                 CarFollowingUtil.freeAcceleration(carFollowingModel, behavioralCharacteristics, speed, speedLimitInfo);
144             Length add = new Length(speed.si * timeStep.si + .5 * a.si * timeStep.si * timeStep.si, LengthUnit.SI);
145             Length remain = distance.minus(xCumul);
146             if (add.lt(remain))
147             {
148                 xCumul = xCumul.plus(add);
149                 speed = speed.plus(a.multiplyBy(timeStep));
150                 out = out.plus(timeStep);
151             }
152             else
153             {
154                 Duration timeInStep;
155                 double tmp = Math.sqrt(2 * a.si * remain.si + speed.si * speed.si) - speed.si;
156                 if (tmp < 0.000001)
157                 {
158                     // (near) constant speed
159                     timeInStep = remain.divideBy(speed);
160                 }
161                 else
162                 {
163                     timeInStep = new Duration(tmp / a.si, TimeUnit.SI);
164                     speed = speed.plus(a.multiplyBy(timeInStep));
165                 }
166                 out = out.plus(timeInStep);
167                 return new AnticipationInfo(out, speed);
168             }
169         }
170         // should not happen
171         throw new RuntimeException("Distance for anticipation of conflict movement is surpassed.");
172     }
173 
174     /** {@inheritDoc} */
175     @Override
176     public String toString()
177     {
178         return "AnticipationInfo [duration = " + this.duration + ", endSpeed = " + this.endSpeed + "]"; 
179     }
180 
181 }