[Cleanup] Cleaned up the ThrustCurveMotor class Interface
- Cleaned up the ThrustCurveMotor api interface -- Converted 'getTimePoints().length' -> 'getSampleSize()' -- Unified ThrustCurveMotor gets to the form getXXXX(double motorTime) -- Restricted access for several methods from public -> protected - Updated ThrustCurveMotorTest.java
This commit is contained in:
parent
14860ee51c
commit
7b2e195392
@ -271,8 +271,8 @@ public class ThrustCurveMotorSet implements Comparable<ThrustCurveMotorSet> {
|
||||
}
|
||||
|
||||
// 2. Number of data points (more is better)
|
||||
if (o1.getTimePoints().length != o2.getTimePoints().length) {
|
||||
return o2.getTimePoints().length - o1.getTimePoints().length;
|
||||
if (o1.getSampleSize() != o2.getSampleSize()) {
|
||||
return o2.getSampleSize() - o1.getSampleSize();
|
||||
}
|
||||
|
||||
// 3. Comment length (longer is better)
|
||||
|
@ -415,7 +415,7 @@ public class OpenRocketDocument implements ComponentChangeListener {
|
||||
* Clear the undo history.
|
||||
*/
|
||||
public void clearUndo() {
|
||||
log.info("Clearing undo history of " + this);
|
||||
//log.info("Clearing undo history of " + this);
|
||||
undoHistory.clear();
|
||||
undoDescription.clear();
|
||||
|
||||
|
@ -346,7 +346,7 @@ public class MassCalculator implements Monitorable {
|
||||
for (MotorClusterState curConfig : activeMotorList ) {
|
||||
int instanceCount = curConfig.getMount().getInstanceCount();
|
||||
double motorTime = curConfig.getMotorTime(status.getSimulationTime());
|
||||
mass += (curConfig.getMotor().getMassAtMotorTime(motorTime) - curConfig.getMotor().getBurnoutMass())*instanceCount;
|
||||
mass += (curConfig.getMotor().getTotalMass(motorTime) - curConfig.getMotor().getBurnoutMass())*instanceCount;
|
||||
}
|
||||
return mass;
|
||||
}
|
||||
@ -539,7 +539,6 @@ public class MassCalculator implements Monitorable {
|
||||
rocketTreeModID != configuration.getRocket().getTreeModID()) {
|
||||
rocketMassModID = configuration.getRocket().getMassModID();
|
||||
rocketTreeModID = configuration.getRocket().getTreeModID();
|
||||
log.debug("Voiding the mass cache");
|
||||
voidMassCache();
|
||||
}
|
||||
}
|
||||
|
@ -116,10 +116,6 @@ public interface Motor extends Cloneable {
|
||||
public String getDigest();
|
||||
|
||||
public Motor clone();
|
||||
|
||||
// this is probably a badly-designed way to expose the thrust, but it's not worth worrying about until
|
||||
// there's a second (non-trivial) type of motor to support...
|
||||
public double getThrustAtMotorTime( final double motorTimeDelta );
|
||||
|
||||
public double getAverageThrust( final double startTime, final double endTime );
|
||||
|
||||
@ -152,9 +148,32 @@ public interface Motor extends Cloneable {
|
||||
public double getTotalImpulseEstimate();
|
||||
|
||||
|
||||
double getMassAtMotorTime(final double motorTime);
|
||||
|
||||
|
||||
double getBurnTime();
|
||||
|
||||
|
||||
/**
|
||||
* Return the thrust at a time offset from motor ignition
|
||||
*
|
||||
* this is probably a badly-designed way to expose the thrust, but it's not worth worrying about until
|
||||
* there's a second (non-trivial) type of motor to support...
|
||||
*
|
||||
* @param motorTime time (in seconds) since motor ignition
|
||||
* @return thrust (double, in Newtons) at given time
|
||||
*/
|
||||
public double getThrust( final double motorTime);
|
||||
|
||||
/**
|
||||
* Return the mass at a time offset from motor ignition
|
||||
*
|
||||
* @param motorTime time (in seconds) since motor ignition
|
||||
*/
|
||||
public double getTotalMass( final double motorTime);
|
||||
|
||||
/** Return the mass at a given time
|
||||
*
|
||||
* @param motorTime time (in seconds) since motor ignition
|
||||
* @return
|
||||
*/
|
||||
public double getCGx( final double motorTime);
|
||||
|
||||
}
|
||||
|
@ -143,9 +143,9 @@ public class MotorDigest {
|
||||
MotorDigest motorDigest = new MotorDigest();
|
||||
motorDigest.update(DataType.TIME_ARRAY, m.getTimePoints());
|
||||
|
||||
Coordinate[] cg = m.getCGPoints();
|
||||
double[] cgx = new double[cg.length];
|
||||
double[] mass = new double[cg.length];
|
||||
final Coordinate[] cg = m.getCGPoints();
|
||||
final double[] cgx = new double[cg.length];
|
||||
final double[] mass = new double[cg.length];
|
||||
for (int i = 0; i < cg.length; i++) {
|
||||
cgx[i] = cg[i].x;
|
||||
mass[i] = cg[i].weight;
|
||||
|
@ -14,7 +14,8 @@ import net.sf.openrocket.util.Inertia;
|
||||
import net.sf.openrocket.util.MathUtil;
|
||||
|
||||
public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Serializable {
|
||||
// NECESSARY field, for this class -- this class is serialized in the motor database, and loaded directly.
|
||||
// NECESSARY field, for this class -- this class is serialized in the motor database....
|
||||
// and loaded directly-- bypassing the existing class constructors.
|
||||
private static final long serialVersionUID = -1490333207132694479L;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ -54,6 +55,7 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
|
||||
private final double unitLongitudinalInertia;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Deep copy constructor.
|
||||
* Constructs a new ThrustCurveMotor from an existing ThrustCurveMotor.
|
||||
@ -212,7 +214,7 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
|
||||
* @param is time after motor ignition, in seconds
|
||||
* @return a pseudo index to this motor's data.
|
||||
*/
|
||||
public double getPseudoIndex( final double motorTime ){
|
||||
protected double getPseudoIndex( final double motorTime ){
|
||||
final double SNAP_DISTANCE = 0.001;
|
||||
|
||||
if( time.length == 0 ){
|
||||
@ -230,7 +232,7 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
|
||||
}
|
||||
lowerBoundIndex = upperBoundIndex-1;
|
||||
if( upperBoundIndex == time.length ){
|
||||
return time.length - 1;
|
||||
return lowerBoundIndex; // == time.length-1;
|
||||
}
|
||||
|
||||
if ( SNAP_DISTANCE > Math.abs( motorTime - time[lowerBoundIndex])){
|
||||
@ -253,7 +255,7 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
|
||||
return lowerBoundIndex + indexFraction;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double getAverageThrust( final double startTime, final double endTime ) {
|
||||
|
||||
@ -298,13 +300,20 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
|
||||
|
||||
return avgImpulse / (endTime - startTime);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double getThrustAtMotorTime( final double searchTime ){
|
||||
double pseudoIndex = getPseudoIndex( searchTime );
|
||||
return getThrustAtIndex( pseudoIndex );
|
||||
public double getThrust( final double motorTime ){
|
||||
double pseudoIndex = getPseudoIndex( motorTime );
|
||||
return ThrustCurveMotor.interpolateAtIndex( thrust, pseudoIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCGx( final double motorTime ){
|
||||
double pseudoIndex = getPseudoIndex( motorTime );
|
||||
return this.interpolateCenterOfMassAtIndex( pseudoIndex).x;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the array of thrust points for this thrust curve.
|
||||
@ -323,7 +332,7 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
|
||||
// }
|
||||
|
||||
public Coordinate[] getCGPoints(){
|
||||
return cg.clone();
|
||||
return cg;
|
||||
}
|
||||
|
||||
// /**
|
||||
@ -361,16 +370,16 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
|
||||
return this.unitRotationalInertia;
|
||||
}
|
||||
|
||||
public double getIxxAtTime( final double searchTime) {
|
||||
final double index = getPseudoIndex( searchTime);
|
||||
public double getIxx( final double searchTime) {
|
||||
final double pseudoIndex = getPseudoIndex( searchTime);
|
||||
//return this.unitLongitudinalInertia * this.getMassAtIndex( index);
|
||||
return this.unitLongitudinalInertia * this.getCGAtIndex( index).weight;
|
||||
return this.unitLongitudinalInertia * interpolateCenterOfMassAtIndex( pseudoIndex).weight;
|
||||
}
|
||||
|
||||
public double getIyyAtTime( final double searchTime) {
|
||||
final double index = getPseudoIndex( searchTime);
|
||||
public double getIyy( final double searchTime) {
|
||||
final double pseudoIndex = getPseudoIndex( searchTime);
|
||||
//return this.unitRotationalInertia * this.getMassAtIndex( index);
|
||||
return this.unitRotationalInertia * this.getCGAtIndex( index).weight;
|
||||
return this.unitRotationalInertia * interpolateCenterOfMassAtIndex( pseudoIndex).weight;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -430,16 +439,18 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
|
||||
}
|
||||
|
||||
// FIXME - there seems to be some numeric problems in here...
|
||||
private static double interpolateValueAtIndex( final double[] values, final double pseudoIndex ){
|
||||
// simple linear interpolation... not sample density for anything more complex
|
||||
private static double interpolateAtIndex( final double[] values, final double pseudoIndex ){
|
||||
final double SNAP_TOLERANCE = 0.0001;
|
||||
|
||||
// assumes that pseudoIndex > 1
|
||||
final double upperFrac = pseudoIndex%1;
|
||||
final double lowerFrac = 1-upperFrac;
|
||||
final int lowerIndex = (int)pseudoIndex;
|
||||
final int upperIndex= lowerIndex+1;
|
||||
|
||||
// if the pseudo
|
||||
if( SNAP_TOLERANCE > lowerFrac ){ // 1-lowerFrac = 1-(1-upperFrac) = upperFrac ?!?
|
||||
if( SNAP_TOLERANCE > lowerFrac ){
|
||||
// index ~= int ... therefore:
|
||||
return values[ lowerIndex ];
|
||||
}else if( SNAP_TOLERANCE > upperFrac ){
|
||||
@ -453,23 +464,27 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
|
||||
return ( lowerValue*lowerFrac + upperValue*upperFrac );
|
||||
}
|
||||
|
||||
public double getThrustAtIndex( final double pseudoIndex ){
|
||||
return interpolateValueAtIndex( this.thrust, pseudoIndex );
|
||||
}
|
||||
|
||||
public double getMotorTimeAtIndex( final double index ){
|
||||
return interpolateValueAtIndex( this.time, index );
|
||||
|
||||
/**
|
||||
* for testing. In practice, the return value should generally match the parameter value, (except for error conditions)
|
||||
*
|
||||
* @ignore javadoc ignore
|
||||
* @param motorTime
|
||||
* @return the time at requested time
|
||||
*/
|
||||
public double getTime( final double motorTime ){
|
||||
final double pseudoIndex = getPseudoIndex( motorTime);
|
||||
final double foundTime = ThrustCurveMotor.interpolateAtIndex( this.time, pseudoIndex);
|
||||
return foundTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMassAtMotorTime( final double motorTime ) {
|
||||
double pseudoIndex = getPseudoIndex(motorTime);
|
||||
Coordinate cg = getCGAtIndex( pseudoIndex );
|
||||
return cg.weight;
|
||||
public double getTotalMass( final double motorTime){
|
||||
final double pseudoIndex = getPseudoIndex( motorTime);
|
||||
return interpolateCenterOfMassAtIndex( pseudoIndex).weight;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Coordinate getCGAtIndex( final double pseudoIndex ){
|
||||
protected Coordinate interpolateCenterOfMassAtIndex( final double pseudoIndex ){
|
||||
final double SNAP_TOLERANCE = 0.0001;
|
||||
|
||||
final double upperFrac = pseudoIndex%1;
|
||||
@ -477,9 +492,8 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
|
||||
final int lowerIndex = (int)pseudoIndex;
|
||||
final int upperIndex= lowerIndex+1;
|
||||
|
||||
// if the pseudo
|
||||
// if the pseudo index is close to an integer:
|
||||
if( SNAP_TOLERANCE > (1-lowerFrac) ){
|
||||
// index ~= int ... therefore:
|
||||
return cg[ (int) pseudoIndex ];
|
||||
}else if( SNAP_TOLERANCE > upperFrac ){
|
||||
return cg[ (int)upperIndex ];
|
||||
@ -492,27 +506,6 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
|
||||
return lowerValue.average( upperValue );
|
||||
}
|
||||
|
||||
|
||||
// public double getCGxAtIndex( final double index){
|
||||
// //return interpolateValueAtIndex( this.cgx, index );
|
||||
//
|
||||
// }
|
||||
//
|
||||
// public double getMassAtIndex( final double index){
|
||||
// //return interpolateValueAtIndex( this.mass, index );
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// int getCutoffIndex();
|
||||
|
||||
// double getCutoffTime()
|
||||
// int getCutoffIndex();
|
||||
|
||||
// Coordinate interpolateCG( ... )
|
||||
|
||||
//
|
||||
public int getDataSize() {
|
||||
return this.time.length;
|
||||
}
|
||||
@ -664,8 +657,14 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
|
||||
return "" + delay;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This is the number of data points of measured thrust, CGx, mass, time.
|
||||
*
|
||||
* @return return the size of the data arrays
|
||||
*/
|
||||
public int getSampleSize(){
|
||||
return time.length;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -194,24 +194,28 @@ public class ThrustCurveMotorPlaceholder implements Motor {
|
||||
|
||||
|
||||
@Override
|
||||
public double getThrustAtMotorTime(double pseudoIndex) {
|
||||
public double getThrust(double pseudoIndex) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double getAverageThrust(double startTime, double endTime) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMassAtMotorTime(final double motorTime) {
|
||||
public double getTotalMass(final double motorTime) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCGx(double pseudoIndex) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getBurnTime() {
|
||||
return 0;
|
||||
public double getBurnTime() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ public abstract class AbstractSimulationStepper implements SimulationStepper {
|
||||
* @param stepMotors whether to step the motors forward or work on a clone object
|
||||
* @return the average thrust during the time step.
|
||||
*/
|
||||
protected double calculateThrust(SimulationStatus status, double timestep,
|
||||
protected double calculateAvrageThrust(SimulationStatus status, double timestep,
|
||||
double acceleration, AtmosphericConditions atmosphericConditions,
|
||||
boolean stepMotors) throws SimulationException {
|
||||
double thrust;
|
||||
@ -173,6 +173,7 @@ public abstract class AbstractSimulationStepper implements SimulationStepper {
|
||||
Collection<MotorClusterState> activeMotorList = status.getMotors();
|
||||
for (MotorClusterState currentMotorState : activeMotorList ) {
|
||||
thrust += currentMotorState.getAverageThrust( status.getSimulationTime(), currentTime );
|
||||
//thrust += currentMotorState.getThrust( currentTime );
|
||||
}
|
||||
|
||||
// Post-listeners
|
||||
|
@ -1,7 +1,6 @@
|
||||
package net.sf.openrocket.simulation;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@ -9,7 +8,6 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.sf.openrocket.aerodynamics.Warning;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.motor.MotorConfiguration;
|
||||
import net.sf.openrocket.motor.MotorConfigurationId;
|
||||
import net.sf.openrocket.rocketcomponent.AxialStage;
|
||||
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
|
||||
@ -378,10 +376,11 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
||||
// Add ejection charge event
|
||||
MotorClusterState motorState = (MotorClusterState) event.getData();
|
||||
motorState.burnOut( event.getTime() );
|
||||
|
||||
|
||||
AxialStage stage = motorState.getMount().getStage();
|
||||
log.debug( " adding EJECTION_CHARGE event for stage "+stage.getStageNumber()+": "+stage.getName());
|
||||
log.debug( " .... for motor "+motorState.getMotor().getDesignation());
|
||||
//log.debug( " adding EJECTION_CHARGE event for motor "+motorState.getMotor().getDesignation()+" on stage "+stage.getStageNumber()+": "+stage.getName());
|
||||
log.debug( " detected Motor Burnout for motor "+motorState.getMotor().getDesignation()+"@ "+event.getTime()+" on stage "+stage.getStageNumber()+": "+stage.getName());
|
||||
|
||||
|
||||
double delay = motorState.getEjectionDelay();
|
||||
if ( motorState.hasEjectionCharge() ){
|
||||
|
@ -117,11 +117,28 @@ public class MotorClusterState {
|
||||
* @param cond
|
||||
* @return
|
||||
*/
|
||||
public double getAverageThrust( final double startTime, final double endTime) {
|
||||
public double getAverageThrust( final double startSimulationTime, final double endSimulationTime) {
|
||||
if( this.currentState.isThrusting() ) {
|
||||
double motorStartTime = this.getMotorTime( startTime );
|
||||
double motorEndTime = this.getMotorTime(endTime);
|
||||
double motorStartTime = this.getMotorTime( startSimulationTime);
|
||||
double motorEndTime = this.getMotorTime( endSimulationTime);
|
||||
return this.motorCount * motor.getAverageThrust( motorStartTime, motorEndTime );
|
||||
}else{
|
||||
return 0.00;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the average thrust over an interval.
|
||||
*
|
||||
* @param simulationTime
|
||||
* @param cond
|
||||
* @return
|
||||
*/
|
||||
public double getThrust( final double simulationTime){
|
||||
if( this.currentState.isThrusting() ){
|
||||
double motorTime = this.getMotorTime( simulationTime);
|
||||
return this.motorCount * motor.getThrust( motorTime );
|
||||
|
||||
}else{
|
||||
return 0.0;
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ public class RK4SimulationStepper extends AbstractSimulationStepper {
|
||||
/*
|
||||
* Compute the initial thrust estimate. This is used for the first time step computation.
|
||||
*/
|
||||
store.thrustForce = calculateThrust(status, store.timestep, status.getPreviousAcceleration(),
|
||||
store.thrustForce = calculateAvrageThrust(status, store.timestep, status.getPreviousAcceleration(),
|
||||
status.getPreviousAtmosphericConditions(), false);
|
||||
|
||||
|
||||
@ -180,7 +180,7 @@ public class RK4SimulationStepper extends AbstractSimulationStepper {
|
||||
* diminished by it affecting only 1/6th of the total, so it's an acceptable error.
|
||||
*/
|
||||
double thrustEstimate = store.thrustForce;
|
||||
store.thrustForce = calculateThrust(status, store.timestep, store.longitudinalAcceleration,
|
||||
store.thrustForce = calculateAvrageThrust(status, store.timestep, store.longitudinalAcceleration,
|
||||
store.atmosphericConditions, true);
|
||||
log.trace("Thrust at time " + store.timestep + " thrustForce = " + store.thrustForce);
|
||||
double thrustDiff = Math.abs(store.thrustForce - thrustEstimate);
|
||||
@ -246,9 +246,6 @@ public class RK4SimulationStepper extends AbstractSimulationStepper {
|
||||
|
||||
|
||||
//// Sum all together, y(n+1) = y(n) + h*(k1 + 2*k2 + 2*k3 + k4)/6
|
||||
|
||||
|
||||
|
||||
Coordinate deltaV, deltaP, deltaR, deltaO;
|
||||
deltaV = k2.a.add(k3.a).multiply(2).add(k1.a).add(k4.a).multiply(store.timestep / 6);
|
||||
deltaP = k2.v.add(k3.v).multiply(2).add(k1.v).add(k4.v).multiply(store.timestep / 6);
|
||||
@ -256,7 +253,6 @@ public class RK4SimulationStepper extends AbstractSimulationStepper {
|
||||
deltaO = k2.rv.add(k3.rv).multiply(2).add(k1.rv).add(k4.rv).multiply(store.timestep / 6);
|
||||
|
||||
|
||||
|
||||
status.setRocketVelocity(status.getRocketVelocity().add(deltaV));
|
||||
status.setRocketPosition(status.getRocketPosition().add(deltaP));
|
||||
status.setRocketRotationVelocity(status.getRocketRotationVelocity().add(deltaR));
|
||||
|
@ -72,7 +72,7 @@ public class MotorCheck {
|
||||
ok = false;
|
||||
}
|
||||
|
||||
int points = ((ThrustCurveMotor) m).getTimePoints().length;
|
||||
int points = ((ThrustCurveMotor) m).getSampleSize();
|
||||
if (points < WARN_POINTS) {
|
||||
System.out.println("WARNING: Only " + points + " data points");
|
||||
ok = false;
|
||||
|
@ -256,8 +256,8 @@ public class MotorCompare {
|
||||
maxPoints = 0;
|
||||
System.out.printf("Points :");
|
||||
for (Motor m : motors) {
|
||||
System.out.printf("\t%d", ((ThrustCurveMotor) m).getTimePoints().length);
|
||||
maxPoints = Math.max(maxPoints, ((ThrustCurveMotor) m).getTimePoints().length);
|
||||
System.out.printf("\t%d", ((ThrustCurveMotor) m).getSampleSize());
|
||||
maxPoints = Math.max(maxPoints, ((ThrustCurveMotor) m).getSampleSize());
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
@ -318,7 +318,7 @@ public class MotorCompare {
|
||||
ThrustCurveMotor m = motors.get(i);
|
||||
if (m.getStandardDelays().length == maxDelays)
|
||||
goodness[i] += 1000;
|
||||
if (((ThrustCurveMotor) m).getTimePoints().length == maxPoints)
|
||||
if (((ThrustCurveMotor) m).getSampleSize() == maxPoints)
|
||||
goodness[i] += 100;
|
||||
if (m.getDescription().length() == maxCommentLen)
|
||||
goodness[i] += 10;
|
||||
@ -333,7 +333,7 @@ public class MotorCompare {
|
||||
|
||||
|
||||
// Verify enough points
|
||||
int pts = ((ThrustCurveMotor) motors.get(best)).getTimePoints().length;
|
||||
int pts = ((ThrustCurveMotor) motors.get(best)).getSampleSize();
|
||||
if (pts < MIN_POINTS) {
|
||||
System.out.println("WARNING: Best has only " + pts + " data points");
|
||||
}
|
||||
|
@ -64,8 +64,8 @@ public class MotorCorrelation {
|
||||
double cross = 0;
|
||||
for (t = 0; t < 1000; t += 0.01) {
|
||||
|
||||
double thrust1 = motor1.getThrustAtMotorTime( t);
|
||||
double thrust2 = motor2.getThrustAtMotorTime( t);
|
||||
double thrust1 = motor1.getThrust( t);
|
||||
double thrust2 = motor2.getThrust( t);
|
||||
|
||||
if ( thrust1 < 0 || thrust2 < 0) {
|
||||
throw new BugException("Negative thrust, t1=" + thrust1 + " t2=" + thrust2);
|
||||
|
@ -5,6 +5,8 @@ import static org.junit.Assert.assertEquals;
|
||||
import org.junit.Test;
|
||||
|
||||
import net.sf.openrocket.util.Coordinate;
|
||||
import net.sf.openrocket.util.Pair;
|
||||
|
||||
|
||||
public class ThrustCurveMotorTest {
|
||||
|
||||
@ -13,7 +15,7 @@ public class ThrustCurveMotorTest {
|
||||
private final double radius = 0.025;
|
||||
private final double length = 0.10;
|
||||
|
||||
private final ThrustCurveMotor motor =
|
||||
private final ThrustCurveMotor motorX6 =
|
||||
new ThrustCurveMotor(Manufacturer.getManufacturer("foo"),
|
||||
"X6", "Description of X6", Motor.Type.RELOAD,
|
||||
new double[] {0, 2, Motor.PLUGGED_DELAY}, radius*2, length,
|
||||
@ -26,127 +28,149 @@ public class ThrustCurveMotorTest {
|
||||
new Coordinate(0.03,0,0,0.03)
|
||||
}, "digestA");
|
||||
|
||||
|
||||
private final double radiusA8 = 0.018;
|
||||
private final double lengthA8 = 0.10;
|
||||
private final ThrustCurveMotor motorEstesA8_3 =
|
||||
new ThrustCurveMotor(Manufacturer.getManufacturer("Estes"),
|
||||
"A8-3", "A8 Test Motor", Motor.Type.SINGLE,
|
||||
new double[] {0, 2, Motor.PLUGGED_DELAY}, radiusA8*2, lengthA8,
|
||||
|
||||
new double[] { // time (sec)
|
||||
0, 0.041, 0.084, 0.127,
|
||||
0.166, 0.192, 0.206, 0.226,
|
||||
0.236, 0.247, 0.261, 0.277,
|
||||
0.306, 0.351, 0.405, 0.467,
|
||||
0.532, 0.589, 0.632, 0.652,
|
||||
0.668, 0.684, 0.703, 0.73},
|
||||
new double[] { // thrust (N)
|
||||
0, 0.512, 2.115, 4.358,
|
||||
6.794, 8.588, 9.294, 9.73,
|
||||
8.845, 7.179, 5.063, 3.717,
|
||||
3.205, 2.884, 2.499, 2.371,
|
||||
2.307, 2.371, 2.371, 2.243,
|
||||
1.794, 1.153, 0.448, 0},
|
||||
new Coordinate[] { /// ( m, m, m, kg)
|
||||
new Coordinate(0.0350, 0, 0, 0.016350),new Coordinate(0.0352, 0, 0, 0.016335),new Coordinate(0.0354, 0, 0, 0.016255),new Coordinate(0.0356, 0, 0, 0.016057),
|
||||
new Coordinate(0.0358, 0, 0, 0.015748),new Coordinate(0.0360, 0, 0, 0.015463),new Coordinate(0.0362, 0, 0, 0.015285),new Coordinate(0.0364, 0, 0, 0.015014),
|
||||
new Coordinate(0.0366, 0, 0, 0.014882),new Coordinate(0.0368, 0, 0, 0.014757),new Coordinate(0.0370, 0, 0, 0.014635),new Coordinate(0.0372, 0, 0, 0.014535),
|
||||
new Coordinate(0.0374, 0, 0, 0.014393),new Coordinate(0.0376, 0, 0, 0.014198),new Coordinate(0.0378, 0, 0, 0.013991),new Coordinate(0.0380, 0, 0, 0.013776),
|
||||
new Coordinate(0.0382, 0, 0, 0.013560),new Coordinate(0.0384, 0, 0, 0.013370),new Coordinate(0.0386, 0, 0, 0.013225),new Coordinate(0.0388, 0, 0, 0.013160),
|
||||
new Coordinate(0.0390, 0, 0, 0.013114),new Coordinate(0.0392, 0, 0, 0.013080),new Coordinate(0.0394, 0, 0, 0.013059),new Coordinate(0.0396, 0, 0, 0.013050)
|
||||
}, "digestA8-3");
|
||||
|
||||
|
||||
@Test
|
||||
public void testVerifyMotorA8_3Times(){
|
||||
final ThrustCurveMotor mtr = motorEstesA8_3;
|
||||
|
||||
assertEquals( 0.041, mtr.getTime( 0.041), 0.001 );
|
||||
|
||||
assertEquals( 0.206, mtr.getTime( 0.206), 0.001 );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVerifyMotorA8_3Thrusts(){
|
||||
final ThrustCurveMotor mtr = motorEstesA8_3;
|
||||
|
||||
assertEquals( 0.512, mtr.getThrust( 0.041), 0.001 );
|
||||
|
||||
assertEquals( 9.294, mtr.getThrust( 0.206), 0.001 );
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testVerifyMotorA8_3CG(){
|
||||
final ThrustCurveMotor mtr = motorEstesA8_3;
|
||||
|
||||
final double actCGx0p041 = mtr.getCGx(0.041);
|
||||
assertEquals( 0.0352, actCGx0p041, 0.001 );
|
||||
final double actMass0p041 = mtr.getTotalMass( 0.041 );
|
||||
assertEquals( 0.016335, actMass0p041, 0.001 );
|
||||
|
||||
final double actCGx0p206 = mtr.getCGx( 0.206 );
|
||||
assertEquals( 0.0362, actCGx0p206, 0.001 );
|
||||
final double actMass0p206 = mtr.getTotalMass( 0.206 );
|
||||
assertEquals( 0.015285, actMass0p206, 0.001 );
|
||||
}
|
||||
|
||||
private class TestPair extends Pair<Double,Double>{
|
||||
private TestPair(){ super( 0., 0.);}
|
||||
|
||||
public TestPair( Double u, Double v){
|
||||
super(u,v);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThrustInterpolation(){
|
||||
final ThrustCurveMotor mtr = motorEstesA8_3;
|
||||
|
||||
Pair<Double, Double> testPairs[] = new TestPair[]{
|
||||
new TestPair(0.512, 0.041),
|
||||
new TestPair(2.115, 0.084),
|
||||
new TestPair( 1.220, 0.060),
|
||||
new TestPair( 1.593, 0.070),
|
||||
new TestPair( 1.965, 0.080),
|
||||
new TestPair( 2.428, 0.090),
|
||||
};
|
||||
|
||||
for( Pair<Double,Double> testCase : testPairs ){
|
||||
final double time = testCase.getV();
|
||||
final double expThrust = testCase.getU();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMotorData() {
|
||||
|
||||
assertEquals("X6", motor.getDesignation());
|
||||
assertEquals("X6-5", motor.getDesignation(5.0));
|
||||
assertEquals("Description of X6", motor.getDescription());
|
||||
assertEquals(Motor.Type.RELOAD, motor.getMotorType());
|
||||
|
||||
assertEquals("X6", motorX6.getDesignation());
|
||||
assertEquals("X6-5", motorX6.getDesignation(5.0));
|
||||
assertEquals("Description of X6", motorX6.getDescription());
|
||||
assertEquals(Motor.Type.RELOAD, motorX6.getMotorType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeIndexingNegative(){
|
||||
final ThrustCurveMotor mtr = motorX6;
|
||||
// attempt to retrieve for a time before the motor ignites
|
||||
assertEquals( 0.0, motor.getPseudoIndex( -1 ), 0.001 );
|
||||
assertEquals( 0.0, mtr.getTime( -1 ), 0.00000001 );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeIndexingPastBurnout(){
|
||||
final ThrustCurveMotor mtr = motorX6;
|
||||
|
||||
// attempt to retrieve for a time after the motor finishes
|
||||
// should retrieve the last time value. In this case: 4.0
|
||||
assertEquals( 4.0, mtr.getTime( Double.MAX_VALUE ), 0.00000001 );
|
||||
assertEquals( 4.0, mtr.getTime( 20.0 ), 0.00000001 );
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTimeIndexingAtBurnout(){
|
||||
// attempt to retrieve for a time after motor cutoff
|
||||
assertEquals( 4.0, motorX6.getTime( 4.0), 0.00001 );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeRetrieval(){
|
||||
// attempt to retrieve an integer index:
|
||||
assertEquals( 0.0, motor.getMotorTimeAtIndex( 0 ), 0.001 );
|
||||
assertEquals( 1.0, motor.getMotorTimeAtIndex( 1 ), 0.001 );
|
||||
assertEquals( 4.0, motor.getMotorTimeAtIndex( 3 ), 0.001 );
|
||||
final ThrustCurveMotor mtr = motorX6;
|
||||
|
||||
final double searchTime = 0.2;
|
||||
assertEquals( searchTime, motor.getMotorTimeAtIndex( motor.getPseudoIndex(searchTime)), 0.001 );
|
||||
final double[] timeList = { 0.2, 0.441, 0.512, 1., 2., 3};
|
||||
|
||||
for( double searchTime : timeList ){
|
||||
assertEquals( searchTime, mtr.getTime(searchTime), 0.00001);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThrustRetrieval(){
|
||||
// attempt to retrieve an integer index:
|
||||
assertEquals( 2.0, motor.getThrustAtIndex( 1 ), 0.001 );
|
||||
assertEquals( 3.0, motor.getThrustAtIndex( 2 ), 0.001 );
|
||||
assertEquals( 0.0, motor.getThrustAtIndex( 3 ), 0.001 );
|
||||
assertEquals( 2.0, motorX6.getThrust( 1 ), 0.001 );
|
||||
assertEquals( 2.5, motorX6.getThrust( 2 ), 0.001 );
|
||||
assertEquals( 3.0, motorX6.getThrust( 3 ), 0.001 );
|
||||
}
|
||||
|
||||
// using better interface
|
||||
// @Test
|
||||
// public void testCGRetrievalByDouble(){
|
||||
// final double actCGx0 = motor.getCGxAtIndex( 0.0 );
|
||||
// assertEquals( 0.02, actCGx0, 0.001 );
|
||||
// final double actMass0 = motor.getMassAtIndex( 0.0 );
|
||||
// assertEquals( 0.05, actMass0, 0.001 );
|
||||
//
|
||||
// final double actCGx25 = motor.getCGxAtIndex( 2.5 );
|
||||
// assertEquals( 0.025, actCGx25, 0.001 );
|
||||
// final double actMass25 = motor.getMassAtIndex( 2.5 );
|
||||
// assertEquals( 0.04, actMass25, 0.001 );
|
||||
// }
|
||||
|
||||
// deprecated version.
|
||||
// delete this method upon change to new function signatures
|
||||
@Test
|
||||
public void testCGRetrieval(){
|
||||
final double actCGx0 = motor.getCGAtIndex( 0.0 ).x;
|
||||
assertEquals( 0.02, actCGx0, 0.001 );
|
||||
final double actMass0 = motor.getCGAtIndex( 0.0 ).weight;
|
||||
assertEquals( 0.05, actMass0, 0.001 );
|
||||
|
||||
final double actCGx25 = motor.getCGAtIndex( 2.5 ).x;
|
||||
assertEquals( 0.025, actCGx25, 0.001 );
|
||||
final double actMass25 = motor.getCGAtIndex( 2.5 ).weight;
|
||||
assertEquals( 0.04, actMass25, 0.001 );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeIndexingPastEnd(){
|
||||
// attempt to retrieve for a time after motor cutoff
|
||||
assertEquals( 3.0, motor.getPseudoIndex( 5.0), 0.001 );
|
||||
}
|
||||
@Test
|
||||
public void testTimeIndexingAtEnd(){
|
||||
// attempt to retrieve for a time just at motor cutoff
|
||||
assertEquals( 3.0, motor.getPseudoIndex( 4.0), 0.001 );
|
||||
}
|
||||
@Test
|
||||
public void testTimeIndexingDuring(){
|
||||
// attempt to retrieve for a generic time during the motor's burn
|
||||
assertEquals( 1.6, motor.getPseudoIndex( 2.2), 0.001 );
|
||||
}
|
||||
@Test
|
||||
public void testTimeIndexingSnapUp(){
|
||||
// attempt to retrieve for a generic time during the motor's burn
|
||||
assertEquals( 3.0, motor.getPseudoIndex( 3.9999), 0.001 );
|
||||
}
|
||||
@Test
|
||||
public void testTimeIndexingSnapDown(){
|
||||
// attempt to retrieve for a generic time during the motor's burn
|
||||
assertEquals( 2.0, motor.getPseudoIndex( 3.0001), 0.001 );
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testInstance() {
|
||||
// ThrustCurveMotorState instance = motor.getNewInstance();
|
||||
//
|
||||
// verify(instance, 0, 0.05, 0.02);
|
||||
// instance.step(0.0, null);
|
||||
// verify(instance, 0, 0.05, 0.02);
|
||||
// instance.step(0.5, null);
|
||||
// verify(instance, 0.5, 0.05, 0.02);
|
||||
// instance.step(1.5, null);
|
||||
// verify(instance, (1.5 + 2.125)/2, 0.05, 0.02);
|
||||
// instance.step(2.5, null);
|
||||
// verify(instance, (2.125 + 2.875)/2, 0.05, 0.02);
|
||||
// instance.step(3.0, null);
|
||||
// verify(instance, (2+3.0/4 + 3)/2, 0.05, 0.02);
|
||||
// instance.step(3.5, null);
|
||||
// verify(instance, (1.5 + 3)/2, 0.045, 0.0225);
|
||||
// instance.step(4.5, null);
|
||||
// // mass and cg is simply average of the end points
|
||||
// verify(instance, 1.5/4, 0.035, 0.0275);
|
||||
// instance.step(5.0, null);
|
||||
// verify(instance, 0, 0.03, 0.03);
|
||||
// }
|
||||
//
|
||||
// private void verify(ThrustCurveMotorState instance, double thrust, double mass, double cgx) {
|
||||
// assertEquals("Testing thrust", thrust, instance.getThrust(), EPS);
|
||||
// assertEquals("Testing mass", mass, instance.getCG().weight, EPS);
|
||||
// assertEquals("Testing cg x", cgx, instance.getCG().x, EPS);
|
||||
// assertEquals("Testing longitudinal inertia", mass*longitudinal, instance.getMotor().getLongitudinalInertia(), EPS);
|
||||
// assertEquals("Testing rotational inertia", mass*rotational, instance.getMotor().getRotationalInertia(), EPS);
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
@ -249,7 +249,7 @@ class MotorInformationPanel extends JPanel {
|
||||
selectedMotor.getLaunchMass()));
|
||||
emptyMassLabel.setText(UnitGroup.UNITS_MASS.getDefaultUnit().toStringUnit(
|
||||
selectedMotor.getBurnoutMass()));
|
||||
dataPointsLabel.setText("" + (selectedMotor.getTimePoints().length - 1));
|
||||
dataPointsLabel.setText("" + (selectedMotor.getSampleSize() - 1));
|
||||
if (digestLabel != null) {
|
||||
digestLabel.setText(selectedMotor.getDigest());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user