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          if (distance.lt(Length.ZERO))
92          {
93              return new AnticipationInfo(Duration.ZERO, initialSpeed);
94          }
95          // solve constant speed movement
96          if (acceleration.eq(Acceleration.ZERO))
97          {
98              if (initialSpeed.gt(Speed.ZERO))
99              {
100                 return new AnticipationInfo(distance.divideBy(initialSpeed), initialSpeed);
101             }
102             // stand-still, so infinite
103             return new AnticipationInfo(new Duration(Double.POSITIVE_INFINITY, TimeUnit.SI), Speed.ZERO);
104         }
105         // solve parabolic movement
106         double tmp = initialSpeed.si * initialSpeed.si + 2.0 * acceleration.si * distance.si;
107         if (tmp < 0)
108         {
109             // will never cover distance due to deceleration
110             return new AnticipationInfo(new Duration(Double.POSITIVE_INFINITY, TimeUnit.SI), Speed.ZERO);
111         }
112         // parabolic solution
113         Duration d = new Duration((Math.sqrt(tmp) - initialSpeed.si) / acceleration.si, TimeUnit.SI);
114         // check max speed
115         Speed endSpeed = initialSpeed.plus(acceleration.multiplyBy(d));
116         if (endSpeed.le(maxSpeed))
117         {
118             return new AnticipationInfo(d, endSpeed);
119         }
120         // maximum speed exceeded, calculate in two steps
121         Duration d1 = maxSpeed.minus(initialSpeed).divideBy(acceleration);
122         Length x2 = new Length(distance.si - initialSpeed.si * d1.si - .5 * acceleration.si * d1.si * d1.si, LengthUnit.SI);
123         return new AnticipationInfo(d1.plus(x2.divideBy(maxSpeed)), maxSpeed);
124     }
125     
126     /**
127      * Returns info of the anticipation using free acceleration from car-following model.
128      * @param distance distance to cover
129      * @param initialSpeed initial speed
130      * @param behavioralCharacteristics behavioral characteristics of the anticipated GTU
131      * @param carFollowingModel car-following model of the anticipated GTU
132      * @param speedLimitInfo speed limit info of the anticipated GTU
133      * @param timeStep time step to use
134      * @return info regarding anticipation of movement
135      * @throws ParameterException if parameter is not defined
136      */
137     public static AnticipationInfo anticipateMovementFreeAcceleration(final Length distance, final Speed initialSpeed,
138         final BehavioralCharacteristics behavioralCharacteristics, final CarFollowingModel carFollowingModel,
139         final SpeedLimitInfo speedLimitInfo, final Duration timeStep) throws ParameterException
140     {
141         if (distance.lt(Length.ZERO))
142         {
143             return new AnticipationInfo(Duration.ZERO, initialSpeed);
144         }
145         Duration out = Duration.ZERO;
146         if (distance.lt(Length.ZERO))
147         {
148             return new AnticipationInfo(out, initialSpeed);
149         }
150         Length xCumul = Length.ZERO;
151         Speed speed = initialSpeed;
152         while (xCumul.lt(distance))
153         {
154             Acceleration a =
155                 CarFollowingUtil.freeAcceleration(carFollowingModel, behavioralCharacteristics, speed, speedLimitInfo);
156             Length add = new Length(speed.si * timeStep.si + .5 * a.si * timeStep.si * timeStep.si, LengthUnit.SI);
157             Length remain = distance.minus(xCumul);
158             if (add.lt(remain))
159             {
160                 xCumul = xCumul.plus(add);
161                 speed = speed.plus(a.multiplyBy(timeStep));
162                 out = out.plus(timeStep);
163             }
164             else
165             {
166                 Duration timeInStep;
167                 double tmp = Math.sqrt(2 * a.si * remain.si + speed.si * speed.si) - speed.si;
168                 if (tmp < 0.000001)
169                 {
170                     // (near) constant speed
171                     timeInStep = remain.divideBy(speed);
172                 }
173                 else
174                 {
175                     timeInStep = new Duration(tmp / a.si, TimeUnit.SI);
176                     speed = speed.plus(a.multiplyBy(timeInStep));
177                 }
178                 out = out.plus(timeInStep);
179                 return new AnticipationInfo(out, speed);
180             }
181         }
182         // should not happen
183         throw new RuntimeException("Distance for anticipation of conflict movement is surpassed.");
184     }
185 
186     /** {@inheritDoc} */
187     @Override
188     public String toString()
189     {
190         return "AnticipationInfo [duration = " + this.duration + ", endSpeed = " + this.endSpeed + "]"; 
191     }
192 
193 }