From 7c72bc88b1a958dd059e16ec6c67b8dc95c229ce Mon Sep 17 00:00:00 2001 From: bkuker Date: Tue, 25 Feb 2014 09:51:03 -0500 Subject: [PATCH 1/2] Fix BasicTumbleStatus to initialize drag to non-zero. computeTumbleDrag() is never called without this fix. The one-arg constructor is the only constructor ever used, to init this status based on the previous status, copying the tumble drag if it can. The first BasicTumbleStatus is constructed from an RK4 Status, so it's drag is not copied, but neither is the drag computed. From then on the 0 is copied from one BasicTumbleStatus to the next. --- .../sf/openrocket/simulation/BasicTumbleStatus.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/core/src/net/sf/openrocket/simulation/BasicTumbleStatus.java b/core/src/net/sf/openrocket/simulation/BasicTumbleStatus.java index dfb44a1ad..1993c5aaf 100644 --- a/core/src/net/sf/openrocket/simulation/BasicTumbleStatus.java +++ b/core/src/net/sf/openrocket/simulation/BasicTumbleStatus.java @@ -18,19 +18,21 @@ public class BasicTumbleStatus extends SimulationStatus { // offset the indexes so finEff[1] is the coefficient for one fin from the table in techdoc.pdf private final static double[] finEff = { 0.0, 0.5, 1.0, 1.41, 1.81, 1.73, 1.90, 1.85 }; - private double drag; + private final double drag; public BasicTumbleStatus(Configuration configuration, MotorInstanceConfiguration motorConfiguration, SimulationConditions simulationConditions) { super(configuration, motorConfiguration, simulationConditions); - computeTumbleDrag(); + this.drag = computeTumbleDrag(); } public BasicTumbleStatus(SimulationStatus orig) { super(orig); if (orig instanceof BasicTumbleStatus) { this.drag = ((BasicTumbleStatus) orig).drag; + } else { + this.drag = computeTumbleDrag(); } } @@ -39,7 +41,7 @@ public class BasicTumbleStatus extends SimulationStatus { } - public void computeTumbleDrag() { + private double computeTumbleDrag() { // Computed based on Sampo's experimentation as documented in the pdf. @@ -69,6 +71,6 @@ public class BasicTumbleStatus extends SimulationStatus { } } - drag = (cDFin * aFins + cDBt * aBt); + return (cDFin * aFins + cDBt * aBt); } } From 8e063f0a646c688b61e517e9dfe559c7d80a0322 Mon Sep 17 00:00:00 2001 From: bkuker Date: Tue, 25 Feb 2014 15:39:12 -0500 Subject: [PATCH 2/2] The changes to the tumble transition discussed on or-dev --- core/resources/l10n/messages.properties | 2 + .../sf/openrocket/aerodynamics/Warning.java | 6 +++ .../BasicEventSimulationEngine.java | 38 ++++++++++++++----- .../sf/openrocket/gui/plot/EventGraphics.java | 1 + 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 78ffce980..be5724c5d 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -1539,6 +1539,8 @@ Warning.PARALLEL_FINS = Too many parallel fins Warning.SUPERSONIC = Body calculations may not be entirely accurate at supersonic speeds. Warning.RECOVERY_LAUNCH_ROD = Recovery device device deployed while on the launch guide. Warning.RECOVERY_HIGH_SPEED = Recovery device deployment at high speed +Warning.TUMBLE_UNDER_THRUST = Stage began to tumble under thrust. +Warning.TUMBLE_BEFORE_APOGEE = Sustainer became unstable before apogee. ! Scale dialog diff --git a/core/src/net/sf/openrocket/aerodynamics/Warning.java b/core/src/net/sf/openrocket/aerodynamics/Warning.java index 72df1ec49..44b0a3d85 100644 --- a/core/src/net/sf/openrocket/aerodynamics/Warning.java +++ b/core/src/net/sf/openrocket/aerodynamics/Warning.java @@ -325,4 +325,10 @@ public abstract class Warning { public static final Warning RECOVERY_LAUNCH_ROD = new Other(trans.get("Warning.RECOVERY_LAUNCH_ROD")); + + public static final Warning TUMBLE_UNDER_THRUST = + new Other(trans.get("Warning.TUMBLE_UNDER_THRUST")); + + public static final Warning TUMBLE_BEFORE_APOGEE = + new Other(trans.get("Warning.TUMBLE_BEFORE_APOGEE")); } diff --git a/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java b/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java index 22f7bcbb1..fb8d32020 100644 --- a/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java +++ b/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java @@ -42,10 +42,14 @@ public class BasicEventSimulationEngine implements SimulationEngine { private SimulationStepper landingStepper = new BasicLandingStepper(); private SimulationStepper tumbleStepper = new BasicTumbleStepper(); - // Constant holding 10 degress in radians. This is the AOA condition + // Constant holding 20 degress in radians. This is the AOA condition // necessary to transistion to tumbling. private final static double AOA_TUMBLE_CONDITION = Math.PI / 9.0; + // The thrust must be below this value for the transition to tumbling. + // TODO: this is an arbitrary value + private final static double THRUST_TUMBLE_CONDITION = 0.01; + private SimulationStepper currentStepper; private SimulationStatus status; @@ -202,18 +206,32 @@ public class BasicEventSimulationEngine implements SimulationEngine { // Check for Tumbling // Conditions for transision are: - // apogee reached + // apogee reached (if sustainer stage) // and is not already tumbling // and not stable (cg > cp) - // and aoa > 30 + // and aoa > AOA_TUMBLE_CONDITION threshold + // and thrust < THRUST_TUMBLE_CONDITION threshold - if (status.isApogeeReached() && !status.isTumbling()) { - double cp = status.getFlightData().getLast(FlightDataType.TYPE_CP_LOCATION); - double cg = status.getFlightData().getLast(FlightDataType.TYPE_CG_LOCATION); - double aoa = status.getFlightData().getLast(FlightDataType.TYPE_AOA); - if (cg > cp && aoa > AOA_TUMBLE_CONDITION) { - addEvent(new FlightEvent(FlightEvent.Type.TUMBLE, status.getSimulationTime())); - status.setTumbling(true); + if (!status.isTumbling()) { + final double t = status.getFlightData().getLast(FlightDataType.TYPE_THRUST_FORCE); + final double cp = status.getFlightData().getLast(FlightDataType.TYPE_CP_LOCATION); + final double cg = status.getFlightData().getLast(FlightDataType.TYPE_CG_LOCATION); + final double aoa = status.getFlightData().getLast(FlightDataType.TYPE_AOA); + + final boolean wantToTumble = (cg > cp && aoa > AOA_TUMBLE_CONDITION); + + if (wantToTumble) { + final boolean tooMuchThrust = t > THRUST_TUMBLE_CONDITION; + final boolean isSustainer = status.getConfiguration().isStageActive(0); + final boolean notUntilApogee = isSustainer && !status.isApogeeReached(); + if (tooMuchThrust) { + status.getWarnings().add(Warning.TUMBLE_UNDER_THRUST); + } else if (notUntilApogee) { + status.getWarnings().add(Warning.TUMBLE_BEFORE_APOGEE); + } else { + addEvent(new FlightEvent(FlightEvent.Type.TUMBLE, status.getSimulationTime())); + status.setTumbling(true); + } } } diff --git a/swing/src/net/sf/openrocket/gui/plot/EventGraphics.java b/swing/src/net/sf/openrocket/gui/plot/EventGraphics.java index 7a09ae910..3443e9be5 100644 --- a/swing/src/net/sf/openrocket/gui/plot/EventGraphics.java +++ b/swing/src/net/sf/openrocket/gui/plot/EventGraphics.java @@ -39,6 +39,7 @@ public class EventGraphics { EVENT_COLORS.put(FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT, new Color(0, 0, 128)); EVENT_COLORS.put(FlightEvent.Type.GROUND_HIT, new Color(0, 0, 0)); EVENT_COLORS.put(FlightEvent.Type.SIMULATION_END, new Color(128, 0, 0)); + EVENT_COLORS.put(FlightEvent.Type.TUMBLE, new Color(196, 0, 255)); } private static final Map EVENT_IMAGES = new HashMap();