From e3250c9a91df28439211a63425c5ad8cb721fc49 Mon Sep 17 00:00:00 2001 From: Daniel_M_Williams Date: Sun, 22 Nov 2015 10:12:30 -0500 Subject: [PATCH] added exploratory code for non-axisymmetric CPs --- .../aerodynamics/AerodynamicForces.java | 11 +++ .../aerodynamics/BarrowmanCalculator.java | 69 ++++++++++++------- .../rocketcomponent/ComponentAssembly.java | 4 ++ .../rocketcomponent/ParallelStage.java | 3 - .../rocketcomponent/RingInstanceable.java | 2 +- .../rocketcomponent/RocketComponent.java | 3 + .../aerodynamics/BarrowmanCalculatorTest.java | 38 +++++++--- .../gui/scalefigure/RocketFigure.java | 2 +- 8 files changed, 93 insertions(+), 39 deletions(-) diff --git a/core/src/net/sf/openrocket/aerodynamics/AerodynamicForces.java b/core/src/net/sf/openrocket/aerodynamics/AerodynamicForces.java index 2bb6d75b1..6df0dda49 100644 --- a/core/src/net/sf/openrocket/aerodynamics/AerodynamicForces.java +++ b/core/src/net/sf/openrocket/aerodynamics/AerodynamicForces.java @@ -70,8 +70,18 @@ public class AerodynamicForces implements Cloneable, Monitorable { private double yawDampingMoment = Double.NaN; private int modID = 0; + + private boolean axisymmetric = true; + public boolean isAxisymmetric(){ + return this.axisymmetric; + } + + public void setAxisymmetric( final boolean isSym ){ + this.axisymmetric = isSym; + } + public void setComponent(RocketComponent component) { this.component = component; modID++; @@ -254,6 +264,7 @@ public class AerodynamicForces implements Cloneable, Monitorable { public void zero() { // component untouched + setAxisymmetric(true); setCP(Coordinate.NUL); setCNa(0); setCN(0); diff --git a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java index 256d0a13a..96926580a 100644 --- a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java +++ b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java @@ -10,10 +10,11 @@ import java.util.Map; import net.sf.openrocket.aerodynamics.barrowman.FinSetCalc; import net.sf.openrocket.aerodynamics.barrowman.RocketComponentCalc; -import net.sf.openrocket.rocketcomponent.FlightConfiguration; import net.sf.openrocket.rocketcomponent.ExternalComponent; import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish; import net.sf.openrocket.rocketcomponent.FinSet; +import net.sf.openrocket.rocketcomponent.FlightConfiguration; +import net.sf.openrocket.rocketcomponent.RingInstanceable; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.SymmetricComponent; import net.sf.openrocket.util.Coordinate; @@ -38,7 +39,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { private double cacheDiameter = -1; private double cacheLength = -1; - + public boolean debug = false; public BarrowmanCalculator() { @@ -183,33 +184,52 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { if (!component.isAerodynamic()) continue; - // Check for discontinuities - if (component instanceof SymmetricComponent) { - SymmetricComponent sym = (SymmetricComponent) component; - // TODO:LOW: Ignores other cluster components (not clusterable) - double x = component.toAbsolute(Coordinate.NUL)[0].x; - - // Check for lengthwise discontinuity - if (x > componentX + 0.0001) { - if (!MathUtil.equals(radius, 0)) { - warnings.add(Warning.DISCONTINUITY); - radius = 0; - } - } - componentX = component.toAbsolute(new Coordinate(component.getLength()))[0].x; - - // Check for radius discontinuity - if (!MathUtil.equals(sym.getForeRadius(), radius)) { - warnings.add(Warning.DISCONTINUITY); - // TODO: MEDIUM: Apply correction to values to cp and to map - } - radius = sym.getAftRadius(); - } + // TODO: refactor this code block to a separate method, where it will operate on each stage separately. + // + // Developer's Note: + // !! this code assumes all SymmetricComponents are along the centerline + // With the implementation of ParallelStages and Pods, this is no longer true. -Daniel Williams + // +// // Check for discontinuities +// if (component instanceof SymmetricComponent) { +// SymmetricComponent sym = (SymmetricComponent) component; +// // TODO:LOW: Ignores other cluster components (not clusterable) +// double x = component.toAbsolute(Coordinate.NUL)[0].x; +// +// // Check for lengthwise discontinuity +// if (x > componentX + 0.0001) { +// if (!MathUtil.equals(radius, 0)) { +// warnings.add(Warning.DISCONTINUITY); +// radius = 0; +// } +// } +// componentX = component.toAbsolute(new Coordinate(component.getLength()))[0].x; +// +// // Check for radius discontinuity +// if (!MathUtil.equals(sym.getForeRadius(), radius)) { +// warnings.add(Warning.DISCONTINUITY); +// // TODO: MEDIUM: Apply correction to values to cp and to map +// } +// radius = sym.getAftRadius(); +// } // Call calculation method forces.zero(); calcMap.get(component).calculateNonaxialForces(conditions, forces, warnings); + // to account for non axi-symmetric rockets such as + if(( ! component.isAxisymmetric()) &&( component instanceof RingInstanceable )){ + RingInstanceable ring = (RingInstanceable)component; + forces.setAxisymmetric(false); + total.setAxisymmetric(false); + + // TODO : Implement Best-Case, Worst-Case Cp calculations.... here + double minAngle = ring.getAngularOffset(); // angle of minimum CP, MOI + double maxAngle = minAngle+Math.PI/2; // angle of maximum CP, MOI + + + } + int instanceCount = component.getLocations().length; Coordinate x_cp_comp = forces.getCP(); Coordinate x_cp_weighted = x_cp_comp.setWeight(x_cp_comp.weight * instanceCount); @@ -722,5 +742,4 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { return 0; } - } diff --git a/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java b/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java index f12d270e8..260c586af 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java +++ b/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java @@ -114,6 +114,10 @@ public abstract class ComponentAssembly extends RocketComponent { return false; } + @Override + public boolean isAxisymmetric(){ + return !(2 == this.getInstanceCount()); + } @Override public void setAxialOffset(final double _pos) { diff --git a/core/src/net/sf/openrocket/rocketcomponent/ParallelStage.java b/core/src/net/sf/openrocket/rocketcomponent/ParallelStage.java index 02a36fdfe..bf56b433e 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/ParallelStage.java +++ b/core/src/net/sf/openrocket/rocketcomponent/ParallelStage.java @@ -3,9 +3,6 @@ package net.sf.openrocket.rocketcomponent; import java.util.ArrayList; import java.util.Collection; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.startup.Application; import net.sf.openrocket.util.BugException; diff --git a/core/src/net/sf/openrocket/rocketcomponent/RingInstanceable.java b/core/src/net/sf/openrocket/rocketcomponent/RingInstanceable.java index 2b57af619..b54b9697d 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RingInstanceable.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RingInstanceable.java @@ -6,7 +6,7 @@ public interface RingInstanceable extends Instanceable { public double getRadialOffset(); - public void setAngularOffset(final double radius); + public void setAngularOffset(final double angle); public void setRadialOffset(final double radius); diff --git a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java index 657e1e085..e16259f16 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java @@ -279,6 +279,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab return (Position.AFTER == this.relativePosition); } + public boolean isAxisymmetric(){ + return true; + } /** * Shift the coordinates in the array corresponding to radial movement. A component diff --git a/core/test/net/sf/openrocket/aerodynamics/BarrowmanCalculatorTest.java b/core/test/net/sf/openrocket/aerodynamics/BarrowmanCalculatorTest.java index dd84d533a..3676fea23 100644 --- a/core/test/net/sf/openrocket/aerodynamics/BarrowmanCalculatorTest.java +++ b/core/test/net/sf/openrocket/aerodynamics/BarrowmanCalculatorTest.java @@ -1,11 +1,18 @@ package net.sf.openrocket.aerodynamics; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Module; import net.sf.openrocket.ServicesForTesting; import net.sf.openrocket.motor.MotorInstance; import net.sf.openrocket.plugin.PluginModule; -import net.sf.openrocket.rocketcomponent.BodyTube; import net.sf.openrocket.rocketcomponent.FlightConfiguration; import net.sf.openrocket.rocketcomponent.FlightConfigurationID; import net.sf.openrocket.rocketcomponent.InnerTube; @@ -15,13 +22,6 @@ import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.MathUtil; import net.sf.openrocket.util.TestRockets; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.google.inject.Module; - public class BarrowmanCalculatorTest { protected final double EPSILON = MathUtil.EPSILON; @@ -86,6 +86,26 @@ public class BarrowmanCalculatorTest { fail("Not yet implemented"); } + + @Test + public void testCPDoubleStrapOn() { + Rocket rocket = TestRockets.makeFalcon9Heavy(); + FlightConfiguration config = rocket.getDefaultConfiguration(); + BarrowmanCalculator calc = new BarrowmanCalculator(); + FlightConditions conditions = new FlightConditions(config); + WarningSet warnings = new WarningSet(); + + calc.debug = true; + // calculated from OpenRocket 15.03 + double expCPx = 0.225; // cm + Coordinate calcCP = calc.getCP(config, conditions, warnings); + + fail("NYI"); + assertEquals(" Falcon Heavy CP x value is incorrect:", expCPx, calcCP.x, EPSILON); + Coordinate expCP = new Coordinate(expCPx, 0,0,0); + assertEquals(" Falcon Heavy CP is incorrect:", expCP, calcCP); + } + @Test public void testGetWorstCP() { fail("Not yet implemented"); diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java index 8fcf9acae..4a0bfad19 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java @@ -421,8 +421,8 @@ public class RocketFigure extends AbstractScaleFigure { // facade for the recursive function below private void getShapes(ArrayList allShapes, FlightConfiguration configuration){ for( AxialStage stage : configuration.getActiveStages()){ - int stageNumber = stage.getStageNumber(); // for debug... + //int stageNumber = stage.getStageNumber(); //String activeString = ( configuration.isStageActive(stageNumber) ? "active" : "inactive"); getShapeTree( allShapes, stage, Coordinate.ZERO);