Merge pull request #603 from JoePfeiffer/fix-568
[Fixes 568] Consider all instances of components when calculating drag
This commit is contained in:
commit
18a8caa5b7
@ -388,90 +388,100 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
|
||||
|
||||
double finFriction = 0;
|
||||
double bodyFriction = 0;
|
||||
double maxR = 0, len = 0;
|
||||
double maxR = 0, minX = Double.MAX_VALUE, maxX = 0;
|
||||
|
||||
double[] roughnessLimited = new double[Finish.values().length];
|
||||
Arrays.fill(roughnessLimited, Double.NaN);
|
||||
|
||||
for (RocketComponent c : configuration.getActiveComponents()) {
|
||||
|
||||
final InstanceMap imap = configuration.getActiveInstances();
|
||||
for(Map.Entry<RocketComponent, ArrayList<InstanceContext>> entry: imap.entrySet() ) {
|
||||
final RocketComponent c = entry.getKey();
|
||||
|
||||
// Consider only SymmetricComponents and FinSets:
|
||||
if (!(c instanceof SymmetricComponent) &&
|
||||
!(c instanceof FinSet))
|
||||
continue;
|
||||
|
||||
// Calculate the roughness-limited friction coefficient
|
||||
Finish finish = ((ExternalComponent) c).getFinish();
|
||||
if (Double.isNaN(roughnessLimited[finish.ordinal()])) {
|
||||
roughnessLimited[finish.ordinal()] =
|
||||
0.032 * Math.pow(finish.getRoughnessSize() / configuration.getLength(), 0.2) *
|
||||
roughnessCorrection;
|
||||
}
|
||||
|
||||
/*
|
||||
* Actual Cf is maximum of Cf and the roughness-limited value.
|
||||
* For perfect finish require additionally that Re > 1e6
|
||||
*/
|
||||
double componentCf;
|
||||
if (configuration.getRocket().isPerfectFinish()) {
|
||||
|
||||
// For perfect finish require Re > 1e6
|
||||
if ((Re > 1.0e6) && (roughnessLimited[finish.ordinal()] > Cf)) {
|
||||
componentCf = roughnessLimited[finish.ordinal()];
|
||||
} else {
|
||||
componentCf = Cf;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// For fully turbulent use simple max
|
||||
componentCf = Math.max(Cf, roughnessLimited[finish.ordinal()]);
|
||||
|
||||
}
|
||||
|
||||
//Handle Overriden CD for Whole Rocket
|
||||
if(c.isCDOverridden()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Calculate the friction drag:
|
||||
if (c instanceof SymmetricComponent) {
|
||||
|
||||
SymmetricComponent s = (SymmetricComponent) c;
|
||||
|
||||
bodyFriction += componentCf * s.getComponentWetArea();
|
||||
|
||||
if (map != null) {
|
||||
// Corrected later
|
||||
map.get(c).setFrictionCD(componentCf * s.getComponentWetArea()
|
||||
/ conditions.getRefArea());
|
||||
}
|
||||
|
||||
double r = Math.max(s.getForeRadius(), s.getAftRadius());
|
||||
if (r > maxR)
|
||||
maxR = r;
|
||||
len += c.getLength();
|
||||
|
||||
} else if (c instanceof FinSet) {
|
||||
|
||||
FinSet f = (FinSet) c;
|
||||
double mac = ((FinSetCalc) calcMap.get(c)).getMACLength();
|
||||
double cd = componentCf * (1 + 2 * f.getThickness() / mac) *
|
||||
2 * f.getFinCount() * f.getPlanformArea();
|
||||
finFriction += cd;
|
||||
|
||||
if (map != null) {
|
||||
map.get(c).setFrictionCD(cd / conditions.getRefArea());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// iterate across component instances
|
||||
final ArrayList<InstanceContext> contextList = entry.getValue();
|
||||
for(InstanceContext context: contextList ) {
|
||||
|
||||
// Calculate the roughness-limited friction coefficient
|
||||
Finish finish = ((ExternalComponent) c).getFinish();
|
||||
if (Double.isNaN(roughnessLimited[finish.ordinal()])) {
|
||||
roughnessLimited[finish.ordinal()] =
|
||||
0.032 * Math.pow(finish.getRoughnessSize() / configuration.getLength(), 0.2) *
|
||||
roughnessCorrection;
|
||||
}
|
||||
|
||||
/*
|
||||
* Actual Cf is maximum of Cf and the roughness-limited value.
|
||||
* For perfect finish require additionally that Re > 1e6
|
||||
*/
|
||||
double componentCf;
|
||||
if (configuration.getRocket().isPerfectFinish()) {
|
||||
|
||||
// For perfect finish require Re > 1e6
|
||||
if ((Re > 1.0e6) && (roughnessLimited[finish.ordinal()] > Cf)) {
|
||||
componentCf = roughnessLimited[finish.ordinal()];
|
||||
} else {
|
||||
componentCf = Cf;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// For fully turbulent use simple max
|
||||
componentCf = Math.max(Cf, roughnessLimited[finish.ordinal()]);
|
||||
|
||||
}
|
||||
|
||||
//Handle Overriden CD for Whole Rocket
|
||||
if(c.isCDOverridden()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Calculate the friction drag:
|
||||
if (c instanceof SymmetricComponent) {
|
||||
|
||||
SymmetricComponent s = (SymmetricComponent) c;
|
||||
|
||||
bodyFriction += componentCf * s.getComponentWetArea();
|
||||
|
||||
if (map != null) {
|
||||
// Corrected later
|
||||
map.get(c).setFrictionCD(componentCf * s.getComponentWetArea()
|
||||
/ conditions.getRefArea());
|
||||
}
|
||||
|
||||
final double componentMinX = context.getLocation().x;
|
||||
minX = Math.min(minX, componentMinX);
|
||||
|
||||
final double componentMaxX = componentMinX + c.getLength();
|
||||
maxX = Math.max(maxX, componentMaxX);
|
||||
|
||||
final double componentMaxR = Math.max(s.getForeRadius(), s.getAftRadius());
|
||||
maxR = Math.max(maxR, componentMaxR);
|
||||
|
||||
} else if (c instanceof FinSet) {
|
||||
|
||||
FinSet f = (FinSet) c;
|
||||
double mac = ((FinSetCalc) calcMap.get(c)).getMACLength();
|
||||
double cd = componentCf * (1 + 2 * f.getThickness() / mac) *
|
||||
2 * f.getPlanformArea();
|
||||
finFriction += cd;
|
||||
|
||||
if (map != null) {
|
||||
map.get(c).setFrictionCD(cd / conditions.getRefArea());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// fB may be POSITIVE_INFINITY, but that's ok for us
|
||||
double fB = (len + 0.0001) / maxR;
|
||||
double fB = (maxX - minX + 0.0001) / maxR;
|
||||
double correction = (1 + 1.0 / (2 * fB));
|
||||
|
||||
// Correct body data in map
|
||||
@ -482,8 +492,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return (finFriction + correction * bodyFriction) / conditions.getRefArea();
|
||||
}
|
||||
@ -502,7 +510,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
|
||||
Map<RocketComponent, AerodynamicForces> map, WarningSet warnings) {
|
||||
|
||||
double stagnation, base, total;
|
||||
double radius = 0;
|
||||
|
||||
if (calcMap == null)
|
||||
buildCalcMap(configuration);
|
||||
@ -511,43 +518,54 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
|
||||
base = calculateBaseCD(conditions.getMach());
|
||||
|
||||
total = 0;
|
||||
for (RocketComponent c : configuration.getActiveComponents()) {
|
||||
final InstanceMap imap = configuration.getActiveInstances();
|
||||
for(Map.Entry<RocketComponent, ArrayList<InstanceContext>> entry: imap.entrySet() ) {
|
||||
final RocketComponent c = entry.getKey();
|
||||
if (!c.isAerodynamic())
|
||||
continue;
|
||||
|
||||
// Pressure fore drag
|
||||
double cd = calcMap.get(c).calculatePressureDragForce(conditions, stagnation, base,
|
||||
warnings);
|
||||
total += cd;
|
||||
|
||||
if (map != null) {
|
||||
map.get(c).setPressureCD(cd);
|
||||
}
|
||||
|
||||
if(c.isCDOverridden()) continue;
|
||||
|
||||
|
||||
// Stagnation drag
|
||||
if (c instanceof SymmetricComponent) {
|
||||
SymmetricComponent s = (SymmetricComponent) c;
|
||||
|
||||
if (radius < s.getForeRadius()) {
|
||||
double area = Math.PI * (pow2(s.getForeRadius()) - pow2(radius));
|
||||
cd = stagnation * area / conditions.getRefArea();
|
||||
total += cd;
|
||||
if (map != null) {
|
||||
map.get(c).setPressureCD(map.get(c).getPressureCD() + cd);
|
||||
}
|
||||
// iterate across component instances
|
||||
final ArrayList<InstanceContext> contextList = entry.getValue();
|
||||
for(InstanceContext context: contextList ) {
|
||||
|
||||
// Pressure fore drag
|
||||
double cd = calcMap.get(c).calculatePressureDragForce(conditions, stagnation, base,
|
||||
warnings);
|
||||
total += cd;
|
||||
|
||||
if (map != null) {
|
||||
map.get(c).setPressureCD(cd);
|
||||
}
|
||||
|
||||
radius = s.getAftRadius();
|
||||
if(c.isCDOverridden())
|
||||
continue;
|
||||
|
||||
// Stagnation drag
|
||||
if (c instanceof SymmetricComponent) {
|
||||
SymmetricComponent s = (SymmetricComponent) c;
|
||||
|
||||
double radius = 0;
|
||||
final SymmetricComponent prevComponent = s.getPreviousSymmetricComponent();
|
||||
if (prevComponent != null)
|
||||
radius = prevComponent.getAftRadius();
|
||||
|
||||
if (radius < s.getForeRadius()) {
|
||||
double area = Math.PI * (pow2(s.getForeRadius()) - pow2(radius));
|
||||
cd = stagnation * area / conditions.getRefArea();
|
||||
total += cd;
|
||||
|
||||
if (map != null) {
|
||||
map.get(c).setPressureCD(map.get(c).getPressureCD() + cd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Calculation of drag coefficient due to base
|
||||
*
|
||||
@ -558,11 +576,9 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
|
||||
* @return
|
||||
*/
|
||||
private double calculateBaseDrag(FlightConfiguration configuration, FlightConditions conditions,
|
||||
Map<RocketComponent, AerodynamicForces> map, WarningSet warnings) {
|
||||
Map<RocketComponent, AerodynamicForces> map, WarningSet warnings) {
|
||||
|
||||
double base, total;
|
||||
double radius = 0;
|
||||
RocketComponent prevComponent = null;
|
||||
|
||||
if (calcMap == null)
|
||||
buildCalcMap(configuration);
|
||||
@ -570,36 +586,51 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
|
||||
base = calculateBaseCD(conditions.getMach());
|
||||
total = 0;
|
||||
|
||||
for (RocketComponent c : configuration.getActiveComponents()) {
|
||||
final InstanceMap imap = configuration.getActiveInstances();
|
||||
for(Map.Entry<RocketComponent, ArrayList<InstanceContext>> entry: imap.entrySet() ) {
|
||||
final RocketComponent c = entry.getKey();
|
||||
|
||||
if (!(c instanceof SymmetricComponent))
|
||||
continue;
|
||||
|
||||
SymmetricComponent s = (SymmetricComponent) c;
|
||||
|
||||
if(c.isCDOverridden()) {
|
||||
total += c.getOverrideCD();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (radius > s.getForeRadius()) {
|
||||
double area = Math.PI * (pow2(radius) - pow2(s.getForeRadius()));
|
||||
double cd = base * area / conditions.getRefArea();
|
||||
total += cd;
|
||||
if (map != null) {
|
||||
map.get(prevComponent).setBaseCD(cd);
|
||||
// iterate across component instances
|
||||
final ArrayList<InstanceContext> contextList = entry.getValue();
|
||||
for(InstanceContext context: contextList ) {
|
||||
if(c.isCDOverridden()) {
|
||||
total += c.getOverrideCD();
|
||||
continue;
|
||||
}
|
||||
|
||||
// if aft radius of previous component is greater than my forward radius, set
|
||||
// its aft CD
|
||||
double radius = 0;
|
||||
final SymmetricComponent prevComponent = s.getPreviousSymmetricComponent();
|
||||
if (prevComponent != null) {
|
||||
radius = prevComponent.getAftRadius();
|
||||
}
|
||||
|
||||
if (radius > s.getForeRadius()) {
|
||||
double area = Math.PI * (pow2(radius) - pow2(s.getForeRadius()));
|
||||
double cd = base * area / conditions.getRefArea();
|
||||
total += cd;
|
||||
if ((map != null) && (prevComponent != null)) {
|
||||
map.get(prevComponent).setBaseCD(cd);
|
||||
}
|
||||
}
|
||||
|
||||
// if I'm the last componenet, set my base CD
|
||||
// note I can't depend on the iterator serving up components in order,
|
||||
// so I can't just do this after the last iteration.
|
||||
if (s.getNextSymmetricComponent() == null) {
|
||||
double area = Math.PI * pow2(s.getAftRadius());
|
||||
double cd = base * area / conditions.getRefArea();
|
||||
total += cd;
|
||||
if (map != null) {
|
||||
map.get(s).setBaseCD(cd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
radius = s.getAftRadius();
|
||||
prevComponent = c;
|
||||
}
|
||||
|
||||
if (radius > 0) {
|
||||
double area = Math.PI * pow2(radius);
|
||||
double cd = base * area / conditions.getRefArea();
|
||||
total += cd;
|
||||
if (map != null) {
|
||||
map.get(prevComponent).setBaseCD(cd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -645,7 +645,7 @@ public class FinSetCalc extends RocketComponentCalc {
|
||||
// Airfoil assumed to have zero base drag
|
||||
|
||||
// Scale to correct reference area
|
||||
drag *= finCount * span * thickness / conditions.getRefArea();
|
||||
drag *= span * thickness / conditions.getRefArea();
|
||||
|
||||
return drag;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import net.sf.openrocket.preset.ComponentPreset;
|
||||
import net.sf.openrocket.rocketcomponent.PodSet;
|
||||
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
||||
import net.sf.openrocket.util.Coordinate;
|
||||
import net.sf.openrocket.util.MathUtil;
|
||||
@ -561,34 +562,37 @@ public abstract class SymmetricComponent extends BodyComponent implements Radial
|
||||
|
||||
/**
|
||||
* Return the previous symmetric component, or null if none exists.
|
||||
* NOTE: This method currently assumes that there are no external
|
||||
* "pods".
|
||||
*
|
||||
* @return the previous SymmetricComponent, or null.
|
||||
*/
|
||||
protected final SymmetricComponent getPreviousSymmetricComponent() {
|
||||
public final SymmetricComponent getPreviousSymmetricComponent() {
|
||||
RocketComponent c;
|
||||
for (c = this.getPreviousComponent(); c != null; c = c.getPreviousComponent()) {
|
||||
if (c instanceof PodSet) {
|
||||
return null;
|
||||
}
|
||||
if (c instanceof SymmetricComponent) {
|
||||
return (SymmetricComponent) c;
|
||||
}
|
||||
if (!(c instanceof AxialStage) &&
|
||||
(c.axialMethod == AxialMethod.AFTER))
|
||||
(c.axialMethod == AxialMethod.AFTER)) {
|
||||
return null; // Bad component type as "parent"
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the next symmetric component, or null if none exists.
|
||||
* NOTE: This method currently assumes that there are no external
|
||||
* "pods".
|
||||
*
|
||||
* @return the next SymmetricComponent, or null.
|
||||
*/
|
||||
protected final SymmetricComponent getNextSymmetricComponent() {
|
||||
public final SymmetricComponent getNextSymmetricComponent() {
|
||||
RocketComponent c;
|
||||
for (c = this.getNextComponent(); c != null; c = c.getNextComponent()) {
|
||||
if (c instanceof PodSet) {
|
||||
return null;
|
||||
}
|
||||
if (c instanceof SymmetricComponent) {
|
||||
return (SymmetricComponent) c;
|
||||
}
|
||||
|
@ -1,13 +1,16 @@
|
||||
package net.sf.openrocket.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.Map;
|
||||
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;
|
||||
import net.sf.openrocket.document.Simulation;
|
||||
import net.sf.openrocket.file.openrocket.OpenRocketSaver;
|
||||
import net.sf.openrocket.material.Material;
|
||||
import net.sf.openrocket.material.Material.Type;
|
||||
import net.sf.openrocket.motor.Manufacturer;
|
||||
@ -34,6 +37,8 @@ import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
|
||||
import net.sf.openrocket.rocketcomponent.FreeformFinSet;
|
||||
import net.sf.openrocket.rocketcomponent.InnerTube;
|
||||
import net.sf.openrocket.rocketcomponent.InstanceContext;
|
||||
import net.sf.openrocket.rocketcomponent.InstanceMap;
|
||||
import net.sf.openrocket.rocketcomponent.InternalComponent;
|
||||
import net.sf.openrocket.rocketcomponent.LaunchLug;
|
||||
import net.sf.openrocket.rocketcomponent.MassComponent;
|
||||
@ -1629,5 +1634,54 @@ public class TestRockets {
|
||||
rocket.enableEvents();
|
||||
return rocketDoc;
|
||||
}
|
||||
|
||||
// Alpha III modified to put fins on "phantom" pods
|
||||
public static final Rocket makeEstesAlphaIIIWithPods() {
|
||||
Rocket rocket = TestRockets.makeEstesAlphaIII();
|
||||
|
||||
// find the body and fins
|
||||
final InstanceMap imap = rocket.getSelectedConfiguration().getActiveInstances();
|
||||
for(Map.Entry<RocketComponent, ArrayList<InstanceContext>> entry: imap.entrySet() ) {
|
||||
RocketComponent c = entry.getKey();
|
||||
if (c instanceof TrapezoidFinSet) {
|
||||
final TrapezoidFinSet fins = (TrapezoidFinSet) c;
|
||||
final BodyTube body = (BodyTube) fins.getParent();
|
||||
body.removeChild(fins);
|
||||
|
||||
// create a PodSet to hook the fins to
|
||||
PodSet podset = new PodSet();
|
||||
podset.setInstanceCount(fins.getFinCount());
|
||||
|
||||
body.addChild(podset);
|
||||
|
||||
// put a phantom body tube on the pods
|
||||
BodyTube podBody = new BodyTube(fins.getRootChord(), 0);
|
||||
podBody.setName("Pod Body");
|
||||
podset.addChild(podBody);
|
||||
|
||||
// change the number of fins to 1 and put the revised
|
||||
// finset on the podbody
|
||||
fins.setFinCount(1);
|
||||
podBody.addChild(fins);
|
||||
}
|
||||
}
|
||||
|
||||
return rocket;
|
||||
}
|
||||
|
||||
/**
|
||||
* dump a test rocket to a file, so we can open it in OR
|
||||
*/
|
||||
static void dumpRocket(Rocket rocket, String filename) {
|
||||
|
||||
OpenRocketDocument doc = OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
|
||||
OpenRocketSaver saver = new OpenRocketSaver();
|
||||
try {
|
||||
FileOutputStream str = new FileOutputStream(filename);
|
||||
saver.save(str, doc, null);
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.err.println("exception " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -231,4 +231,50 @@ public class BarrowmanCalculatorTest {
|
||||
|
||||
assertFalse(" Missed discontinuity in Falcon 9 Heavy:", calc.isContinuous( rocket));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPhantomTubes() {
|
||||
Rocket rocketNoPods = TestRockets.makeEstesAlphaIII();
|
||||
FlightConfiguration configNoPods = rocketNoPods.getSelectedConfiguration();
|
||||
FlightConditions conditionsNoPods = new FlightConditions(configNoPods);
|
||||
WarningSet warningsNoPods = new WarningSet();
|
||||
|
||||
Rocket rocketWithPods = TestRockets.makeEstesAlphaIIIWithPods();
|
||||
FlightConfiguration configPods = rocketWithPods.getSelectedConfiguration();
|
||||
FlightConditions conditionsPods = new FlightConditions(configPods);
|
||||
WarningSet warningsPods = new WarningSet();
|
||||
AerodynamicCalculator calcPods = new BarrowmanCalculator();
|
||||
AerodynamicCalculator calcNoPods = new BarrowmanCalculator();
|
||||
|
||||
final AerodynamicForces forcesNoPods = calcPods.getAerodynamicForces(configNoPods, conditionsNoPods, warningsNoPods);
|
||||
final AerodynamicForces forcesPods = calcPods.getAerodynamicForces(configPods, conditionsPods, warningsPods);
|
||||
assertEquals(" Estes Alpha III With Pods rocket CD value is incorrect:", forcesPods.getCD(), forcesNoPods.getCD(), EPSILON);
|
||||
|
||||
// The "with pods" version has no way of seeing the fins are
|
||||
// on the actual body tube rather than the phantom tubes,
|
||||
// so CD won't take fin-body interference into consideration.
|
||||
// So we'll adjust our CD in these tests. The magic numbers
|
||||
// in x and w come from temporarily disabling the
|
||||
// interference calculation in FinSetCalc and comparing
|
||||
// results with and without it
|
||||
// cpNoPods (0.34125,0.00000,0.00000,w=16.20502) -- interference disabled
|
||||
// cpNoPods (0.34797,0.00000,0.00000,w=19.34773) -- interference enabled
|
||||
|
||||
// another note: the fact that this is seen as three one-fin
|
||||
// FinSets instead of a single three-fin FinSet means the CP
|
||||
// will be off-axis (one of the fins is taken as having an
|
||||
// angle of 0 to the airstream, so it has no contribution).
|
||||
// This doesn't turn out to cause a problem in an actual
|
||||
// simulation.
|
||||
|
||||
final Coordinate cpNoPods = calcNoPods.getCP(configNoPods, conditionsNoPods, warningsNoPods);
|
||||
final Coordinate cpPods = calcPods.getCP(configPods, conditionsPods, warningsPods);
|
||||
System.out.printf("with pods %s\n", cpPods.toString());
|
||||
System.out.printf("without pods %s\n", cpNoPods.toString());
|
||||
assertEquals(" Alpha III With Pods rocket cp x value is incorrect:", cpNoPods.x - 0.002788761352, cpPods.x, EPSILON);
|
||||
assertEquals(" Alpha III With Pods rocket cp y value is incorrect:", cpNoPods.y - 0.005460218430206499, cpPods.y, EPSILON);
|
||||
assertEquals(" Alpha III With Pods rocket cp z value is incorrect:", cpNoPods.z, cpPods.z, EPSILON);
|
||||
assertEquals(" Alpha III With Pods rocket CNa value is incorrect:", cpPods.weight, cpNoPods.weight - 3.91572, EPSILON);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user