Merge pull request #688 from JoePfeiffer/fin-moi
fixes Fin MOI calculations
This commit is contained in:
commit
056c6b2b39
@ -638,17 +638,18 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return an approximation of the longitudinal unitary inertia of the fin set.
|
* Return an approximation of the longitudinal unitary moment of inertia
|
||||||
|
*
|
||||||
* The process is the following:
|
* The process is the following:
|
||||||
*
|
*
|
||||||
* 1. Approximate the fin with a rectangular fin
|
* 1. Approximate a fin with a rectangular thin plate
|
||||||
*
|
*
|
||||||
* 2. The inertia of one fin is taken as the average of the moments of inertia
|
* 2. The unitary moment of inertia of one fin is taken as the average
|
||||||
* through its center perpendicular to the plane, and the inertia through
|
* of the unitary moments of inertia through its center perpendicular
|
||||||
* its center parallel to the plane
|
* to the plane (Izz/M), and through its center parallel to the plane (Iyy/M)
|
||||||
*
|
*
|
||||||
* 3. If there are multiple fins, the inertia is shifted to the center of the fin
|
* 3. If there are multiple fins, the inertia is shifted to the center of the
|
||||||
* set and multiplied by the number of fins.
|
* FinSet using the Parallel Axis Theorem
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public double getLongitudinalUnitInertia() {
|
public double getLongitudinalUnitInertia() {
|
||||||
@ -661,23 +662,34 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
|
|||||||
double w = getLength();
|
double w = getLength();
|
||||||
double h = getSpan();
|
double h = getSpan();
|
||||||
double w2, h2;
|
double w2, h2;
|
||||||
|
|
||||||
if (MathUtil.equals(w * h, 0)) {
|
// If either h or w is 0, we punt and treat the fin as square
|
||||||
|
if (MathUtil.equals(h * w, 0)) {
|
||||||
w2 = singlePlanformArea;
|
w2 = singlePlanformArea;
|
||||||
h2 = singlePlanformArea;
|
h2 = singlePlanformArea;
|
||||||
} else {
|
} else {
|
||||||
w2 = w * singlePlanformArea / h;
|
w2 = w * singlePlanformArea / h;
|
||||||
h2 = h * singlePlanformArea / w;
|
h2 = h * singlePlanformArea / w;
|
||||||
}
|
}
|
||||||
|
|
||||||
double inertia = (h2 + 2 * w2) / 24;
|
// Iyy = h * w^3 / 12, so Iyy/M = w^2 / 12
|
||||||
|
// Izz = h * w * (h^2 + w^2) / 12, so Izz/M = (h^2 + w^2) / 12
|
||||||
|
// (Iyy / M + Izz / M) / 2 = (h^2 + 2 * w^2)/24
|
||||||
|
final double inertia = (h2 + 2 * w2) / 24;
|
||||||
|
|
||||||
|
System.out.println("component " + this);
|
||||||
|
System.out.println("finCount " + finCount);
|
||||||
|
System.out.println("inertia " + inertia);
|
||||||
|
|
||||||
if (finCount == 1)
|
if (finCount == 1)
|
||||||
return inertia;
|
return inertia;
|
||||||
|
|
||||||
final double rFront = this.getFinFront().y;
|
// Move axis to center of FinSet. We need to apply the Parallel Axis Theorem
|
||||||
|
// to Izz, but not to Iyy (as the displacement as we move to the new axis
|
||||||
return finCount * (inertia + MathUtil.pow2(MathUtil.safeSqrt(h2) + rFront));
|
// is along Y). Since our moment of inertia is the average of Iyy and Izz,
|
||||||
|
// this is accomplished by just weighting the transformation from the theorem
|
||||||
|
// by 1/2
|
||||||
|
return inertia + MathUtil.pow2(MathUtil.safeSqrt(h2) / 2 + getBodyRadius()) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -685,11 +697,13 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
|
|||||||
* Return an approximation of the rotational unitary inertia of the fin set.
|
* Return an approximation of the rotational unitary inertia of the fin set.
|
||||||
* The process is the following:
|
* The process is the following:
|
||||||
*
|
*
|
||||||
* 1. Approximate the fin with a rectangular fin and calculate the inertia of the
|
* 1. Approximate the fin with a rectangular thin plate
|
||||||
* rectangular approximate
|
*
|
||||||
|
* 2. calculate the unitary rotational inertia (Ixx/M) of the
|
||||||
|
* rectangular approximation, about the center of the approximated fin.
|
||||||
*
|
*
|
||||||
* 2. If there are multiple fins, shift the inertia center to the fin set center
|
* 2. If there are multiple fins, shift the inertia axis to the center
|
||||||
* and multiply with the number of fins.
|
* of the Finset.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public double getRotationalUnitInertia() {
|
public double getRotationalUnitInertia() {
|
||||||
@ -698,18 +712,26 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Approximate fin with a rectangular fin
|
// Approximate fin with a rectangular fin
|
||||||
|
// h2 is square of fin height
|
||||||
double w = getLength();
|
double w = getLength();
|
||||||
double h = getSpan();
|
double h = getSpan();
|
||||||
|
double h2;
|
||||||
|
|
||||||
|
// If either h or w is 0, punt and treat it as a square fin
|
||||||
if (MathUtil.equals(w * h, 0)) {
|
if (MathUtil.equals(w * h, 0)) {
|
||||||
h = MathUtil.safeSqrt(singlePlanformArea);
|
h2 = singlePlanformArea;
|
||||||
} else {
|
} else {
|
||||||
h = MathUtil.safeSqrt(h * singlePlanformArea/ w);
|
h2 = h * singlePlanformArea / w;
|
||||||
}
|
}
|
||||||
|
|
||||||
final double rFront = this.getFinFront().y;
|
// Ixx = w * h^3 / 12, so Ixx / M = h^2 / 12
|
||||||
|
final double inertia = h2 / 12;
|
||||||
|
|
||||||
return finCount * (h * h / 12 + MathUtil.pow2(h / 2 + rFront));
|
if (finCount == 1)
|
||||||
|
return inertia;
|
||||||
|
|
||||||
|
// Move axis to center of FinSet using Parallel Axis Theorem
|
||||||
|
return inertia + MathUtil.pow2(MathUtil.safeSqrt(h2) / 2 + getBodyRadius());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@ public class MassCalculatorTest extends BaseTestCase {
|
|||||||
assertEquals("Simple Rocket CM is incorrect: ", expCM, actualRocketDryCM);
|
assertEquals("Simple Rocket CM is incorrect: ", expCM, actualRocketDryCM);
|
||||||
|
|
||||||
|
|
||||||
double expMOIrot = 5.394503232245634E-5;
|
double expMOIrot = 1.8763734635622462E-5;
|
||||||
double expMOIlong = 3.029224106873237E-4;
|
double expMOIlong = 1.7808603404853048E-4;
|
||||||
|
|
||||||
double actualMOIrot = actualStructure.getRotationalInertia();
|
double actualMOIrot = actualStructure.getRotationalInertia();
|
||||||
double actualMOIlong = actualStructure.getLongitudinalInertia();
|
double actualMOIlong = actualStructure.getLongitudinalInertia();
|
||||||
@ -442,10 +442,10 @@ public class MassCalculatorTest extends BaseTestCase {
|
|||||||
assertEquals(cc.getName() + " Longitudinal MOI calculated incorrectly: ", expInertia, compInertia, EPSILON);
|
assertEquals(cc.getName() + " Longitudinal MOI calculated incorrectly: ", expInertia, compInertia, EPSILON);
|
||||||
|
|
||||||
final FinSet boosterFins = (FinSet) boosters.getChild(1).getChild(1);
|
final FinSet boosterFins = (FinSet) boosters.getChild(1).getChild(1);
|
||||||
expInertia = 0.00413298;
|
expInertia = 0.001377661595723823;
|
||||||
compInertia = boosterFins.getRotationalInertia();
|
compInertia = boosterFins.getRotationalInertia();
|
||||||
assertEquals(boosterFins.getName() + " Rotational MOI calculated incorrectly: ", expInertia, compInertia, EPSILON);
|
assertEquals(boosterFins.getName() + " Rotational MOI calculated incorrectly: ", expInertia, compInertia, EPSILON);
|
||||||
expInertia = 0.01215133;
|
expInertia = 0.0016272177418619116;
|
||||||
compInertia = boosterFins.getLongitudinalInertia();
|
compInertia = boosterFins.getLongitudinalInertia();
|
||||||
assertEquals(boosterFins.getName() + " Longitudinal MOI calculated incorrectly: ", expInertia, compInertia, EPSILON);
|
assertEquals(boosterFins.getName() + " Longitudinal MOI calculated incorrectly: ", expInertia, compInertia, EPSILON);
|
||||||
|
|
||||||
@ -668,11 +668,11 @@ public class MassCalculatorTest extends BaseTestCase {
|
|||||||
|
|
||||||
RigidBody spent = MassCalculator.calculateBurnout(config);
|
RigidBody spent = MassCalculator.calculateBurnout(config);
|
||||||
|
|
||||||
double expMOIRotational = 0.01593066;
|
double expMOIRotational = 0.010420016485489425;
|
||||||
double boosterMOIRotational = spent.getRotationalInertia();
|
double boosterMOIRotational = spent.getRotationalInertia();
|
||||||
assertEquals(" Booster x-axis MOI is incorrect: ", expMOIRotational, boosterMOIRotational, EPSILON);
|
assertEquals(" Booster x-axis MOI is incorrect: ", expMOIRotational, boosterMOIRotational, EPSILON);
|
||||||
|
|
||||||
double expMOI_tr = 0.08018692435877221;
|
double expMOI_tr = 0.05913869705973017;
|
||||||
double boosterMOI_tr = spent.getLongitudinalInertia();
|
double boosterMOI_tr = spent.getLongitudinalInertia();
|
||||||
assertEquals(" Booster transverse MOI is incorrect: ", expMOI_tr, boosterMOI_tr, EPSILON);
|
assertEquals(" Booster transverse MOI is incorrect: ", expMOI_tr, boosterMOI_tr, EPSILON);
|
||||||
}
|
}
|
||||||
@ -688,9 +688,9 @@ public class MassCalculatorTest extends BaseTestCase {
|
|||||||
|
|
||||||
RigidBody launchData = MassCalculator.calculateLaunch(config);
|
RigidBody launchData = MassCalculator.calculateLaunch(config);
|
||||||
|
|
||||||
final double expIxx = 0.01899116;
|
final double expIxx = 0.013480523485489424;
|
||||||
final double actIxx = launchData.getRotationalInertia();
|
final double actIxx = launchData.getRotationalInertia();
|
||||||
final double expIyy = 0.08637653;
|
final double expIyy = 0.06532830810235105;
|
||||||
final double actIyy = launchData.getLongitudinalInertia();
|
final double actIyy = launchData.getLongitudinalInertia();
|
||||||
|
|
||||||
assertEquals(" Booster x-axis MOI is incorrect: ", expIxx, actIxx, EPSILON);
|
assertEquals(" Booster x-axis MOI is incorrect: ", expIxx, actIxx, EPSILON);
|
||||||
@ -731,11 +731,11 @@ public class MassCalculatorTest extends BaseTestCase {
|
|||||||
assertEquals(" Booster Launch CM is incorrect: ", expCM, boosterSetCM);
|
assertEquals(" Booster Launch CM is incorrect: ", expCM, boosterSetCM);
|
||||||
|
|
||||||
// Validate MOI
|
// Validate MOI
|
||||||
double expMOI_axial = 0.01261079;
|
double expMOI_axial = 0.007100144485489424;
|
||||||
double boosterMOI_xx = burnout.getRotationalInertia();
|
double boosterMOI_xx = burnout.getRotationalInertia();
|
||||||
assertEquals(" Booster x-axis MOI is incorrect: ", expMOI_axial, boosterMOI_xx, EPSILON);
|
assertEquals(" Booster x-axis MOI is incorrect: ", expMOI_axial, boosterMOI_xx, EPSILON);
|
||||||
|
|
||||||
double expMOI_tr = 16.046826943504207;
|
double expMOI_tr = 16.025778716205167;
|
||||||
double boosterMOI_tr = burnout.getLongitudinalInertia();
|
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);
|
||||||
}
|
}
|
||||||
@ -785,11 +785,11 @@ public class MassCalculatorTest extends BaseTestCase {
|
|||||||
assertEquals(" Booster Launch CM is incorrect: ", expCM, boosterCM);
|
assertEquals(" Booster Launch CM is incorrect: ", expCM, boosterCM);
|
||||||
|
|
||||||
// Validate MOI
|
// Validate MOI
|
||||||
double expMOI_axial = 0.031538609;
|
double expMOI_axial = 0.026027963480146098;
|
||||||
double boosterMOI_xx = boosterData.getRotationalInertia();
|
double boosterMOI_xx = boosterData.getRotationalInertia();
|
||||||
assertEquals(" Booster x-axis MOI is incorrect: ", expMOI_axial, boosterMOI_xx, EPSILON);
|
assertEquals(" Booster x-axis MOI is incorrect: ", expMOI_axial, boosterMOI_xx, EPSILON);
|
||||||
|
|
||||||
double expMOI_tr = 0.37548843;
|
double expMOI_tr = 0.35444021118310487;
|
||||||
double boosterMOI_tr = boosterData.getLongitudinalInertia();
|
double boosterMOI_tr = boosterData.getLongitudinalInertia();
|
||||||
assertEquals(" Booster transverse MOI is incorrect: ", expMOI_tr, boosterMOI_tr, EPSILON);
|
assertEquals(" Booster transverse MOI is incorrect: ", expMOI_tr, boosterMOI_tr, EPSILON);
|
||||||
}
|
}
|
||||||
@ -798,7 +798,7 @@ public class MassCalculatorTest extends BaseTestCase {
|
|||||||
public void testFalcon9HeavyComponentCMxOverride() {
|
public void testFalcon9HeavyComponentCMxOverride() {
|
||||||
Rocket rocket = TestRockets.makeFalcon9Heavy();
|
Rocket rocket = TestRockets.makeFalcon9Heavy();
|
||||||
rocket.setName("Falcon9Heavy." + Thread.currentThread().getStackTrace()[1].getMethodName());
|
rocket.setName("Falcon9Heavy." + Thread.currentThread().getStackTrace()[1].getMethodName());
|
||||||
|
|
||||||
FlightConfiguration config = rocket.getEmptyConfiguration();
|
FlightConfiguration config = rocket.getEmptyConfiguration();
|
||||||
rocket.setSelectedConfiguration(config.getId());
|
rocket.setSelectedConfiguration(config.getId());
|
||||||
|
|
||||||
@ -832,11 +832,11 @@ public class MassCalculatorTest extends BaseTestCase {
|
|||||||
assertEquals(" Booster Launch CM is incorrect: ", expCM, structure.getCM());
|
assertEquals(" Booster Launch CM is incorrect: ", expCM, structure.getCM());
|
||||||
|
|
||||||
// Validate MOI
|
// Validate MOI
|
||||||
final double expMOI_axial = 0.012610790;
|
final double expMOI_axial = 0.007100144485489424;
|
||||||
double boosterMOI_xx = structure.getRotationalInertia();
|
double boosterMOI_xx = structure.getRotationalInertia();
|
||||||
assertEquals(" Booster x-axis MOI is incorrect: ", expMOI_axial, boosterMOI_xx, EPSILON);
|
assertEquals(" Booster x-axis MOI is incorrect: ", expMOI_axial, boosterMOI_xx, EPSILON);
|
||||||
|
|
||||||
final double expMOI_tr = 0.063491225;
|
final double expMOI_tr = 0.04244299775219597;
|
||||||
double boosterMOI_tr = structure.getLongitudinalInertia();
|
double boosterMOI_tr = structure.getLongitudinalInertia();
|
||||||
assertEquals(" Booster transverse MOI is incorrect: ", expMOI_tr, boosterMOI_tr, EPSILON);
|
assertEquals(" Booster transverse MOI is incorrect: ", expMOI_tr, boosterMOI_tr, EPSILON);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user