1 package net.sf.openrocket.motor;
3 import net.sf.openrocket.util.Coordinate;
4 import net.sf.openrocket.util.MathUtil;
7 * A class of motors specified by a fixed thrust curve. This is the most
8 * accurate for solid rocket motors.
10 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
12 public class ThrustCurveMotor extends Motor {
14 public static final double MAX_THRUST = 10e6;
16 private final double[] time;
17 private final double[] thrust;
18 private final Coordinate[] cg;
20 private final double totalTime;
21 private final double maxThrust;
25 * Sole constructor. Sets all the properties of the motor.
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.
36 public ThrustCurveMotor(Manufacturer manufacturer, String designation, String description,
37 Motor.Type type, double[] delays, double diameter, double length,
38 double[] time, double[] thrust, Coordinate[] cg, String digest) {
39 super(manufacturer, designation, description, type, delays, diameter, length, digest);
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 +
49 if (time.length < 2) {
50 throw new IllegalArgumentException("Too short thrust-curve, length=" +
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]);
60 if (!MathUtil.equals(time[0], 0)) {
61 throw new IllegalArgumentException("Curve starts at time " + time[0]);
63 if (!MathUtil.equals(thrust[0], 0)) {
64 throw new IllegalArgumentException("Curve starts at thrust " + thrust[0]);
66 if (!MathUtil.equals(thrust[thrust.length-1], 0)) {
67 throw new IllegalArgumentException("Curve ends at thrust " +
68 thrust[thrust.length-1]);
70 for (double t: thrust) {
72 throw new IllegalArgumentException("Negative thrust.");
74 if (t > MAX_THRUST || Double.isNaN(t)) {
75 throw new IllegalArgumentException("Invalid thrust " + t);
80 for (Coordinate c: cg) {
82 throw new IllegalArgumentException("Invalid CG " + c);
84 if (c.x < 0 || c.x > length) {
85 throw new IllegalArgumentException("Invalid CG position " + c.x);
88 throw new IllegalArgumentException("Negative mass " + c.weight);
93 this.time = time.clone();
94 this.thrust = thrust.clone();
96 this.totalTime = time[time.length-1];
101 public double getTotalTime() {
106 public double getMaxThrust() {
111 public double getThrust(double t) {
112 if ((t < 0) || (t > totalTime))
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) {
122 return thrust[i] * (1 - t/delta) + thrust[i+1] * (t/delta);
125 assert false : "Should not be reached.";
131 public Coordinate getCG(double t) {
135 return cg[cg.length-1];
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];
141 return cg[i].multiply(1 - t/delta).add(cg[i+1].multiply(t/delta));
144 assert false : "Should not be reached.";
145 return cg[cg.length-1];
149 public double[] getTimePoints() {
153 public double[] getThrustPoints() {
154 return thrust.clone();
157 public Coordinate[] getCGPoints() {