Refactored MassCalculation.calculateAssembly() to separate calculation
of structure from calculation of motors, so mass and CG overrides don't affect motors Modified structure calculation so that when an override is in effect and children are also being overridden, don't include root of tree as an element in its own right when computing MOI. Modified MassCalculatorTest to look for correct MOI value.
This commit is contained in:
parent
fc5ef54d9d
commit
efacebf5d8
@ -246,6 +246,108 @@ public class MassCalculation {
|
||||
*
|
||||
*/
|
||||
/* package-scope */ MassCalculation calculateAssembly(){
|
||||
|
||||
if (this.type.includesStructure) {
|
||||
MassCalculation structureCalc = this.copy(this.root, this.transform);
|
||||
structureCalc.calculateStructure();
|
||||
this.merge(structureCalc);
|
||||
}
|
||||
|
||||
if (this.type.includesMotorCasing || this.type.includesPropellant) {
|
||||
MassCalculation motorCalc = this.copy(this.root, this.transform);
|
||||
motorCalc.calculateMotors();
|
||||
this.merge(motorCalc);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
MassCalculation calculateStructure() {
|
||||
final RocketComponent component = this.root;
|
||||
final Transformation parentTransform = this.transform;
|
||||
final int instanceCount = component.getInstanceCount();
|
||||
Coordinate[] instanceLocations = component.getInstanceLocations();
|
||||
|
||||
// // vvv DEBUG
|
||||
// if( this.config.isComponentActive(component) ){
|
||||
// System.err.println(String.format( "%s[%s]....", prefix, component.getName()));
|
||||
// }
|
||||
|
||||
// iterate over the aggregated instances for the whole tree.
|
||||
MassCalculation children = this.copy(component, parentTransform );
|
||||
for( int instanceNumber = 0; instanceNumber < instanceCount; ++instanceNumber) {
|
||||
Coordinate currentLocation = instanceLocations[instanceNumber];
|
||||
Transformation currentTransform = parentTransform.applyTransformation( Transformation.getTranslationTransform( currentLocation ));
|
||||
|
||||
for (RocketComponent child : component.getChildren()) {
|
||||
// child data, relative to rocket reference frame
|
||||
MassCalculation eachChild = copy( child, currentTransform);
|
||||
|
||||
eachChild.prefix = prefix + "....";
|
||||
eachChild.calculateStructure();
|
||||
|
||||
// accumulate children's data
|
||||
children.merge( eachChild );
|
||||
}
|
||||
}
|
||||
|
||||
if( 0 < children.getMass() ) {
|
||||
this.merge( children );
|
||||
// // vvv DEBUG
|
||||
// System.err.println(String.format( "%s....assembly mass (incl/children): %s", prefix, this.toCMDebug()));
|
||||
}
|
||||
|
||||
if (this.config.isComponentActive(component) ){
|
||||
Coordinate compCM = component.getComponentCG();
|
||||
|
||||
if (!component.getOverrideSubcomponents()) {
|
||||
if (component.isMassOverridden()) {
|
||||
// System.err.println("mass override=" + component.getOverrideMass());
|
||||
compCM = compCM.setWeight(MathUtil.max(component.getOverrideMass(), MIN_MASS));
|
||||
}
|
||||
if (component.isCGOverridden())
|
||||
compCM = compCM.setXYZ(component.getOverrideCG());
|
||||
}
|
||||
|
||||
// mass data for *this component only* in the rocket-frame
|
||||
compCM = parentTransform.transform( compCM.add(component.getPosition()) );
|
||||
this.addMass( compCM );
|
||||
|
||||
double compIx = component.getRotationalUnitInertia() * compCM.weight;
|
||||
double compIt = component.getLongitudinalUnitInertia() * compCM.weight;
|
||||
RigidBody componentInertia = new RigidBody( compCM, compIx, compIt, compIt );
|
||||
|
||||
this.addInertia( componentInertia );
|
||||
// vvv DEBUG
|
||||
// if( 0 < compCM.weight ) {
|
||||
// System.err.println(String.format( "%s....componentData: %s", prefix, compCM.toPreciseString() ));
|
||||
// }
|
||||
|
||||
if (component.getOverrideSubcomponents()) {
|
||||
if (component.isMassOverridden()) {
|
||||
double newMass = MathUtil.max(component.getOverrideMass(), MIN_MASS);
|
||||
Coordinate newCM = this.getCM().setWeight( newMass );
|
||||
this.setCM( newCM );
|
||||
}
|
||||
|
||||
if (component.isCGOverridden()) {
|
||||
Coordinate newCM = this.getCM().setX( component.getOverrideCGX() );
|
||||
this.setCM( newCM );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// // vvv DEBUG
|
||||
// if( this.config.isComponentActive(component) && 0 < this.getMass() ) {
|
||||
// System.err.println(String.format( "%s....<< return assemblyData: %s (tree @%s)", prefix, this.toCMDebug(), component.getName() ));
|
||||
// }
|
||||
// // ^^^ DEBUG
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
MassCalculation calculateMotors() {
|
||||
|
||||
final RocketComponent component = this.root;
|
||||
final Transformation parentTransform = this.transform;
|
||||
|
||||
@ -257,37 +359,14 @@ public class MassCalculation {
|
||||
// System.err.println(String.format( "%s[%s]....", prefix, component.getName()));
|
||||
// }
|
||||
|
||||
if( this.type.includesStructure && this.config.isComponentActive(component) ){
|
||||
Coordinate compCM = component.getCG();
|
||||
double compIx = component.getRotationalUnitInertia() * compCM.weight;
|
||||
double compIt = component.getLongitudinalUnitInertia() * compCM.weight;
|
||||
|
||||
if (!component.getOverrideSubcomponents()) {
|
||||
if (component.isMassOverridden())
|
||||
compCM = compCM.setWeight(MathUtil.max(component.getOverrideMass(), MIN_MASS));
|
||||
if (component.isCGOverridden())
|
||||
compCM = compCM.setXYZ(component.getOverrideCG());
|
||||
}
|
||||
|
||||
// mass data for *this component only* in the rocket-frame
|
||||
compCM = parentTransform.transform( compCM.add(component.getPosition()) );
|
||||
this.addMass( compCM );
|
||||
|
||||
RigidBody componentInertia = new RigidBody( compCM, compIx, compIt, compIt );
|
||||
this.addInertia( componentInertia );
|
||||
|
||||
// if( 0 < compCM.weight ) { // vvv DEBUG
|
||||
// System.err.println(String.format( "%s....componentData: %s", prefix, compCM.toPreciseString() ));
|
||||
// }
|
||||
}
|
||||
|
||||
if( component.isMotorMount() && ( this.type.includesMotorCasing || this.type.includesPropellant )) {
|
||||
if (component.isMotorMount()) {
|
||||
MassCalculation propellant = this.copy(component, parentTransform);
|
||||
|
||||
propellant.calculateMountData();
|
||||
|
||||
this.merge( propellant );
|
||||
|
||||
|
||||
// // vvv DEBUG
|
||||
// if( 0 < propellant.getMass() ) {
|
||||
// System.err.println(String.format( "%s........++ propellantData: %s", prefix, propellant.toCMDebug()));
|
||||
// }
|
||||
@ -304,7 +383,7 @@ public class MassCalculation {
|
||||
MassCalculation eachChild = copy( child, currentTransform);
|
||||
|
||||
eachChild.prefix = prefix + "....";
|
||||
eachChild.calculateAssembly();
|
||||
eachChild.calculateMotors();
|
||||
|
||||
// accumulate children's data
|
||||
children.merge( eachChild );
|
||||
@ -316,25 +395,11 @@ public class MassCalculation {
|
||||
//System.err.println(String.format( "%s....assembly mass (incl/children): %s", prefix, this.toCMDebug()));
|
||||
}
|
||||
|
||||
// Override total data
|
||||
if (component.getOverrideSubcomponents()) {
|
||||
if (component.isMassOverridden()) {
|
||||
double newMass = MathUtil.max(component.getOverrideMass(), MIN_MASS);
|
||||
Coordinate newCM = this.getCM().setWeight( newMass );
|
||||
this.setCM( newCM );
|
||||
}
|
||||
if (component.isCGOverridden()) {
|
||||
Coordinate newCM = this.getCM().setX( component.getOverrideCGX() );
|
||||
this.setCM( newCM );
|
||||
}
|
||||
}
|
||||
|
||||
// vvv DEBUG
|
||||
//if( this.config.isComponentActive(component) && 0 < this.getMass() ) {
|
||||
//System.err.println(String.format( "%s....<< return assemblyData: %s (tree @%s)", prefix, this.toCMDebug(), component.getName() ));
|
||||
// System.err.println(String.format( "%s Ixx = %.8f Iyy = %.8f", prefix, getIxx(), getIyy() ));
|
||||
//}
|
||||
// ^^^ DEBUG
|
||||
// // vvv DEBUG
|
||||
// if( this.config.isComponentActive(component) && 0 < this.getMass() ) {
|
||||
// System.err.println(String.format( "%s....<< return assemblyData: %s (tree @%s)", prefix, this.toCMDebug(), component.getName() ));
|
||||
// }
|
||||
// ^^^ DEBUG
|
||||
|
||||
return this;
|
||||
}
|
||||
@ -350,11 +415,10 @@ public class MassCalculation {
|
||||
double Ir=0, It=0;
|
||||
for( final RigidBody eachLocal : this.bodies ){
|
||||
final RigidBody eachGlobal = eachLocal.rebase( this.centerOfMass );
|
||||
|
||||
Ir += eachGlobal.Ixx;
|
||||
It += eachGlobal.Iyy;
|
||||
}
|
||||
|
||||
|
||||
return new RigidBody( centerOfMass, Ir, It, It );
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@ public class MassCalculatorTest extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testAlphaIIIStructure() {
|
||||
System.err.println("testing AlphaIII structure");
|
||||
Rocket rocket = TestRockets.makeEstesAlphaIII();
|
||||
rocket.setName("AlphaIII."+Thread.currentThread().getStackTrace()[1].getMethodName());
|
||||
|
||||
@ -51,6 +52,33 @@ public class MassCalculatorTest extends BaseTestCase {
|
||||
assertEquals("Simple Rocket CM.y is incorrect: ", expCM.y, actualRocketDryCM.y, EPSILON);
|
||||
assertEquals("Simple Rocket CM.z is incorrect: ", expCM.z, actualRocketDryCM.z, EPSILON);
|
||||
assertEquals("Simple Rocket CM is incorrect: ", expCM, actualRocketDryCM);
|
||||
|
||||
|
||||
double expMOIrot = 5.441190348849436E-5;
|
||||
double expMOIlong = 3.03467093714368E-4;
|
||||
|
||||
double actualMOIrot = actualStructure.getRotationalInertia();
|
||||
double actualMOIlong = actualStructure.getLongitudinalInertia();
|
||||
assertEquals("Alpha III Rotational MOI calculated incorrectly: ", expMOIrot, actualMOIrot, EPSILON);
|
||||
assertEquals("Alpha III Longitudinal MOI calculated incorrectly: ", expMOIlong, actualMOIlong, EPSILON);
|
||||
|
||||
// if we use a mass override, setting to same mass, we should get same result
|
||||
System.err.println("calculating AlphaIII with mass override");
|
||||
AxialStage sustainer = (AxialStage) rocket.getChild(0);
|
||||
|
||||
sustainer.setOverrideSubcomponents(true);
|
||||
sustainer.setMassOverridden(true);
|
||||
sustainer.setOverrideMass(actualRocketDryMass);
|
||||
|
||||
final RigidBody overrideStructure = MassCalculator.calculateStructure( config );
|
||||
final Coordinate overrideRocketDryCM = overrideStructure.cm;
|
||||
|
||||
assertEquals("Simple Rocket Override CM is incorrect: ", actualRocketDryCM, overrideRocketDryCM);
|
||||
|
||||
double overrideMOIrot = overrideStructure.getRotationalInertia();
|
||||
double overrideMOIlong = overrideStructure.getLongitudinalInertia();
|
||||
assertEquals("Alpha III Rotational MOI calculated incorrectly: ", actualMOIrot, overrideMOIrot, EPSILON);
|
||||
assertEquals("Alpha III Longitudinal MOI calculated incorrectly: ", actualMOIlong, overrideMOIlong, EPSILON);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -713,10 +741,10 @@ public class MassCalculatorTest extends BaseTestCase {
|
||||
double expMOI_axial = 0.01261079;
|
||||
double boosterMOI_xx= burnout.getRotationalInertia();
|
||||
assertEquals(" Booster x-axis MOI is incorrect: ", expMOI_axial, boosterMOI_xx, EPSILON);
|
||||
|
||||
double expMOI_tr = 16.163954943504205;
|
||||
|
||||
double expMOI_tr = 16.046826943504207;
|
||||
double boosterMOI_tr= burnout.getLongitudinalInertia();
|
||||
assertEquals(" Booster transverse MOI is incorrect: ", expMOI_tr, boosterMOI_tr, EPSILON);
|
||||
assertEquals(" Booster transverse MOI is incorrect: ", expMOI_tr, boosterMOI_tr, EPSILON);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -734,17 +762,24 @@ public class MassCalculatorTest extends BaseTestCase {
|
||||
NoseCone nose = (NoseCone)boosters.getChild(0);
|
||||
nose.setMassOverridden(true);
|
||||
nose.setOverrideMass( 0.71 );
|
||||
|
||||
// cm= 0.71000000g @[0.53971058,0.07700000,0.00000000]
|
||||
|
||||
BodyTube body = (BodyTube)boosters.getChild(1);
|
||||
body.setMassOverridden(true);
|
||||
body.setOverrideMass( 0.622 );
|
||||
|
||||
// cm= 0.62200000g @[0.96400000,0.07700000,0.00000000]
|
||||
|
||||
InnerTube mmt = (InnerTube)boosters.getChild(1).getChild(0);
|
||||
mmt.setMassOverridden(true);
|
||||
mmt.setOverrideMass( 0.213 );
|
||||
// cm= 0.21300000g @[1.28900000,0.07700000,0.00000000]
|
||||
|
||||
// Fin mass is not overriden
|
||||
// cm= 0.15995232g @[1.23793939,0.07700000,0.00000000]
|
||||
|
||||
RigidBody boosterData = MassCalculator.calculateStructure( config );
|
||||
Coordinate boosterCM = boosterData.getCM();
|
||||
// cm= 3.409905g@[0.853614,-0.000000,0.000000]
|
||||
|
||||
double expTotalMass = 3.40990464;
|
||||
assertEquals(" Booster Launch Mass is incorrect: ", expTotalMass, boosterData.getMass(), EPSILON);
|
||||
|
Loading…
x
Reference in New Issue
Block a user