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;
// 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);
thrust.add(0, 0.0);
for (List l : lists) {
@ -188,16 +195,32 @@ public abstract class AbstractMotorLoader implements MotorLoader {
}
}
// End
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);
}
// Not-uncommon issue at start of thrust curves: two points
// for t=0, one with thrust zero and one non-zero. We'll throw
// out the 0-thrust point and go on.
if (MathUtil.equals(time.get(0), 0) && MathUtil.equals(time.get(1), 0)) {
time.remove(0);
thrust.remove(0);
}
// 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);
}
for (int i = 0; i < motor.time.length - 1; i++) {
if (motor.time[i + 1] < motor.time[i]) {
throw new IllegalArgumentException("Time goes backwards, " +
if (motor.time[i + 1] <= motor.time[i]) {
throw new IllegalArgumentException("Time stalls or goes backwards, " +
"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)) {
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]);
}
if (!MathUtil.equals(motor.thrust[motor.thrust.length - 1], 0)) {
throw new IllegalArgumentException("Curve ends at thrust " +
motor.thrust[motor.thrust.length - 1]);
}
// these conditions actually are error, but quite a few of
// the files on thrustcurvemotor.org have one or the
// other of them, and they make less of a difference to
// the simulation result than the normal variation between motors.
// 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) {
if (t < 0) {
throw new IllegalArgumentException("Negative thrust.");
@ -630,45 +638,51 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
maxThrust = t;
}
// Burn start time
double thrustLimit = maxThrust * MARGINAL_THRUST;
double burnStart, burnEnd;
int pos;
for (pos = 1; pos < thrust.length; pos++) {
if (thrust[pos] >= thrustLimit)
break;
if (thrust[0] >= thrustLimit)
burnStart = time[0];
else {
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
for (pos = thrust.length - 2; pos >= 0; pos--) {
if (thrust[pos] >= thrustLimit)
break;
if (thrust[thrust.length-1] >= thrustLimit)
burnEnd = time[time.length-1];
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
burnTimeEstimate = Math.max(burnEnd - burnStart, 0);
@ -677,12 +691,12 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
// Total impulse and average thrust
totalImpulse = 0;
averageThrust = 0;
for (pos = 0; pos < time.length - 1; pos++) {
double t0 = time[pos];
double t1 = time[pos + 1];
double f0 = thrust[pos];
double f1 = thrust[pos + 1];
int impulsePos;
for (impulsePos = 0; impulsePos < time.length - 1; impulsePos++) {
double t0 = time[impulsePos];
double t1 = time[impulsePos + 1];
double f0 = thrust[impulsePos];
double f1 = thrust[impulsePos + 1];
totalImpulse += (t1 - t0) * (f0 + f1) / 2;

View File

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

View File

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

View File

@ -115,37 +115,46 @@ public class SerializeThrustcurveMotors {
System.out.println(message);
List<MotorBurnFile> b = getThrustCurvesForMotorId(mi.getMotor_id());
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();
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);
}
builder.setCaseInfo(mi.getCase_info());
builder.setPropellantInfo(mi.getProp_info());
builder.setDiameter(mi.getDiameter() / 1000.0);
builder.setLength(mi.getLength() / 1000.0);
builder.setMotorType(type);
builder.setCaseInfo(mi.getCase_info());
builder.setPropellantInfo(mi.getProp_info());
builder.setDiameter(mi.getDiameter() / 1000.0);
builder.setLength(mi.getLength() / 1000.0);
builder.setMotorType(type);
if ("OOP".equals(mi.getAvailiability())) {
builder.setDesignation(mi.getDesignation());
builder.setAvailablity(false);
} else if (mi.getDesignation().startsWith("Micro")) {
builder.setDesignation(mi.getDesignation());
} else {
builder.setDesignation(mi.getCommon_name());
}
if ("OOP".equals(mi.getAvailiability())) {
builder.setDesignation(mi.getDesignation());
builder.setAvailablity(false);
} else if (mi.getDesignation().startsWith("Micro")) {
builder.setDesignation(mi.getDesignation());
} else {
builder.setDesignation(mi.getCommon_name());
allMotors.add(builder.build());
} catch (IllegalArgumentException e) {
System.out.println("\tError in simFile " + burnFile.getSimfileId() + ": " + e.getMessage() + " (continuing)");
try {
FileOutputStream out = new FileOutputStream(("simfile-" + burnFile.getSimfileId()).toString());
out.write(burnFile.getContents().getBytes());
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());
@ -160,12 +169,12 @@ public class SerializeThrustcurveMotors {
try {
b.addAll(ThrustCurveAPI.downloadData(motorId, "RockSim"));
} catch (Exception ex) {
System.out.println("\tError downloading RockSim");
System.out.println("\tError downloading RockSim for motorID=" + motorId);
}
try {
b.addAll(ThrustCurveAPI.downloadData(motorId, "RASP"));
} catch (Exception ex) {
System.out.println("\tError downloading RASP");
System.out.println("\tError downloading RASP for motorID=" + motorId);
}
return b;
}

1
openrocket.log Normal file
View File

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