From df00500077b53831fd55927d06167ef99a44e390 Mon Sep 17 00:00:00 2001 From: JoePfeiffer Date: Sat, 15 Oct 2022 16:43:34 -0600 Subject: [PATCH 1/4] Clarify comments and debug logging --- .../gui/simulation/SimulationRunDialog.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/simulation/SimulationRunDialog.java b/swing/src/net/sf/openrocket/gui/simulation/SimulationRunDialog.java index fd8dc025e..d5e9f6531 100644 --- a/swing/src/net/sf/openrocket/gui/simulation/SimulationRunDialog.java +++ b/swing/src/net/sf/openrocket/gui/simulation/SimulationRunDialog.java @@ -275,8 +275,10 @@ public class SimulationRunDialog extends JDialog { private final CustomExpressionSimulationListener exprListener; /* - * -2 = time from 0 ... burnoutTimeEstimate -1 = velocity from - * v(burnoutTimeEstimate) ... 0 0 ... n = stages from alt(max) ... 0 + * Keep track of current phase ("stage") of simulation + * -2: Boost. Estimate progress using time from 0 to burnoutTimeEstimate + * -1: Coast. Estimate progress using velocity from v(burnoutTimeEstimate) to 0 + * 0 ... n: Landing. stages from alt(max) ... 0 (?) */ private volatile int simulationStage = -2; @@ -332,39 +334,41 @@ public class SimulationRunDialog extends JDialog { SimulationStatus status = chunks.get(chunks.size() - 1); simulationStatuses[index] = status; - // 1. time = 0 ... burnoutTimeEstimate + // -2: Boost. time = 0 ... burnoutTimeEstimate if (simulationStage == -2 && status.getSimulationTime() < burnoutTimeEstimate) { - log.debug("Method 1: t=" + status.getSimulationTime() + " est=" + burnoutTimeEstimate); + log.debug("simulationStage boost: t=" + status.getSimulationTime() + " est=" + burnoutTimeEstimate); setSimulationProgress( MathUtil.map(status.getSimulationTime(), 0, burnoutTimeEstimate, 0.0, BURNOUT_PROGRESS)); updateProgress(); return; } + // Past burnout time estimate, switch to coast. if (simulationStage == -2) { simulationStage++; burnoutVelocity = MathUtil.max(status.getRocketVelocity().z, 0.1); - log.debug("CHANGING to Method 2, vel=" + burnoutVelocity); + log.debug("CHANGING to simulationStage " + simulationStage + ", vel=" + burnoutVelocity); } - // 2. z-velocity from burnout velocity to zero + // -1: Coast. z-velocity from burnout velocity to zero if (simulationStage == -1 && status.getRocketVelocity().z >= 0) { - log.debug("Method 2: vel=" + status.getRocketVelocity().z + " burnout=" + burnoutVelocity); + log.debug("simulationStage coast: vel=" + status.getRocketVelocity().z + " burnout=" + burnoutVelocity); setSimulationProgress(MathUtil.map(status.getRocketVelocity().z, burnoutVelocity, 0, BURNOUT_PROGRESS, APOGEE_PROGRESS)); updateProgress(); return; } + // Past apogee, switch to landing if (simulationStage == -1 && status.getRocketVelocity().z < 0) { simulationStage++; apogeeAltitude = MathUtil.max(status.getRocketPosition().z, 1); - log.debug("CHANGING to Method 3, apogee=" + apogeeAltitude); + log.debug("CHANGING to simulationStage " + simulationStage + ", apogee=" + apogeeAltitude); } - // 3. z-position from apogee to zero + // >= 0 Landing. z-position from apogee to zero // TODO: MEDIUM: several stages - log.debug("Method 3: alt=" + status.getRocketPosition().z + " apogee=" + apogeeAltitude); + log.debug("simulationStage landing (" + simulationStage + "): alt=" + status.getRocketPosition().z + " apogee=" + apogeeAltitude); setSimulationProgress(MathUtil.map(status.getRocketPosition().z, apogeeAltitude, 0, APOGEE_PROGRESS, 1.0)); updateProgress(); } From 942b3adacfe379b5982aa983b706f68c8a6922e4 Mon Sep 17 00:00:00 2001 From: JoePfeiffer Date: Sat, 15 Oct 2022 16:59:42 -0600 Subject: [PATCH 2/4] Get rid of redundant apogeeAltitude. Use maxAltitude[index] instead (this actually solves the reported bug; apogeeAltitude was being set to the first altitude after apogee which could in pathological conditions already be 0). --- .../gui/simulation/SimulationRunDialog.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/simulation/SimulationRunDialog.java b/swing/src/net/sf/openrocket/gui/simulation/SimulationRunDialog.java index d5e9f6531..669db71af 100644 --- a/swing/src/net/sf/openrocket/gui/simulation/SimulationRunDialog.java +++ b/swing/src/net/sf/openrocket/gui/simulation/SimulationRunDialog.java @@ -270,7 +270,6 @@ public class SimulationRunDialog extends JDialog { private final int index; private final double burnoutTimeEstimate; private volatile double burnoutVelocity; - private volatile double apogeeAltitude; private final CustomExpressionSimulationListener exprListener; @@ -278,7 +277,8 @@ public class SimulationRunDialog extends JDialog { * Keep track of current phase ("stage") of simulation * -2: Boost. Estimate progress using time from 0 to burnoutTimeEstimate * -1: Coast. Estimate progress using velocity from v(burnoutTimeEstimate) to 0 - * 0 ... n: Landing. stages from alt(max) ... 0 (?) + * 0 ... n: Landing. Estimate progress using altitude from alt(max) ... 0 + * (it appears as if the idea is to use values above 0 to support multiple stages, but this is not implemented) */ private volatile int simulationStage = -2; @@ -362,14 +362,13 @@ public class SimulationRunDialog extends JDialog { // Past apogee, switch to landing if (simulationStage == -1 && status.getRocketVelocity().z < 0) { simulationStage++; - apogeeAltitude = MathUtil.max(status.getRocketPosition().z, 1); - log.debug("CHANGING to simulationStage " + simulationStage + ", apogee=" + apogeeAltitude); + log.debug("CHANGING to simulationStage " + simulationStage + ", apogee=" + simulationMaxAltitude[index]); } // >= 0 Landing. z-position from apogee to zero // TODO: MEDIUM: several stages - log.debug("simulationStage landing (" + simulationStage + "): alt=" + status.getRocketPosition().z + " apogee=" + apogeeAltitude); - setSimulationProgress(MathUtil.map(status.getRocketPosition().z, apogeeAltitude, 0, APOGEE_PROGRESS, 1.0)); + log.debug("simulationStage landing (" + simulationStage + "): alt=" + status.getRocketPosition().z + " apogee=" + simulationMaxAltitude[index]); + setSimulationProgress(MathUtil.map(status.getRocketPosition().z, simulationMaxAltitude[index], 0, APOGEE_PROGRESS, 1.0)); updateProgress(); } @@ -444,7 +443,6 @@ public class SimulationRunDialog extends JDialog { switch (event.getType()) { case APOGEE: simulationStage = 0; - apogeeAltitude = status.getRocketPosition().z; log.debug("APOGEE, setting progress"); setSimulationProgress(APOGEE_PROGRESS); publish(status); From 2725c859a44c15c791cf46971f5202ed19772af4 Mon Sep 17 00:00:00 2001 From: JoePfeiffer Date: Sun, 16 Oct 2022 16:48:24 -0600 Subject: [PATCH 3/4] Improve display of max altitude in simulation run progress dialog 1) Since portions of a simulation may be run multiple times (notably in calculating optimal coast time), update the max altitude whenever the rocket's vertical velocity is positive rather than actually looking for a max. The last run is the "real" one, so the correct apogee is recorded as max altitude 2) Don't have handleFlightEvent() set the simulation progress directly, as this can end up skipping some updates from the postStep() listener. --- .../gui/simulation/SimulationRunDialog.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/simulation/SimulationRunDialog.java b/swing/src/net/sf/openrocket/gui/simulation/SimulationRunDialog.java index 669db71af..bb1f11147 100644 --- a/swing/src/net/sf/openrocket/gui/simulation/SimulationRunDialog.java +++ b/swing/src/net/sf/openrocket/gui/simulation/SimulationRunDialog.java @@ -324,10 +324,15 @@ public class SimulationRunDialog extends JDialog { @Override protected void process(List chunks) { - // Update max. altitude and velocity + // Update max. altitude and velocity of sustainer. Because parts of the simulation may be run more than once + // in order to calculate things like optimal coast time, we'll keep updating max altitude + // whenever we see that the rocket is going upwards. The last apogee found is the real one. for (SimulationStatus s : chunks) { - simulationMaxAltitude[index] = Math.max(simulationMaxAltitude[index], s.getRocketPosition().z); - simulationMaxVelocity[index] = Math.max(simulationMaxVelocity[index], s.getRocketVelocity().length()); + if (s.getConfiguration().isStageActive(0) && (s.getRocketVelocity().z > 0)) { + log.debug("updating simulationMaxAltitude[" + index + "] to " + s.getRocketPosition().z); + simulationMaxAltitude[index] = s.getRocketPosition().z; + simulationMaxVelocity[index] = Math.max(simulationMaxVelocity[index], s.getRocketVelocity().length()); + } } // Calculate the progress @@ -367,6 +372,7 @@ public class SimulationRunDialog extends JDialog { // >= 0 Landing. z-position from apogee to zero // TODO: MEDIUM: several stages + System.out.flush(); log.debug("simulationStage landing (" + simulationStage + "): alt=" + status.getRocketPosition().z + " apogee=" + simulationMaxAltitude[index]); setSimulationProgress(MathUtil.map(status.getRocketPosition().z, simulationMaxAltitude[index], 0, APOGEE_PROGRESS, 1.0)); updateProgress(); @@ -442,9 +448,7 @@ public class SimulationRunDialog extends JDialog { public boolean handleFlightEvent(SimulationStatus status, FlightEvent event) { switch (event.getType()) { case APOGEE: - simulationStage = 0; - log.debug("APOGEE, setting progress"); - setSimulationProgress(APOGEE_PROGRESS); + log.debug("APOGEE"); publish(status); break; @@ -453,8 +457,8 @@ public class SimulationRunDialog extends JDialog { break; case SIMULATION_END: - log.debug("END, setting progress"); - setSimulationProgress(1.0); + log.debug("END"); + publish(status); break; default: From 194a802ea01cfbb96a954080bbaf1a4278f83cb7 Mon Sep 17 00:00:00 2001 From: JoePfeiffer Date: Sun, 23 Oct 2022 10:04:18 -0600 Subject: [PATCH 4/4] add some timeStep debug to BasicLandingStepper --- .../net/sf/openrocket/simulation/BasicLandingStepper.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/src/net/sf/openrocket/simulation/BasicLandingStepper.java b/core/src/net/sf/openrocket/simulation/BasicLandingStepper.java index ca809dcbb..d11a9c788 100644 --- a/core/src/net/sf/openrocket/simulation/BasicLandingStepper.java +++ b/core/src/net/sf/openrocket/simulation/BasicLandingStepper.java @@ -79,7 +79,8 @@ public class BasicLandingStepper extends AbstractSimulationStepper { } // but don't let it get *too* small timeStep = Math.max(timeStep, MIN_TIME_STEP); - + log.debug("timeStep is " + timeStep); + // Perform Euler integration Coordinate newPosition = status.getRocketPosition().add(status.getRocketVelocity().multiply(timeStep)). add(linearAcceleration.multiply(MathUtil.pow2(timeStep) / 2)); @@ -94,6 +95,7 @@ public class BasicLandingStepper extends AbstractSimulationStepper { // The new timestep is the solution of // 1/2 at^2 + vt + z0 = 0 timeStep = (-v - Math.sqrt(v*v - 2*a*z0))/a; + log.debug("ground hit changes timeStep to " + timeStep); newPosition = status.getRocketPosition().add(status.getRocketVelocity().multiply(timeStep)). add(linearAcceleration.multiply(MathUtil.pow2(timeStep) / 2)); @@ -101,7 +103,7 @@ public class BasicLandingStepper extends AbstractSimulationStepper { // avoid rounding error in new altitude newPosition = newPosition.setZ(0); } - + status.setSimulationTime(status.getSimulationTime() + timeStep); status.setPreviousTimeStep(timeStep); @@ -113,7 +115,6 @@ public class BasicLandingStepper extends AbstractSimulationStepper { WorldCoordinate w = status.getSimulationConditions().getLaunchSite(); w = status.getSimulationConditions().getGeodeticComputation().addCoordinate(w, status.getRocketPosition()); status.setRocketWorldPosition(w); - // Store data FlightDataBranch data = status.getFlightData();