From fbd80f480d7a4155d8b86725851071217c4c81af Mon Sep 17 00:00:00 2001 From: JoePfeiffer Date: Fri, 13 May 2022 10:32:00 -0600 Subject: [PATCH] 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