Merge pull request #5 from teyrana/massfix

MassCalculator bug fix branch
This commit is contained in:
kruland2607 2016-03-18 10:03:19 -05:00
commit a2bec89054
6 changed files with 348 additions and 139 deletions

View File

@ -373,19 +373,27 @@ public class MassCalculator implements Monitorable {
private MassData calculateAssemblyMassData(RocketComponent component, String indent) {
Coordinate parentCM = component.getComponentCG();
double parentIx = component.getRotationalUnitInertia() * parentCM.weight;
double parentIt = component.getLongitudinalUnitInertia() * parentCM.weight;
MassData parentData = new MassData( parentCM, parentIx, parentIt);
Coordinate compCM = component.getComponentCG();
double compIx = component.getRotationalUnitInertia() * compCM.weight;
double compIt = component.getLongitudinalUnitInertia() * compCM.weight;
if (!component.getOverrideSubcomponents()) {
if (component.isMassOverridden())
parentCM = parentCM.setWeight(MathUtil.max(component.getOverrideMass(), MIN_MASS));
compCM = compCM.setWeight(MathUtil.max(component.getOverrideMass(), MIN_MASS));
if (component.isCGOverridden())
parentCM = parentCM.setXYZ(component.getOverrideCG());
compCM = compCM.setXYZ(component.getOverrideCG());
}
if(( debug) &&( 0 < component.getChildCount()) && (MIN_MASS < parentCM.weight)){
System.err.println(String.format("%-32s: %s ",indent+">>["+ component.getName()+"]", parentData.toDebug() ));
// default if not instanced (instance count == 1)
MassData resultantData = new MassData( compCM, compIx, compIt);
if( debug && (MIN_MASS < compCM.weight)){
System.err.println(String.format("%-32s: %s ",indent+"ea["+ component.getName()+"]", compCM ));
if( component.isMassOverridden() && component.isMassOverridden() && component.getOverrideSubcomponents()){
System.err.println(indent+" ?["+ component.isMassOverridden()+"]["+
component.isMassOverridden()+"]["+
component.getOverrideSubcomponents()+"]");
}
}
MassData childrenData = MassData.ZERO_DATA;
@ -401,50 +409,40 @@ public class MassCalculator implements Monitorable {
childrenData = childrenData.add( childData );
}
resultantData = resultantData.add( childrenData);
MassData resultantData = parentData; // default if not instanced
// compensate for component-instancing propogating to children's data
int instanceCount = component.getInstanceCount();
boolean hasChildren = ( 0 < component.getChildCount());
if (( 1 < instanceCount )&&( hasChildren )){
// if(( debug )){
// System.err.println(String.format("%s Found instanceable with %d children: %s (t= %s)",
// indent, component.getInstanceCount(), component.getName(), component.getClass().getSimpleName() ));
// }
// if instanced, adjust children's data too.
if ( 1 < component.getInstanceCount() ){
if( debug ){
System.err.println(String.format("%s Found instanceable with %d children: %s (t= %s)",
indent, component.getInstanceCount(), component.getName(), component.getClass().getSimpleName() ));
}
final double curIxx = childrenData.getIxx(); // MOI about x-axis
final double curIyy = childrenData.getIyy(); // MOI about y axis
final double curIzz = childrenData.getIzz(); // MOI about z axis
Coordinate eachCM = childrenData.cm;
Coordinate templateCM = resultantData.cm;
MassData instAccumData = new MassData(); // accumulator for instance MassData
Coordinate[] instanceLocations = ((Instanceable) component).getInstanceOffsets();
for( Coordinate curOffset : instanceLocations ){
// if( debug){
// //System.err.println(String.format("%-32s: %s", indent+" inst Accum", instAccumData.toCMDebug() ));
// System.err.println(String.format("%-32s: %s", indent+" inst Accum", instAccumData.toDebug() ));
// }
Coordinate instanceCM = curOffset.add(eachCM);
Coordinate instanceCM = curOffset.add(templateCM);
MassData instanceData = new MassData( instanceCM, curIxx, curIyy, curIzz);
// 3) Project the template data to the new CM
// and add to the total
instAccumData = instAccumData.add( instanceData);
}
childrenData = instAccumData;
resultantData = instAccumData;
if( debug && (MIN_MASS < compCM.weight)){
System.err.println(String.format("%-32s: %s ", indent+"x"+component.getInstanceCount()+"["+component.getName()+"][asbly]", resultantData.toDebug()));
}
}
// combine the parent's and children's data
resultantData = parentData.add( childrenData);
if( debug){
System.err.println(String.format("%-32s: %s ", indent+"<==>["+component.getName()+"][asbly]", resultantData.toDebug()));
}
// move to parent's reference point
resultantData = resultantData.move( component.getOffset() );
if( component instanceof ParallelStage ){

View File

@ -100,20 +100,19 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
public void clearAllStages() {
this.setAllStages(false, true);
this._setAllStages(false);
this.updateMotors();
}
public void setAllStages() {
this.setAllStages(true, true);
this._setAllStages(true);
this.updateMotors();
}
private void setAllStages(final boolean _active, final boolean updateRequired ) {
private void _setAllStages(final boolean _active) {
for (StageFlags cur : stages.values()) {
cur.active = _active;
}
if( updateRequired ){
update();
}
}
/**
@ -122,7 +121,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
* @param stageNumber stage number to inactivate
*/
public void clearStage(final int stageNumber) {
setStageActive( stageNumber, false );
_setStageActive( stageNumber, false );
}
/**
@ -131,8 +130,9 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
* @param stageNumber stage number to activate
*/
public void setOnlyStage(final int stageNumber) {
setAllStages(false, false);
setStageActive(stageNumber, true);
_setAllStages(false);
_setStageActive(stageNumber, true);
updateMotors();
}
/**
@ -141,7 +141,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
* @param stageNumber stage number to flag
* @param _active inactive (<code>false</code>) or active (<code>true</code>)
*/
private void setStageActive(final int stageNumber, final boolean _active ) {
private void _setStageActive(final int stageNumber, final boolean _active ) {
if ((0 <= stageNumber) && (stages.containsKey(stageNumber))) {
stages.get(stageNumber).active = _active;
return;
@ -156,6 +156,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
flags.active = !flags.active;
return;
}
this.updateMotors();
log.error("error: attempt to retrieve via a bad stage number: " + stageNumber);
}

View File

@ -517,6 +517,7 @@ public class TestRockets {
bodytube.setMaterial(material);
finset.setMaterial(material);
rocket.setSelectedConfiguration( rocket.getFlightConfiguration( fcid[0]));
rocket.getSelectedConfiguration().setAllStages();
rocket.enableEvents();
return rocket;
@ -1162,6 +1163,7 @@ public class TestRockets {
}
rocket.enableEvents();
rocket.setSelectedConfiguration(config);
config.setAllStages();
return rocket;

View File

@ -7,21 +7,30 @@ import org.junit.Test;
import net.sf.openrocket.masscalc.MassCalculator.MassCalcType;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.InnerTube;
import net.sf.openrocket.rocketcomponent.NoseCone;
import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.TestRockets;
import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
public class MassCalculatorTest extends BaseTestCase {
// tolerance for compared double test results
protected final double EPSILON = MathUtil.EPSILON;
protected final double EPSILON = 0.000001;
private final double BOOSTER_NOSE_MASS_EA = 0.0222459863653;
private final double BOOSTER_BODY_MASS_EA = 0.129886006;
private final double BOOSTER_MMT_MASS_EA = 0.01890610458;
private final double BOOSTER_TOTAL_DRY_MASS_EACH = 0.4555128227852;
private final double BOOSTER_TOTAL_DRY_CMX = 1.246297525;
private final double G77_MASS_LAUNCH = 0.123;
@Test
public void testRocketNoMotors() {
Rocket rkt = TestRockets.makeNoMotorRocket();
@ -52,7 +61,7 @@ public class MassCalculatorTest extends BaseTestCase {
}
@Test
public void testTestComponentMasses() {
public void testComponentMasses() {
Rocket rkt = TestRockets.makeFalcon9Heavy();
rkt.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
@ -119,25 +128,26 @@ public class MassCalculatorTest extends BaseTestCase {
// ====== ====== ======
ParallelStage boosters = (ParallelStage) rkt.getChild(1).getChild(1);
{
expMass = 0.01530561538;
cc= boosters.getChild(0);
compMass = cc.getComponentMass();
assertEquals(cc.getName()+" mass calculated incorrectly: ", expMass, compMass, EPSILON);
expMass = 0.08374229377;
cc= boosters.getChild(1);
compMass = cc.getComponentMass();
assertEquals(cc.getName()+" mass calculated incorrectly: ", expMass, compMass, EPSILON);
expMass = 0.018906104589303415;
cc= boosters.getChild(1).getChild(0);
compMass = cc.getComponentMass();
assertEquals(cc.getName()+" mass calculated incorrectly: ", expMass, compMass, EPSILON);
expMass = BOOSTER_NOSE_MASS_EA;
// think of the casts as an assert that ( child instanceof NoseCone) == true
NoseCone nose = (NoseCone) boosters.getChild(0);
compMass = nose.getComponentMass();
assertEquals( nose.getName()+" mass calculated incorrectly: ", expMass, compMass, EPSILON);
expMass = BOOSTER_BODY_MASS_EA;
BodyTube body = (BodyTube) boosters.getChild(1);
compMass = body.getComponentMass();
assertEquals( body.getName()+" mass calculated incorrectly: ", expMass, compMass, EPSILON);
expMass = BOOSTER_MMT_MASS_EA;
InnerTube mmt = (InnerTube)boosters.getChild(1).getChild(0);
compMass = mmt.getComponentMass();
assertEquals( mmt.getName()+" mass calculated incorrectly: ", expMass, compMass, EPSILON);
}
}
@Test
public void testTestComponentMOIs() {
public void testComponentMOIs() {
Rocket rkt = TestRockets.makeFalcon9Heavy();
rkt.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
@ -233,18 +243,18 @@ public class MassCalculatorTest extends BaseTestCase {
ParallelStage boosters = (ParallelStage) rkt.getChild(1).getChild(1);
{
cc= boosters.getChild(0);
expInertia = 5.20107e-6;
expInertia = 1.82665797857e-5;
compInertia = cc.getRotationalInertia();
assertEquals(cc.getName()+" Rotational MOI calculated incorrectly: ", expInertia, compInertia, EPSILON);
expInertia = 0;
expInertia = 1.96501191666e-7;
compInertia = cc.getLongitudinalInertia();
assertEquals(cc.getName()+" Longitudinal MOI calculated incorrectly: ", expInertia, compInertia, EPSILON);
cc= boosters.getChild(1);
expInertia = 5.02872e-5;
expInertia = 1.875878651e-4;
compInertia = cc.getRotationalInertia();
assertEquals(cc.getName()+" Rotational MOI calculated incorrectly: ", expInertia, compInertia, EPSILON);
expInertia = 0.00449140;
expInertia = 0.00702104762;
compInertia = cc.getLongitudinalInertia();
assertEquals(cc.getName()+" Longitudinal MOI calculated incorrectly: ", expInertia, compInertia, EPSILON);
@ -258,24 +268,21 @@ public class MassCalculatorTest extends BaseTestCase {
}
}
@Test
public void testTestBoosterStructureCM() {
public void testBoosterStructureCM() {
Rocket rocket = TestRockets.makeFalcon9Heavy();
rocket.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
ParallelStage boosters = (ParallelStage) rocket.getChild(1).getChild(1);
int boostNum = boosters.getStageNumber();
rocket.getSelectedConfiguration().clearAllStages();
rocket.getSelectedConfiguration().setOnlyStage( boostNum);
// String treeDump = rocket.toDebugTree();
// System.err.println( treeDump);
// Validate Boosters
MassCalculator mc = new MassCalculator();
Coordinate boosterSetCM = mc.getCM( rocket.getSelectedConfiguration(), MassCalcType.NO_MOTORS);
double expMass = 0.23590802751203407;
double expCMx = 0.9615865040919498;
double expMass = BOOSTER_TOTAL_DRY_MASS_EACH;
double expCMx = BOOSTER_TOTAL_DRY_CMX;
double calcMass = boosterSetCM.weight;
assertEquals(" Delta Heavy Booster Mass is incorrect: ", expMass, calcMass, EPSILON);
@ -295,8 +302,8 @@ public class MassCalculatorTest extends BaseTestCase {
Motor activeMotor = mmt.getMotorInstance( rocket.getSelectedConfiguration().getId()).getMotor();
String desig = activeMotor.getDesignation();
double expLaunchMass = 0.0227; // kg
double expSpentMass = 0.0102; // kg
double expLaunchMass = 0.0164; // kg
double expSpentMass = 0.0131; // kg
assertEquals(" Motor Mass "+desig+" is incorrect: ", expLaunchMass, activeMotor.getLaunchCG().weight, EPSILON);
assertEquals(" Motor Mass "+desig+" is incorrect: ", expSpentMass, activeMotor.getEmptyCG().weight, EPSILON);
@ -314,7 +321,8 @@ public class MassCalculatorTest extends BaseTestCase {
Rocket rocket = TestRockets.makeFalcon9Heavy();
ParallelStage boosters = (ParallelStage) rocket.getChild(1).getChild(1);
int boostNum = boosters.getStageNumber();
rocket.getSelectedConfiguration().setOnlyStage( boostNum);
FlightConfiguration currentConfig = rocket.getSelectedConfiguration();
currentConfig.setOnlyStage( boostNum);
// String treeDump = rocket.toDebugTree();
// System.err.println( treeDump);
@ -359,22 +367,19 @@ public class MassCalculatorTest extends BaseTestCase {
ParallelStage boosters = (ParallelStage) rocket.getChild(1).getChild(1);
int boostNum = boosters.getStageNumber();
//rocket.getDefaultConfiguration().setAllStages(false);
rocket.getSelectedConfiguration().setOnlyStage( boostNum);
// String treeDump = rocket.toDebugTree();
// System.err.println( treeDump);
{
// Validate Booster Launch Mass
MassCalculator mc = new MassCalculator();
//mc.debug = true;
Coordinate boosterSetCM = mc.getCM( rocket.getSelectedConfiguration(), MassCalcType.LAUNCH_MASS);
double calcTotalMass = boosterSetCM.weight;
double expTotalMass = 1.219908027512034;
double expX = 1.2461238889997992;
Coordinate expCM = new Coordinate(expX,0,0, expTotalMass);
double expTotalMass = BOOSTER_TOTAL_DRY_MASS_EACH + 8*G77_MASS_LAUNCH;
assertEquals(" Booster Launch Mass is incorrect: ", expTotalMass, calcTotalMass, EPSILON);
double expX = 1.292808951;
Coordinate expCM = new Coordinate(expX,0,0, expTotalMass);
assertEquals(" Booster Launch CM.x is incorrect: ", expCM.x, boosterSetCM.x, EPSILON);
assertEquals(" Booster Launch CM.y is incorrect: ", expCM.y, boosterSetCM.y, EPSILON);
assertEquals(" Booster Launch CM.z is incorrect: ", expCM.z, boosterSetCM.z, EPSILON);
@ -387,20 +392,20 @@ public class MassCalculatorTest extends BaseTestCase {
Coordinate boosterSetCM = mc.getCM( rocket.getSelectedConfiguration(), MassCalcType.BURNOUT_MASS);
double calcTotalMass = boosterSetCM.weight;
double expTotalMass = 0.7479080275020341;
assertEquals(" Booster Launch Mass is incorrect: ", expTotalMass, calcTotalMass, EPSILON);
double expTotalMass = BOOSTER_TOTAL_DRY_MASS_EACH + 8*0.064;
assertEquals(" Booster Burnout Mass is incorrect: ", expTotalMass, calcTotalMass, EPSILON);
double expX = 1.2030731351529202;
double expX = 1.282305055;
Coordinate expCM = new Coordinate(expX,0,0, expTotalMass);
assertEquals(" Booster Launch CM.x is incorrect: ", expCM.x, boosterSetCM.x, EPSILON);
assertEquals(" Booster Launch CM.y is incorrect: ", expCM.y, boosterSetCM.y, EPSILON);
assertEquals(" Booster Launch CM.z is incorrect: ", expCM.z, boosterSetCM.z, EPSILON);
assertEquals(" Booster Launch CM is incorrect: ", expCM, boosterSetCM);
assertEquals(" Booster Burnout CM.x is incorrect: ", expCM.x, boosterSetCM.x, EPSILON);
assertEquals(" Booster Burnout CM.y is incorrect: ", expCM.y, boosterSetCM.y, EPSILON);
assertEquals(" Booster Burnout CM.z is incorrect: ", expCM.z, boosterSetCM.z, EPSILON);
assertEquals(" Booster Burnout CM is incorrect: ", expCM, boosterSetCM);
}
}
@Test
public void testTestBoosterStructureMOI() {
public void testBoosterStructureMOI() {
Rocket rocket = TestRockets.makeFalcon9Heavy();
rocket.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
FlightConfiguration defaultConfig = rocket.getSelectedConfiguration();
@ -409,17 +414,14 @@ public class MassCalculatorTest extends BaseTestCase {
int boostNum = boosters.getStageNumber();
rocket.getSelectedConfiguration().setOnlyStage( boostNum);
// String treeDump = rocket.toDebugTree();
// System.err.println( treeDump);
// Validate Boosters
MassCalculator mc = new MassCalculator();
//mc.debug = true;
double expMOI_axial = .00144619;
double expMOI_axial = .00304203;
double boosterMOI_xx= mc.getRotationalInertia( defaultConfig, MassCalcType.NO_MOTORS);
assertEquals(" Booster x-axis MOI is incorrect: ", expMOI_axial, boosterMOI_xx, EPSILON);
double expMOI_tr = 0.01845152840733412;
double expMOI_tr = 0.129566277;
double boosterMOI_tr= mc.getLongitudinalInertia( defaultConfig, MassCalcType.NO_MOTORS);
assertEquals(" Booster transverse MOI is incorrect: ", expMOI_tr, boosterMOI_tr, EPSILON);
}
@ -428,22 +430,19 @@ public class MassCalculatorTest extends BaseTestCase {
public void testBoosterTotalMOI() {
Rocket rocket = TestRockets.makeFalcon9Heavy();
FlightConfiguration defaultConfig = rocket.getSelectedConfiguration();
rocket.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
rocket.setName("TestRocket:F9H:Total_MOI");
ParallelStage boosters = (ParallelStage) rocket.getChild(1).getChild(1);
int boostNum = boosters.getStageNumber();
//rocket.getDefaultConfiguration().setAllStages(false);
rocket.getSelectedConfiguration().setOnlyStage( boostNum);
//String treeDump = rocket.toDebugTree();
//System.err.println( treeDump);
// Validate Boosters
MassCalculator mc = new MassCalculator();
final double expMOI_axial = 0.05009613217;//0.00752743;
final double expMOI_axial = 0.0516919744;
final double boosterMOI_xx= mc.getRotationalInertia( defaultConfig, MassCalcType.LAUNCH_MASS);
final double expMOI_tr = 0.05263041249; // 0.0436639379937;
final double expMOI_tr = 0.141508294;
final double boosterMOI_tr= mc.getLongitudinalInertia( defaultConfig, MassCalcType.LAUNCH_MASS);
assertEquals(" Booster x-axis MOI is incorrect: ", expMOI_axial, boosterMOI_xx, EPSILON);
@ -452,7 +451,7 @@ public class MassCalculatorTest extends BaseTestCase {
@Test
public void testMassOverride() {
public void testStageMassOverride() {
Rocket rocket = TestRockets.makeFalcon9Heavy();
FlightConfiguration config = rocket.getSelectedConfiguration();
rocket.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
@ -461,24 +460,22 @@ public class MassCalculatorTest extends BaseTestCase {
int boostNum = boosters.getStageNumber();
config.setOnlyStage( boostNum);
// String treeDump = rocket.toDebugTree();
// System.err.println( treeDump);
double overrideMass = 0.5;
boosters.setMassOverridden(true);
boosters.setOverrideMass(overrideMass);
boosters.setCGOverridden(true);
boosters.setOverrideCGX(6.0);
{
// Validate Mass
MassCalculator mc = new MassCalculator();
//mc.debug = true;
Coordinate boosterSetCM = mc.getCM( rocket.getSelectedConfiguration(), MassCalcType.NO_MOTORS);
double calcTotalMass = boosterSetCM.weight;
double expTotalMass = overrideMass;
assertEquals(" Booster Launch Mass is incorrect: ", expTotalMass, calcTotalMass, EPSILON);
double expCMx = 0.9615865040919498;
double expCMx = 6.0;
Coordinate expCM = new Coordinate( expCMx, 0, 0, expTotalMass);
assertEquals(" Booster Launch CM.x is incorrect: ", expCM.x, boosterSetCM.x, EPSILON);
assertEquals(" Booster Launch CM.y is incorrect: ", expCM.y, boosterSetCM.y, EPSILON);
@ -486,20 +483,66 @@ public class MassCalculatorTest extends BaseTestCase {
assertEquals(" Booster Launch CM is incorrect: ", expCM, boosterSetCM);
// Validate MOI
double oldMass = 0.23590802751203407;
double scaleMass = overrideMass / oldMass;
//mc.debug = true;
double expMOI_axial = .00144619 * scaleMass;
double expMOI_axial = .00333912717;
double boosterMOI_xx= mc.getRotationalInertia( config, MassCalcType.NO_MOTORS);
assertEquals(" Booster x-axis MOI is incorrect: ", expMOI_axial, boosterMOI_xx, EPSILON);
double expMOI_tr = 0.01845152840733412 * scaleMass;
double expMOI_tr = 0.142220231;
double boosterMOI_tr= mc.getLongitudinalInertia( config, MassCalcType.NO_MOTORS);
assertEquals(" Booster transverse MOI is incorrect: ", expMOI_tr, boosterMOI_tr, EPSILON);
}
}
@Test
public void testComponentMassOverride() {
Rocket rocket = TestRockets.makeFalcon9Heavy();
FlightConfiguration config = rocket.getSelectedConfiguration();
rocket.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
ParallelStage boosters = (ParallelStage) rocket.getChild(1).getChild(1);
int boostNum = boosters.getStageNumber();
config.setOnlyStage( boostNum);
NoseCone nose = (NoseCone)boosters.getChild(0);
nose.setMassOverridden(true);
nose.setOverrideMass( 0.71 );
BodyTube body = (BodyTube)boosters.getChild(1);
body.setMassOverridden(true);
body.setOverrideMass( 0.622 );
InnerTube mmt = (InnerTube)boosters.getChild(1).getChild(0);
mmt.setMassOverridden(true);
mmt.setOverrideMass( 0.213 );
{
// Validate Mass
MassCalculator mc = new MassCalculator();
Coordinate boosterSetCM = mc.getCM( rocket.getSelectedConfiguration(), MassCalcType.NO_MOTORS);
double calcTotalMass = boosterSetCM.weight;
double expTotalMass = 4.368;
assertEquals(" Booster Launch Mass is incorrect: ", expTotalMass, calcTotalMass, EPSILON);
double expCMx = 1.20642422735;
Coordinate expCM = new Coordinate( expCMx, 0, 0, expTotalMass);
assertEquals(" Booster Launch CM.x is incorrect: ", expCM.x, boosterSetCM.x, EPSILON);
assertEquals(" Booster Launch CM.y is incorrect: ", expCM.y, boosterSetCM.y, EPSILON);
assertEquals(" Booster Launch CM.z is incorrect: ", expCM.z, boosterSetCM.z, EPSILON);
assertEquals(" Booster Launch CM is incorrect: ", expCM, boosterSetCM);
// Validate MOI
double expMOI_axial = 0.0257485;
double boosterMOI_xx= mc.getRotationalInertia( config, MassCalcType.NO_MOTORS);
assertEquals(" Booster x-axis MOI is incorrect: ", expMOI_axial, boosterMOI_xx, EPSILON);
double expMOI_tr = 1.633216231;
double boosterMOI_tr= mc.getLongitudinalInertia( config, MassCalcType.NO_MOTORS);
assertEquals(" Booster transverse MOI is incorrect: ", expMOI_tr, boosterMOI_tr, EPSILON);
}
}
@Test
public void testCMOverride() {
@ -511,23 +554,29 @@ public class MassCalculatorTest extends BaseTestCase {
int boostNum = boosters.getStageNumber();
config.setOnlyStage( boostNum);
//String treeDump = rocket.toDebugTree();
//System.err.println( treeDump);
double overrideCMx = 0.5;
boosters.setCGOverridden(true);
boosters.setOverrideCGX(overrideCMx); // only allows x-axis corrections
NoseCone nose = (NoseCone)boosters.getChild(0);
nose.setCGOverridden(true);
nose.setOverrideCGX(0.22);
BodyTube body = (BodyTube)boosters.getChild(1);
body.setCGOverridden(true);
body.setOverrideCGX( 0.433);
InnerTube mmt = (InnerTube)boosters.getChild(1).getChild(0);
mmt.setCGOverridden(true);
mmt.setOverrideCGX( 0.395 );
{
// Validate Mass
MassCalculator mc = new MassCalculator();
//mc.debug = true;
Coordinate boosterSetCM = mc.getCM( rocket.getSelectedConfiguration(), MassCalcType.NO_MOTORS);
double expMass = 0.23590802751203407;
double expMass = BOOSTER_TOTAL_DRY_MASS_EACH;
double calcTotalMass = boosterSetCM.weight;
assertEquals(" Booster Launch Mass is incorrect: ", expMass, calcTotalMass, EPSILON);
double expCMx = overrideCMx; //0.9615865040919498;
double expCMx = 1.38741685552577;
Coordinate expCM = new Coordinate( expCMx, 0, 0, expMass);
assertEquals(" Booster Launch CM.x is incorrect: ", expCM.x, boosterSetCM.x, EPSILON);
assertEquals(" Booster Launch CM.y is incorrect: ", expCM.y, boosterSetCM.y, EPSILON);
@ -535,11 +584,11 @@ public class MassCalculatorTest extends BaseTestCase {
assertEquals(" Booster Launch CM is incorrect: ", expCM, boosterSetCM);
// Validate MOI
double expMOI_axial = .00144619 ;
double expMOI_axial = 0.00304203;
double boosterMOI_xx= mc.getRotationalInertia( config, MassCalcType.NO_MOTORS);
assertEquals(" Booster x-axis MOI is incorrect: ", expMOI_axial, boosterMOI_xx, EPSILON);
double expMOI_tr = 0.01845152840733412 ;
double expMOI_tr = 0.1893499746;
double boosterMOI_tr= mc.getLongitudinalInertia( config, MassCalcType.NO_MOTORS);
assertEquals(" Booster transverse MOI is incorrect: ", expMOI_tr, boosterMOI_tr, EPSILON);
}

View File

@ -7,13 +7,6 @@ import static org.junit.Assert.assertTrue;
import org.junit.Test;
import net.sf.openrocket.motor.Manufacturer;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.motor.ThrustCurveMotor;
import net.sf.openrocket.optimization.rocketoptimization.TestRocketOptimizationFunction;
import net.sf.openrocket.rocketcomponent.RocketComponent.Position;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.TestRockets;
import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
@ -157,19 +150,12 @@ public class FlightConfigurationTest extends BaseTestCase {
public void testConfigurationSwitching() {
/* Setup */
Rocket rkt = TestRockets.makeEstesAlphaIII();
//FlightConfiguration config = rkt.getSelectedConfiguration();
InnerTube smmt = (InnerTube)rkt.getChild(0).getChild(1).getChild(2);
System.err.println( smmt.toMotorDebug());
final String configDump= rkt.toDebugConfigs();
System.err.println("configs:\n" +configDump);
// final String treedump = rkt.toDebugTree();
// System.err.println("treedump: \n" + treedump);
//int actualMotorCount = smmt.getM
//assertThat("number of motor configurations doesn't actually match.", actualMotorCount, equalTo(expectedMotorCount));
int expectedMotorCount = 5;
int actualMotorCount = smmt.getMotorCount();
assertThat("number of motor configurations doesn't match.", actualMotorCount, equalTo(expectedMotorCount));
// test that all configurations correctly loaded:
int expectedConfigCount = 5;

View File

@ -0,0 +1,173 @@
package net.sf.openrocket.rocketcomponent;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.TestRockets;
import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
public class TransitionTest extends BaseTestCase {
protected final double EPSILON = MathUtil.EPSILON*1000;
@Test
public void testVerifyConicNose(){
NoseCone nose = new NoseCone(Transition.Shape.CONICAL, 0.06, 0.01);
assertEquals("nose cone length is wrong ", 0.06, nose.getLength(), EPSILON );
assertEquals("nose cone fore radius is wrong ", 0.00, nose.getForeRadius(), EPSILON );
assertEquals("nose cone aft radius is wrong ", 0.01, nose.getAftRadius(), EPSILON );
assertThat("nose cone shape type is wrong ", Transition.Shape.CONICAL, equalTo(nose.getType()));
assertEquals("nose cone shape parameter is wrong ", 0.0, nose.getShapeParameter(), EPSILON );
assertEquals("bad shape - conical forward ", 0.0, nose.getRadius(0.00), EPSILON );
assertEquals("bad shape - conical forward ", 0.0025, nose.getRadius(0.015), EPSILON );
assertEquals("bad shape - conical forward ", 0.005, nose.getRadius(0.03), EPSILON );
assertEquals("bad shape - conical forward ", 0.0075, nose.getRadius(0.045), EPSILON );
assertEquals("bad shape - conical forward ", 0.01, nose.getRadius(0.06), EPSILON );
}
@Test
public void testVerifyForwardConicTransition(){
Transition nose = new Transition();
nose.setType( Transition.Shape.CONICAL);
nose.setForeRadius( 0.5);
nose.setAftRadius( 1.0);
nose.setLength( 5.0);
assertEquals("nose cone length is wrong ", 5.0, nose.getLength(), EPSILON );
assertEquals("nose cone fore radius is wrong ", 0.5, nose.getForeRadius(), EPSILON );
assertEquals("nose cone aft radius is wrong ", 1.0, nose.getAftRadius(), EPSILON );
assertThat("nose cone shape type is wrong ", Transition.Shape.CONICAL, equalTo(nose.getType()));
assertEquals("nose cone shape parameter is wrong ", 0.0, nose.getShapeParameter(), EPSILON );
assertEquals("bad shape - conical forward transition", 0.5, nose.getRadius(0.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.6, nose.getRadius(1.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.7, nose.getRadius(2.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.8, nose.getRadius(3.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.9, nose.getRadius(4.0), EPSILON );
assertEquals("bad shape - conical forward transition", 1.0, nose.getRadius(5.0), EPSILON );
}
@Test
public void testVerifyBackwardConicTransition(){
Transition nose = new Transition();
nose.setType( Transition.Shape.CONICAL);
nose.setForeRadius( 1.0);
nose.setAftRadius( 0.5);
nose.setLength( 5.0);
assertEquals("nose cone length is wrong ", 5.0, nose.getLength(), EPSILON );
assertEquals("nose cone fore radius is wrong ", 1.0, nose.getForeRadius(), EPSILON );
assertEquals("nose cone aft radius is wrong ", 0.5, nose.getAftRadius(), EPSILON );
assertThat("nose cone shape type is wrong ", Transition.Shape.CONICAL, equalTo(nose.getType()));
assertEquals("nose cone shape parameter is wrong ", 0.0, nose.getShapeParameter(), EPSILON );
assertEquals("bad shape - conical forward transition", 1.0, nose.getRadius(0.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.9, nose.getRadius(1.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.8, nose.getRadius(2.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.7, nose.getRadius(3.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.6, nose.getRadius(4.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.5, nose.getRadius(5.0), EPSILON );
}
@Test
public void testVerifyOgiveNoseCone(){
Transition nose = new Transition();
nose.setType( Transition.Shape.OGIVE);
nose.setForeRadius( 0.0);
nose.setAftRadius( 1.0);
nose.setLength( 8.0);
assertEquals("nose cone length is wrong ", 8.0, nose.getLength(), EPSILON );
assertEquals("nose cone fore radius is wrong ", 0.0, nose.getForeRadius(), EPSILON );
assertEquals("nose cone aft radius is wrong ", 1.0, nose.getAftRadius(), EPSILON );
assertThat("nose cone shape type is wrong ", Transition.Shape.OGIVE, equalTo(nose.getType()));
assertEquals("nose cone shape parameter is wrong ", 1.0, nose.getShapeParameter(), EPSILON );
assertEquals("bad shape - conical forward transition", 0.0, nose.getRadius(0.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.23720214511, nose.getRadius(1.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.44135250736, nose.getRadius(2.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.61308144666, nose.getRadius(3.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.75290684574, nose.getRadius(4.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.86124225056, nose.getRadius(5.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.93840316661, nose.getRadius(6.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.98461174156, nose.getRadius(7.0), EPSILON );
assertEquals("bad shape - conical forward transition", 1.0, nose.getRadius(8.0), EPSILON );
}
@Test
public void testVerifyForwardOgiveTransition(){
Transition nose = new Transition();
nose.setType( Transition.Shape.OGIVE);
nose.setForeRadius( 0.44135);
nose.setAftRadius( 1.0);
nose.setLength( 6.0);
assertEquals("nose cone length is wrong ", 6.0, nose.getLength(), EPSILON );
assertEquals("nose cone fore radius is wrong ", 0.44135, nose.getForeRadius(), EPSILON );
assertEquals("nose cone aft radius is wrong ", 1.0, nose.getAftRadius(), EPSILON );
assertThat("nose cone shape type is wrong ", Transition.Shape.OGIVE, equalTo(nose.getType()));
assertEquals("nose cone shape parameter is wrong ", 1.0, nose.getShapeParameter(), EPSILON );
assertEquals("bad shape - conical forward transition", 0.44135250736, nose.getRadius(0.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.61308144666, nose.getRadius(1.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.75290684574, nose.getRadius(2.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.86124225056, nose.getRadius(3.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.93840316661, nose.getRadius(4.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.98461174156, nose.getRadius(5.0), EPSILON );
assertEquals("bad shape - conical forward transition", 1.0, nose.getRadius(6.0), EPSILON );
}
@Test
public void testVerifyBackwardOgiveTransition(){
Transition nose = new Transition();
nose.setType( Transition.Shape.OGIVE);
nose.setForeRadius( 1.0);
nose.setAftRadius( 0.44135);
nose.setLength( 6.0);
assertEquals("nose cone length is wrong ", 6.0, nose.getLength(), EPSILON );
assertEquals("nose cone fore radius is wrong ", 1.0, nose.getForeRadius(), EPSILON );
assertEquals("nose cone aft radius is wrong ", 0.44135, nose.getAftRadius(), EPSILON );
assertThat("nose cone shape type is wrong ", Transition.Shape.OGIVE, equalTo(nose.getType()));
assertEquals("nose cone shape parameter is wrong ",1.0, nose.getShapeParameter(), EPSILON );
assertEquals("bad shape - conical forward transition", 1.0, nose.getRadius(0.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.98461174156, nose.getRadius(1.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.93840316661, nose.getRadius(2.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.86124225056, nose.getRadius(3.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.75290684574, nose.getRadius(4.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.61308144666, nose.getRadius(5.0), EPSILON );
assertEquals("bad shape - conical forward transition", 0.44135250736, nose.getRadius(6.0), EPSILON );
}
@Test
public void testStockIntegration(){
Rocket rocket = TestRockets.makeEstesAlphaIII();
NoseCone nose = (NoseCone)rocket.getChild(0).getChild(0);
assertEquals("Alpha3 nose cone length is wrong ", 0.07, nose.getLength(), EPSILON );
assertEquals("Alpha3 nose cone fore radius is wrong ", 0.00, nose.getForeRadius(), EPSILON );
assertEquals("Alpha3 nose cone aft radius is wrong ", 0.012, nose.getAftRadius(), EPSILON );
assertThat("Alpha3 nose cone shape type is wrong ", Transition.Shape.OGIVE, equalTo(nose.getType()));
assertEquals("Alpha3 nose cone shape parameter is wrong ", 1.0, nose.getShapeParameter(), EPSILON );
assertEquals("Alpha3 nose cone aft shoulder length is wrong ", 0.02, nose.getAftShoulderLength(), EPSILON );
assertEquals("Alpha3 nose cone aft shoulder radius is wrong ", 0.011, nose.getAftShoulderRadius(), EPSILON );
}
}