Changed logging in BarrowmanCalculator.java to use stderr (easier to

use with unittest)

Added "End Plate Test" rocket to TestRockets and BarrowmanCalcTest
This commit is contained in:
JoePfeiffer 2019-02-04 11:34:35 -07:00
parent 2e7b3da1c0
commit 13f7c583fd
4 changed files with 183 additions and 21 deletions

View File

@ -11,9 +11,6 @@ import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sf.openrocket.aerodynamics.barrowman.FinSetCalc;
import net.sf.openrocket.aerodynamics.barrowman.RocketComponentCalc;
import net.sf.openrocket.rocketcomponent.ComponentAssembly;
@ -43,9 +40,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
private static final String BARROWMAN_PACKAGE = "net.sf.openrocket.aerodynamics.barrowman";
private static final String BARROWMAN_SUFFIX = "Calc";
private static final Logger log = LoggerFactory.getLogger(BarrowmanCalculator.class);
private Map<RocketComponent, RocketComponentCalc> calcMap = null;
private double cacheDiameter = -1;
@ -193,8 +187,8 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
for(Map.Entry<RocketComponent, ArrayList<InstanceContext>> entry: imap.entrySet() ) {
final RocketComponent comp = entry.getKey();
RocketComponentCalc calcObj = calcMap.get(comp);
log.debug("comp=" + comp);
// System.err.println("comp=" + comp);
if (null != calcObj) {
// iterate across component instances
final ArrayList<InstanceContext> contextList = entry.getValue();
@ -209,23 +203,23 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
AerodynamicForces instanceForces = new AerodynamicForces().zero();
calcObj.calculateNonaxialForces(conditions, context.transform, instanceForces, warnings);
log.debug("instanceForces[" + context.instanceNumber + "]=" + instanceForces);
Coordinate cp_comp = instanceForces.getCP();
Coordinate cp_abs = context.transform.transform(cp_comp);
if ((comp instanceof FinSet) && (((FinSet)comp).getFinCount() > 2))
cp_abs = cp_abs.setY(0.0).setZ(0.0);
instanceForces.setCP(cp_abs);
double CN_instanced = instanceForces.getCN();
instanceForces.setCm(CN_instanced * instanceForces.getCP().x / conditions.getRefLength());
log.debug("instanceForces=" + instanceForces);
// System.err.println("instanceForces=" + instanceForces);
assemblyForces.merge(instanceForces);
}
}
}
}
log.debug("assemblyForces=" + assemblyForces);
// System.err.println("assemblyForces=" + assemblyForces);
return assemblyForces;
}

View File

@ -331,9 +331,9 @@ public final class Coordinate implements Cloneable, Serializable {
@Override
public String toString() {
if (isWeighted())
return String.format("(%.3f,%.3f,%.3f,w=%.3f)", x, y, z, weight);
return String.format("(%.5f,%.5f,%.5f,w=%.5f)", x, y, z, weight);
else
return String.format("(%.3f,%.3f,%.3f)", x, y, z);
return String.format("(%.5f,%.5f,%.5f)", x, y, z);
}
// high-precision output, for use with verifying calculations

View File

@ -3,6 +3,7 @@ package net.sf.openrocket.util;
import java.util.Random;
import net.sf.openrocket.appearance.Appearance;
import net.sf.openrocket.file.openrocket.OpenRocketSaver;
import net.sf.openrocket.database.Databases;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.OpenRocketDocumentFactory;
@ -39,6 +40,7 @@ import net.sf.openrocket.rocketcomponent.MassComponent;
import net.sf.openrocket.rocketcomponent.NoseCone;
import net.sf.openrocket.rocketcomponent.Parachute;
import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.PodSet;
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import net.sf.openrocket.rocketcomponent.ReferenceType;
import net.sf.openrocket.rocketcomponent.Rocket;
@ -851,6 +853,14 @@ public class TestRockets {
// This function is used for unit, integration tests, DO NOT CHANGE (without updating tests).
// Comments starting with cp: are center of pressure calculations
// for components of the rocket. Note that a cp: without a weight
// has a weight of 0 (see for example body tubes) -- included for
// completeness.
// Instanced components (ie components on the side boosters) have
// a cp: for each instance.
// The unit tests change the number of fins on the side boosters;
// cp: comments are shown for 1-fin, 2-fin, and 3-fin cases
public static Rocket makeFalcon9Heavy() {
Rocket rocket = new Rocket();
rocket.setName("Falcon9H Scale Rocket");
@ -876,10 +886,12 @@ public class TestRockets {
payloadFairingNoseCone.setAftShoulderThickness( 0.001 );
payloadFairingNoseCone.setAftShoulderCapped( false );
payloadStage.addChild(payloadFairingNoseCone);
// cp:(0.05900,0.00000,0.00000,w=2.00000)
BodyTube payloadBody = new BodyTube(0.132, 0.052, 0.001);
payloadBody.setName("PL Fairing Body");
payloadStage.addChild(payloadBody);
// cp:(0.18400,0.00000,0.00000)
Transition payloadFairingTail = new Transition();
payloadFairingTail.setName("PL Fairing Transition");
@ -888,10 +900,12 @@ public class TestRockets {
payloadFairingTail.setForeRadiusAutomatic(true);
payloadFairingTail.setAftRadiusAutomatic(true);
payloadStage.addChild(payloadFairingTail);
// cp:(0.25665,0.00000,0.00000,w=-0.90366)
BodyTube upperStageBody= new BodyTube(0.18, 0.0385, 0.001);
upperStageBody.setName("Upper Stage Body ");
payloadStage.addChild( upperStageBody);
// cp:(0.35400,0.00000,0.00000)
{
// Parachute
@ -916,6 +930,7 @@ public class TestRockets {
BodyTube interstage= new BodyTube(0.12, 0.0385, 0.001);
interstage.setName("Interstage");
payloadStage.addChild( interstage);
// cp:(0.50400,0.00000,0.00000)
}
// ====== Core Stage ======
@ -930,6 +945,7 @@ public class TestRockets {
coreBody.setName("Core Stage Body");
coreBody.setMotorMount(true);
coreStage.addChild( coreBody);
// cp:(0.96400,0.00000,0.00000)
{
MotorConfiguration coreMotorConfig = new MotorConfiguration(coreBody, selFCID);
Motor mtr = TestRockets.generateMotor_M1350_75mm();
@ -961,12 +977,15 @@ public class TestRockets {
boosterCone.setAftShoulderThickness( 0.001 );
boosterCone.setAftShoulderCapped( false );
boosterStage.addChild( boosterCone);
// cp:(0.52400,0.07700,0.00000,w=1.09634)
// cp:(0.52400,-0.07700,0.00000,w=1.09634)
BodyTube boosterBody = new BodyTube(0.8, 0.0385, 0.001);
boosterBody.setName("Booster Body");
boosterBody.setOuterRadiusAutomatic(true);
boosterStage.addChild( boosterBody);
// cp:(0.96400,0.07700,0.00000)
// cp:(0.96400,-0.07700,0.00000)
{
InnerTube boosterMotorTubes = new InnerTube();
boosterMotorTubes.setName("Booster Motor Tubes");
@ -997,6 +1016,12 @@ public class TestRockets {
boosterFins.setSweep(0.18);
boosterFins.setAxialMethod(AxialMethod.BOTTOM);
boosterFins.setAxialOffset(0.0);
// cp:(1.17873,0.10422,0.02722,w=6.07405) (1 fin case)
// cp:(1.17873,-0.10422,-0.02722,w=6.07405) (1 fin case)
// cp:(1.17873,0.10422,0.02722,w=12.14810) (2 fin case)
// cp:(1.17873,-0.10422,-0.02722,w=12.14810) (2 fin case)
// cp:(1.17873,0.00000,0.00000,w=9.11107) (3 fin case)
// cp:(1.17873,0.00000,0.00000,w=9.11107) (3 fin case)
}
}
@ -1009,6 +1034,128 @@ public class TestRockets {
return rocket;
}
// This is a simple four-fin rocket with large endplates on the
// fins, for testing CG and CP calculations with fins on pods.
// not a complete rocket (no motor mount nor recovery system)
// it's parameterized to make things easy to change, but be sure
// to adjust the unit test to match!
public static Rocket makeEndPlateRocket() {
// rocket design parameters
double radius = 0.01; // note this is diameter/2!
int finCount = 4; // also determines pod count
// nose cone
double noseThick = 0.002;
double noseLength = 0.05;
// body tube
double bodyWallThick = 0.002;
double bodyLength = 0.254;
// main body tube fins
int bodyFinCount = 4;
double bodyFinRootChord = 0.05;
double bodyFinTipChord = bodyFinRootChord;
double bodyFinHeight = 0.025;
double bodyFinSweep = 0.0;
AxialMethod bodyFinAxialMethod = AxialMethod.BOTTOM;
double bodyFinAxialOffset = 0.0;
double bodyFinThickness = 0.003;
// pods for end plates
int podSetCount = bodyFinCount;
double podSetOffset = bodyFinHeight;
AxialMethod podSetAxialMethod = bodyFinAxialMethod;
double podSetAxialOffset = 0.0;
// "phantom" tube on pods to give us somewhere to connect end
// plates
double phantomLength = bodyFinTipChord;
double phantomRadius = 0;
double phantomWallThickness = 0;
// end plates
int endPlateCount = 2;
double endPlateRootChord = bodyFinTipChord;
double endPlateTipChord = endPlateRootChord;
double endPlateSweep = 0.0;
double endPlateThickness = bodyFinThickness;
double endPlateHeight = bodyFinHeight;
double endPlateRotation = Math.PI/2.0;
AxialMethod endPlateAxialMethod = AxialMethod.BOTTOM;
double endPlateAxialOffset = 0;
// create bare rocket
Rocket rocket = new Rocket();
rocket.enableEvents();
rocket.setName("End Plate Test");
// rocket has one stage
AxialStage sustainer = new AxialStage();
rocket.addChild(sustainer);
sustainer.setName("Sustainer");
// nose cone
NoseCone noseCone = new NoseCone(Transition.Shape.OGIVE, noseLength, radius);
sustainer.addChild(noseCone);
noseCone.setName("Nose Cone");
// cp:(0.02303,0.00000,0.00000,w=2.00000)
// body tube
BodyTube bodyTube = new BodyTube(bodyLength, radius, bodyWallThick);
sustainer.addChild(bodyTube);
bodyTube.setName("Body tube");
// cp:(0.17700,0.00000,0.00000)
// Trapezoidal fin set on body tube
TrapezoidFinSet bodyFinSet = new TrapezoidFinSet(bodyFinCount, bodyFinRootChord, bodyFinTipChord, bodyFinSweep, bodyFinHeight);
bodyTube.addChild(bodyFinSet);
bodyFinSet.setName("Body Tube FinSet");
bodyFinSet.setAxialMethod(bodyFinAxialMethod);
bodyFinSet.setAxialOffset(bodyFinAxialOffset);
bodyFinSet.setThickness(bodyFinThickness);
// cp:(0.26650,0.00000,0.00000,w=15.24857)
// Pod set to put an end plate on each fin
PodSet podSet = new PodSet();
bodyTube.addChild(podSet);
podSet.setName("Pod Set");
podSet.setInstanceCount(podSetCount);
podSet.setRadiusOffset(podSetOffset);
podSet.setAxialMethod(podSetAxialMethod);
podSet.setAxialOffset(podSetAxialOffset);
// 0-diameter "body tube" to give us something to hook the
// endplates to. Note that this causes a "thick fins"
// warning.
BodyTube phantom = new BodyTube(phantomLength, phantomRadius, phantomWallThickness);
podSet.addChild(phantom);
phantom.setName("Phantom");
// cp:(0.25400,0.03540,0.00000)
// cp:(0.25400,0.00000,0.03540)
// cp:(0.25400,-0.03540,0.00000)
// cp:(0.25400,-0.00000,-0.03540)
// end plates
TrapezoidFinSet endPlate = new TrapezoidFinSet(endPlateCount, endPlateRootChord, endPlateTipChord, endPlateSweep, endPlateHeight);
phantom.addChild(endPlate);
endPlate.setName("End plates");
endPlate.setBaseRotation(endPlateRotation);
endPlate.setAxialMethod(endPlateAxialMethod);
endPlate.setAxialOffset(endPlateAxialOffset);
endPlate.setThickness(endPlateThickness);
// cp:(0.26650,0.03540,0.00000,w=0.00000)
// cp:(0.26650,0.00000,0.03540,w=11.86000)
// cp:(0.26650,-0.03540,0.00000,w=0.00000)
// cp:(0.26650,-0.00000,-0.03540,w=11.86000)
// Total cp:(0.25461,-0.00000,0.00000,w=40.96857)
return rocket;
}
/*
* Create a new file version 1.00 rocket
@ -1406,6 +1553,7 @@ public class TestRockets {
public static OpenRocketDocument makeTestRocket_v108_withBoosters() {
Rocket rocket = makeFalcon9Heavy();
OpenRocketDocument document = OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
return document;
}

View File

@ -86,7 +86,7 @@ public class BarrowmanCalculatorTest {
assertEquals(" Estes Alpha III CNa value is incorrect:", exp_cna, cp_calc.weight, EPSILON);
assertEquals(" Estes Alpha III cp x value is incorrect:", exp_cpx, cp_calc.x, EPSILON);
assertEquals(" Estes Alpha III cp x value is incorrect:", 0.0, cp_calc.y, EPSILON);
assertEquals(" Estes Alpha III cp y value is incorrect:", 0.0, cp_calc.y, EPSILON);
}
@Test
@ -107,7 +107,8 @@ public class BarrowmanCalculatorTest {
assertEquals(" Estes Alpha III cp x value is incorrect:", expCPx, calcCP.x, EPSILON);
assertEquals(" Estes Alpha III CNa value is incorrect:", exp_cna, calcCP.weight, EPSILON);
}
// Component CP calculations resulting in expected test values are in comments in TestRockets.makeFalcon9Heavy()
@Test
public void testCPParallelBoosters() {
final Rocket rocket = TestRockets.makeFalcon9Heavy();
@ -128,21 +129,40 @@ public class BarrowmanCalculatorTest {
}{
boosterFins.setFinCount(2);
final Coordinate cp_2fin = calc.getCP(config, conditions, warnings);
assertEquals(" Falcon 9 Heavy CNa value is incorrect:", 15.43711197, cp_2fin.weight, EPSILON);
assertEquals(" Falcon 9 Heavy CP x value is incorrect:", 0.99464238, cp_2fin.x, EPSILON);
assertEquals(" Falcon 9 Heavy CNa value is incorrect:", 27.585207667168696, cp_2fin.weight, EPSILON);
assertEquals(" Falcon 9 Heavy CP x value is incorrect:", 1.0757127676940474, cp_2fin.x, EPSILON);
assertEquals(" Falcon 9 Heavy CP y value is incorrect:", 0.0, cp_2fin.y, EPSILON);
assertEquals(" Falcon 9 Heavy CP z value is incorrect:", 0.0, cp_2fin.z, EPSILON);
}{
boosterFins.setFinCount(1);
final Coordinate cp_1fin = calc.getCP(config, conditions, warnings);
assertEquals(" Falcon 9 Heavy CNa value is incorrect:", 9.36306412, cp_1fin.weight, EPSILON);
assertEquals(" Falcon 9 Heavy CP x value is incorrect:", 0.87521867, cp_1fin.x, EPSILON);
assertEquals(" Falcon 9 Heavy CNa value is incorrect:", 15.43711196967902, cp_1fin.weight, EPSILON);
assertEquals(" Falcon 9 Heavy CP x value is incorrect:", 0.99464, cp_1fin.x, EPSILON);
assertEquals(" Falcon 9 Heavy CP y value is incorrect:", 0f, cp_1fin.y, EPSILON);
assertEquals(" Falcon 9 Heavy CP z value is incorrect:", 0f, cp_1fin.z, EPSILON);
}{
// absent -- 3.28901627g @[0.31469937,0.05133333,0.00000000]
}
}
// test rocket with endplates on fins. Comments tracing
// calculation of CP are in TestRockets.makeEndPlateRocket().
@Test
public void testEndPlateCP() {
final Rocket rocket = TestRockets.makeEndPlateRocket();
final FlightConfiguration config = new FlightConfiguration(rocket, null);
// rocket.setFlightConfiguration(config.getId(), config);
// rocket.setSelectedConfiguration(config.getId());
final AerodynamicCalculator calc = new BarrowmanCalculator();
final FlightConditions conditions = new FlightConditions(config);
final WarningSet warnings = new WarningSet();
final Coordinate cp = calc.getCP(config, conditions, warnings);
assertEquals(" Endplate rocket cp x value is incorrect:", 0.25461, cp.x, EPSILON);
assertEquals(" Endplate rocket cp y value is incorrect:", 0.0, cp.y, EPSILON);
assertEquals(" Endplate rocket cp z value is incorrect:", 0.0, cp.z, EPSILON);
assertEquals(" Endplate rocket CNa value is incorrect:", 40.96857, cp.weight, EPSILON);
}
@Test
public void testGetWorstCP() {