View Javadoc

1   /*
2    * @(#)DecelerationProfile.java Jul 5, 2004
3    * 
4    * Copyright (c) 2003, 2004 Delft University of Technology Jaffalaan 5, 2628 BX
5    * Delft, the Netherlands All rights reserved.
6    * 
7    * This software is proprietary information of Delft University of Technology
8    * The code is published under the General Public License
9    */
10  
11  package nl.tudelft.simulation.traffic.vehicle;
12  
13  import java.util.ArrayList;
14  
15  import nl.tudelft.simulation.jstats.ode.DifferentialEquation;
16  import nl.tudelft.simulation.jstats.ode.integrators.NumericalIntegrator;
17  
18  /***
19   * <br>
20   * (c) copyright 2003-2004 <a href="http://www.simulation.tudelft.nl">Delft
21   * University of Technology </a>, the Netherlands. <br>
22   * See for project information <a href="http://www.simulation.tudelft.nl">
23   * www.simulation.tudelft.nl </a> <br>
24   * License of use: <a href="http://www.gnu.org/copyleft/gpl.html">General
25   * Public License (GPL) </a>, no warranty <br>
26   * 
27   * @version Jul 5, 2004 <br>
28   * @author <a
29   * href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">Alexander
30   * Verbraeck </a>
31   */
32  public class AccelerationProfile
33  {
34      /*** the speed dependent acceleration / deceleration parameters */
35      private ArrayList accdecList = new ArrayList();
36  
37      /*** the maximum speed that we have in the arraylist */
38      private double maxSpeed = 0.0;
39  
40      /*** the dirty bit */
41      private boolean initialized;
42  
43      /*** the profile */
44      private Profile profile;
45      
46      /*** print table for debugging */
47      protected static boolean debug = false;
48  
49      /***
50       * create a new acceleration / deceleration profile
51       * 
52       * @param maxSpeed
53       */
54      public AccelerationProfile(final double maxSpeed)
55      {
56          super();
57          this.initialized = false;
58          this.maxSpeed = maxSpeed;
59      }
60  
61      /***
62       * Set the acceleration / deceleration for current speed HIGHER than speed.
63       * Add the points in increasing speed. Sorting is not (yet) done
64       * automatically.
65       * 
66       * @param speed the speed above which accdec is used
67       * @param accdec the acceleration (positive) or deceleration (negative)
68       */
69      public void setAccelerationFromSpeed(final double speed, final double accdec)
70      {
71          this.accdecList.add(new AccDecPoint(speed, accdec));
72          this.initialized = false;
73      }
74  
75      /***
76       * Gets the acceleration / deceleration for a given speed
77       * 
78       * @param speed
79       * @return
80       */
81      public double getAcceleration(final double speed)
82      {
83          double accdec = 0.0;
84          for (int i = 0; i < this.accdecList.size(); i++)
85          {
86              double adspeed = ((AccDecPoint) this.accdecList.get(i)).getSpeed();
87              if (speed >= adspeed)
88              {
89                  accdec = ((AccDecPoint) this.accdecList.get(i)).getAccDec();
90              } else
91              {
92                  return accdec;
93              }
94          }
95          return accdec;
96      }
97  
98      /***
99       *  
100      */
101     public void initializeProfile()
102     {
103         this.profile = new Profile(this, this.maxSpeed);
104         this.initialized = true;
105     }
106 
107     /***
108      * @param initialSpeed
109      * @param endSpeed
110      * @return the time to brake from the initialSpeed to the endSpeed
111      */
112     public double getAccelerationTime(final double initialSpeed,
113             final double endSpeed)
114     {
115         if (!this.initialized)
116             initializeProfile();
117         return this.profile.getAccelerationTime(initialSpeed, endSpeed);
118     }
119 
120     /***
121      * @param initialSpeed
122      * @param endSpeed
123      * @return the distance to brake from the initialSpeed to the endSpeed
124      */
125     public double getAccelerationDistance(final double initialSpeed,
126             final double endSpeed)
127     {
128         if (!this.initialized)
129             initializeProfile();
130         return this.profile.getAccelerationDistance(initialSpeed, endSpeed);
131     }
132 
133     /***
134      * Inner class to store the acc/dec points at certain speeds <br>
135      * (c) <br>
136      * (c) copyright 2003-2004 <a href="http://www.simulation.tudelft.nl">Delft
137      * University of Technology </a>, the Netherlands. <br>
138      * See for project information <a href="http://www.simulation.tudelft.nl">
139      * www.simulation.tudelft.nl </a> <br>
140      * License of use: <a href="http://www.gnu.org/copyleft/gpl.html">General
141      * Public License (GPL) </a>, no warranty <br>
142      * 
143      * @version Jul 5, 2004 <br>
144      * @author <a
145      * href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">Alexander
146      * Verbraeck </a>
147      */
148     private class AccDecPoint
149     {
150         /*** the speed from which the acceleration/deceleration holds */
151         private double speed;
152 
153         /*** the acceleration/deceleration */
154         private double accdec;
155 
156         /***
157          * @param speed
158          * @param accdec
159          */
160         public AccDecPoint(final double speed, final double accdec)
161         {
162             this.speed = speed;
163             this.accdec = accdec;
164         }
165 
166         /***
167          * @return Returns the acceleration/deceleration.
168          */
169         public double getAccDec()
170         {
171             return this.accdec;
172         }
173 
174         /***
175          * @return Returns the speed.
176          */
177         public double getSpeed()
178         {
179             return this.speed;
180         }
181     }
182     /***
183      * Inner class to store the acceleration or deceleration profile based on
184      * the speed and the acceleration / decelation panel. The class uses a
185      * differential equation to make the calculations. <br>
186      * (c) copyright 2003-2004 <a href="http://www.simulation.tudelft.nl">Delft
187      * University of Technology </a>, the Netherlands. <br>
188      * See for project information <a href="http://www.simulation.tudelft.nl">
189      * www.simulation.tudelft.nl </a> <br>
190      * License of use: <a href="http://www.gnu.org/copyleft/gpl.html">General
191      * Public License (GPL) </a>, no warranty <br>
192      * 
193      * @version Jul 6, 2004 <br>
194      * @author <a
195      * href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">Alexander
196      * Verbraeck </a>
197      */
198     private class Profile
199     {
200         /*** the acceleration / deceleration profile */
201         private AccelerationProfile owner;
202 
203         /*** the list of speed to brake time */
204         private double[] accTime;
205 
206         /*** the list of speed to brake distance */
207         private double[] accDistance;
208 
209         /*** the resolution of the points */
210         private double resolution = 0.1;
211 
212         /*** the maximum speed that we have in the arraylist */
213         private double maxSpeed = 0.0;
214 
215         /*** the number of points in our profile */
216         private int points;
217 
218         /***
219          * @param owner
220          * @param maxSpeed
221          */
222         public Profile(final AccelerationProfile owner, final double maxSpeed)
223         {
224             this.maxSpeed = maxSpeed;
225             this.points = (int) (this.maxSpeed / this.resolution) + 1;
226             this.owner = owner;
227             this.accTime = new double[this.points];
228             this.accDistance = new double[this.points];
229             // instantiate the driving differential equation, and
230             // calculate the speed and driven distance.
231             Driving driving = new Driving(this.owner, 0.001,
232                     NumericalIntegrator.RUNGEKUTTA4);
233             double speed = 0.0;
234             double x = 0.0;
235             double time = 0.0;
236             while (speed <= this.maxSpeed)
237             {
238                 driving.initialize(time, new double[]{speed, x});
239                 time = time + 0.001;
240                 double[] vx = driving.y(time);
241                 speed = vx[0];
242                 double dx = vx[1] - x;
243                 x = vx[1];
244                 int i = getPoint(speed);
245                 this.accTime[i] += 0.001;
246                 this.accDistance[i] += dx;
247             }
248             for (int i = 0; i < this.points - 1; i++)
249             {
250                 this.accTime[i + 1] += this.accTime[i];
251                 this.accDistance[i + 1] += this.accDistance[i];
252             }
253             if (AccelerationProfile.debug)
254             {
255             for (int i = 0; i < this.points; i++)
256             {
257                 System.out.println("v=" + getSpeed(i) + ", [t,x]=["
258                         + this.accTime[i] + "," + this.accDistance[i] + "]");
259             }
260             }
261         }
262 
263         /***
264          * @param speed
265          * @return
266          */
267         private int getPoint(final double speed)
268         {
269             int point = (int) ((speed / this.maxSpeed) * this.points);
270             return Math.min(this.points - 1, Math.max(point, 0));
271         }
272 
273         /***
274          * @param point
275          * @return
276          */
277         private double getSpeed(final int point)
278         {
279             return this.resolution * point;
280         }
281 
282         /***
283          * @param initialSpeed
284          * @param endSpeed
285          * @return the time to accelerate from the initialSpeed to the endSpeed
286          */
287         public double getAccelerationTime(final double initialSpeed,
288                 final double endSpeed)
289         {
290             return this.accTime[getPoint(endSpeed)]
291                     - this.accTime[getPoint(initialSpeed)];
292         }
293 
294         /***
295          * @param initialSpeed
296          * @param endSpeed
297          * @return the distance to accelerate from the initialSpeed to the
298          * endSpeed
299          */
300         public double getAccelerationDistance(final double initialSpeed,
301                 final double endSpeed)
302         {
303             return this.accDistance[getPoint(endSpeed)]
304                     - this.accDistance[getPoint(initialSpeed)];
305         }
306 
307         /***
308          * The differential equation for braking <br>
309          * (c) copyright 2003-2004 <a
310          * href="http://www.simulation.tudelft.nl">Delft University of
311          * Technology </a>, the Netherlands. <br>
312          * See for project information <a
313          * href="http://www.simulation.tudelft.nl"> www.simulation.tudelft.nl
314          * </a> <br>
315          * License of use: <a
316          * href="http://www.gnu.org/copyleft/gpl.html">General Public License
317          * (GPL) </a>, no warranty <br>
318          * 
319          * @version Jul 6, 2004 <br>
320          * @author <a
321          * href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">Alexander
322          * Verbraeck </a>
323          */
324         private class Driving extends DifferentialEquation
325         {
326             /*** the acceleration / deceleration profile */
327             private AccelerationProfile owner;
328 
329             /***
330              * @param owner
331              * @param timeStep
332              */
333             public Driving(final AccelerationProfile owner,
334                     final double timeStep)
335             {
336                 super(timeStep);
337                 this.owner = owner;
338             }
339 
340             /***
341              * @param owner
342              * @param timeStep
343              * @param integrator
344              */
345             public Driving(final AccelerationProfile owner,
346                     final double timeStep, final NumericalIntegrator integrator)
347             {
348                 super(timeStep, integrator);
349                 this.owner = owner;
350             }
351 
352             /***
353              * @param owner
354              * @param timeStep
355              * @param integrationMethod
356              */
357             public Driving(final AccelerationProfile owner,
358                     final double timeStep, final short integrationMethod)
359             {
360                 super(timeStep, integrationMethod);
361                 this.owner = owner;
362             }
363 
364             /***
365              * @see nl.tudelft.simulation.jstats.ode.DifferentialEquationInterface#dy(double,
366              * double[])
367              */
368             public double[] dy(double x, double[] y)
369             {
370                 // y[0] = v, y[1] = x
371                 double[] dy = new double[2];
372                 dy[0] = this.owner.getAcceleration(y[0]);
373                 dy[1] = y[0];
374                 return dy;
375             }
376         }
377     }
378 
379     /***
380      * @param args
381      */
382     public static void main(String[] args)
383     {
384         try
385         {
386             AccelerationProfile dp = new AccelerationProfile(14.0); // m/s
387             dp.setAccelerationFromSpeed(0.0, 1.0);
388             dp.initializeProfile();
389             System.out.println("Acceleration distance from 0.0 to 14.0 = "
390                     + dp.getAccelerationDistance(0.0, 14.0));
391             System.out.println("Acceleration distance from 7.0 to 14.0 = "
392                     + dp.getAccelerationDistance(7.0, 14.0));
393             System.out.println("Acceleration distance from  0.0 to 7.0 = "
394                     + dp.getAccelerationDistance(0.0, 7.0));
395             System.out.println("Acceleration time from 0.0 to 14.0 = "
396                     + dp.getAccelerationTime(0.0, 14.0));
397             System.out.println("Acceleration time from 7.0 to 14.0 = "
398                     + dp.getAccelerationTime(7.0, 14.0));
399             System.out.println("Acceleration time from  0.0 to 7.0 = "
400                     + dp.getAccelerationTime(0.0, 7.0));
401         } catch (Exception e)
402         {
403             e.printStackTrace();
404         }
405     }
406 }