Updates for 0.9.3
[debian/openrocket] / src / net / sf / openrocket / rocketcomponent / ThrustCurveMotor.java
1 package net.sf.openrocket.rocketcomponent;
2
3 import net.sf.openrocket.util.Coordinate;
4 import net.sf.openrocket.util.MathUtil;
5
6 /**
7  * A class of motors specified by a fixed thrust curve.  This is the most
8  * accurate for solid rocket motors.
9  * 
10  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
11  */
12 public class ThrustCurveMotor extends Motor {
13         
14         public static final double MAX_THRUST = 10e6;
15
16         private final double[] time;
17         private final double[] thrust;
18         private final Coordinate[] cg;
19         
20         private final double totalTime;
21         private final double maxThrust;
22         
23
24         /**
25          * Sole constructor.  Sets all the properties of the motor.
26          * 
27          * @param manufacturer  the manufacturer of the motor.
28          * @param designation   the designation of the motor.
29          * @param description   extra description of the motor.
30          * @param diameter      diameter of the motor.
31          * @param length        length of the motor.
32          * @param time          the time points for the thrust curve.
33          * @param thrust        thrust at the time points.
34          * @param cg            cg at the time points.
35          */
36         public ThrustCurveMotor(String manufacturer, String designation, String description, 
37                         Motor.Type type, double[] delays, double diameter, double length,
38                         double[] time, double[] thrust, Coordinate[] cg) {
39                 super(manufacturer, designation, description, type, delays, diameter, length);
40
41                 double max = -1;
42
43                 // Check argument validity
44                 if ((time.length != thrust.length) || (time.length != cg.length)) {
45                         throw new IllegalArgumentException("Array lengths do not match, " +
46                                         "time:" + time.length + " thrust:" + thrust.length +
47                                         " cg:" + cg.length);
48                 }
49                 if (time.length < 2) {
50                         throw new IllegalArgumentException("Too short thrust-curve, length=" + 
51                                         time.length);
52                 }
53                 for (int i=0; i < time.length-1; i++) {
54                         if (time[i+1] < time[i]) {
55                                 throw new IllegalArgumentException("Time goes backwards, " +
56                                                 "time[" + i + "]=" + time[i] + " " +
57                                                 "time[" + (i+1) + "]=" + time[i+1]);
58                         }
59                 }
60                 if (!MathUtil.equals(time[0], 0)) {
61                         throw new IllegalArgumentException("Curve starts at time " + time[0]);
62                 }
63                 if (!MathUtil.equals(thrust[0], 0)) {
64                         throw new IllegalArgumentException("Curve starts at thrust " + thrust[0]);
65                 }
66                 if (!MathUtil.equals(thrust[thrust.length-1], 0)) {
67                         throw new IllegalArgumentException("Curve ends at thrust " + 
68                                         thrust[thrust.length-1]);
69                 }
70                 for (double t: thrust) {
71                         if (t < 0) {
72                                 throw new IllegalArgumentException("Negative thrust.");
73                         }
74                         if (t > MAX_THRUST || Double.isNaN(t)) {
75                                 throw new IllegalArgumentException("Invalid thrust " + t);
76                         }
77                         if (t > max)
78                                 max = t;
79                 }
80                 for (Coordinate c: cg) {
81                         if (c.isNaN()) {
82                                 throw new IllegalArgumentException("Invalid CG " + c);
83                         }
84                         if (c.x < 0 || c.x > length) {
85                                 throw new IllegalArgumentException("Invalid CG position " + c.x);
86                         }
87                         if (c.weight < 0) {
88                                 throw new IllegalArgumentException("Negative mass " + c.weight);
89                         }
90                 }
91
92                 this.maxThrust = max;
93                 this.time = time.clone();
94                 this.thrust = thrust.clone();
95                 this.cg = cg.clone();
96                 this.totalTime = time[time.length-1];
97         }
98
99
100         @Override
101         public double getTotalTime() {
102                 return totalTime;
103         }
104
105         @Override
106         public double getMaxThrust() {
107                 return maxThrust;
108         }
109         
110         @Override
111         public double getThrust(double t) {
112                 if ((t < 0) || (t > totalTime))
113                         return 0;
114
115                 for (int i=0; i < time.length-1; i++) {
116                         if ((t >= time[i]) && (t <= time[i+1])) {
117                                 double delta = time[i+1] - time[i];
118                                 if (delta < 0.0001) {
119                                         return thrust[i];
120                                 }
121                                 t = t - time[i];
122                                 return thrust[i] * (1 - t/delta) + thrust[i+1] * (t/delta);
123                         }
124                 }
125                 assert false : "Should not be reached.";
126                 return 0;
127         }
128
129
130         @Override
131         public Coordinate getCG(double t) {
132                 if (t <= 0)
133                         return cg[0];
134                 if (t >= totalTime)
135                         return cg[cg.length-1];
136                 
137                 for (int i=0; i < time.length-1; i++) {
138                         if ((t >= time[i]) && (t <= time[i+1])) {
139                                 double delta = time[i+1] - time[i];
140                                 t = t - time[i];
141                                 return cg[i].multiply(1 - t/delta).add(cg[i+1].multiply(t/delta));
142                         }
143                 }
144                 assert false : "Should not be reached.";
145                 return cg[cg.length-1];
146         }
147
148         
149         public double[] getTimePoints() {
150                 return time.clone();
151         }
152         
153         public double[] getThrustPoints() {
154                 return thrust.clone();
155         }
156         
157         public Coordinate[] getCGPoints() {
158                 return cg.clone();
159         }
160         
161 }