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 {
|
} else {
|
||||||
|
|
||||||
// Check ground hit after liftoff
|
// 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.GROUND_HIT, currentStatus.getSimulationTime()));
|
||||||
|
|
||||||
// addEvent(new FlightEvent(FlightEvent.Type.SIMULATION_END, 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.MathUtil;
|
||||||
import net.sf.openrocket.util.WorldCoordinate;
|
import net.sf.openrocket.util.WorldCoordinate;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class BasicLandingStepper extends AbstractSimulationStepper {
|
public class BasicLandingStepper extends AbstractSimulationStepper {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(BasicLandingStepper.class);
|
||||||
|
|
||||||
private static final double RECOVERY_TIME_STEP = 0.5;
|
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);
|
double timeStep = MathUtil.min(0.5 / linearAcceleration.length(), RECOVERY_TIME_STEP);
|
||||||
|
|
||||||
// Perform Euler integration
|
// Perform Euler integration
|
||||||
status.setRocketPosition(status.getRocketPosition().add(status.getRocketVelocity().multiply(timeStep)).
|
Coordinate newPosition = status.getRocketPosition().add(status.getRocketVelocity().multiply(timeStep)).
|
||||||
add(linearAcceleration.multiply(MathUtil.pow2(timeStep) / 2)));
|
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)));
|
status.setRocketVelocity(status.getRocketVelocity().add(linearAcceleration.multiply(timeStep)));
|
||||||
|
airSpeed = status.getRocketVelocity().add(windSpeed);
|
||||||
status.setSimulationTime(status.getSimulationTime() + timeStep);
|
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_TIME_STEP, timeStep);
|
||||||
data.setValue(FlightDataType.TYPE_COMPUTATION_TIME,
|
data.setValue(FlightDataType.TYPE_COMPUTATION_TIME,
|
||||||
(System.nanoTime() - status.getSimulationStartWallTime()) / 1000000000.0);
|
(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
|
@Override
|
||||||
public void step(SimulationStatus status, double timeStep) throws SimulationException {
|
public void step(SimulationStatus status, double timeStep) throws SimulationException {
|
||||||
log.trace("step: position=" + status.getRocketPosition() + ", velocity=" + status.getRocketVelocity());
|
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();
|
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;
|
return Double.NaN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for the index of the right end point.
|
// Look for the index of the right end point.
|
||||||
int right = 1;
|
int right = 1;
|
||||||
while (t > domain.get(right)) {
|
while (t > domain.get(right) + EPSILON) {
|
||||||
right++;
|
right++;
|
||||||
}
|
}
|
||||||
int left = right - 1;
|
int left = right - 1;
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit c9bd1a6f539aab4bb724ecbdb54e65100a33e701
|
Subproject commit 8304c0fd3dc80d65c40af4da83268ec1b32931d6
|
Loading…
x
Reference in New Issue
Block a user