Merge pull request #519 from JoePfeiffer/fix-516

fix issue 516
This commit is contained in:
Wes Cravens 2019-05-29 10:25:33 -05:00 committed by GitHub
commit b5cde10824
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 168 additions and 95 deletions

View File

@ -179,7 +179,14 @@ public abstract class AbstractMotorLoader implements MotorLoader {
return; return;
// Start // Start
if (!MathUtil.equals(time.get(0), 0) || !MathUtil.equals(thrust.get(0), 0)) { // If there is no datapoint at t=0, put one there (this is the
// normal case for a RASP file). If there is a nonzero thrust
// at time 0 it's an error, but not one that calls for not
// using the file. We *don't* want to also put a 0-thrust
// point at time 0 in that case, as that will cause the
// simulation to throw an exception just like in the
// commented-out case below.
if (!MathUtil.equals(time.get(0), 0)) {
time.add(0, 0.0); time.add(0, 0.0);
thrust.add(0, 0.0); thrust.add(0, 0.0);
for (List l : lists) { for (List l : lists) {
@ -188,16 +195,32 @@ public abstract class AbstractMotorLoader implements MotorLoader {
} }
} }
// End // Not-uncommon issue at start of thrust curves: two points
int n = time.size() - 1; // for t=0, one with thrust zero and one non-zero. We'll throw
if (!MathUtil.equals(thrust.get(n), 0)) { // out the 0-thrust point and go on.
time.add(time.get(n)); if (MathUtil.equals(time.get(0), 0) && MathUtil.equals(time.get(1), 0)) {
thrust.add(0.0); time.remove(0);
for (List l : lists) { thrust.remove(0);
Object o = l.get(n);
l.add(o);
}
} }
// End
// Ah, no, we don't want to do this (I'm leaving the dead code
// in case there's a temptation to put it back in). This ends
// up putting the new 0-thrust point at the same time as the
// previous last datapoint, which will cause
// ThrustCurveMotor.getAverageThrust() to fail when it tries
// to interpolate (the exception is actually thrown by
// MathUtil.map())
//
// int n = time.size() - 1;
// if (!MathUtil.equals(thrust.get(n), 0)) {
// time.add(time.get(n));
// thrust.add(0.0);
// for (List l : lists) {
// Object o = l.get(n);
// l.add(o);
// }
// }
} }
} }

View File

@ -166,22 +166,30 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
throw new IllegalArgumentException("Too short thrust-curve, length=" + motor.time.length); throw new IllegalArgumentException("Too short thrust-curve, length=" + motor.time.length);
} }
for (int i = 0; i < motor.time.length - 1; i++) { for (int i = 0; i < motor.time.length - 1; i++) {
if (motor.time[i + 1] < motor.time[i]) { if (motor.time[i + 1] <= motor.time[i]) {
throw new IllegalArgumentException("Time goes backwards, " + throw new IllegalArgumentException("Time stalls or goes backwards, " +
"time[" + i + "]=" + motor.time[i] + " " + "time[" + i + "]=" + motor.time[i] + " " +
"time[" + (i + 1) + "]=" + motor.time[i + 1]); "time[" + (i + 1) + "]=" + motor.time[i + 1] +
", thrust=(" + motor.thrust[i] + ", " + motor.thrust[i+1] + ")");
} }
} }
if (!MathUtil.equals(motor.time[0], 0)) { if (!MathUtil.equals(motor.time[0], 0)) {
throw new IllegalArgumentException("Curve starts at time " + motor.time[0]); throw new IllegalArgumentException("Curve starts at time " + motor.time[0]);
} }
if (!MathUtil.equals(motor.thrust[0], 0)) {
throw new IllegalArgumentException("Curve starts at thrust " + motor.thrust[0]); // these conditions actually are error, but quite a few of
} // the files on thrustcurvemotor.org have one or the
if (!MathUtil.equals(motor.thrust[motor.thrust.length - 1], 0)) { // other of them, and they make less of a difference to
throw new IllegalArgumentException("Curve ends at thrust " + // the simulation result than the normal variation between motors.
motor.thrust[motor.thrust.length - 1]); // if (!MathUtil.equals(motor.thrust[0], 0)) {
} // throw new IllegalArgumentException("Curve starts at thrust " + motor.thrust[0]);
// }
//
// if (!MathUtil.equals(motor.thrust[motor.thrust.length - 1], 0)) {
// throw new IllegalArgumentException("Curve ends at thrust " +
// motor.thrust[motor.thrust.length - 1]);
//}
for (double t : motor.thrust) { for (double t : motor.thrust) {
if (t < 0) { if (t < 0) {
throw new IllegalArgumentException("Negative thrust."); throw new IllegalArgumentException("Negative thrust.");
@ -630,45 +638,51 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
maxThrust = t; maxThrust = t;
} }
// Burn start time // Burn start time
double thrustLimit = maxThrust * MARGINAL_THRUST; double thrustLimit = maxThrust * MARGINAL_THRUST;
double burnStart, burnEnd; double burnStart, burnEnd;
int pos; if (thrust[0] >= thrustLimit)
for (pos = 1; pos < thrust.length; pos++) { burnStart = time[0];
if (thrust[pos] >= thrustLimit) else {
break; int startPos;
for (startPos = 1; startPos < thrust.length; startPos++) {
if (thrust[startPos] >= thrustLimit)
break;
}
if (startPos >= thrust.length) {
throw new BugException("Could not compute burn start time, maxThrust=" + maxThrust +
" limit=" + thrustLimit + " thrust=" + Arrays.toString(thrust));
}
if (MathUtil.equals(thrust[startPos - 1], thrust[startPos])) {
// For safety
burnStart = (time[startPos - 1] + time[startPos]) / 2;
} else {
burnStart = MathUtil.map(thrustLimit, thrust[startPos - 1], thrust[startPos], time[startPos - 1], time[startPos]);
}
} }
if (pos >= thrust.length) {
throw new BugException("Could not compute burn start time, maxThrust=" + maxThrust +
" limit=" + thrustLimit + " thrust=" + Arrays.toString(thrust));
}
if (MathUtil.equals(thrust[pos - 1], thrust[pos])) {
// For safety
burnStart = (time[pos - 1] + time[pos]) / 2;
} else {
burnStart = MathUtil.map(thrustLimit, thrust[pos - 1], thrust[pos], time[pos - 1], time[pos]);
}
// Burn end time // Burn end time
for (pos = thrust.length - 2; pos >= 0; pos--) { if (thrust[thrust.length-1] >= thrustLimit)
if (thrust[pos] >= thrustLimit) burnEnd = time[time.length-1];
break; else {
int endPos;
for (endPos = thrust.length - 2; endPos >= 0; endPos--) {
if (thrust[endPos] >= thrustLimit)
break;
}
if (endPos < 0) {
throw new BugException("Could not compute burn end time, maxThrust=" + maxThrust +
" limit=" + thrustLimit + " thrust=" + Arrays.toString(thrust));
}
if (MathUtil.equals(thrust[endPos], thrust[endPos + 1])) {
// For safety
burnEnd = (time[endPos] + time[endPos + 1]) / 2;
} else {
burnEnd = MathUtil.map(thrustLimit, thrust[endPos], thrust[endPos + 1],
time[endPos], time[endPos + 1]);
}
} }
if (pos < 0) {
throw new BugException("Could not compute burn end time, maxThrust=" + maxThrust +
" limit=" + thrustLimit + " thrust=" + Arrays.toString(thrust));
}
if (MathUtil.equals(thrust[pos], thrust[pos + 1])) {
// For safety
burnEnd = (time[pos] + time[pos + 1]) / 2;
} else {
burnEnd = MathUtil.map(thrustLimit, thrust[pos], thrust[pos + 1],
time[pos], time[pos + 1]);
}
// Burn time // Burn time
burnTimeEstimate = Math.max(burnEnd - burnStart, 0); burnTimeEstimate = Math.max(burnEnd - burnStart, 0);
@ -677,12 +691,12 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
// Total impulse and average thrust // Total impulse and average thrust
totalImpulse = 0; totalImpulse = 0;
averageThrust = 0; averageThrust = 0;
int impulsePos;
for (pos = 0; pos < time.length - 1; pos++) { for (impulsePos = 0; impulsePos < time.length - 1; impulsePos++) {
double t0 = time[pos]; double t0 = time[impulsePos];
double t1 = time[pos + 1]; double t1 = time[impulsePos + 1];
double f0 = thrust[pos]; double f0 = thrust[impulsePos];
double f1 = thrust[pos + 1]; double f1 = thrust[impulsePos + 1];
totalImpulse += (t1 - t0) * (f0 + f1) / 2; totalImpulse += (t1 - t0) * (f0 + f1) / 2;

View File

@ -57,6 +57,8 @@ public class DownloadResponseParser implements ElementHandler {
response.add(motorBurnFile); response.add(motorBurnFile);
} else if (motor_id_tag.equals(element)) { } else if (motor_id_tag.equals(element)) {
motorBurnFile.setMotorId(Integer.parseInt(content)); motorBurnFile.setMotorId(Integer.parseInt(content));
} else if (simfile_id_tag.equals(element)) {
motorBurnFile.setSimfileId(Integer.parseInt(content));
} else if (format_tag.equals(element)) { } else if (format_tag.equals(element)) {
motorBurnFile.setFiletype(content); motorBurnFile.setFiletype(content);
} else if (data_tag.equals(element)) { } else if (data_tag.equals(element)) {

View File

@ -11,8 +11,10 @@ import net.sf.openrocket.motor.ThrustCurveMotor;
public class MotorBurnFile { public class MotorBurnFile {
private Integer motorId; private Integer motorId;
private Integer simfileId;
private String filetype; private String filetype;
private ThrustCurveMotor.Builder thrustCurveMotor; private ThrustCurveMotor.Builder thrustCurveMotor;
private String data;
public void init() { public void init() {
this.motorId = null; this.motorId = null;
@ -29,8 +31,9 @@ public class MotorBurnFile {
return clone; return clone;
} }
public void decodeFile(String data) throws IOException { public void decodeFile(String _data) throws IOException {
data = Base64Decoder.decodeData(data); _data = Base64Decoder.decodeData(_data);
data = _data;
try { try {
if (SupportedFileTypes.RASP_FORMAT.equals(filetype)) { if (SupportedFileTypes.RASP_FORMAT.equals(filetype)) {
RASPMotorLoader loader = new RASPMotorLoader(); RASPMotorLoader loader = new RASPMotorLoader();
@ -47,19 +50,33 @@ public class MotorBurnFile {
} }
/** /**
* @return the motor_id * @return the motor id
*/ */
public Integer getMotorId() { public Integer getMotorId() {
return motorId; return motorId;
} }
/** /**
* @param motor_id the motor_id to set * @param motorId the motor id to set
*/ */
public void setMotorId(Integer motorId) { public void setMotorId(Integer motorId) {
this.motorId = motorId; this.motorId = motorId;
} }
/**
* @return the simfile id
*/
public Integer getSimfileId() {
return simfileId;
}
/**
* @param simfileId the simfileId to set
*/
public void setSimfileId(Integer simfileId) {
this.simfileId = simfileId;
}
/** /**
* @return the filetype * @return the filetype
*/ */
@ -81,4 +98,11 @@ public class MotorBurnFile {
return thrustCurveMotor; return thrustCurveMotor;
} }
/**
* @return the file contents
*/
public String getContents() {
return data;
}
} }

View File

@ -115,37 +115,46 @@ public class SerializeThrustcurveMotors {
System.out.println(message); System.out.println(message);
List<MotorBurnFile> b = getThrustCurvesForMotorId(mi.getMotor_id()); List<MotorBurnFile> b = getThrustCurvesForMotorId(mi.getMotor_id());
for (MotorBurnFile burnFile : b) { for (MotorBurnFile burnFile : b) {
try {
ThrustCurveMotor.Builder builder = burnFile.getThrustCurveMotor();
if (builder == null) {
continue;
}
if (mi.getTot_mass_g() != null) {
builder.setInitialMass(mi.getTot_mass_g() / 1000.0);
}
if (mi.getProp_mass_g() != null) {
// builder.setPropellantMass(mi.getProp_mass_g() / 1000.0);
}
ThrustCurveMotor.Builder builder = burnFile.getThrustCurveMotor(); builder.setCaseInfo(mi.getCase_info());
if (builder == null) { builder.setPropellantInfo(mi.getProp_info());
continue; builder.setDiameter(mi.getDiameter() / 1000.0);
} builder.setLength(mi.getLength() / 1000.0);
if (mi.getTot_mass_g() != null) { builder.setMotorType(type);
builder.setInitialMass(mi.getTot_mass_g() / 1000.0);
}
if (mi.getProp_mass_g() != null) {
// builder.setPropellantMass(mi.getProp_mass_g() / 1000.0);
}
builder.setCaseInfo(mi.getCase_info()); if ("OOP".equals(mi.getAvailiability())) {
builder.setPropellantInfo(mi.getProp_info()); builder.setDesignation(mi.getDesignation());
builder.setDiameter(mi.getDiameter() / 1000.0); builder.setAvailablity(false);
builder.setLength(mi.getLength() / 1000.0); } else if (mi.getDesignation().startsWith("Micro")) {
builder.setMotorType(type); builder.setDesignation(mi.getDesignation());
} else {
builder.setDesignation(mi.getCommon_name());
}
if ("OOP".equals(mi.getAvailiability())) { allMotors.add(builder.build());
builder.setDesignation(mi.getDesignation()); } catch (IllegalArgumentException e) {
builder.setAvailablity(false); System.out.println("\tError in simFile " + burnFile.getSimfileId() + ": " + e.getMessage() + " (continuing)");
} else if (mi.getDesignation().startsWith("Micro")) { try {
builder.setDesignation(mi.getDesignation()); FileOutputStream out = new FileOutputStream(("simfile-" + burnFile.getSimfileId()).toString());
} else { out.write(burnFile.getContents().getBytes());
builder.setDesignation(mi.getCommon_name()); out.close();
} catch (IOException i) {
System.out.println("unable to write bad file: " + i.getMessage());
}
} }
allMotors.add(builder.build());
} }
System.out.println("\t curves: " + b.size()); System.out.println("\t curves: " + b.size());
@ -160,12 +169,12 @@ public class SerializeThrustcurveMotors {
try { try {
b.addAll(ThrustCurveAPI.downloadData(motorId, "RockSim")); b.addAll(ThrustCurveAPI.downloadData(motorId, "RockSim"));
} catch (Exception ex) { } catch (Exception ex) {
System.out.println("\tError downloading RockSim"); System.out.println("\tError downloading RockSim for motorID=" + motorId);
} }
try { try {
b.addAll(ThrustCurveAPI.downloadData(motorId, "RASP")); b.addAll(ThrustCurveAPI.downloadData(motorId, "RASP"));
} catch (Exception ex) { } catch (Exception ex) {
System.out.println("\tError downloading RASP"); System.out.println("\tError downloading RASP for motorID=" + motorId);
} }
return b; return b;
} }

1
openrocket.log Normal file
View File

@ -0,0 +1 @@
Error: Unable to access jarfile OpenRocket.jar