Update SymmetricComponentVolumeTest to check moments of inertia
This commit is contained in:
parent
5b18f73da0
commit
6af25c3f4a
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user