[fix] MassCalculator now accounts for rotation in Component Assembly Instance Trees
This commit is contained in:
parent
91652e7e4f
commit
cce900d408
@ -266,18 +266,25 @@ public class MassCalculation {
|
||||
final RocketComponent component = this.root;
|
||||
final Transformation parentTransform = this.transform;
|
||||
final int instanceCount = component.getInstanceCount();
|
||||
Coordinate[] instanceLocations = component.getInstanceLocations();
|
||||
final Coordinate[] allInstanceOffsets = component.getInstanceLocations();
|
||||
final double[] allInstanceAngles = component.getInstanceAngles();
|
||||
|
||||
// // vvv DEBUG
|
||||
// if( this.config.isComponentActive(component) ){
|
||||
// System.err.println(String.format( "%s[%s]....", prefix, component.getName()));
|
||||
// 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( int currentInstanceNumber = 0; currentInstanceNumber < instanceCount; ++currentInstanceNumber) {
|
||||
final Coordinate currentInstanceOffset = allInstanceOffsets[currentInstanceNumber];
|
||||
final Transformation offsetTransform = Transformation.getTranslationTransform( currentInstanceOffset );
|
||||
|
||||
final double currentInstanceAngle = allInstanceAngles[currentInstanceNumber];
|
||||
final Transformation angleTransform = Transformation.getAxialRotation(currentInstanceAngle);
|
||||
|
||||
final Transformation currentTransform = parentTransform.applyTransformation(offsetTransform)
|
||||
.applyTransformation(angleTransform);
|
||||
|
||||
for (RocketComponent child : component.getChildren()) {
|
||||
// child data, relative to rocket reference frame
|
||||
@ -302,8 +309,9 @@ public class MassCalculation {
|
||||
|
||||
if (!component.getOverrideSubcomponents()) {
|
||||
if (component.isMassOverridden()) {
|
||||
// System.err.println("mass override=" + component.getOverrideMass());
|
||||
compCM = compCM.setWeight(MathUtil.max(component.getOverrideMass(), MIN_MASS));
|
||||
// // vvv DEBUG
|
||||
// System.err.println(String.format( "%s....mass overridden to: %s", prefix, compCM.toPreciseString()));
|
||||
}
|
||||
if (component.isCGOverridden())
|
||||
compCM = compCM.setXYZ(component.getOverrideCG());
|
||||
@ -318,7 +326,7 @@ public class MassCalculation {
|
||||
RigidBody componentInertia = new RigidBody( compCM, compIx, compIt, compIt );
|
||||
|
||||
this.addInertia( componentInertia );
|
||||
// vvv DEBUG
|
||||
// // vvv DEBUG
|
||||
// if( 0 < compCM.weight ) {
|
||||
// System.err.println(String.format( "%s....componentData: %s", prefix, compCM.toPreciseString() ));
|
||||
// }
|
||||
@ -339,7 +347,7 @@ public class MassCalculation {
|
||||
|
||||
// // 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....<< return data @ %s: %s", prefix, component.getName(), this.toCMDebug() ));
|
||||
// }
|
||||
// // ^^^ DEBUG
|
||||
|
||||
|
@ -1,24 +1,14 @@
|
||||
package net.sf.openrocket.masscalc;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import net.sf.openrocket.rocketcomponent.*;
|
||||
import net.sf.openrocket.rocketcomponent.position.AngleMethod;
|
||||
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
||||
import net.sf.openrocket.rocketcomponent.position.RadiusMethod;
|
||||
import org.junit.Test;
|
||||
|
||||
import net.sf.openrocket.motor.Motor;
|
||||
import net.sf.openrocket.rocketcomponent.AxialStage;
|
||||
import net.sf.openrocket.rocketcomponent.BodyComponent;
|
||||
import net.sf.openrocket.rocketcomponent.BodyTube;
|
||||
import net.sf.openrocket.rocketcomponent.FinSet;
|
||||
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
|
||||
import net.sf.openrocket.rocketcomponent.InnerTube;
|
||||
import net.sf.openrocket.rocketcomponent.MotorMount;
|
||||
import net.sf.openrocket.rocketcomponent.NoseCone;
|
||||
import net.sf.openrocket.rocketcomponent.Parachute;
|
||||
import net.sf.openrocket.rocketcomponent.ParallelStage;
|
||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.rocketcomponent.ShockCord;
|
||||
import net.sf.openrocket.rocketcomponent.Transition;
|
||||
import net.sf.openrocket.simulation.SimulationConditions;
|
||||
import net.sf.openrocket.simulation.SimulationStatus;
|
||||
import net.sf.openrocket.util.Coordinate;
|
||||
@ -28,7 +18,7 @@ import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
|
||||
public class MassCalculatorTest extends BaseTestCase {
|
||||
|
||||
// tolerance for compared double test results
|
||||
private static final double EPSILON = 0.000001;
|
||||
private static final double EPSILON = 0.00000001; // note: this precision matches MathUtil.java
|
||||
|
||||
@Test
|
||||
public void testAlphaIIIStructure() {
|
||||
@ -37,6 +27,7 @@ public class MassCalculatorTest extends BaseTestCase {
|
||||
rocket.setName("AlphaIII." + Thread.currentThread().getStackTrace()[1].getMethodName());
|
||||
|
||||
FlightConfiguration config = rocket.getEmptyConfiguration();
|
||||
|
||||
config.setAllStages();
|
||||
|
||||
final RigidBody actualStructure = MassCalculator.calculateStructure(config);
|
||||
@ -54,8 +45,8 @@ public class MassCalculatorTest extends BaseTestCase {
|
||||
assertEquals("Simple Rocket CM is incorrect: ", expCM, actualRocketDryCM);
|
||||
|
||||
|
||||
double expMOIrot = 5.441190348849436E-5;
|
||||
double expMOIlong = 3.03467093714368E-4;
|
||||
double expMOIrot = 5.394503232245634E-5;
|
||||
double expMOIlong = 3.029224106873237E-4;
|
||||
|
||||
double actualMOIrot = actualStructure.getRotationalInertia();
|
||||
double actualMOIlong = actualStructure.getLongitudinalInertia();
|
||||
@ -153,13 +144,15 @@ public class MassCalculatorTest extends BaseTestCase {
|
||||
RigidBody actualMotorData = MassCalculator.calculateMotor(status);
|
||||
double expMass = activeMotor.getTotalMass(simTime);
|
||||
assertEquals(" Motor Mass " + desig + " is incorrect: ", expMass, actualMotorData.getMass(), EPSILON);
|
||||
}{
|
||||
}
|
||||
{
|
||||
final double simTime = 1.03; // middle
|
||||
status.setSimulationTime(simTime);
|
||||
RigidBody actualMotorData = MassCalculator.calculateMotor(status);
|
||||
double expMass = activeMotor.getTotalMass(simTime);
|
||||
assertEquals(" Motor Mass " + desig + " is incorrect: ", expMass, actualMotorData.getMass(), EPSILON);
|
||||
}{
|
||||
}
|
||||
{
|
||||
final double simTime = 2.03; // after burnout
|
||||
status.setSimulationTime(simTime);
|
||||
RigidBody actualMotorData = MassCalculator.calculateMotor(status);
|
||||
@ -473,8 +466,8 @@ public class MassCalculatorTest extends BaseTestCase {
|
||||
final RigidBody actualStructureData = MassCalculator.calculateStructure(config);
|
||||
final Coordinate actualCM = actualStructureData.cm;
|
||||
|
||||
double expMass = 0.116287;
|
||||
double expCMx = 0.278070785749;
|
||||
double expMass = 0.1162869499;
|
||||
double expCMx = 0.2780707857;
|
||||
assertEquals("Upper Stage Mass is incorrect: ", expMass, actualCM.weight, EPSILON);
|
||||
|
||||
assertEquals("Upper Stage CM.x is incorrect: ", expCMx, actualCM.x, EPSILON);
|
||||
@ -849,4 +842,67 @@ public class MassCalculatorTest extends BaseTestCase {
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSimplePhantomPodRocket() {
|
||||
Rocket rocket = new Rocket();
|
||||
rocket.setName("Test Phantom Pods");
|
||||
|
||||
rocket.createFlightConfiguration(TestRockets.TEST_FCID_0);
|
||||
rocket.setSelectedConfiguration(TestRockets.TEST_FCID_0);
|
||||
final FlightConfiguration config = rocket.getSelectedConfiguration();
|
||||
|
||||
final AxialStage stage = new AxialStage();
|
||||
stage.setName("Primary Stage");
|
||||
rocket.addChild(stage);
|
||||
|
||||
final BodyTube primaryBody = new BodyTube(0.4, 0.02);
|
||||
primaryBody.setThickness(0.001);
|
||||
primaryBody.setName("Primary Body");
|
||||
stage.addChild(primaryBody);
|
||||
|
||||
final PodSet pods = new PodSet();
|
||||
pods.setName("Pods");
|
||||
pods.setInstanceCount(2);
|
||||
primaryBody.addChild(pods);
|
||||
pods.setAxialMethod(AxialMethod.BOTTOM); pods.setAxialOffset(0.0);
|
||||
pods.setAngleMethod(AngleMethod.RELATIVE); pods.setAngleOffset(0.0);
|
||||
pods.setRadiusMethod(RadiusMethod.FREE); pods.setRadiusOffset(0.04);
|
||||
|
||||
final BodyTube podBody = new BodyTube(0.0, 0.02);
|
||||
podBody.setThickness(0.001);
|
||||
podBody.setName("Primary Body");
|
||||
pods.addChild(podBody);
|
||||
|
||||
final TrapezoidFinSet fins = new TrapezoidFinSet(1, 0.05, 0.05, 0.0, 0.001);
|
||||
fins.setName("podFins");
|
||||
fins.setThickness(0.01);
|
||||
fins.setMassOverridden(true); fins.setOverrideMass(0.02835);
|
||||
fins.setOverrideSubcomponents(false);
|
||||
fins.setAxialOffset(-0.01); fins.setAxialMethod(AxialMethod.BOTTOM);
|
||||
podBody.addChild(fins);
|
||||
|
||||
rocket.enableEvents();
|
||||
config.setAllStages();
|
||||
|
||||
// =======================================================================
|
||||
|
||||
// DEBUG
|
||||
System.err.println(rocket.toDebugTree());
|
||||
|
||||
RigidBody structure = MassCalculator.calculateStructure(config);
|
||||
final double expMass = 0.0900260149;
|
||||
double calcTotalMass = structure.getMass();
|
||||
assertEquals(" Booster Launch Mass is incorrect: ", expMass, calcTotalMass, EPSILON);
|
||||
|
||||
final double expCMx = 0.3039199615;
|
||||
final double expCMy = 0.0;
|
||||
final double expCMz = 0.0;
|
||||
Coordinate expCM = new Coordinate(expCMx, expCMy, expCMz, expMass);
|
||||
assertEquals(" Booster Launch CM.x is incorrect: ", expCM.x, structure.getCM().x, EPSILON);
|
||||
assertEquals(" Booster Launch CM.y is incorrect: ", expCM.y, structure.getCM().y, EPSILON);
|
||||
assertEquals(" Booster Launch CM.z is incorrect: ", expCM.z, structure.getCM().z, EPSILON);
|
||||
assertEquals(" Booster Launch CM is incorrect: ", expCM, structure.getCM());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user