Refactored the initialization and copying of SimulationStatus objects.

Initialization is now done in the constructor instead of
BasicEventSimulationEngine.  Copying SimulationStatus is implemented in
copy constructors instead of using SimulationStatus.copyFrom().
This commit is contained in:
kruland2607 2012-10-24 22:28:40 -05:00
parent 6d8b27068f
commit 27d6322f09
4 changed files with 135 additions and 131 deletions

View File

@ -66,7 +66,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
throw new MotorIgnitionException("No motors defined in the simulation.");
}
status = initialStatus(configuration, motorConfiguration, simulationConditions, flightData);
status = new SimulationStatus(configuration, motorConfiguration, simulationConditions, flightData.getWarningSet());
stages.add(status);
SimulationListenerHelper.fireStartSimulation(status);
@ -200,83 +200,6 @@ public class BasicEventSimulationEngine implements SimulationEngine {
return status.getFlightData();
}
private SimulationStatus initialStatus(Configuration configuration,
MotorInstanceConfiguration motorConfiguration,
SimulationConditions simulationConditions, FlightData flightData) {
SimulationStatus init = new SimulationStatus();
init.setSimulationConditions(simulationConditions);
init.setConfiguration(configuration);
init.setMotorConfiguration(motorConfiguration);
init.setSimulationTime(0);
init.setPreviousTimeStep(simulationConditions.getTimeStep());
init.setRocketPosition(Coordinate.NUL);
init.setRocketVelocity(Coordinate.NUL);
init.setRocketWorldPosition(simulationConditions.getLaunchSite());
// Initialize to roll angle with least stability w.r.t. the wind
Quaternion o;
FlightConditions cond = new FlightConditions(configuration);
simulationConditions.getAerodynamicCalculator().getWorstCP(configuration, cond, null);
double angle = -cond.getTheta() - simulationConditions.getLaunchRodDirection();
o = Quaternion.rotation(new Coordinate(0, 0, angle));
// Launch rod angle and direction
o = o.multiplyLeft(Quaternion.rotation(new Coordinate(0, simulationConditions.getLaunchRodAngle(), 0)));
o = o.multiplyLeft(Quaternion.rotation(new Coordinate(0, 0, simulationConditions.getLaunchRodDirection())));
init.setRocketOrientationQuaternion(o);
init.setRocketRotationVelocity(Coordinate.NUL);
/*
* Calculate the effective launch rod length taking into account launch lugs.
* If no lugs are found, assume a tower launcher of full length.
*/
double length = simulationConditions.getLaunchRodLength();
double lugPosition = Double.NaN;
for (RocketComponent c : configuration) {
if (c instanceof LaunchLug) {
double pos = c.toAbsolute(new Coordinate(c.getLength()))[0].x;
if (Double.isNaN(lugPosition) || pos > lugPosition) {
lugPosition = pos;
}
}
}
if (!Double.isNaN(lugPosition)) {
double maxX = 0;
for (Coordinate c : configuration.getBounds()) {
if (c.x > maxX)
maxX = c.x;
}
if (maxX >= lugPosition) {
length = Math.max(0, length - (maxX - lugPosition));
}
}
init.setEffectiveLaunchRodLength(length);
init.setSimulationStartWallTime(System.nanoTime());
init.setMotorIgnited(false);
init.setLiftoff(false);
init.setLaunchRodCleared(false);
init.setApogeeReached(false);
init.getEventQueue().add(new FlightEvent(FlightEvent.Type.LAUNCH, 0, simulationConditions.getRocket()));
init.setFlightData(new FlightDataBranch("MAIN", FlightDataType.TYPE_TIME));
init.setWarnings(flightData.getWarningSet());
return init;
}
/**
* Create a rocket configuration from the launch conditions.
*
@ -484,8 +407,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
int n = stage.getStageNumber();
// Prepare the booster status for simulation.
SimulationStatus boosterStatus = new SimulationStatus();
boosterStatus.copyFrom(status);
SimulationStatus boosterStatus = new SimulationStatus(status);
FlightDataBranch boosterFlightData = new FlightDataBranch( "Stage-" + n, FlightDataType.TYPE_TIME);
boosterStatus.setFlightData(boosterFlightData);

View File

@ -1,6 +1,9 @@
package net.sf.openrocket.simulation;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.models.atmosphere.AtmosphericConditions;
import net.sf.openrocket.motor.MotorInstanceConfiguration;
import net.sf.openrocket.rocketcomponent.Configuration;
import net.sf.openrocket.util.Coordinate;
public class RK4SimulationStatus extends SimulationStatus {
@ -13,7 +16,22 @@ public class RK4SimulationStatus extends SimulationStatus {
private double maxZVelocity = 0;
private double startWarningTime = -1;
public RK4SimulationStatus(Configuration configuration,
MotorInstanceConfiguration motorConfiguration,
SimulationConditions simulationConditions, WarningSet warnings) {
super(configuration, motorConfiguration, simulationConditions, warnings);
}
public RK4SimulationStatus( SimulationStatus other ) {
super(other);
if ( other instanceof RK4SimulationStatus ) {
this.launchRodDirection = ((RK4SimulationStatus) other).launchRodDirection;
this.previousAcceleration = ((RK4SimulationStatus) other).previousAcceleration;
this.maxZVelocity = ((RK4SimulationStatus) other).maxZVelocity;
this.startWarningTime = ((RK4SimulationStatus) other).startWarningTime;
this.previousAtmosphericConditions = ((RK4SimulationStatus) other).previousAtmosphericConditions;
}
}
public void setLaunchRodDirection(Coordinate launchRodDirection) {
this.launchRodDirection = launchRodDirection;
}
@ -65,8 +83,6 @@ public class RK4SimulationStatus extends SimulationStatus {
this.startWarningTime = startWarningTime;
}
@Override
public RK4SimulationStatus clone() {
return (RK4SimulationStatus) super.clone();
}

View File

@ -66,9 +66,7 @@ public class RK4SimulationStepper extends AbstractSimulationStepper {
@Override
public RK4SimulationStatus initialize(SimulationStatus original) {
RK4SimulationStatus status = new RK4SimulationStatus();
status.copyFrom(original);
RK4SimulationStatus status = new RK4SimulationStatus(original);
SimulationConditions sim = original.getSimulationConditions();

View File

@ -5,11 +5,14 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import net.sf.openrocket.aerodynamics.FlightConditions;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.motor.MotorId;
import net.sf.openrocket.motor.MotorInstanceConfiguration;
import net.sf.openrocket.rocketcomponent.Configuration;
import net.sf.openrocket.rocketcomponent.LaunchLug;
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.Monitorable;
@ -22,7 +25,7 @@ import net.sf.openrocket.util.WorldCoordinate;
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class SimulationStatus implements Cloneable, Monitorable {
public class SimulationStatus implements Monitorable {
/*
* NOTE! All fields must be added to copyFrom() method!!
@ -81,6 +84,115 @@ public class SimulationStatus implements Cloneable, Monitorable {
private int modID = 0;
private int modIDadd = 0;
public SimulationStatus( Configuration configuration,
MotorInstanceConfiguration motorConfiguration,
SimulationConditions simulationConditions, WarningSet warnings ) {
this.setSimulationConditions(simulationConditions);
this.setConfiguration(configuration);
this.setMotorConfiguration(motorConfiguration);
this.setSimulationTime(0);
this.setPreviousTimeStep(simulationConditions.getTimeStep());
this.setRocketPosition(Coordinate.NUL);
this.setRocketVelocity(Coordinate.NUL);
this.setRocketWorldPosition(simulationConditions.getLaunchSite());
// Initialize to roll angle with least stability w.r.t. the wind
Quaternion o;
FlightConditions cond = new FlightConditions(configuration);
simulationConditions.getAerodynamicCalculator().getWorstCP(configuration, cond, null);
double angle = -cond.getTheta() - simulationConditions.getLaunchRodDirection();
o = Quaternion.rotation(new Coordinate(0, 0, angle));
// Launch rod angle and direction
o = o.multiplyLeft(Quaternion.rotation(new Coordinate(0, simulationConditions.getLaunchRodAngle(), 0)));
o = o.multiplyLeft(Quaternion.rotation(new Coordinate(0, 0, simulationConditions.getLaunchRodDirection())));
this.setRocketOrientationQuaternion(o);
this.setRocketRotationVelocity(Coordinate.NUL);
/*
* Calculate the effective launch rod length taking into account launch lugs.
* If no lugs are found, assume a tower launcher of full length.
*/
double length = simulationConditions.getLaunchRodLength();
double lugPosition = Double.NaN;
for (RocketComponent c : configuration) {
if (c instanceof LaunchLug) {
double pos = c.toAbsolute(new Coordinate(c.getLength()))[0].x;
if (Double.isNaN(lugPosition) || pos > lugPosition) {
lugPosition = pos;
}
}
}
if (!Double.isNaN(lugPosition)) {
double maxX = 0;
for (Coordinate c : configuration.getBounds()) {
if (c.x > maxX)
maxX = c.x;
}
if (maxX >= lugPosition) {
length = Math.max(0, length - (maxX - lugPosition));
}
}
this.setEffectiveLaunchRodLength(length);
this.setSimulationStartWallTime(System.nanoTime());
this.setMotorIgnited(false);
this.setLiftoff(false);
this.setLaunchRodCleared(false);
this.setApogeeReached(false);
this.getEventQueue().add(new FlightEvent(FlightEvent.Type.LAUNCH, 0, simulationConditions.getRocket()));
this.setFlightData(new FlightDataBranch("MAIN", FlightDataType.TYPE_TIME));
this.setWarnings(warnings);
}
/**
* Copies the data from the provided object to this object. Most included object are
* deep-cloned, except for the flight data object.
*
* @param orig the object from which to copy
*/
public SimulationStatus( SimulationStatus orig ) {
this.simulationConditions = orig.simulationConditions.clone();
this.configuration = orig.configuration.clone();
this.motorConfiguration = orig.motorConfiguration.clone();
this.flightData = orig.flightData;
this.time = orig.time;
this.previousTimeStep = orig.previousTimeStep;
this.position = orig.position;
this.worldPosition = orig.worldPosition;
this.velocity = orig.velocity;
this.orientation = orig.orientation;
this.rotationVelocity = orig.rotationVelocity;
this.effectiveLaunchRodLength = orig.effectiveLaunchRodLength;
this.simulationStartWallTime = orig.simulationStartWallTime;
this.motorIgnited = orig.motorIgnited;
this.liftoff = orig.liftoff;
this.launchRodCleared = orig.launchRodCleared;
this.apogeeReached = orig.apogeeReached;
this.motorBurntOut = orig.motorBurntOut;
this.deployedRecoveryDevices.clear();
this.deployedRecoveryDevices.addAll(orig.deployedRecoveryDevices);
this.eventQueue.clear();
this.eventQueue.addAll(orig.eventQueue);
this.warnings = orig.warnings;
this.extraData.clear();
this.extraData.putAll(orig.extraData);
this.modID = orig.modID;
this.modIDadd = orig.modIDadd;
}
public void setSimulationTime(double time) {
this.time = time;
@ -323,7 +435,6 @@ public class SimulationStatus implements Cloneable, Monitorable {
return extraData.get(key);
}
/**
* Returns a copy of this object. The general purpose is that the conditions,
* rocket configuration, flight data etc. point to the same objects. However,
@ -331,7 +442,6 @@ public class SimulationStatus implements Cloneable, Monitorable {
* to the current orientation of the rocket. The purpose is to allow creating intermediate
* copies of this object used during step computation.
*
* TODO: HIGH: Deep cloning required for branch saving.
*/
@Override
public SimulationStatus clone() {
@ -344,48 +454,6 @@ public class SimulationStatus implements Cloneable, Monitorable {
}
/**
* Copies the data from the provided object to this object. Most included object are
* deep-cloned, except for the flight data object.
*
* @param orig the object from which to copy
*/
public void copyFrom(SimulationStatus orig) {
this.simulationConditions = orig.simulationConditions.clone();
this.configuration = orig.configuration.clone();
this.motorConfiguration = orig.motorConfiguration.clone();
this.flightData = orig.flightData;
this.time = orig.time;
this.previousTimeStep = orig.previousTimeStep;
this.position = orig.position;
this.worldPosition = orig.worldPosition;
this.velocity = orig.velocity;
this.orientation = orig.orientation;
this.rotationVelocity = orig.rotationVelocity;
this.effectiveLaunchRodLength = orig.effectiveLaunchRodLength;
this.simulationStartWallTime = orig.simulationStartWallTime;
this.motorIgnited = orig.motorIgnited;
this.liftoff = orig.liftoff;
this.launchRodCleared = orig.launchRodCleared;
this.apogeeReached = orig.apogeeReached;
this.motorBurntOut = orig.motorBurntOut;
this.deployedRecoveryDevices.clear();
this.deployedRecoveryDevices.addAll(orig.deployedRecoveryDevices);
this.eventQueue.clear();
this.eventQueue.addAll(orig.eventQueue);
this.warnings = orig.warnings;
this.extraData.clear();
this.extraData.putAll(orig.extraData);
this.modID = orig.modID;
this.modIDadd = orig.modIDadd;
}
@Override
public int getModID() {
return (modID + modIDadd + simulationConditions.getModID() + configuration.getModID() +