1 package net.sf.openrocket.file.motor;
3 import java.io.BufferedReader;
4 import java.io.IOException;
6 import java.nio.charset.Charset;
7 import java.util.ArrayList;
8 import java.util.Collections;
11 import net.sf.openrocket.motor.Manufacturer;
12 import net.sf.openrocket.motor.Motor;
13 import net.sf.openrocket.motor.MotorDigest;
14 import net.sf.openrocket.motor.MotorDigest.DataType;
15 import net.sf.openrocket.motor.ThrustCurveMotor;
16 import net.sf.openrocket.util.Coordinate;
18 public class RASPMotorLoader extends AbstractMotorLoader {
20 public static final String CHARSET_NAME = "ISO-8859-1";
22 public static final Charset CHARSET = Charset.forName(CHARSET_NAME);
28 protected Charset getDefaultCharset() {
34 * Load a <code>Motor</code> from a RASP file specified by the <code>Reader</code>.
35 * The <code>Reader</code> is responsible for using the correct charset.
37 * The CG is assumed to be located at the center of the motor casing and the mass
38 * is calculated from the thrust curve by assuming a constant exhaust velocity.
40 * @param reader the source of the file.
41 * @return a list of the {@link Motor} objects defined in the file.
42 * @throws IOException if an I/O error occurs or if the file format is illegal.
45 public List<Motor> load(Reader reader, String filename) throws IOException {
46 List<Motor> motors = new ArrayList<Motor>();
47 BufferedReader in = new BufferedReader(reader);
49 String manufacturer = "";
50 String designation = "";
55 ArrayList<Double> delays = null;
57 List<Double> time = new ArrayList<Double>();
58 List<Double> thrust = new ArrayList<Double>();
68 main: while (line != null) { // Until EOF
75 delays = new ArrayList<Double>();
82 while (line.length() == 0 || line.charAt(0) == ';') {
83 if (line.length() > 0) {
84 comment += line.substring(1).trim() + "\n";
90 comment = comment.trim();
92 // Parse header line, example:
93 // F32 24 124 5-10-15-P .0377 .0695 RV
94 // desig diam len delays prop.w tot.w manufacturer
96 if (pieces.length != 7) {
97 throw new IOException("Illegal file format.");
100 designation = pieces[0];
101 diameter = Double.parseDouble(pieces[1]) / 1000.0;
102 length = Double.parseDouble(pieces[2]) / 1000.0;
104 if (pieces[3].equalsIgnoreCase("None")) {
107 buf = split(pieces[3], "[-,]+");
108 for (int i = 0; i < buf.length; i++) {
109 if (buf[i].equalsIgnoreCase("P") ||
110 buf[i].equalsIgnoreCase("plugged")) {
111 delays.add(Motor.PLUGGED);
113 // Many RASP files have "100" as an only delay
114 double d = Double.parseDouble(buf[i]);
119 Collections.sort(delays);
122 propW = Double.parseDouble(pieces[4]);
123 totalW = Double.parseDouble(pieces[5]);
124 manufacturer = pieces[6];
126 if (propW > totalW) {
127 throw new IOException("Propellant weight exceeds total weight in " +
128 "RASP file " + filename);
132 for (line = in.readLine(); (line != null) && (line.length() == 0 || line.charAt(0) != ';'); line = in.readLine()) {
135 if (buf.length == 0) {
137 } else if (buf.length == 2) {
139 time.add(Double.parseDouble(buf[0]));
140 thrust.add(Double.parseDouble(buf[1]));
143 throw new IOException("Illegal file format.");
147 // Comment of EOF encountered, marks the start of the next motor
148 if (time.size() < 2) {
149 throw new IOException("Illegal file format, too short thrust-curve.");
151 double[] delayArray = new double[delays.size()];
152 for (int i = 0; i < delays.size(); i++) {
153 delayArray[i] = delays.get(i);
155 motors.add(createRASPMotor(manufacturer, designation, comment,
156 length, diameter, delayArray, propW, totalW, time, thrust));
159 } catch (NumberFormatException e) {
161 throw new IOException("Illegal file format.");
170 * Create a motor from RASP file data.
171 * @throws IOException if the data is illegal for a thrust curve
173 private static Motor createRASPMotor(String manufacturer, String designation,
174 String comment, double length, double diameter, double[] delays,
175 double propW, double totalW, List<Double> time, List<Double> thrust)
178 // Add zero time/thrust if necessary
179 sortLists(time, thrust);
180 finalizeThrustCurve(time, thrust);
181 List<Double> mass = calculateMass(time, thrust, totalW, propW);
183 double[] timeArray = new double[time.size()];
184 double[] thrustArray = new double[time.size()];
185 Coordinate[] cgArray = new Coordinate[time.size()];
186 for (int i = 0; i < time.size(); i++) {
187 timeArray[i] = time.get(i);
188 thrustArray[i] = thrust.get(i);
189 cgArray[i] = new Coordinate(length / 2, 0, 0, mass.get(i));
192 designation = removeDelay(designation);
194 // Create the motor digest from data available in RASP files
195 MotorDigest motorDigest = new MotorDigest();
196 motorDigest.update(DataType.TIME_ARRAY, timeArray);
197 motorDigest.update(DataType.MASS_SPECIFIC, totalW, totalW - propW);
198 motorDigest.update(DataType.FORCE_PER_TIME, thrustArray);
199 final String digest = motorDigest.getDigest();
203 Manufacturer m = Manufacturer.getManufacturer(manufacturer);
204 return new ThrustCurveMotor(m, designation, comment, m.getMotorType(),
205 delays, diameter, length, timeArray, thrustArray, cgArray, digest);
207 } catch (IllegalArgumentException e) {
209 // Bad data read from file.
210 throw new IOException("Illegal file format.", e);