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 DecelerationProfile
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 DecelerationProfile(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 setDecelerationFromSpeed(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 getDeceleration(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 getBrakeTime(final double initialSpeed, final double endSpeed)
113     {
114         if (!this.initialized)
115             initializeProfile();
116         return this.profile.getBrakeTime(initialSpeed, endSpeed);
117     }
118 
119     /***
120      * @param initialSpeed
121      * @param endSpeed
122      * @return the distance to brake from the initialSpeed to the endSpeed
123      */
124     public double getBrakeDistance(final double initialSpeed,
125             final double endSpeed)
126     {
127         if (!this.initialized)
128             initializeProfile();
129         return this.profile.getBrakeDistance(initialSpeed, endSpeed);
130     }
131 
132     /***
133      * Inner class to store the acc/dec points at certain speeds <br>
134      * (c) <br>
135      * (c) copyright 2003-2004 <a href="http://www.simulation.tudelft.nl">Delft
136      * University of Technology </a>, the Netherlands. <br>
137      * See for project information <a href="http://www.simulation.tudelft.nl">
138      * www.simulation.tudelft.nl </a> <br>
139      * License of use: <a href="http://www.gnu.org/copyleft/gpl.html">General
140      * Public License (GPL) </a>, no warranty <br>
141      * 
142      * @version Jul 5, 2004 <br>
143      * @author <a
144      * href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">Alexander
145      * Verbraeck </a>
146      */
147     private class AccDecPoint
148     {
149         /*** the speed from which the acceleration/deceleration holds */
150         private double speed;
151 
152         /*** the acceleration/deceleration */
153         private double accdec;
154 
155         /***
156          * @param speed
157          * @param accdec
158          */
159         public AccDecPoint(final double speed, final double accdec)
160         {
161             this.speed = speed;
162             this.accdec = accdec;
163         }
164 
165         /***
166          * @return Returns the acceleration/deceleration.
167          */
168         public double getAccDec()
169         {
170             return this.accdec;
171         }
172 
173         /***
174          * @return Returns the speed.
175          */
176         public double getSpeed()
177         {
178             return this.speed;
179         }
180     }
181     /***
182      * Inner class to store the acceleration or deceleration profile based on
183      * the speed and the acceleration / decelation panel. The class uses a
184      * differential equation to make the calculations. <br>
185      * (c) copyright 2003-2004 <a href="http://www.simulation.tudelft.nl">Delft
186      * University of Technology </a>, the Netherlands. <br>
187      * See for project information <a href="http://www.simulation.tudelft.nl">
188      * www.simulation.tudelft.nl </a> <br>
189      * License of use: <a href="http://www.gnu.org/copyleft/gpl.html">General
190      * Public License (GPL) </a>, no warranty <br>
191      * 
192      * @version Jul 6, 2004 <br>
193      * @author <a
194      * href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">Alexander
195      * Verbraeck </a>
196      */
197     private class Profile
198     {
199         /*** the acceleration / deceleration profile */
200         private DecelerationProfile owner;
201 
202         /*** the list of speed to brake time */
203         private double[] brakeTime;
204 
205         /*** the list of speed to brake distance */
206         private double[] brakeDistance;
207 
208         /*** the resolution of the points */
209         private double resolution = 0.1;
210 
211         /*** the maximum speed that we have in the arraylist */
212         private double maxSpeed = 0.0;
213 
214         /*** the number of points in our profile */
215         private int points;
216 
217         /***
218          * @param owner
219          * @param maxSpeed
220          */
221         public Profile(final DecelerationProfile owner, final double maxSpeed)
222         {
223             this.maxSpeed = maxSpeed;
224             this.points = (int) (this.maxSpeed / this.resolution) + 1;
225             this.owner = owner;
226             this.brakeTime = new double[this.points];
227             this.brakeDistance = new double[this.points];
228             // instantiate the driving differential equation, and
229             // calculate the speed and driven distance.
230             Driving driving = new Driving(this.owner, 0.001,
231                     NumericalIntegrator.RUNGEKUTTA4);
232             double speed = this.maxSpeed;
233             double x = 0.0;
234             double time = 0.0;
235             while (speed > 0)
236             {
237                 driving.initialize(time, new double[]{speed, x});
238                 time = time + 0.001;
239                 double[] vx = driving.y(time);
240                 speed = vx[0];
241                 double dx = vx[1] - x;
242                 x = vx[1];
243                 int i = getPoint(speed);
244                 this.brakeTime[i] += 0.001;
245                 this.brakeDistance[i] += dx;
246             }
247             for (int i = 0; i < this.points - 1; i++)
248             {
249                 this.brakeTime[i + 1] += this.brakeTime[i];
250                 this.brakeDistance[i + 1] += this.brakeDistance[i];
251             }
252             if (DecelerationProfile.debug)
253             {
254                 for (int i = 0; i < this.points; i++)
255                 {
256                     System.out.println("v=" + getSpeed(i) + ", [t,x]=["
257                             + this.brakeTime[i] + "," + this.brakeDistance[i]
258                             + "]");
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 brake from the initialSpeed to the endSpeed
286          */
287         public double getBrakeTime(final double initialSpeed,
288                 final double endSpeed)
289         {
290             return this.brakeTime[getPoint(initialSpeed)]
291                     - this.brakeTime[getPoint(endSpeed)];
292         }
293 
294         /***
295          * @param initialSpeed
296          * @param endSpeed
297          * @return the distance to brake from the initialSpeed to the endSpeed
298          */
299         public double getBrakeDistance(final double initialSpeed,
300                 final double endSpeed)
301         {
302             return this.brakeDistance[getPoint(initialSpeed)]
303                     - this.brakeDistance[getPoint(endSpeed)];
304         }
305 
306         /***
307          * The differential equation for braking <br>
308          * (c) copyright 2003-2004 <a
309          * href="http://www.simulation.tudelft.nl">Delft University of
310          * Technology </a>, the Netherlands. <br>
311          * See for project information <a
312          * href="http://www.simulation.tudelft.nl"> www.simulation.tudelft.nl
313          * </a> <br>
314          * License of use: <a
315          * href="http://www.gnu.org/copyleft/gpl.html">General Public License
316          * (GPL) </a>, no warranty <br>
317          * 
318          * @version Jul 6, 2004 <br>
319          * @author <a
320          * href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">Alexander
321          * Verbraeck </a>
322          */
323         private class Driving extends DifferentialEquation
324         {
325             /*** the acceleration / deceleration profile */
326             private DecelerationProfile owner;
327 
328             /***
329              * @param owner
330              * @param timeStep
331              */
332             public Driving(final DecelerationProfile owner,
333                     final double timeStep)
334             {
335                 super(timeStep);
336                 this.owner = owner;
337             }
338 
339             /***
340              * @param owner
341              * @param timeStep
342              * @param integrator
343              */
344             public Driving(final DecelerationProfile owner,
345                     final double timeStep, final NumericalIntegrator integrator)
346             {
347                 super(timeStep, integrator);
348                 this.owner = owner;
349             }
350 
351             /***
352              * @param owner
353              * @param timeStep
354              * @param integrationMethod
355              */
356             public Driving(final DecelerationProfile owner,
357                     final double timeStep, final short integrationMethod)
358             {
359                 super(timeStep, integrationMethod);
360                 this.owner = owner;
361             }
362 
363             /***
364              * @see nl.tudelft.simulation.jstats.ode.DifferentialEquationInterface#dy(double,
365              * double[])
366              */
367             public double[] dy(double x, double[] y)
368             {
369                 // y[0] = v, y[1] = x
370                 double[] dy = new double[2];
371                 dy[0] = this.owner.getDeceleration(y[0]);
372                 dy[1] = y[0];
373                 return dy;
374             }
375 
376             /***
377              * @see nl.tudelft.simulation.jstats.ode.DifferentialEquationInterface#y(double)
378              */
379             public double[] y(double x)
380             {
381                 double[] y = super.y(x);
382                 y[0] = Math.max(0.0, y[0]);
383                 return y;
384             }
385         }
386     }
387 
388     /***
389      * @param args
390      */
391     public static void main(String[] args)
392     {
393         try
394         {
395             DecelerationProfile dp = new DecelerationProfile(14.0); // m/s
396             dp.setDecelerationFromSpeed(0.0, -1.0);
397             dp.initializeProfile();
398             System.out.println("Brake distance from 14.0 to 0.0 = "
399                     + dp.getBrakeDistance(14.0, 0.0));
400             System.out.println("Brake distance from 14.0 to 7.0 = "
401                     + dp.getBrakeDistance(14.0, 7.0));
402             System.out.println("Brake distance from  7.0 to 0.0 = "
403                     + dp.getBrakeDistance(7.0, 0.0));
404             System.out.println("Brake time from 14.0 to 0.0 = "
405                     + dp.getBrakeTime(14.0, 0.0));
406             System.out.println("Brake time from 14.0 to 7.0 = "
407                     + dp.getBrakeTime(14.0, 7.0));
408             System.out.println("Brake time from  7.0 to 0.0 = "
409                     + dp.getBrakeTime(7.0, 0.0));
410         } catch (Exception e)
411         {
412             e.printStackTrace();
413         }
414     }
415 }