Merge pull request #1352 from JoePfeiffer/fix-1349
Get and save correct ground hit velocity
This commit is contained in:
commit
c315aca9e9
@ -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()));
|
||||
|
@ -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,35 @@ 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;
|
||||
|
||||
// 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 +165,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));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit c9bd1a6f539aab4bb724ecbdb54e65100a33e701
|
||||
Subproject commit 8304c0fd3dc80d65c40af4da83268ec1b32931d6
|
Loading…
x
Reference in New Issue
Block a user