Initial commit
[debian/openrocket] / src / net / sf / openrocket / aerodynamics / WindSimulator.java
1 package net.sf.openrocket.aerodynamics;\r
2 \r
3 import java.util.Random;\r
4 \r
5 import net.sf.openrocket.util.MathUtil;\r
6 import net.sf.openrocket.util.PinkNoise;\r
7 \r
8 \r
9 public class WindSimulator {\r
10         \r
11         /** Source for seed numbers. */\r
12         private static final Random seedSource = new Random();\r
13 \r
14     /** Pink noise alpha parameter. */\r
15     private static final double ALPHA = 5.0/3.0;\r
16     \r
17     /** Number of poles to use in the pink noise IIR filter. */\r
18     private static final int POLES = 2;\r
19     \r
20     /** The standard deviation of the generated pink noise with the specified number of poles. */\r
21     private static final double STDDEV = 2.252;\r
22     \r
23     /** Time difference between random samples. */\r
24     private static final double DELTA_T = 0.05;\r
25 \r
26     \r
27     private double average = 0;\r
28     private double standardDeviation = 0;\r
29     \r
30     private int seed;\r
31     \r
32     private PinkNoise randomSource = null;\r
33     private double time1;\r
34     private double value1, value2;\r
35     \r
36 \r
37     /**\r
38      * Construct a new wind simulator with a random starting seed value.\r
39      */\r
40     public WindSimulator() {\r
41         synchronized(seedSource) {\r
42                 seed = seedSource.nextInt();\r
43         }\r
44     }\r
45     \r
46     \r
47     \r
48     /**\r
49      * Return the average wind speed.\r
50      * \r
51      * @return the average wind speed.\r
52      */\r
53     public double getAverage() {\r
54         return average;\r
55     }\r
56     /**\r
57      * Set the average wind speed.  This method will also modify the\r
58      * standard deviation such that the turbulence intensity remains constant.\r
59      * \r
60      * @param average the average wind speed to set\r
61      */\r
62     public void setAverage(double average) {\r
63         double intensity = getTurbulenceIntensity();\r
64         this.average = Math.max(average, 0);\r
65         setTurbulenceIntensity(intensity);\r
66     }\r
67     \r
68     \r
69     \r
70     /**\r
71      * Return the standard deviation from the average wind speed.\r
72      * \r
73      * @return the standard deviation of the wind speed\r
74      */\r
75     public double getStandardDeviation() {\r
76         return standardDeviation;\r
77     }\r
78     \r
79     /**\r
80      * Set the standard deviation of the average wind speed.\r
81      * \r
82      * @param standardDeviation the standardDeviation to set\r
83      */\r
84     public void setStandardDeviation(double standardDeviation) {\r
85         this.standardDeviation = Math.max(standardDeviation, 0);\r
86     }\r
87     \r
88     \r
89     /**\r
90      * Return the turbulence intensity (standard deviation / average).\r
91      * \r
92      * @return  the turbulence intensity\r
93      */\r
94     public double getTurbulenceIntensity() {\r
95         if (MathUtil.equals(average, 0)) {\r
96             if (MathUtil.equals(standardDeviation, 0))\r
97                 return 0;\r
98             else\r
99                 return 1000;\r
100         }\r
101         return standardDeviation / average;\r
102     }\r
103 \r
104     /**\r
105      * Set the standard deviation to match the turbulence intensity.\r
106      * \r
107      * @param intensity   the turbulence intensity\r
108      */\r
109     public void setTurbulenceIntensity(double intensity) {\r
110         setStandardDeviation(intensity * average);\r
111     }\r
112     \r
113     \r
114     \r
115     \r
116     \r
117     public int getSeed() {\r
118         return seed;\r
119     }\r
120     \r
121     public void setSeed(int seed) {\r
122         if (this.seed == seed)\r
123             return;\r
124         this.seed = seed;\r
125     }\r
126     \r
127     \r
128     \r
129     public double getWindSpeed(double time) {\r
130         if (time < 0) {\r
131                 throw new IllegalArgumentException("Requesting wind speed at t="+time);\r
132         }\r
133         \r
134         if (randomSource == null) {\r
135                 randomSource = new PinkNoise(ALPHA, POLES, new Random(seed));\r
136             time1 = 0;\r
137             value1 = randomSource.nextValue();\r
138             value2 = randomSource.nextValue();\r
139         }\r
140         \r
141         if (time < time1) {\r
142                 reset();\r
143                 return getWindSpeed(time);\r
144         }\r
145         \r
146         while (time1 + DELTA_T < time) {\r
147             value1 = value2;\r
148             value2 = randomSource.nextValue();\r
149             time1 += DELTA_T;\r
150         }\r
151         \r
152         double a = (time - time1)/DELTA_T;\r
153 \r
154         \r
155         return average + (value1 * (1-a) + value2 * a) * standardDeviation / STDDEV;\r
156     }\r
157 \r
158     \r
159     private void reset() {\r
160         randomSource = null;\r
161     }\r
162     \r
163     \r
164     public static void main(String[] str) {\r
165         \r
166         WindSimulator sim = new WindSimulator();\r
167         \r
168         sim.setAverage(2);\r
169         sim.setStandardDeviation(0.5);\r
170         \r
171         for (int i=0; i < 10000; i++) {\r
172             double t = 0.01*i;\r
173             double v = sim.getWindSpeed(t);\r
174             System.out.printf("%d.%03d  %d.%03d\n", (int)t,((int)(t*1000))%1000, (int)v, ((int)(v*1000))%1000);\r
175 //            if ((i % 5) == 0)\r
176 //                System.out.println(" ***");\r
177 //            else\r
178 //                System.out.println("");\r
179         }\r
180         \r
181     }\r
182     \r
183 }\r