diff --git a/core/src/net/sf/openrocket/simulation/BasicLandingStepper.java b/core/src/net/sf/openrocket/simulation/BasicLandingStepper.java index c2e492d77..48b848937 100644 --- a/core/src/net/sf/openrocket/simulation/BasicLandingStepper.java +++ b/core/src/net/sf/openrocket/simulation/BasicLandingStepper.java @@ -70,8 +70,14 @@ public class BasicLandingStepper extends AbstractSimulationStepper { // Select tentative time step - double timeStep = MathUtil.min(0.5 / linearAcceleration.length(), RECOVERY_TIME_STEP); - + double timeStep = RECOVERY_TIME_STEP; + + // adjust based on change in acceleration (ie jerk) + final double jerk = linearAcceleration.sub(status.getRocketAcceleration()).multiply(1.0/status.getPreviousTimeStep()).length(); + if (jerk > MathUtil.EPSILON) { + timeStep = Math.min(timeStep, 1.0/jerk); + } + // Perform Euler integration Coordinate newPosition = status.getRocketPosition().add(status.getRocketVelocity().multiply(timeStep)). add(linearAcceleration.multiply(MathUtil.pow2(timeStep) / 2)); @@ -82,7 +88,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 @@ -95,12 +100,12 @@ public class BasicLandingStepper extends AbstractSimulationStepper { 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); - + status.setPreviousTimeStep(timeStep); + + status.setRocketPosition(newPosition); + status.setRocketVelocity(status.getRocketVelocity().add(linearAcceleration.multiply(timeStep))); + status.setRocketAcceleration(linearAcceleration); // Update the world coordinate WorldCoordinate w = status.getSimulationConditions().getLaunchSite(); @@ -117,6 +122,8 @@ public class BasicLandingStepper extends AbstractSimulationStepper { 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); + + airSpeed = status.getRocketVelocity().add(windSpeed); if (extra) { data.setValue(FlightDataType.TYPE_POSITION_XY, MathUtil.hypot(status.getRocketPosition().x, status.getRocketPosition().y)); diff --git a/core/src/net/sf/openrocket/simulation/SimulationStatus.java b/core/src/net/sf/openrocket/simulation/SimulationStatus.java index 6618fefea..f3457b532 100644 --- a/core/src/net/sf/openrocket/simulation/SimulationStatus.java +++ b/core/src/net/sf/openrocket/simulation/SimulationStatus.java @@ -46,6 +46,7 @@ public class SimulationStatus implements Monitorable { private Coordinate position; private WorldCoordinate worldPosition; private Coordinate velocity; + private Coordinate acceleration; private Quaternion orientation; private Coordinate rotationVelocity; @@ -105,6 +106,7 @@ public class SimulationStatus implements Monitorable { this.position = this.simulationConditions.getLaunchPosition(); this.velocity = this.simulationConditions.getLaunchVelocity(); this.worldPosition = this.simulationConditions.getLaunchSite(); + this.acceleration = Coordinate.ZERO; // Initialize to roll angle with least stability w.r.t. the wind Quaternion o; @@ -175,6 +177,7 @@ public class SimulationStatus implements Monitorable { this.time = orig.time; this.previousTimeStep = orig.previousTimeStep; this.position = orig.position; + this.acceleration = orig.acceleration; this.worldPosition = orig.worldPosition; this.velocity = orig.velocity; this.orientation = orig.orientation; @@ -300,7 +303,15 @@ public class SimulationStatus implements Monitorable { public Coordinate getRocketVelocity() { return velocity; } + + public void setRocketAcceleration(Coordinate acceleration) { + this.acceleration = acceleration; + this.modID++; + } + public Coordinate getRocketAcceleration() { + return acceleration; + } public boolean moveBurntOutMotor( final MotorConfigurationId motor) { // get motor from normal list