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