From fbd80f480d7a4155d8b86725851071217c4c81af Mon Sep 17 00:00:00 2001 From: JoePfeiffer Date: Fri, 13 May 2022 10:32:00 -0600 Subject: [PATCH 1/3] Modify GroundStepper to not add datapoint to simulation status Modify BasicLandingStepper to recalculate timestep on last step to find actual landing data Modify BasicEventSimulationEngine to watch for altitude less than MathUtil.EPSILON rather than 0 (since BasicLandingStepper now finds altitude exactly equal to 0) --- .../BasicEventSimulationEngine.java | 2 +- .../simulation/BasicLandingStepper.java | 34 +++++++++- .../openrocket/simulation/GroundStepper.java | 65 ------------------- swing/resources-src/datafiles/components | 2 +- 4 files changed, 33 insertions(+), 70 deletions(-) diff --git a/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java b/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java index 69fdf3d3d..c17daff2d 100644 --- a/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java +++ b/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java @@ -173,7 +173,7 @@ public class BasicEventSimulationEngine implements SimulationEngine { } else { // Check ground hit after liftoff - if ((currentStatus.getRocketPosition().z < 0) && !currentStatus.isLanded()) { + if ((currentStatus.getRocketPosition().z < MathUtil.EPSILON) && !currentStatus.isLanded()) { addEvent(new FlightEvent(FlightEvent.Type.GROUND_HIT, currentStatus.getSimulationTime())); // addEvent(new FlightEvent(FlightEvent.Type.SIMULATION_END, currentStatus.getSimulationTime())); diff --git a/core/src/net/sf/openrocket/simulation/BasicLandingStepper.java b/core/src/net/sf/openrocket/simulation/BasicLandingStepper.java index a111d1227..c2e492d77 100644 --- a/core/src/net/sf/openrocket/simulation/BasicLandingStepper.java +++ b/core/src/net/sf/openrocket/simulation/BasicLandingStepper.java @@ -8,7 +8,11 @@ import net.sf.openrocket.util.GeodeticComputationStrategy; import net.sf.openrocket.util.MathUtil; import net.sf.openrocket.util.WorldCoordinate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class BasicLandingStepper extends AbstractSimulationStepper { + private static final Logger log = LoggerFactory.getLogger(BasicLandingStepper.class); private static final double RECOVERY_TIME_STEP = 0.5; @@ -65,13 +69,36 @@ public class BasicLandingStepper extends AbstractSimulationStepper { - // Select time step + // Select tentative time step double timeStep = MathUtil.min(0.5 / linearAcceleration.length(), RECOVERY_TIME_STEP); // Perform Euler integration - status.setRocketPosition(status.getRocketPosition().add(status.getRocketVelocity().multiply(timeStep)). - add(linearAcceleration.multiply(MathUtil.pow2(timeStep) / 2))); + Coordinate newPosition = status.getRocketPosition().add(status.getRocketVelocity().multiply(timeStep)). + add(linearAcceleration.multiply(MathUtil.pow2(timeStep) / 2)); + + // If I've hit the ground, recalculate time step and position + if (newPosition.z < 0) { + + final double a = linearAcceleration.z; + final double v = status.getRocketVelocity().z; + final double z0 = status.getRocketPosition().z; + final double z = linearAcceleration.x; + + // The new timestep is the solution of + // 1/2 at^2 + vt + z0 = 0 + timeStep = (-v - Math.sqrt(v*v - 2*a*z0))/a; + + newPosition = status.getRocketPosition().add(status.getRocketVelocity().multiply(timeStep)). + add(linearAcceleration.multiply(MathUtil.pow2(timeStep) / 2)); + + // avoid rounding error in new altitude + newPosition = newPosition.setZ(0); + } + + status.setRocketPosition(newPosition); + status.setRocketVelocity(status.getRocketVelocity().add(linearAcceleration.multiply(timeStep))); + airSpeed = status.getRocketVelocity().add(windSpeed); status.setSimulationTime(status.getSimulationTime() + timeStep); @@ -139,6 +166,7 @@ public class BasicLandingStepper extends AbstractSimulationStepper { data.setValue(FlightDataType.TYPE_TIME_STEP, timeStep); data.setValue(FlightDataType.TYPE_COMPUTATION_TIME, (System.nanoTime() - status.getSimulationStartWallTime()) / 1000000000.0); + log.debug("time " + data.getLast(FlightDataType.TYPE_TIME) + ", altitude " + data.getLast(FlightDataType.TYPE_ALTITUDE) + ", velocity " + data.getLast(FlightDataType.TYPE_VELOCITY_Z)); } } diff --git a/core/src/net/sf/openrocket/simulation/GroundStepper.java b/core/src/net/sf/openrocket/simulation/GroundStepper.java index db9ea466d..49c8b5b4f 100644 --- a/core/src/net/sf/openrocket/simulation/GroundStepper.java +++ b/core/src/net/sf/openrocket/simulation/GroundStepper.java @@ -20,70 +20,5 @@ public class GroundStepper extends AbstractSimulationStepper { @Override public void step(SimulationStatus status, double timeStep) throws SimulationException { log.trace("step: position=" + status.getRocketPosition() + ", velocity=" + status.getRocketVelocity()); - - status.setRocketVelocity(Coordinate.ZERO); - status.setRocketRotationVelocity(Coordinate.ZERO); - status.setRocketPosition(status.getRocketPosition().setZ(0)); - - // Store data - FlightDataBranch data = status.getFlightData(); - boolean extra = status.getSimulationConditions().isCalculateExtras(); - data.addPoint(); - - data.setValue(FlightDataType.TYPE_TIME, status.getSimulationTime()); - data.setValue(FlightDataType.TYPE_ALTITUDE, status.getRocketPosition().z); - data.setValue(FlightDataType.TYPE_POSITION_X, status.getRocketPosition().x); - data.setValue(FlightDataType.TYPE_POSITION_Y, status.getRocketPosition().y); - if (extra) { - data.setValue(FlightDataType.TYPE_POSITION_XY, - MathUtil.hypot(status.getRocketPosition().x, status.getRocketPosition().y)); - data.setValue(FlightDataType.TYPE_POSITION_DIRECTION, - Math.atan2(status.getRocketPosition().y, status.getRocketPosition().x)); - - data.setValue(FlightDataType.TYPE_VELOCITY_XY, - MathUtil.hypot(status.getRocketVelocity().x, status.getRocketVelocity().y)); - data.setValue(FlightDataType.TYPE_ACCELERATION_XY, 0.0); - - data.setValue(FlightDataType.TYPE_ACCELERATION_TOTAL, 0.0); - - data.setValue(FlightDataType.TYPE_REYNOLDS_NUMBER, Double.POSITIVE_INFINITY); - } - - data.setValue(FlightDataType.TYPE_LATITUDE, status.getRocketWorldPosition().getLatitudeRad()); - data.setValue(FlightDataType.TYPE_LONGITUDE, status.getRocketWorldPosition().getLongitudeRad()); - data.setValue(FlightDataType.TYPE_GRAVITY, modelGravity(status)); - - data.setValue(FlightDataType.TYPE_CORIOLIS_ACCELERATION, 0.0); - - data.setValue(FlightDataType.TYPE_VELOCITY_Z, status.getRocketVelocity().z); - data.setValue(FlightDataType.TYPE_ACCELERATION_Z, 0.0); - - data.setValue(FlightDataType.TYPE_VELOCITY_TOTAL, 0.0); - data.setValue(FlightDataType.TYPE_MACH_NUMBER, 0.0); - - - // Calculate mass data - double rocketMass = calculateStructureMass(status).getMass(); - double motorMass = calculateMotorMass(status).getMass(); - - double mass = rocketMass + motorMass; - data.setValue(FlightDataType.TYPE_MASS, mass); - data.setValue(FlightDataType.TYPE_MOTOR_MASS, motorMass); - - data.setValue(FlightDataType.TYPE_THRUST_FORCE, 0.0); - data.setValue(FlightDataType.TYPE_DRAG_FORCE, 0.0); - - data.setValue(FlightDataType.TYPE_WIND_VELOCITY, modelWindVelocity(status).length()); - - AtmosphericConditions atmosphere = modelAtmosphericConditions(status); - data.setValue(FlightDataType.TYPE_AIR_TEMPERATURE, atmosphere.getTemperature()); - data.setValue(FlightDataType.TYPE_AIR_PRESSURE, atmosphere.getPressure()); - data.setValue(FlightDataType.TYPE_SPEED_OF_SOUND, atmosphere.getMachSpeed()); - - data.setValue(FlightDataType.TYPE_TIME_STEP, timeStep); - data.setValue(FlightDataType.TYPE_COMPUTATION_TIME, - (System.nanoTime() - status.getSimulationStartWallTime()) / 1000000000.0); - - status.setSimulationTime(status.getSimulationTime() + timeStep); } } diff --git a/swing/resources-src/datafiles/components b/swing/resources-src/datafiles/components index c9bd1a6f5..8304c0fd3 160000 --- a/swing/resources-src/datafiles/components +++ b/swing/resources-src/datafiles/components @@ -1 +1 @@ -Subproject commit c9bd1a6f539aab4bb724ecbdb54e65100a33e701 +Subproject commit 8304c0fd3dc80d65c40af4da83268ec1b32931d6 From 0910317bf62c1b8ff7a1ea62fe2c1edfa4a8df12 Mon Sep 17 00:00:00 2001 From: JoePfeiffer Date: Fri, 13 May 2022 11:52:22 -0600 Subject: [PATCH 2/3] Make MathUtil::interpolate a bit more robust in the presence of possible rounding errors. --- core/src/net/sf/openrocket/util/MathUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/net/sf/openrocket/util/MathUtil.java b/core/src/net/sf/openrocket/util/MathUtil.java index e1ae86c12..e948ee8d5 100644 --- a/core/src/net/sf/openrocket/util/MathUtil.java +++ b/core/src/net/sf/openrocket/util/MathUtil.java @@ -331,13 +331,13 @@ public class MathUtil { } int length = domain.size(); - if (length <= 1 || t < domain.get(0) || t > domain.get(length - 1)) { + if (length <= 1 || t < domain.get(0) || t > domain.get(length - 1) + EPSILON) { return Double.NaN; } // Look for the index of the right end point. int right = 1; - while (t > domain.get(right)) { + while (t > domain.get(right) + EPSILON) { right++; } int left = right - 1; From 62f219a9637042782ae6b763174de6d28c999d10 Mon Sep 17 00:00:00 2001 From: JoePfeiffer Date: Fri, 13 May 2022 15:28:01 -0600 Subject: [PATCH 3/3] clean up a line of debug code --- core/src/net/sf/openrocket/simulation/BasicLandingStepper.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/net/sf/openrocket/simulation/BasicLandingStepper.java b/core/src/net/sf/openrocket/simulation/BasicLandingStepper.java index c2e492d77..f6fe081a0 100644 --- a/core/src/net/sf/openrocket/simulation/BasicLandingStepper.java +++ b/core/src/net/sf/openrocket/simulation/BasicLandingStepper.java @@ -82,7 +82,6 @@ public class BasicLandingStepper extends AbstractSimulationStepper { final double a = linearAcceleration.z; final double v = status.getRocketVelocity().z; final double z0 = status.getRocketPosition().z; - final double z = linearAcceleration.x; // The new timestep is the solution of // 1/2 at^2 + vt + z0 = 0