Update SymmetricComponentVolumeTest to check moments of inertia

This commit is contained in:
JoePfeiffer 2023-12-19 09:04:00 -07:00
parent 5b18f73da0
commit 6af25c3f4a

View File

@ -14,6 +14,12 @@ public class SymmetricComponentVolumeTest extends BaseTestCase {
// helper functions
// project thickness onto yz plane to get height of frustrum wall
private double getHeight(double length, double foreRadius, double aftRadius, double thickness) {
final double angle = Math.atan((aftRadius - foreRadius)/length);
return thickness/Math.cos(angle);
}
// return Coordinate containing CG and volume of (possibly hollow if thickness < outerR) shoulder
private Coordinate calculateShoulderCG(double x1, double length, double outerR, double thickness) {
final double cg = x1 + length/2.0;
@ -25,7 +31,7 @@ public class SymmetricComponentVolumeTest extends BaseTestCase {
}
// return Coordinate containing CG and volume of frustum
// still OK if foreward radius is 0 (ie a cone)
// still OK if forward radius is 0 (ie a cone)
private Coordinate calculateFrustumCG(double length, double foreRadius, double aftRadius) {
final double moment = Math.PI * pow2(length) * (pow2(foreRadius) + 2.0 * foreRadius * aftRadius + 3.0 * pow2(aftRadius))/12.0;
final double volume = Math.PI * length * (pow2(foreRadius) + foreRadius * aftRadius + pow2(aftRadius)) / 3.0;
@ -38,9 +44,7 @@ public class SymmetricComponentVolumeTest extends BaseTestCase {
// get moment and volume of outer frustum
final Coordinate fullCG = calculateFrustumCG(length, foreRadius, aftRadius);
// project thickness onto yz plane to get height
final double angle = Math.atan((aftRadius - foreRadius)/length);
final double height = thickness/Math.cos(angle);
final double height = getHeight(length, foreRadius, aftRadius, thickness);
// if aftRadius <= height the transition is filled and we don't need to mess with
// the inner frustum
@ -52,9 +56,9 @@ public class SymmetricComponentVolumeTest extends BaseTestCase {
double innerForeRad = foreRadius - height;
final double innerAftRad = aftRadius - height;
// if forward radius <= height the transition is a cone; we
// need to determine its length
if (foreRadius < height) {
// if inner forward radius <= 0 the transition is a cone; we
// need to determine its length (if it's exactly equal the inner length is the same as the outer)
if (innerForeRad < 0) {
innerLen = length * (aftRadius - height) / (aftRadius - foreRadius);
innerForeRad = 0;
}
@ -69,14 +73,17 @@ public class SymmetricComponentVolumeTest extends BaseTestCase {
return new Coordinate(moment/volume, 0, 0, volume);
}
// combine three CGs (typically forward shoulder, transition, and aft shoulder)
private Coordinate combineCG(Coordinate cg1, Coordinate cg2, Coordinate cg3) {
// combine five CGs (typically forward shoulder cap, forward shoulder, transition, aft shoulder, and aft shoulder cap)
// Use Coordinate.ZERO as a CG to combine fewer than five
private Coordinate combineCG(Coordinate cg1, Coordinate cg2, Coordinate cg3, Coordinate cg4, Coordinate cg5) {
final double moment1 = cg1.x * cg1.weight;
final double moment2 = cg2.x * cg2.weight;
final double moment3 = cg3.x * cg3.weight;
final double moment4 = cg4.x * cg4.weight;
final double moment5 = cg5.x * cg5.weight;
final double volume = cg1.weight + cg2.weight + cg3.weight;
return new Coordinate((moment1 + moment2 + moment3) / volume, 0, 0, volume);
final double volume = cg1.weight + cg2.weight + cg3.weight + cg4.weight + cg5.weight;
return new Coordinate((moment1 + moment2 + moment3 + moment4 + moment5) / volume, 0, 0, volume);
}
// check CG, volume, mass
@ -91,9 +98,136 @@ public class SymmetricComponentVolumeTest extends BaseTestCase {
assertEquals("Mass (stored in cg.weight) is incorrect", mass, cg.weight, EPSILON);
}
// calculate longitudinal moment of inertia of shoulder.
// axis through center of mass of component
private double calculateShoulderLongitudinalMOI(double length, double outerRad, double thickness, double cgShift) {
final double innerRad = Math.max(0.0, outerRad - thickness);
final double volume = length * Math.PI * (pow2(outerRad) - pow2(innerRad));
final double moi = volume * (3 * (pow2(outerRad) + pow2(innerRad)) + pow2(length)) / 12.0;
// parallel axis theorem
return moi + volume * pow2(cgShift);
}
// longitudinal MOI of a cone
// axis is through point of cone
private double calculateLongMOICone(double h, double r) {
final double m = Math.PI * pow2(r) * h / 3.0;
final double unitIyy = 3.0*pow2(r)/20.0 + 3.0*pow2(h)/5.0;
final double Iyy = m * unitIyy;
return Iyy;
}
// calculate the longitudinal moment of inertia of a solid conical frustum
// computes by calculating for two cones, and subtracting
// still OK if forward radius is 0 (ie a cone)
// axis is at forward end of frustum
private double calculateFrustumLongMOI(double length, double forwardRad, double aftRad) {
// Find the heights of the two cones.
final double h2 = length*aftRad / (aftRad - forwardRad);
final double h1 = h2*forwardRad / aftRad;
final double moi1 = calculateLongMOICone(h1, forwardRad);
final double moi2 = calculateLongMOICone(h2, aftRad);
// compute MOI relative to tip of cones (they share the same tip, of course)
double moi = moi2 - moi1;
// use parallel axis theorem to move MOI to be relative to CG of frustum
final Coordinate cg = calculateFrustumCG(length, forwardRad, aftRad);
moi = moi - pow2(cg.x + h1) * cg.weight;
// move MOI to be relative to back surface of frustum
moi = moi + pow2(length - cg.x) * cg.weight;
return moi;
}
// calculates the longitudinal moment of of inertia of a (possibly hollow) conical frustum.
// axis is through CG of frustrum
private double calculateConicalTransitionLongitudinalMOI(double length, double foreRadius, double aftRadius, double thickness, Coordinate cg, double cgShift) {
// get MOI of outer frustum, axis through base (aft end) of frustum
final double fullMOI = calculateFrustumLongMOI(length, foreRadius, aftRadius);
final double height = getHeight(length, foreRadius, aftRadius, thickness);
// if frustum is solid, MOI of inner part is 0. If not, we need to calculate it
double moi;
if (height >= aftRadius) {
moi = fullMOI;
} else {
double innerLen = length;
double innerForeRad = foreRadius - height;
final double innerAftRad = aftRadius - height;
// if inner forward radius <= 0 the transition is a cone; we
// need to determine its length (if it's exactly 0 the inner length is equal to the length
if (innerForeRad < 0) {
innerLen = length * (aftRadius - height) / (aftRadius - foreRadius);
innerForeRad = 0;
}
final double innerMOI = calculateFrustumLongMOI(innerLen, innerForeRad, innerAftRad);
moi = fullMOI - innerMOI;
}
// use parallel axis theorem to move moi relative to CG
moi = moi - pow2(length - cg.x)*cg.weight;
// now axis through component CG
return moi + cg.weight * pow2(cgShift);
}
// calculate rotational moment of inertia of shoulder
private double calculateShoulderRotationalMOI(double length, double outerRad, double thickness) {
final double innerRad = Math.max(0.0, outerRad - thickness);
return length * Math.PI * (Math.pow(outerRad, 4) - Math.pow(innerRad, 4)) / 2.0;
}
// calculate rotational moment of inertia of solid frustum
// still OK if forward radius is 0 (ie a cone)
private double calculateFrustumRotationalMOI(double length, double foreRadius, double aftRadius) {
final double unitMOI = 3.0 * (Math.pow(aftRadius, 5) - Math.pow(foreRadius, 5)) / (10.0 * (Math.pow(aftRadius, 3) - Math.pow(foreRadius, 3)));
final double volume = Math.PI * length * (pow2(foreRadius) + foreRadius * aftRadius + pow2(aftRadius)) / 3.0;
return unitMOI * volume;
}
// calculate rotational moment of inertia of transition
private double calculateConicalTransitionRotationalMOI(double length, double foreRadius, double aftRadius, double thickness) {
// get MOI of outer frustum
double fullMOI = calculateFrustumRotationalMOI(length, foreRadius, aftRadius);
final double height = getHeight(length, foreRadius, aftRadius, thickness);
// if aftRadius <= height the transition is filled and we don't need to mess with
// the inner frustum
if (aftRadius <= height) {
return fullMOI;
}
double innerLen = length;
double innerForeRad = foreRadius - height;
final double innerAftRad = aftRadius - height;
// if forward radius <= height the transition is a cone; we
// need to determine its length
if (foreRadius < height) {
innerLen = length * (aftRadius - height) / (aftRadius - foreRadius);
innerForeRad = 0;
}
final double innerMOI = calculateFrustumRotationalMOI(innerLen, innerForeRad, innerAftRad);
return fullMOI - innerMOI;
}
@Test
public void testVolumeSimpleConeFilled() {
final double length = 1.0;
final double aftRadius = 1.0;
final double density = 2.0;
@ -108,6 +242,16 @@ public class SymmetricComponentVolumeTest extends BaseTestCase {
Coordinate expectedCG = calculateConicalTransitionCG(length, 0, aftRadius, aftRadius);
checkCG(expectedCG, nc);
final double moi = calculateConicalTransitionLongitudinalMOI(length, 0, aftRadius, aftRadius, expectedCG, 0);
final double expectedLongUnitMOI = moi / expectedCG.weight;
assertEquals("Longitudinal unit MOI is incorrect", expectedLongUnitMOI, nc.getLongitudinalUnitInertia(), EPSILON);
final double expectedRotUnitMOI = calculateConicalTransitionRotationalMOI(length, 0, aftRadius, aftRadius)/expectedCG.weight;
assertEquals("Rotational unit MOI is incorrect", expectedRotUnitMOI, nc.getRotationalUnitInertia(), EPSILON);
}
@Test
@ -133,6 +277,21 @@ public class SymmetricComponentVolumeTest extends BaseTestCase {
final Coordinate expectedCG = coneCG.average(shoulderCG);
checkCG(expectedCG, nc);
double transitionLongMOI = calculateConicalTransitionLongitudinalMOI(length, 0, aftRadius, aftRadius, coneCG, expectedCG.x - coneCG.x);
double shoulderLongMOI = calculateShoulderLongitudinalMOI(length, aftRadius, aftRadius, expectedCG.x - shoulderCG.x);
double moi = shoulderLongMOI + transitionLongMOI;
moi /= expectedCG.weight;
assertEquals("Longitudinal unit MOI is incorrect", moi, nc.getLongitudinalUnitInertia(), EPSILON);
final double coneRotMOI = calculateConicalTransitionRotationalMOI(length, 0, aftRadius, aftRadius);
final double shoulderRotMOI = calculateShoulderRotationalMOI(length, aftRadius, aftRadius);
final double expectedRotUnitMOI = (coneRotMOI + shoulderRotMOI)/expectedCG.weight;
assertEquals("Rotational unit MOI is incorrect", expectedRotUnitMOI, nc.getRotationalUnitInertia(), EPSILON);
}
@Test
@ -153,6 +312,15 @@ public class SymmetricComponentVolumeTest extends BaseTestCase {
Coordinate expectedCG = calculateConicalTransitionCG(length, 0.0, aftRadius, thickness);
checkCG(expectedCG, nc);
final double expectedLongUnitMOI =
calculateConicalTransitionLongitudinalMOI(length, 0, aftRadius, thickness, expectedCG, 0.0) / expectedCG.weight;
assertEquals("Longitudinal unit MOI is incorrect", expectedLongUnitMOI, nc.getLongitudinalUnitInertia(), EPSILON);
final double expectedRotUnitMOI = calculateConicalTransitionRotationalMOI(length, 0, aftRadius, thickness)/expectedCG.weight;
assertEquals("Rotational unit MOI is incorrect", expectedRotUnitMOI, nc.getRotationalUnitInertia(), EPSILON);
}
@Test
@ -173,15 +341,30 @@ public class SymmetricComponentVolumeTest extends BaseTestCase {
nc.setAftShoulderThickness(thickness);
nc.setMaterial(Material.newMaterial(Material.Type.BULK, "test", density, true));
final Coordinate expectedConeCG = calculateConicalTransitionCG(length, 0, aftRadius, thickness);
final Coordinate expectedShoulderCG = calculateShoulderCG(length, length, aftRadius, thickness);
final Coordinate expectedCG = expectedConeCG.average(expectedShoulderCG);
final Coordinate coneCG = calculateConicalTransitionCG(length, 0, aftRadius, thickness);
final Coordinate shoulderCG = calculateShoulderCG(length, length, aftRadius, thickness);
final Coordinate expectedCG = coneCG.average(shoulderCG);
checkCG(expectedCG, nc);
final double coneLongMOI =
calculateConicalTransitionLongitudinalMOI(length, 0.0, aftRadius, thickness, coneCG, coneCG.x - expectedCG.x);
final double shoulderLongMOI =
calculateShoulderLongitudinalMOI(length, aftRadius, thickness, shoulderCG.x - expectedCG.x);
final double longUnitMOI = (coneLongMOI + shoulderLongMOI)/expectedCG.weight;
assertEquals("Longitudinal unit MOI is incorrect", longUnitMOI, nc.getLongitudinalUnitInertia(), EPSILON);
final double coneRotMOI = calculateConicalTransitionRotationalMOI(length, 0, aftRadius, thickness);
final double shoulderRotMOI = calculateShoulderRotationalMOI(length, aftRadius, thickness);
final double expectedRotUnitMOI = (coneRotMOI + shoulderRotMOI)/expectedCG.weight;
assertEquals("Rotational unit MOI is incorrect", expectedRotUnitMOI, nc.getRotationalUnitInertia(), EPSILON);
}
@Test
public void testVolumeSimpleTransitionFilled() {
final double length = 4.0;
final double foreRadius = 1.0;
final double aftRadius = 2.0;
@ -195,9 +378,18 @@ public class SymmetricComponentVolumeTest extends BaseTestCase {
nc.setAftRadius(aftRadius);
nc.setMaterial(Material.newMaterial(Material.Type.BULK, "test", density, true));
Coordinate expectedCG = calculateConicalTransitionCG(length, foreRadius, aftRadius, aftRadius);
final Coordinate expectedCG = calculateConicalTransitionCG(length, foreRadius, aftRadius, aftRadius);
checkCG(expectedCG, nc);
final double expectedLongUnitMOI =
calculateConicalTransitionLongitudinalMOI(length, foreRadius, aftRadius, aftRadius, expectedCG, 0.0) / expectedCG.weight;
assertEquals("Longitudinal unit MOI is incorrect", expectedLongUnitMOI, nc.getLongitudinalUnitInertia(), EPSILON);
final double expectedRotUnitMOI = calculateConicalTransitionRotationalMOI(length, foreRadius, aftRadius, aftRadius)/expectedCG.weight;
assertEquals("Rotational unit MOI is incorrect", expectedRotUnitMOI, nc.getRotationalUnitInertia(), EPSILON);
}
@Test
@ -227,17 +419,34 @@ public class SymmetricComponentVolumeTest extends BaseTestCase {
final Coordinate foreShoulderCG = calculateShoulderCG(-foreShoulderLength, foreShoulderLength, foreRadius, foreRadius);
final Coordinate transCG = calculateConicalTransitionCG(transLength, foreRadius, aftRadius, aftRadius);
final Coordinate aftShoulderCG = calculateShoulderCG(transLength, aftShoulderLength, aftRadius, aftRadius);
final Coordinate expectedCG = combineCG(foreShoulderCG, transCG, aftShoulderCG);
final Coordinate expectedCG = combineCG(Coordinate.ZERO, foreShoulderCG, transCG, aftShoulderCG, Coordinate.ZERO);
checkCG(expectedCG, nc);
final double foreShoulderLongMOI =
calculateShoulderLongitudinalMOI(foreShoulderLength, foreRadius, foreRadius, expectedCG.x - foreShoulderCG.x);
final double transLongMOI =
calculateConicalTransitionLongitudinalMOI(transLength, foreRadius, aftRadius, aftRadius, transCG, expectedCG.x - transCG.x);
final double aftShoulderLongMOI =
calculateShoulderLongitudinalMOI(aftShoulderLength, aftRadius, aftRadius, expectedCG.x - aftShoulderCG.x);
final double unitMOI = (foreShoulderLongMOI + transLongMOI + aftShoulderLongMOI) / expectedCG.weight;
assertEquals("Longitudinal unit MOI is incorrect", unitMOI, nc.getLongitudinalUnitInertia(), EPSILON);
final double foreShoulderRotMOI = calculateShoulderRotationalMOI(foreShoulderLength, foreRadius, foreRadius);
final double coneRotMOI = calculateConicalTransitionRotationalMOI(transLength, foreRadius, aftRadius, aftRadius);
final double aftShoulderRotMOI = calculateShoulderRotationalMOI(aftShoulderLength, aftRadius, aftRadius);
final double expectedRotUnitMOI = (foreShoulderRotMOI + coneRotMOI + aftShoulderRotMOI)/expectedCG.weight;
assertEquals("Rotational unit MOI is incorrect", expectedRotUnitMOI, nc.getRotationalUnitInertia(), EPSILON);
}
@Test
public void testVolumeSimpleTransitionHollow1() {
final double length = 1.0;
final double foreRadius = 0.5;
final double aftRadius = 0.5;
final double aftRadius = 1.0;
final double thickness = 0.5;
final double density = 2.0;
@ -252,6 +461,15 @@ public class SymmetricComponentVolumeTest extends BaseTestCase {
final Coordinate expectedCG = calculateConicalTransitionCG(length, foreRadius, aftRadius, thickness);
checkCG(expectedCG, nc);
final double expectedLongUnitMOI =
calculateConicalTransitionLongitudinalMOI(length, foreRadius, aftRadius, thickness, expectedCG, 0.0) / expectedCG.weight;
assertEquals("Longitudinal unit MOI is incorrect", expectedLongUnitMOI, nc.getLongitudinalUnitInertia(), EPSILON);
final double expectedRotUnitMOI = calculateConicalTransitionRotationalMOI(length, foreRadius, aftRadius, thickness)/expectedCG.weight;
assertEquals("Rotational unit MOI is incorrect", expectedRotUnitMOI, nc.getRotationalUnitInertia(), EPSILON);
}
@Test
@ -277,16 +495,34 @@ public class SymmetricComponentVolumeTest extends BaseTestCase {
nc.setMaterial(Material.newMaterial(Material.Type.BULK, "test", density, true));
final Coordinate foreShoulderCG = calculateShoulderCG(-length, length, foreRadius, thickness);
final Coordinate transitionCG = calculateConicalTransitionCG(length, foreRadius, aftRadius, thickness);
final Coordinate coneCG = calculateConicalTransitionCG(length, foreRadius, aftRadius, thickness);
final Coordinate aftShoulderCG = calculateShoulderCG(length, length, aftRadius, thickness);
final Coordinate expectedCG = combineCG(foreShoulderCG, transitionCG, aftShoulderCG);
final Coordinate expectedCG = combineCG(Coordinate.ZERO, foreShoulderCG, coneCG, aftShoulderCG, Coordinate.ZERO);
checkCG(expectedCG, nc);
final double foreShoulderLongMOI =
calculateShoulderLongitudinalMOI(length, foreRadius, thickness, foreShoulderCG.x - expectedCG.x);
final double coneLongMOI =
calculateConicalTransitionLongitudinalMOI(length, foreRadius, aftRadius, thickness, coneCG, coneCG.x - expectedCG.x);
final double aftShoulderLongMOI =
calculateShoulderLongitudinalMOI(length, aftRadius, thickness, aftShoulderCG.x - expectedCG.x);
final double longUnitMOI = (foreShoulderLongMOI + coneLongMOI + aftShoulderLongMOI) / expectedCG.weight;
assertEquals("Longitudinal unit MOI is incorrect", longUnitMOI, nc.getLongitudinalUnitInertia(), EPSILON);
final double foreShoulderRotMOI = calculateShoulderRotationalMOI(length, foreRadius, thickness);
final double coneRotMOI = calculateConicalTransitionRotationalMOI(length, foreRadius, aftRadius, thickness);
final double aftShoulderRotMOI = calculateShoulderRotationalMOI(length, aftRadius, thickness);
final double expectedRotUnitMOI = (foreShoulderRotMOI + coneRotMOI + aftShoulderRotMOI)/expectedCG.weight;
assertEquals("Rotational unit MOI is incorrect", expectedRotUnitMOI, nc.getRotationalUnitInertia(), EPSILON);
}
@Test
public void testVolumeSimpleTransitionHollow2() {
final double length = 1.0; // length of transition itself and each shoulder
final double length = 1.0;
final double foreRadius = 0.5;
final double aftRadius = 1.0;
final double thickness = 0.25;
@ -295,18 +531,25 @@ public class SymmetricComponentVolumeTest extends BaseTestCase {
Transition nc = new Transition();
nc.setLength(length);
nc.setShapeType(Transition.Shape.CONICAL);
nc.setForeRadius(foreRadius);
nc.setForeRadius(foreRadius);
nc.setAftRadius(aftRadius);
nc.setThickness(thickness);
nc.setMaterial(Material.newMaterial(Material.Type.BULK, "test", density, true));
final Coordinate expectedCG = calculateConicalTransitionCG(length, foreRadius, aftRadius, thickness);
checkCG(expectedCG, nc);
final double expectedLongUnitMOI =
calculateConicalTransitionLongitudinalMOI(length, foreRadius, aftRadius, thickness, expectedCG, 0.0) / expectedCG.weight;
assertEquals("Longitudinal unit MOI is incorrect", expectedLongUnitMOI, nc.getLongitudinalUnitInertia(), EPSILON);
final double expectedRotUnitMOI = calculateConicalTransitionRotationalMOI(length, foreRadius, aftRadius, thickness)/expectedCG.weight;
assertEquals("Rotational unit MOI is incorrect", expectedRotUnitMOI, nc.getRotationalUnitInertia(), EPSILON);
}
@Test
public void testVolumeSimpleTransitionWithShouldersHollow2() {
final double length = 1.0;
final double foreRadius = 0.5;
final double aftRadius = 1.0;
@ -322,22 +565,51 @@ public class SymmetricComponentVolumeTest extends BaseTestCase {
nc.setAftShoulderLength(length);
nc.setAftShoulderRadius(aftRadius);
nc.setAftShoulderThickness(thickness);
nc.setAftShoulderCapped(true);
nc.setForeShoulderLength(length);
nc.setForeShoulderRadius(foreRadius);
nc.setForeShoulderThickness(thickness);
nc.setForeShoulderCapped(true);
nc.setMaterial(Material.newMaterial(Material.Type.BULK, "test", density, true));
final Coordinate foreCapCG = calculateShoulderCG(-length, thickness, foreRadius - thickness, foreRadius);
final Coordinate foreShoulderCG = calculateShoulderCG(-length, length, foreRadius, thickness);
final Coordinate transitionCG = calculateConicalTransitionCG(length, foreRadius, aftRadius, thickness);
final Coordinate coneCG = calculateConicalTransitionCG(length, foreRadius, aftRadius, thickness);
final Coordinate aftShoulderCG = calculateShoulderCG(length, length, aftRadius, thickness);
final Coordinate expectedCG = combineCG(foreShoulderCG, transitionCG, aftShoulderCG);
final Coordinate aftCapCG = calculateShoulderCG(2.0*length - thickness, thickness, aftRadius - thickness, aftRadius);
final Coordinate expectedCG = combineCG(foreCapCG, foreShoulderCG, coneCG, aftShoulderCG, aftCapCG);
checkCG(expectedCG, nc);
final double foreCapLongMOI =
calculateShoulderLongitudinalMOI(thickness, foreRadius - thickness, foreRadius, foreCapCG.x - expectedCG.x);
final double foreShoulderLongMOI =
calculateShoulderLongitudinalMOI(length, foreRadius, thickness, foreShoulderCG.x - expectedCG.x);
final double coneLongMOI =
calculateConicalTransitionLongitudinalMOI(length, foreRadius, aftRadius, thickness, coneCG, coneCG.x - expectedCG.x);
final double aftShoulderLongMOI =
calculateShoulderLongitudinalMOI(length, aftRadius, thickness, aftShoulderCG.x - expectedCG.x);
final double aftCapLongMOI =
calculateShoulderLongitudinalMOI(thickness, aftRadius - thickness, aftRadius, aftCapCG.x - expectedCG.x);
final double expectedLongUnitMOI =
(foreCapLongMOI + foreShoulderLongMOI + coneLongMOI + aftShoulderLongMOI + aftCapLongMOI) / expectedCG.weight;
assertEquals("Longitudinal Unit MOI is incorrect", expectedLongUnitMOI, nc.getLongitudinalUnitInertia(), EPSILON);
final double foreCapRotMOI = calculateShoulderRotationalMOI(thickness, foreRadius - thickness, foreRadius);
final double foreShoulderRotMOI = calculateShoulderRotationalMOI(length, foreRadius, thickness);
final double coneRotMOI = calculateConicalTransitionRotationalMOI(length, foreRadius, aftRadius, thickness);
final double aftShoulderRotMOI = calculateShoulderRotationalMOI(length, aftRadius, thickness);
final double aftCapRotMOI = calculateShoulderRotationalMOI(thickness, aftRadius - thickness, aftRadius);
final double expectedRotUnitMOI =
(foreCapRotMOI + foreShoulderRotMOI + coneRotMOI + aftShoulderRotMOI + aftCapRotMOI)/expectedCG.weight;
assertEquals("Rotational unit MOI is incorrect", expectedRotUnitMOI, nc.getRotationalUnitInertia(), EPSILON);
}
@Test
public void testTransitionVsTubeFilled() {
System.err.println(">>>> tube filled");
// BodyTubes use closed form solutions for mass properties, while Transitions use
// numerical integration from SymmetricComponent. Properties should agree.
final double radius = 1.0;
@ -369,7 +641,6 @@ public class SymmetricComponentVolumeTest extends BaseTestCase {
@Test
public void testTransitionVsTubeHollow() {
System.err.println(">>>> tube hollow");
final double radius = 1.0;
final double innerRadius = 0.1;
final double length = 10.0;