Support for opening recovery device on stage separation

This commit is contained in:
Sampo Niskanen 2012-04-19 17:24:03 +00:00
parent 74cee3dbbe
commit 1c411548a7
6 changed files with 58 additions and 48 deletions

View File

@ -1,6 +1,10 @@
2012-04-19 Sampo Niskanen
* Allow opening recovery device on stage separation
2012-04-11 Doug Pedrick 2012-04-11 Doug Pedrick
* [BUG] Printed simulation did not honor launch conditions * [BUG] Printed simulation did not honor launch conditions
2012-04-09 Sampo Niskanen 2012-04-09 Sampo Niskanen
@ -17,7 +21,7 @@
2012-03-25 Doug Pedrick 2012-03-25 Doug Pedrick
* Printed rocket figure in design report now honors rotation angle of main figure; fixed bug in layout where the * Printed rocket figure in design report now honors rotation angle of main figure; fixed bug in layout where the
figure was clipped in the page margin. figure was clipped in the page margin.
2012-03-18 Jason Blood 2012-03-18 Jason Blood

View File

@ -39,4 +39,5 @@ The following file format versions exist:
digesting algorithm was changed. Adds <separationevent> and digesting algorithm was changed. Adds <separationevent> and
<separationdelay> elements to stage components (except sustainer). <separationdelay> elements to stage components (except sustainer).
1.5: Introduced with OpenRocket 12.xx. Added ComponentPresets. 1.5: Introduced with OpenRocket 12.xx. Added ComponentPresets.
Added lowerstageseparation as recovery device deployment event.

View File

@ -1197,6 +1197,8 @@ RecoveryDevice.DeployEvent.LAUNCH = Launch (plus NN seconds)
RecoveryDevice.DeployEvent.EJECTION = First ejection charge of this stage RecoveryDevice.DeployEvent.EJECTION = First ejection charge of this stage
RecoveryDevice.DeployEvent.APOGEE = Apogee RecoveryDevice.DeployEvent.APOGEE = Apogee
RecoveryDevice.DeployEvent.ALTITUDE = Specific altitude during descent RecoveryDevice.DeployEvent.ALTITUDE = Specific altitude during descent
RecoveryDevice.DeployEvent.CURRENT_STAGE_SEPARATION = Current stage separation
RecoveryDevice.DeployEvent.LOWER_STAGE_SEPARATION = Lower stage separation
RecoveryDevice.DeployEvent.NEVER = Never RecoveryDevice.DeployEvent.NEVER = Never
! FlightEvent ! FlightEvent

View File

@ -19,6 +19,8 @@ import net.sf.openrocket.file.RocketSaver;
import net.sf.openrocket.logging.LogHelper; import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.rocketcomponent.FinSet; import net.sf.openrocket.rocketcomponent.FinSet;
import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import net.sf.openrocket.rocketcomponent.RecoveryDevice.DeployEvent;
import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.TubeCoupler; import net.sf.openrocket.rocketcomponent.TubeCoupler;
@ -186,6 +188,7 @@ public class OpenRocketSaver extends RocketSaver {
/* /*
* File version 1.5 is requires for: * File version 1.5 is requires for:
* - saving designs using ComponentPrests * - saving designs using ComponentPrests
* - recovery device deployment on lower stage separation
* *
* File version 1.4 is required for: * File version 1.4 is required for:
* - saving simulation data * - saving simulation data
@ -198,31 +201,29 @@ public class OpenRocketSaver extends RocketSaver {
* Otherwise use version 1.0. * Otherwise use version 1.0.
*/ */
// Search the rocket for any ComponentPrests // Search the rocket for any ComponentPresets (version 1.5)
{ for (RocketComponent c : document.getRocket()) {
Rocket r = document.getRocket(); if (c.getPresetComponent() != null) {
Iterator<RocketComponent> componentIterator = r.iterator();
boolean usesComponentPreset = false;
while ( !usesComponentPreset && componentIterator.hasNext() ) {
RocketComponent c = componentIterator.next();
if ( c.getPresetComponent() != null ) {
usesComponentPreset = true;
}
}
if ( usesComponentPreset ) {
return FILE_VERSION_DIVISOR + 5; return FILE_VERSION_DIVISOR + 5;
} }
} }
// Search for recovery device deployment type LOWER_STAGE_SEPARATION (version 1.5)
for (RocketComponent c : document.getRocket()) {
if (c instanceof RecoveryDevice) {
if (((RecoveryDevice) c).getDeployEvent() == DeployEvent.LOWER_STAGE_SEPARATION) {
return FILE_VERSION_DIVISOR + 5;
}
}
}
// Check if design has simulations defined (version 1.4) // Check if design has simulations defined (version 1.4)
if (document.getSimulationCount() > 0) { if (document.getSimulationCount() > 0) {
return FILE_VERSION_DIVISOR + 4; return FILE_VERSION_DIVISOR + 4;
} }
// Check for motor definitions (version 1.4) // Check for motor definitions (version 1.4)
Iterator<RocketComponent> iterator = document.getRocket().iterator(); for (RocketComponent c : document.getRocket()) {
while (iterator.hasNext()) {
RocketComponent c = iterator.next();
if (!(c instanceof MotorMount)) if (!(c instanceof MotorMount))
continue; continue;
@ -235,10 +236,7 @@ public class OpenRocketSaver extends RocketSaver {
} }
// Check for fin tabs (version 1.1) // Check for fin tabs (version 1.1)
iterator = document.getRocket().iterator(); for (RocketComponent c : document.getRocket()) {
while (iterator.hasNext()) {
RocketComponent c = iterator.next();
// Check for fin tabs // Check for fin tabs
if (c instanceof FinSet) { if (c instanceof FinSet) {
FinSet fin = (FinSet) c; FinSet fin = (FinSet) c;

View File

@ -19,7 +19,7 @@ public class RecoveryDeviceSaver extends MassObjectSaver {
else else
elements.add("<cd>" + dev.getCD() + "</cd>"); elements.add("<cd>" + dev.getCD() + "</cd>");
elements.add("<deployevent>" + dev.getDeployEvent().name().toLowerCase(Locale.ENGLISH) + "</deployevent>"); elements.add("<deployevent>" + dev.getDeployEvent().name().toLowerCase(Locale.ENGLISH).replace("_", "") + "</deployevent>");
elements.add("<deployaltitude>" + dev.getDeployAltitude() + "</deployaltitude>"); elements.add("<deployaltitude>" + dev.getDeployAltitude() + "</deployaltitude>");
elements.add("<deploydelay>" + dev.getDeployDelay() + "</deploydelay>"); elements.add("<deploydelay>" + dev.getDeployDelay() + "</deploydelay>");
elements.add(materialParam(dev.getMaterial())); elements.add(materialParam(dev.getMaterial()));

View File

@ -22,16 +22,14 @@ import net.sf.openrocket.util.Pair;
*/ */
public abstract class RecoveryDevice extends MassObject { public abstract class RecoveryDevice extends MassObject {
private static final Translator trans = Application.getTranslator(); private static final Translator trans = Application.getTranslator();
public static enum DeployEvent { public static enum DeployEvent {
//// Launch (plus NN seconds)
LAUNCH(trans.get("RecoveryDevice.DeployEvent.LAUNCH")) { LAUNCH(trans.get("RecoveryDevice.DeployEvent.LAUNCH")) {
@Override @Override
public boolean isActivationEvent(FlightEvent e, RocketComponent source) { public boolean isActivationEvent(FlightEvent e, RocketComponent source) {
return e.getType() == FlightEvent.Type.LAUNCH; return e.getType() == FlightEvent.Type.LAUNCH;
} }
}, },
//// First ejection charge of this stage
EJECTION(trans.get("RecoveryDevice.DeployEvent.EJECTION")) { EJECTION(trans.get("RecoveryDevice.DeployEvent.EJECTION")) {
@Override @Override
public boolean isActivationEvent(FlightEvent e, RocketComponent source) { public boolean isActivationEvent(FlightEvent e, RocketComponent source) {
@ -41,35 +39,42 @@ public abstract class RecoveryDevice extends MassObject {
return charge.getStageNumber() == source.getStageNumber(); return charge.getStageNumber() == source.getStageNumber();
} }
}, },
//// Apogee
APOGEE(trans.get("RecoveryDevice.DeployEvent.APOGEE")) { APOGEE(trans.get("RecoveryDevice.DeployEvent.APOGEE")) {
@Override @Override
public boolean isActivationEvent(FlightEvent e, RocketComponent source) { public boolean isActivationEvent(FlightEvent e, RocketComponent source) {
return e.getType() == FlightEvent.Type.APOGEE; return e.getType() == FlightEvent.Type.APOGEE;
} }
}, },
//// Specific altitude during descent
ALTITUDE(trans.get("RecoveryDevice.DeployEvent.ALTITUDE")) { ALTITUDE(trans.get("RecoveryDevice.DeployEvent.ALTITUDE")) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public boolean isActivationEvent(FlightEvent e, RocketComponent source) { public boolean isActivationEvent(FlightEvent e, RocketComponent source) {
if (e.getType() != FlightEvent.Type.ALTITUDE) if (e.getType() != FlightEvent.Type.ALTITUDE)
return false; return false;
double alt = ((RecoveryDevice)source).getDeployAltitude(); double alt = ((RecoveryDevice) source).getDeployAltitude();
Pair<Double,Double> altitude = (Pair<Double,Double>)e.getData(); Pair<Double, Double> altitude = (Pair<Double, Double>) e.getData();
return (altitude.getU() >= alt) && (altitude.getV() <= alt); return (altitude.getU() >= alt) && (altitude.getV() <= alt);
} }
}, },
//// Never LOWER_STAGE_SEPARATION(trans.get("RecoveryDevice.DeployEvent.LOWER_STAGE_SEPARATION")) {
@Override
public boolean isActivationEvent(FlightEvent e, RocketComponent source) {
if (e.getType() != FlightEvent.Type.STAGE_SEPARATION)
return false;
int separation = e.getSource().getStageNumber();
int current = source.getStageNumber();
return (current + 1 == separation);
}
},
NEVER(trans.get("RecoveryDevice.DeployEvent.NEVER")) { NEVER(trans.get("RecoveryDevice.DeployEvent.NEVER")) {
@Override @Override
public boolean isActivationEvent(FlightEvent e, RocketComponent source) { public boolean isActivationEvent(FlightEvent e, RocketComponent source) {
return false; return false;
} }
} };
;
private final String description; private final String description;
@ -83,7 +88,7 @@ public abstract class RecoveryDevice extends MassObject {
public String toString() { public String toString() {
return description; return description;
} }
} }
@ -96,7 +101,7 @@ public abstract class RecoveryDevice extends MassObject {
private Material.Surface material; private Material.Surface material;
public RecoveryDevice() { public RecoveryDevice() {
this(Application.getPreferences().getDefaultComponentMaterial(RecoveryDevice.class, Material.Type.SURFACE)); this(Application.getPreferences().getDefaultComponentMaterial(RecoveryDevice.class, Material.Type.SURFACE));
@ -106,19 +111,19 @@ public abstract class RecoveryDevice extends MassObject {
super(); super();
setMaterial(material); setMaterial(material);
} }
public RecoveryDevice(double length, double radius, Material material) { public RecoveryDevice(double length, double radius, Material material) {
super(length, radius); super(length, radius);
setMaterial(material); setMaterial(material);
} }
public abstract double getArea(); public abstract double getArea();
public abstract double getComponentCD(double mach); public abstract double getComponentCD(double mach);
public double getCD() { public double getCD() {
@ -130,7 +135,7 @@ public abstract class RecoveryDevice extends MassObject {
cd = getComponentCD(mach); cd = getComponentCD(mach);
return cd; return cd;
} }
public void setCD(double cd) { public void setCD(double cd) {
if (MathUtil.equals(this.cd, cd) && !isCDAutomatic()) if (MathUtil.equals(this.cd, cd) && !isCDAutomatic())
return; return;
@ -138,7 +143,7 @@ public abstract class RecoveryDevice extends MassObject {
this.cdAutomatic = false; this.cdAutomatic = false;
fireComponentChangeEvent(ComponentChangeEvent.AERODYNAMIC_CHANGE); fireComponentChangeEvent(ComponentChangeEvent.AERODYNAMIC_CHANGE);
} }
public boolean isCDAutomatic() { public boolean isCDAutomatic() {
return cdAutomatic; return cdAutomatic;
@ -159,11 +164,11 @@ public abstract class RecoveryDevice extends MassObject {
public final void setMaterial(Material mat) { public final void setMaterial(Material mat) {
if (!(mat instanceof Material.Surface)) { if (!(mat instanceof Material.Surface)) {
throw new IllegalArgumentException("Attempted to set non-surface material "+mat); throw new IllegalArgumentException("Attempted to set non-surface material " + mat);
} }
if (mat.equals(material)) if (mat.equals(material))
return; return;
this.material = (Material.Surface)mat; this.material = (Material.Surface) mat;
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE); fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
} }
@ -173,7 +178,7 @@ public abstract class RecoveryDevice extends MassObject {
public DeployEvent getDeployEvent() { public DeployEvent getDeployEvent() {
return deployEvent; return deployEvent;
} }
public void setDeployEvent(DeployEvent deployEvent) { public void setDeployEvent(DeployEvent deployEvent) {
if (this.deployEvent == deployEvent) if (this.deployEvent == deployEvent)
return; return;
@ -181,11 +186,11 @@ public abstract class RecoveryDevice extends MassObject {
fireComponentChangeEvent(ComponentChangeEvent.EVENT_CHANGE); fireComponentChangeEvent(ComponentChangeEvent.EVENT_CHANGE);
} }
public double getDeployAltitude() { public double getDeployAltitude() {
return deployAltitude; return deployAltitude;
} }
public void setDeployAltitude(double deployAltitude) { public void setDeployAltitude(double deployAltitude) {
if (MathUtil.equals(this.deployAltitude, deployAltitude)) if (MathUtil.equals(this.deployAltitude, deployAltitude))
return; return;
@ -210,10 +215,10 @@ public abstract class RecoveryDevice extends MassObject {
} }
@Override @Override
public double getComponentMass() { public double getComponentMass() {
return getArea() * getMaterial().getDensity(); return getArea() * getMaterial().getDensity();
} }
} }