[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:
Daniel_M_Williams 2016-06-03 17:06:21 -04:00
parent 14860ee51c
commit 7b2e195392
16 changed files with 259 additions and 201 deletions

View File

@ -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)

View File

@ -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();

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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() ){

View File

@ -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;
}

View File

@ -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));

View File

@ -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;

View File

@ -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");
}

View File

@ -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);

View File

@ -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);
// }
}

View File

@ -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());
}