Merge pull request #2514 from JoePfeiffer/fix-2443
Reduce redundant acceleration data storage
This commit is contained in:
		
						commit
						3f8a118298
					
				@ -70,22 +70,24 @@ public abstract class AbstractEulerStepper extends AbstractSimulationStepper {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Compute drag acceleration
 | 
			
		||||
		store.linearAcceleration = airSpeed.normalize().multiply(-store.dragForce / store.rocketMass.getMass());
 | 
			
		||||
		Coordinate linearAcceleration = airSpeed.normalize().multiply(-store.dragForce / store.rocketMass.getMass());
 | 
			
		||||
		
 | 
			
		||||
		// Add effect of gravity
 | 
			
		||||
		store.gravity = modelGravity(status);
 | 
			
		||||
		store.linearAcceleration = store.linearAcceleration.sub(0, 0, store.gravity);
 | 
			
		||||
		linearAcceleration = linearAcceleration.sub(0, 0, store.gravity);
 | 
			
		||||
 | 
			
		||||
		// Add coriolis acceleration
 | 
			
		||||
		store.coriolisAcceleration = status.getSimulationConditions().getGeodeticComputation().getCoriolisAcceleration(
 | 
			
		||||
				status.getRocketWorldPosition(), status.getRocketVelocity());
 | 
			
		||||
		store.linearAcceleration = store.linearAcceleration.add(store.coriolisAcceleration);
 | 
			
		||||
		linearAcceleration = linearAcceleration.add(store.coriolisAcceleration);
 | 
			
		||||
 | 
			
		||||
		store.accelerationData = new AccelerationData(null, null, linearAcceleration, Coordinate.NUL, status.getRocketOrientationQuaternion());
 | 
			
		||||
 | 
			
		||||
		// Select tentative time step
 | 
			
		||||
		store.timeStep = RECOVERY_TIME_STEP;
 | 
			
		||||
 | 
			
		||||
		// adjust based on acceleration
 | 
			
		||||
		final double absAccel = store.linearAcceleration.length();
 | 
			
		||||
		final double absAccel = linearAcceleration.length();
 | 
			
		||||
		if (absAccel > MathUtil.EPSILON) {
 | 
			
		||||
			store.timeStep = Math.min(store.timeStep, 1.0/absAccel);
 | 
			
		||||
		}
 | 
			
		||||
@ -105,7 +107,7 @@ public abstract class AbstractEulerStepper extends AbstractSimulationStepper {
 | 
			
		||||
		log.trace("timeStep is " + store.timeStep);
 | 
			
		||||
		
 | 
			
		||||
		// Perform Euler integration
 | 
			
		||||
		EulerValues newVals = eulerIntegrate(status.getRocketPosition(), status.getRocketVelocity(), store.linearAcceleration, store.timeStep);
 | 
			
		||||
		EulerValues newVals = eulerIntegrate(status.getRocketPosition(), status.getRocketVelocity(), linearAcceleration, store.timeStep);
 | 
			
		||||
 | 
			
		||||
		// Check to see if z or either of its first two derivatives have changed sign and recalculate
 | 
			
		||||
		// time step to point of change if so
 | 
			
		||||
@ -115,7 +117,7 @@ public abstract class AbstractEulerStepper extends AbstractSimulationStepper {
 | 
			
		||||
		// Note that it's virtually impossible for apogee to occur on the same
 | 
			
		||||
		// step as either ground hit or descent rate inflection, and if we get a ground hit
 | 
			
		||||
		// any descent rate inflection won't matter
 | 
			
		||||
		final double a = store.linearAcceleration.z;
 | 
			
		||||
		final double a = linearAcceleration.z;
 | 
			
		||||
		final double v = status.getRocketVelocity().z;
 | 
			
		||||
		final double z = status.getRocketPosition().z;
 | 
			
		||||
		double t = store.timeStep;
 | 
			
		||||
@ -136,11 +138,11 @@ public abstract class AbstractEulerStepper extends AbstractSimulationStepper {
 | 
			
		||||
			// dA/dT = dA/dV * dV/dT
 | 
			
		||||
			final double dFdV = CdA * store.atmosphericConditions.getDensity() * airSpeed.length();
 | 
			
		||||
			final Coordinate dAdV = airSpeed.normalize().multiply(dFdV / store.rocketMass.getMass());
 | 
			
		||||
			final Coordinate jerk = store.linearAcceleration.multiply(dAdV);
 | 
			
		||||
			final Coordinate newAcceleration = store.linearAcceleration.add(jerk.multiply(store.timeStep));
 | 
			
		||||
			final Coordinate jerk = linearAcceleration.multiply(dAdV);
 | 
			
		||||
			final Coordinate newAcceleration = linearAcceleration.add(jerk.multiply(store.timeStep));
 | 
			
		||||
 | 
			
		||||
			// Only do this one if acceleration is appreciably different from 0
 | 
			
		||||
			if (newAcceleration.z * store.linearAcceleration.z < -MathUtil.EPSILON) {
 | 
			
		||||
			if (newAcceleration.z * linearAcceleration.z < -MathUtil.EPSILON) {
 | 
			
		||||
				// If acceleration oscillation is building up, the new timestep is the solution of
 | 
			
		||||
				// a + j*t = 0
 | 
			
		||||
				t = Math.abs(a / jerk.z);
 | 
			
		||||
@ -159,7 +161,7 @@ public abstract class AbstractEulerStepper extends AbstractSimulationStepper {
 | 
			
		||||
				store.timeStep = maxTimeStep;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			newVals = eulerIntegrate(status.getRocketPosition(), status.getRocketVelocity(), store.linearAcceleration, store.timeStep);
 | 
			
		||||
			newVals = eulerIntegrate(status.getRocketPosition(), status.getRocketVelocity(), linearAcceleration, store.timeStep);
 | 
			
		||||
 | 
			
		||||
			// If we just landed chop off rounding error
 | 
			
		||||
			if (Math.abs(newVals.pos.z) < MathUtil.EPSILON) {
 | 
			
		||||
@ -171,7 +173,6 @@ public abstract class AbstractEulerStepper extends AbstractSimulationStepper {
 | 
			
		||||
 | 
			
		||||
		status.setRocketPosition(newVals.pos);
 | 
			
		||||
		status.setRocketVelocity(newVals.vel);
 | 
			
		||||
		status.setRocketAcceleration(store.linearAcceleration);
 | 
			
		||||
 | 
			
		||||
		// Update the world coordinate
 | 
			
		||||
		WorldCoordinate w = status.getSimulationConditions().getLaunchSite();
 | 
			
		||||
 | 
			
		||||
@ -163,14 +163,12 @@ public abstract class AbstractSimulationStepper implements SimulationStepper {
 | 
			
		||||
	 *  
 | 
			
		||||
	 * @param status					the current simulation status.
 | 
			
		||||
	 * @param timestep					the time step of the current iteration.
 | 
			
		||||
	 * @param acceleration				the current (approximate) acceleration
 | 
			
		||||
	 * @param atmosphericConditions		the current atmospheric conditions
 | 
			
		||||
	 * @param store                     the simulation calculation DataStore (contains acceleration, atmosphere)
 | 
			
		||||
	 * @param stepMotors				whether to step the motors forward or work on a clone object
 | 
			
		||||
	 * @return							the average thrust during the time step.
 | 
			
		||||
	 */
 | 
			
		||||
	protected double calculateThrust(SimulationStatus status,
 | 
			
		||||
			double acceleration, AtmosphericConditions atmosphericConditions,
 | 
			
		||||
			boolean stepMotors) throws SimulationException {
 | 
			
		||||
	protected double calculateThrust(SimulationStatus status, DataStore store,
 | 
			
		||||
									 boolean stepMotors) throws SimulationException {
 | 
			
		||||
		double thrust;
 | 
			
		||||
 | 
			
		||||
		// Pre-listeners
 | 
			
		||||
@ -240,16 +238,11 @@ public abstract class AbstractSimulationStepper implements SimulationStepper {
 | 
			
		||||
		
 | 
			
		||||
		public FlightConditions flightConditions;
 | 
			
		||||
		
 | 
			
		||||
		public double longitudinalAcceleration = Double.NaN;
 | 
			
		||||
		
 | 
			
		||||
		public RigidBody rocketMass;
 | 
			
		||||
		
 | 
			
		||||
		public RigidBody motorMass;
 | 
			
		||||
		
 | 
			
		||||
		public Coordinate coriolisAcceleration;
 | 
			
		||||
		
 | 
			
		||||
		public Coordinate linearAcceleration;
 | 
			
		||||
		public Coordinate angularAcceleration;
 | 
			
		||||
 | 
			
		||||
		public Coordinate launchRodDirection = null;
 | 
			
		||||
		
 | 
			
		||||
@ -264,9 +257,6 @@ public abstract class AbstractSimulationStepper implements SimulationStepper {
 | 
			
		||||
		public double dragForce = Double.NaN;
 | 
			
		||||
		public double lateralPitchRate = Double.NaN;
 | 
			
		||||
		
 | 
			
		||||
		public double rollAcceleration = Double.NaN;
 | 
			
		||||
		public double lateralPitchAcceleration = Double.NaN;
 | 
			
		||||
		
 | 
			
		||||
		public Rotation2D thetaRotation;
 | 
			
		||||
 | 
			
		||||
		void storeData(SimulationStatus status) {
 | 
			
		||||
@ -286,12 +276,12 @@ public abstract class AbstractSimulationStepper implements SimulationStepper {
 | 
			
		||||
				dataBranch.setValue(FlightDataType.TYPE_CORIOLIS_ACCELERATION, coriolisAcceleration.length());
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			if (null != linearAcceleration) {
 | 
			
		||||
			if (null != accelerationData) {
 | 
			
		||||
				dataBranch.setValue(FlightDataType.TYPE_ACCELERATION_XY,
 | 
			
		||||
									MathUtil.hypot(linearAcceleration.x, linearAcceleration.y));
 | 
			
		||||
									MathUtil.hypot(accelerationData.getLinearAccelerationWC().x, accelerationData.getLinearAccelerationWC().y));
 | 
			
		||||
				
 | 
			
		||||
				dataBranch.setValue(FlightDataType.TYPE_ACCELERATION_TOTAL, linearAcceleration.length());
 | 
			
		||||
				dataBranch.setValue(FlightDataType.TYPE_ACCELERATION_Z, linearAcceleration.z);
 | 
			
		||||
				dataBranch.setValue(FlightDataType.TYPE_ACCELERATION_TOTAL, accelerationData.getLinearAccelerationWC().length());
 | 
			
		||||
				dataBranch.setValue(FlightDataType.TYPE_ACCELERATION_Z, accelerationData.getLinearAccelerationWC().z);
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			if (null != rocketMass) {
 | 
			
		||||
 | 
			
		||||
@ -57,7 +57,7 @@ public class RK4SimulationStepper extends AbstractSimulationStepper {
 | 
			
		||||
	//	private static final double MAX_ROLL_STEP_ANGLE = 8.32 * Math.PI/180;
 | 
			
		||||
	
 | 
			
		||||
	private static final double MAX_ROLL_RATE_CHANGE = 2 * Math.PI / 180;
 | 
			
		||||
	private static final double MAX_PITCH_CHANGE = 4 * Math.PI / 180;
 | 
			
		||||
	private static final double MAX_PITCH_YAW_CHANGE = 4 * Math.PI / 180;
 | 
			
		||||
	
 | 
			
		||||
	private Random random;
 | 
			
		||||
	DataStore store = new DataStore();
 | 
			
		||||
@ -133,8 +133,10 @@ public class RK4SimulationStepper extends AbstractSimulationStepper {
 | 
			
		||||
		dt[1] = maxTimeStep;
 | 
			
		||||
		dt[2] = status.getSimulationConditions().getMaximumAngleStep() / store.lateralPitchRate;
 | 
			
		||||
		dt[3] = Math.abs(MAX_ROLL_STEP_ANGLE / store.flightConditions.getRollRate());
 | 
			
		||||
		dt[4] = Math.abs(MAX_ROLL_RATE_CHANGE / store.rollAcceleration);
 | 
			
		||||
		dt[5] = Math.abs(MAX_PITCH_CHANGE / store.lateralPitchAcceleration);
 | 
			
		||||
		dt[4] = Math.abs(MAX_ROLL_RATE_CHANGE / store.accelerationData.getRotationalAccelerationRC().z);
 | 
			
		||||
		dt[5] = Math.abs(MAX_PITCH_YAW_CHANGE /
 | 
			
		||||
						 MathUtil.max(Math.abs(store.accelerationData.getRotationalAccelerationRC().x),
 | 
			
		||||
									  Math.abs(store.accelerationData.getRotationalAccelerationRC().y)));
 | 
			
		||||
		if (!status.isLaunchRodCleared()) {
 | 
			
		||||
			dt[0] /= 5.0;
 | 
			
		||||
			dt[6] = status.getSimulationConditions().getLaunchRodLength() / k1.v.length() / 10;
 | 
			
		||||
@ -273,8 +275,8 @@ public class RK4SimulationStepper extends AbstractSimulationStepper {
 | 
			
		||||
		// Call post-listeners
 | 
			
		||||
		store.accelerationData = SimulationListenerHelper.firePostAccelerationCalculation(status, store.accelerationData);
 | 
			
		||||
 | 
			
		||||
		params.a = dataStore.linearAcceleration;
 | 
			
		||||
		params.ra = dataStore.angularAcceleration;
 | 
			
		||||
		params.a = dataStore.accelerationData.getLinearAccelerationWC();
 | 
			
		||||
		params.ra = dataStore.accelerationData.getRotationalAccelerationWC();
 | 
			
		||||
		params.v = status.getRocketVelocity();
 | 
			
		||||
		params.rv = status.getRocketRotationVelocity();
 | 
			
		||||
		
 | 
			
		||||
@ -298,7 +300,9 @@ public class RK4SimulationStepper extends AbstractSimulationStepper {
 | 
			
		||||
	 * @throws SimulationException 
 | 
			
		||||
	 */
 | 
			
		||||
	private AccelerationData calculateAcceleration(SimulationStatus status, DataStore store) throws SimulationException {
 | 
			
		||||
		
 | 
			
		||||
		Coordinate linearAcceleration;
 | 
			
		||||
		Coordinate angularAcceleration;
 | 
			
		||||
			
 | 
			
		||||
		// Compute the forces affecting the rocket
 | 
			
		||||
		calculateForces(status, store);
 | 
			
		||||
		
 | 
			
		||||
@ -325,35 +329,33 @@ public class RK4SimulationStepper extends AbstractSimulationStepper {
 | 
			
		||||
		double fN = store.forces.getCN() * dynP * refArea;
 | 
			
		||||
		double fSide = store.forces.getCside() * dynP * refArea;
 | 
			
		||||
 | 
			
		||||
		store.thrustForce = calculateThrust(status, store.longitudinalAcceleration, store.flightConditions.getAtmosphericConditions(), false);
 | 
			
		||||
		store.thrustForce = calculateThrust(status, store, false);
 | 
			
		||||
		double forceZ =  store.thrustForce - store.dragForce;
 | 
			
		||||
		
 | 
			
		||||
		store.linearAcceleration = new Coordinate(-fN / store.rocketMass.getMass(),
 | 
			
		||||
		linearAcceleration = new Coordinate(-fN / store.rocketMass.getMass(),
 | 
			
		||||
					-fSide / store.rocketMass.getMass(),
 | 
			
		||||
					forceZ / store.rocketMass.getMass());
 | 
			
		||||
		
 | 
			
		||||
		store.linearAcceleration = store.thetaRotation.rotateZ(store.linearAcceleration);
 | 
			
		||||
		linearAcceleration = store.thetaRotation.rotateZ(linearAcceleration);
 | 
			
		||||
		
 | 
			
		||||
		// Convert into rocket world coordinates
 | 
			
		||||
		store.linearAcceleration = status.getRocketOrientationQuaternion().rotate(store.linearAcceleration);
 | 
			
		||||
		linearAcceleration = status.getRocketOrientationQuaternion().rotate(linearAcceleration);
 | 
			
		||||
		
 | 
			
		||||
		// add effect of gravity
 | 
			
		||||
		store.gravity = modelGravity(status);
 | 
			
		||||
		store.linearAcceleration = store.linearAcceleration.sub(0, 0, store.gravity);
 | 
			
		||||
		linearAcceleration = linearAcceleration.sub(0, 0, store.gravity);
 | 
			
		||||
		
 | 
			
		||||
		// add effect of Coriolis acceleration
 | 
			
		||||
		store.coriolisAcceleration = status.getSimulationConditions().getGeodeticComputation()
 | 
			
		||||
				.getCoriolisAcceleration(status.getRocketWorldPosition(), status.getRocketVelocity());
 | 
			
		||||
		store.linearAcceleration = store.linearAcceleration.add(store.coriolisAcceleration);
 | 
			
		||||
		linearAcceleration = linearAcceleration.add(store.coriolisAcceleration);
 | 
			
		||||
		
 | 
			
		||||
		// If still on the launch rod, project acceleration onto launch rod direction and
 | 
			
		||||
		// set angular acceleration to zero.
 | 
			
		||||
		if (!status.isLaunchRodCleared()) {
 | 
			
		||||
			
 | 
			
		||||
			store.linearAcceleration = store.launchRodDirection.multiply(store.linearAcceleration.dot(store.launchRodDirection));
 | 
			
		||||
			store.angularAcceleration = Coordinate.NUL;
 | 
			
		||||
			store.rollAcceleration = 0;
 | 
			
		||||
			store.lateralPitchAcceleration = 0;
 | 
			
		||||
			linearAcceleration = store.launchRodDirection.multiply(linearAcceleration.dot(store.launchRodDirection));
 | 
			
		||||
			angularAcceleration = Coordinate.NUL;
 | 
			
		||||
			
 | 
			
		||||
		} else {
 | 
			
		||||
			
 | 
			
		||||
@ -366,24 +368,18 @@ public class RK4SimulationStepper extends AbstractSimulationStepper {
 | 
			
		||||
			double momY = Cm * dynP * refArea * refLength;
 | 
			
		||||
			double momZ = store.forces.getCroll() * dynP * refArea * refLength;
 | 
			
		||||
			
 | 
			
		||||
			// Compute acceleration in rocket coordinates
 | 
			
		||||
			store.angularAcceleration = new Coordinate(momX / store.rocketMass.getLongitudinalInertia(),
 | 
			
		||||
			// Compute angular acceleration in rocket coordinates
 | 
			
		||||
			angularAcceleration = new Coordinate(momX / store.rocketMass.getLongitudinalInertia(),
 | 
			
		||||
						momY / store.rocketMass.getLongitudinalInertia(),
 | 
			
		||||
						momZ / store.rocketMass.getRotationalInertia());
 | 
			
		||||
			
 | 
			
		||||
			store.rollAcceleration = store.angularAcceleration.z;
 | 
			
		||||
			// TODO: LOW: This should be hypot, but does it matter?
 | 
			
		||||
			store.lateralPitchAcceleration = MathUtil.max(Math.abs(store.angularAcceleration.x),
 | 
			
		||||
						Math.abs(store.angularAcceleration.y));
 | 
			
		||||
			
 | 
			
		||||
			store.angularAcceleration = store.thetaRotation.rotateZ(store.angularAcceleration);
 | 
			
		||||
			angularAcceleration = store.thetaRotation.rotateZ(angularAcceleration);
 | 
			
		||||
			
 | 
			
		||||
			// Convert to world coordinates
 | 
			
		||||
			store.angularAcceleration = status.getRocketOrientationQuaternion().rotate(store.angularAcceleration);
 | 
			
		||||
			
 | 
			
		||||
			angularAcceleration = status.getRocketOrientationQuaternion().rotate(angularAcceleration);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return new AccelerationData(null, null, store.linearAcceleration, store.angularAcceleration, status.getRocketOrientationQuaternion());
 | 
			
		||||
		return new AccelerationData(null, null, linearAcceleration, angularAcceleration, status.getRocketOrientationQuaternion());
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user