Implemented a DeploymentConfiguration object which includes the values
used to determine the deployment of a recovery device. The DeployEvent enum was moved into this class. Added a map of configuration id strings to DeploymentConfiguration objects in the RecoveryDevice. Modified various setter/getters in RecoveryDevice to support a "default" configuration defined in the device's configuration dialog. Modified BasicSimulationEngine to use the DeploymentConfiguration based on the selected configuration. Added to the FlightConfiguration dialogs to support editing these configuration. Missing are serialization of the map in ork files.
This commit is contained in:
parent
e18b081273
commit
3a8d2d5560
@ -185,10 +185,15 @@ edtmotorconfdlg.selectcomp = <html>Select which components function as motor mou
|
||||
edtmotorconfdlg.lbl.Motorconfig = <html><b>Motor configurations:</b>
|
||||
edtmotorconfdlg.lbl.Configname = Configuration name:
|
||||
edtmotorconfdlg.lbl.Motortab = Motors
|
||||
edtmotorconfdlg.lbl.Recoverytab = Recovery
|
||||
edtmotorconfdlg.tbl.None = None
|
||||
edtmotorconfdlg.tbl.Motorheader = Motor
|
||||
edtmotorconfdlg.tbl.Mountheader = Motor Mount
|
||||
edtmotorconfdlg.tbl.Ignitionheader = Ignition
|
||||
edtmotorconfdlg.but.Resetdeployment = Reset to default
|
||||
edtmotorconfdlg.but.Selectdeployment = Select deployment
|
||||
edtmotorconfdlg.tbl.Recoveryheader = Recovery Device
|
||||
edtmotorconfdlg.tbl.Deploymentheader = Deployment
|
||||
|
||||
! Example design dialog
|
||||
exdesigndlg.but.open = Open
|
||||
|
@ -17,10 +17,10 @@ import net.sf.openrocket.document.Simulation;
|
||||
import net.sf.openrocket.document.StorageOptions;
|
||||
import net.sf.openrocket.file.RocketSaver;
|
||||
import net.sf.openrocket.logging.LogHelper;
|
||||
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent;
|
||||
import net.sf.openrocket.rocketcomponent.FinSet;
|
||||
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.RocketComponent;
|
||||
import net.sf.openrocket.rocketcomponent.TubeCoupler;
|
||||
@ -250,7 +250,7 @@ public class OpenRocketSaver extends RocketSaver {
|
||||
// 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) {
|
||||
if (((RecoveryDevice) c).getDefaultDeployEvent() == DeployEvent.LOWER_STAGE_SEPARATION) {
|
||||
return FILE_VERSION_DIVISOR + 5;
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ import net.sf.openrocket.rocketcomponent.Bulkhead;
|
||||
import net.sf.openrocket.rocketcomponent.CenteringRing;
|
||||
import net.sf.openrocket.rocketcomponent.ClusterConfiguration;
|
||||
import net.sf.openrocket.rocketcomponent.Clusterable;
|
||||
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent;
|
||||
import net.sf.openrocket.rocketcomponent.EllipticalFinSet;
|
||||
import net.sf.openrocket.rocketcomponent.EngineBlock;
|
||||
import net.sf.openrocket.rocketcomponent.ExternalComponent;
|
||||
@ -445,13 +446,13 @@ class DocumentConfig {
|
||||
Reflection.findMethod(RecoveryDevice.class, "setCD", double.class),
|
||||
"auto",
|
||||
Reflection.findMethod(RecoveryDevice.class, "setCDAutomatic", boolean.class)));
|
||||
setters.put("RecoveryDevice:deployevent", new EnumSetter<RecoveryDevice.DeployEvent>(
|
||||
Reflection.findMethod(RecoveryDevice.class, "setDeployEvent", RecoveryDevice.DeployEvent.class),
|
||||
RecoveryDevice.DeployEvent.class));
|
||||
setters.put("RecoveryDevice:deployevent", new EnumSetter<DeployEvent>(
|
||||
Reflection.findMethod(RecoveryDevice.class, "setDefaultDeployEvent", DeployEvent.class),
|
||||
DeployEvent.class));
|
||||
setters.put("RecoveryDevice:deployaltitude", new DoubleSetter(
|
||||
Reflection.findMethod(RecoveryDevice.class, "setDeployAltitude", double.class)));
|
||||
Reflection.findMethod(RecoveryDevice.class, "setDefaultDeployAltitude", double.class)));
|
||||
setters.put("RecoveryDevice:deploydelay", new DoubleSetter(
|
||||
Reflection.findMethod(RecoveryDevice.class, "setDeployDelay", double.class)));
|
||||
Reflection.findMethod(RecoveryDevice.class, "setDefaultDeployDelay", double.class)));
|
||||
setters.put("RecoveryDevice:material", new MaterialSetter(
|
||||
Reflection.findMethod(RecoveryDevice.class, "setMaterial", Material.class),
|
||||
Material.Type.SURFACE));
|
||||
@ -876,7 +877,6 @@ class ComponentParameterHandler extends AbstractElementHandler {
|
||||
return new MotorConfigurationHandler((Rocket) component, context);
|
||||
}
|
||||
|
||||
|
||||
return PlainTextHandler.INSTANCE;
|
||||
}
|
||||
|
||||
|
@ -19,10 +19,12 @@ public class RecoveryDeviceSaver extends MassObjectSaver {
|
||||
else
|
||||
elements.add("<cd>" + dev.getCD() + "</cd>");
|
||||
|
||||
elements.add("<deployevent>" + dev.getDeployEvent().name().toLowerCase(Locale.ENGLISH).replace("_", "") + "</deployevent>");
|
||||
elements.add("<deployaltitude>" + dev.getDeployAltitude() + "</deployaltitude>");
|
||||
elements.add("<deploydelay>" + dev.getDeployDelay() + "</deploydelay>");
|
||||
elements.add("<deployevent>" + dev.getDefaultDeployEvent().name().toLowerCase(Locale.ENGLISH).replace("_", "") + "</deployevent>");
|
||||
elements.add("<deployaltitude>" + dev.getDefaultDeployAltitude() + "</deployaltitude>");
|
||||
elements.add("<deploydelay>" + dev.getDefaultDeployDelay() + "</deploydelay>");
|
||||
elements.add(materialParam(dev.getMaterial()));
|
||||
|
||||
// FIXME - add mapping.
|
||||
}
|
||||
|
||||
}
|
||||
|
48
core/src/net/sf/openrocket/gui/adaptors/BasicEnumModel.java
Normal file
48
core/src/net/sf/openrocket/gui/adaptors/BasicEnumModel.java
Normal file
@ -0,0 +1,48 @@
|
||||
package net.sf.openrocket.gui.adaptors;
|
||||
|
||||
import javax.swing.AbstractListModel;
|
||||
import javax.swing.ComboBoxModel;
|
||||
|
||||
|
||||
public class BasicEnumModel<T extends Enum<T>> extends AbstractListModel implements ComboBoxModel {
|
||||
|
||||
private final String nullText;
|
||||
|
||||
private final Enum<T>[] values;
|
||||
private Enum<T> currentValue = null;
|
||||
|
||||
public BasicEnumModel( Class<? extends Enum<T>> clazz ) {
|
||||
this(clazz, null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public BasicEnumModel(Class<? extends Enum<T>> clazz, String nullText) {
|
||||
this.values = clazz.getEnumConstants();
|
||||
this.nullText = nullText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectedItem(Object anItem) {
|
||||
currentValue = (Enum<T>) anItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSelectedItem() {
|
||||
if (currentValue==null)
|
||||
return nullText;
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElementAt(int index) {
|
||||
if (values[index] == null)
|
||||
return nullText;
|
||||
return values[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return values.length;
|
||||
}
|
||||
|
||||
}
|
@ -192,14 +192,14 @@ public class ParachuteConfig extends RecoveryDeviceConfig {
|
||||
//// Deploys at:
|
||||
panel.add(new JLabel(trans.get("ParachuteCfg.lbl.Deploysat")), "");
|
||||
|
||||
combo = new JComboBox(new EnumModel<IgnitionEvent>(component, "DeployEvent"));
|
||||
combo = new JComboBox(new EnumModel<IgnitionEvent>(component, "DefaultDeployEvent"));
|
||||
panel.add(combo, "spanx 3, growx, wrap");
|
||||
|
||||
// ... and delay
|
||||
//// plus
|
||||
panel.add(new JLabel(trans.get("ParachuteCfg.lbl.plusdelay")), "right");
|
||||
|
||||
m = new DoubleModel(component, "DeployDelay", 0);
|
||||
m = new DoubleModel(component, "DefaultDeployDelay", 0);
|
||||
spin = new JSpinner(m.getSpinnerModel());
|
||||
spin.setEditor(new SpinnerEditor(spin,3));
|
||||
panel.add(spin, "spanx, split");
|
||||
@ -212,7 +212,7 @@ public class ParachuteConfig extends RecoveryDeviceConfig {
|
||||
altitudeComponents.add(label);
|
||||
panel.add(label);
|
||||
|
||||
m = new DoubleModel(component, "DeployAltitude", UnitGroup.UNITS_DISTANCE, 0);
|
||||
m = new DoubleModel(component, "DefaultDeployAltitude", UnitGroup.UNITS_DISTANCE, 0);
|
||||
|
||||
spin = new JSpinner(m.getSpinnerModel());
|
||||
spin.setEditor(new SpinnerEditor(spin));
|
||||
|
@ -6,6 +6,7 @@ import java.util.List;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent;
|
||||
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
|
||||
@ -27,8 +28,7 @@ public abstract class RecoveryDeviceConfig extends RocketComponentConfig {
|
||||
if (altitudeComponents == null)
|
||||
return;
|
||||
|
||||
boolean enabled = (((RecoveryDevice) component).getDeployEvent()
|
||||
== RecoveryDevice.DeployEvent.ALTITUDE);
|
||||
boolean enabled = (((RecoveryDevice) component).getDefaultDeployEvent() == DeployEvent.ALTITUDE);
|
||||
|
||||
for (JComponent c : altitudeComponents) {
|
||||
c.setEnabled(enabled);
|
||||
|
@ -193,14 +193,14 @@ public class StreamerConfig extends RecoveryDeviceConfig {
|
||||
//// Deploys at:
|
||||
panel.add(new JLabel(trans.get("StreamerCfg.lbl.Deploysat")), "");
|
||||
|
||||
combo = new JComboBox(new EnumModel<IgnitionEvent>(component, "DeployEvent"));
|
||||
combo = new JComboBox(new EnumModel<IgnitionEvent>(component, "DefaultDeployEvent"));
|
||||
panel.add(combo, "spanx 3, growx, wrap");
|
||||
|
||||
// ... and delay
|
||||
//// plus
|
||||
panel.add(new JLabel(trans.get("StreamerCfg.lbl.plusdelay")), "right");
|
||||
|
||||
m = new DoubleModel(component, "DeployDelay", 0);
|
||||
m = new DoubleModel(component, "DefaultDeployDelay", 0);
|
||||
spin = new JSpinner(m.getSpinnerModel());
|
||||
spin.setEditor(new SpinnerEditor(spin,3));
|
||||
panel.add(spin, "spanx, split");
|
||||
@ -213,7 +213,7 @@ public class StreamerConfig extends RecoveryDeviceConfig {
|
||||
altitudeComponents.add(label);
|
||||
panel.add(label);
|
||||
|
||||
m = new DoubleModel(component, "DeployAltitude", UnitGroup.UNITS_DISTANCE, 0);
|
||||
m = new DoubleModel(component, "DefaultDeployAltitude", UnitGroup.UNITS_DISTANCE, 0);
|
||||
|
||||
spin = new JSpinner(m.getSpinnerModel());
|
||||
spin.setEditor(new SpinnerEditor(spin));
|
||||
|
@ -122,11 +122,14 @@ public class FlightConfigurationDialog extends JDialog {
|
||||
|
||||
//// Tabs for advanced view.
|
||||
JTabbedPane tabs = new JTabbedPane();
|
||||
panel.add( tabs, "spanx, w 700lp, h 500lp, wrap");
|
||||
|
||||
//// Motor tabs
|
||||
JComponent motorTab = makeMotorTab();
|
||||
tabs.add(trans.get("edtmotorconfdlg.lbl.Motortab"), motorTab);
|
||||
panel.add( tabs, "spanx, w 700lp, h 500lp, wrap");
|
||||
|
||||
//// Recovery tab
|
||||
tabs.add(trans.get("edtmotorconfdlg.lbl.Recoverytab"), new RecoveryConfigurationPanel(this,rocket));
|
||||
|
||||
//// Close button
|
||||
JButton close = new JButton(trans.get("dlg.but.close"));
|
||||
@ -386,5 +389,5 @@ public class FlightConfigurationDialog extends JDialog {
|
||||
return panel;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,168 @@
|
||||
package net.sf.openrocket.gui.dialogs.flightconfiguration;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
|
||||
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
|
||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
|
||||
public class RecoveryConfigurationPanel extends JPanel {
|
||||
|
||||
private final FlightConfigurationDialog flightConfigurationDialog;
|
||||
private final Rocket rocket;
|
||||
private final JButton selectDeploymentButton;
|
||||
private final JButton resetDeploymentButton;
|
||||
|
||||
private RecoveryDevice selectedComponent;
|
||||
|
||||
RecoveryConfigurationPanel( FlightConfigurationDialog flightConfigurationDialog, Rocket rocket ) {
|
||||
super( new MigLayout("fill") );
|
||||
this.flightConfigurationDialog = flightConfigurationDialog;
|
||||
this.rocket = rocket;
|
||||
|
||||
//// Recovery selection
|
||||
JTable table = new JTable( new RecoveryTableModel() );
|
||||
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
table.setCellSelectionEnabled(true);
|
||||
table.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
JTable table = (JTable) e.getComponent();
|
||||
int row = table.getSelectedRow();
|
||||
int column = table.getSelectedColumn();
|
||||
|
||||
if ( row >= 0 & column == 1) {
|
||||
selectedComponent = findRecoveryDevice(row);
|
||||
} else {
|
||||
selectedComponent = null;
|
||||
}
|
||||
|
||||
if (e.getClickCount() == 1) {
|
||||
// Single click updates selection
|
||||
updateButtonState();
|
||||
} else if (e.getClickCount() == 2) {
|
||||
// Double-click edits
|
||||
selectDeployment();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
JScrollPane scroll = new JScrollPane(table);
|
||||
this.add(scroll, "span, grow, wrap");
|
||||
|
||||
//// Select deployment
|
||||
selectDeploymentButton = new JButton(FlightConfigurationDialog.trans.get("edtmotorconfdlg.but.Selectdeployment"));
|
||||
selectDeploymentButton.setEnabled(false);
|
||||
selectDeploymentButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
selectDeployment();
|
||||
}
|
||||
});
|
||||
this.add(selectDeploymentButton, "skip, split, sizegroup button");
|
||||
|
||||
//// Reset deployment
|
||||
resetDeploymentButton = new JButton(FlightConfigurationDialog.trans.get("edtmotorconfdlg.but.Resetdeployment"));
|
||||
resetDeploymentButton.setEnabled(false);
|
||||
resetDeploymentButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
//resetDeployment;
|
||||
}
|
||||
});
|
||||
this.add(resetDeploymentButton,"sizegroup button, wrap");
|
||||
|
||||
}
|
||||
|
||||
private void selectDeployment() {
|
||||
JDialog d = new SelectDeploymentConfigDialog( flightConfigurationDialog, rocket, selectedComponent );
|
||||
d.setVisible(true);
|
||||
}
|
||||
|
||||
private void updateButtonState() {
|
||||
boolean buttonsEnabled = selectedComponent != null;
|
||||
selectDeploymentButton.setEnabled(buttonsEnabled);
|
||||
resetDeploymentButton.setEnabled(buttonsEnabled);
|
||||
}
|
||||
|
||||
private RecoveryDevice findRecoveryDevice( int count ) {
|
||||
RecoveryDevice d = null;
|
||||
Iterator<RocketComponent> it = rocket.iterator();
|
||||
while( it.hasNext() && count >= 0 ) {
|
||||
RocketComponent c = it.next();
|
||||
if ( c instanceof RecoveryDevice ) {
|
||||
d = (RecoveryDevice) c;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
private class RecoveryTableModel extends AbstractTableModel {
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
int count = 0;
|
||||
Iterator<RocketComponent> it = rocket.iterator();
|
||||
while( it.hasNext() ) {
|
||||
RocketComponent c = it.next();
|
||||
if ( c instanceof RecoveryDevice ) {
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
RecoveryDevice d = RecoveryConfigurationPanel.this.findRecoveryDevice(rowIndex);
|
||||
switch ( columnIndex ) {
|
||||
case 0:
|
||||
return d.getName();
|
||||
case 1:
|
||||
DeploymentConfiguration deployConfig = d.getDeploymentConfiguration(rocket.getDefaultConfiguration().getMotorConfigurationID());
|
||||
if ( deployConfig == null ) {
|
||||
return "[" + d.getDefaultDeploymentConfiguration().toString() + "]";
|
||||
} else {
|
||||
return deployConfig.toString();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName(int column) {
|
||||
switch ( column ) {
|
||||
case 0:
|
||||
return FlightConfigurationDialog.trans.get("edtmotorconfdlg.tbl.Recoveryheader");
|
||||
case 1:
|
||||
return FlightConfigurationDialog.trans.get("edtmotorconfdlg.tbl.Deploymentheader");
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,144 @@
|
||||
package net.sf.openrocket.gui.dialogs.flightconfiguration;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JSpinner;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import net.sf.openrocket.gui.SpinnerEditor;
|
||||
import net.sf.openrocket.gui.adaptors.BasicEnumModel;
|
||||
import net.sf.openrocket.gui.adaptors.DoubleModel;
|
||||
import net.sf.openrocket.gui.components.BasicSlider;
|
||||
import net.sf.openrocket.gui.components.UnitSelector;
|
||||
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
|
||||
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent;
|
||||
import net.sf.openrocket.rocketcomponent.MotorMount.IgnitionEvent;
|
||||
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
|
||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||
import net.sf.openrocket.unit.UnitGroup;
|
||||
|
||||
public class SelectDeploymentConfigDialog extends JDialog {
|
||||
|
||||
DeploymentConfiguration newConfiguration;
|
||||
|
||||
|
||||
SelectDeploymentConfigDialog( JDialog parent, final Rocket rocket, final RecoveryDevice component ) {
|
||||
super(parent);
|
||||
super.setModal(true);
|
||||
final String configId = rocket.getDefaultConfiguration().getMotorConfigurationID();
|
||||
|
||||
newConfiguration = component.getDeploymentConfiguration(configId);
|
||||
if ( newConfiguration == null ) {
|
||||
newConfiguration = component.getDefaultDeploymentConfiguration().clone();
|
||||
} else {
|
||||
// Clone the existing so cancel works. When the user selects OK, this configuration
|
||||
// is put back in there.
|
||||
newConfiguration = newConfiguration.clone();
|
||||
}
|
||||
|
||||
JPanel panel = new JPanel(new MigLayout("fill"));
|
||||
|
||||
//// Deployment
|
||||
//// Deploys at:
|
||||
panel.add(new JLabel(FlightConfigurationDialog.trans.get("ParachuteCfg.lbl.Deploysat")), "");
|
||||
|
||||
final JComboBox event = new JComboBox(new BasicEnumModel<DeployEvent>(DeployEvent.class));
|
||||
panel.add(event, "spanx 3, growx, wrap");
|
||||
|
||||
// ... and delay
|
||||
//// plus
|
||||
panel.add(new JLabel(FlightConfigurationDialog.trans.get("ParachuteCfg.lbl.plusdelay")), "right");
|
||||
|
||||
final DoubleModel delay = new DoubleModel(newConfiguration.getDeployDelay(), UnitGroup.UNITS_NONE, 0);
|
||||
final JSpinner delaySpinner = new JSpinner( delay.getSpinnerModel() );
|
||||
delaySpinner.setEditor(new SpinnerEditor(delaySpinner,3));
|
||||
panel.add(delaySpinner, "spanx, split");
|
||||
|
||||
//// seconds
|
||||
panel.add(new JLabel(FlightConfigurationDialog.trans.get("ParachuteCfg.lbl.seconds")), "wrap paragraph");
|
||||
|
||||
// Altitude:
|
||||
JLabel label = new JLabel(FlightConfigurationDialog.trans.get("ParachuteCfg.lbl.Altitude"));
|
||||
panel.add(label);
|
||||
|
||||
final DoubleModel alt = new DoubleModel(newConfiguration.getDeployAltitude(), UnitGroup.UNITS_DISTANCE, 0);
|
||||
|
||||
final JSpinner altSpinner = new JSpinner(alt.getSpinnerModel());
|
||||
altSpinner.setEditor(new SpinnerEditor(altSpinner));
|
||||
panel.add(altSpinner, "growx");
|
||||
UnitSelector unit = new UnitSelector(alt);
|
||||
panel.add(unit, "growx");
|
||||
BasicSlider slider = new BasicSlider(alt.getSliderModel(100, 1000));
|
||||
panel.add(slider, "w 100lp, wrap");
|
||||
|
||||
event.addActionListener( new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if ( event.getSelectedItem() == DeployEvent.ALTITUDE ) {
|
||||
delaySpinner.setEnabled(true);
|
||||
altSpinner.setEnabled(true);
|
||||
} else {
|
||||
delaySpinner.setEnabled(false);
|
||||
altSpinner.setEnabled(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Set the value of the combo box at the end to take advantage of the action listener above.
|
||||
event.setSelectedItem( newConfiguration.getDeployEvent() );
|
||||
|
||||
JButton okButton = new JButton("Ok");
|
||||
okButton.addActionListener( new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
//// extract deployment type;
|
||||
DeployEvent deployEvent = (DeployEvent) event.getSelectedItem();
|
||||
newConfiguration.setDeployEvent(deployEvent);
|
||||
|
||||
//// extract deployment time;
|
||||
double deployDelay = delay.getValue();
|
||||
newConfiguration.setDeployDelay(deployDelay);
|
||||
|
||||
//// extract altitude;
|
||||
double deployAltitude = alt.getValue();
|
||||
newConfiguration.setDeployDelay(deployAltitude);
|
||||
|
||||
component.setDeploymentConfiguration(configId, newConfiguration);
|
||||
|
||||
SelectDeploymentConfigDialog.this.setVisible(false);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
panel.add( okButton );
|
||||
|
||||
JButton cancel = new JButton("Cancel");
|
||||
cancel.addActionListener( new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
SelectDeploymentConfigDialog.this.setVisible(false);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
panel.add( cancel );
|
||||
|
||||
this.setContentPane(panel);
|
||||
this.validate();
|
||||
this.pack();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -14,6 +14,7 @@ import net.sf.openrocket.optimization.general.OptimizationException;
|
||||
import net.sf.openrocket.optimization.rocketoptimization.SimulationModifier;
|
||||
import net.sf.openrocket.optimization.rocketoptimization.modifiers.GenericComponentModifier;
|
||||
import net.sf.openrocket.rocketcomponent.BodyTube;
|
||||
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent;
|
||||
import net.sf.openrocket.rocketcomponent.EllipticalFinSet;
|
||||
import net.sf.openrocket.rocketcomponent.FinSet;
|
||||
import net.sf.openrocket.rocketcomponent.FreeformFinSet;
|
||||
@ -24,7 +25,6 @@ import net.sf.openrocket.rocketcomponent.MotorMount;
|
||||
import net.sf.openrocket.rocketcomponent.NoseCone;
|
||||
import net.sf.openrocket.rocketcomponent.Parachute;
|
||||
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
|
||||
import net.sf.openrocket.rocketcomponent.RecoveryDevice.DeployEvent;
|
||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.rocketcomponent.Streamer;
|
||||
@ -256,7 +256,7 @@ public class DefaultSimulationModifierService implements SimulationModifierServi
|
||||
mod.setMaxValue(10);
|
||||
modifiers.add(mod);
|
||||
|
||||
if (device.getDeployEvent() == DeployEvent.ALTITUDE) {
|
||||
if (device.getDefaultDeployEvent() == DeployEvent.ALTITUDE) {
|
||||
mod = new GenericComponentModifier(
|
||||
trans.get("optimization.modifier.recoverydevice.deployAltitude"),
|
||||
trans.get("optimization.modifier.recoverydevice.deployAltitude.desc"),
|
||||
|
@ -0,0 +1,138 @@
|
||||
package net.sf.openrocket.rocketcomponent;
|
||||
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.simulation.FlightEvent;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
import net.sf.openrocket.unit.UnitGroup;
|
||||
import net.sf.openrocket.util.Pair;
|
||||
|
||||
public class DeploymentConfiguration implements Cloneable {
|
||||
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
private DeployEvent deployEvent = DeployEvent.EJECTION;
|
||||
private double deployAltitude = 200;
|
||||
private double deployDelay = 0;
|
||||
|
||||
public boolean isActivationEvent( FlightEvent e, RocketComponent source ) {
|
||||
return deployEvent.isActivationEvent(this, e, source);
|
||||
}
|
||||
|
||||
public DeployEvent getDeployEvent() {
|
||||
return deployEvent;
|
||||
}
|
||||
|
||||
public void setDeployEvent(DeployEvent deployEvent) {
|
||||
this.deployEvent = deployEvent;
|
||||
}
|
||||
|
||||
public double getDeployAltitude() {
|
||||
return deployAltitude;
|
||||
}
|
||||
|
||||
public void setDeployAltitude(double deployAltitude) {
|
||||
this.deployAltitude = deployAltitude;
|
||||
}
|
||||
|
||||
public double getDeployDelay() {
|
||||
return deployDelay;
|
||||
}
|
||||
|
||||
public void setDeployDelay(double deployDelay) {
|
||||
this.deployDelay = deployDelay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String description = deployEvent.toString();
|
||||
if ( deployDelay > 0 ) {
|
||||
description += " + " + deployDelay + "s";
|
||||
}
|
||||
if ( deployEvent == DeployEvent.ALTITUDE && deployAltitude != 0 ) {
|
||||
description += " " + UnitGroup.UNITS_DISTANCE.fromUnit(deployAltitude);
|
||||
}
|
||||
return description;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DeploymentConfiguration clone() {
|
||||
DeploymentConfiguration that = new DeploymentConfiguration();
|
||||
that.deployAltitude = this.deployAltitude;
|
||||
that.deployDelay = this.deployDelay;
|
||||
that.deployEvent = this.deployEvent;
|
||||
return that;
|
||||
}
|
||||
|
||||
|
||||
public static enum DeployEvent {
|
||||
LAUNCH(trans.get("RecoveryDevice.DeployEvent.LAUNCH")) {
|
||||
@Override
|
||||
public boolean isActivationEvent(DeploymentConfiguration config, FlightEvent e, RocketComponent source) {
|
||||
return e.getType() == FlightEvent.Type.LAUNCH;
|
||||
}
|
||||
},
|
||||
EJECTION(trans.get("RecoveryDevice.DeployEvent.EJECTION")) {
|
||||
@Override
|
||||
public boolean isActivationEvent(DeploymentConfiguration config, FlightEvent e, RocketComponent source) {
|
||||
if (e.getType() != FlightEvent.Type.EJECTION_CHARGE)
|
||||
return false;
|
||||
RocketComponent charge = e.getSource();
|
||||
return charge.getStageNumber() == source.getStageNumber();
|
||||
}
|
||||
},
|
||||
APOGEE(trans.get("RecoveryDevice.DeployEvent.APOGEE")) {
|
||||
@Override
|
||||
public boolean isActivationEvent(DeploymentConfiguration config, FlightEvent e, RocketComponent source) {
|
||||
return e.getType() == FlightEvent.Type.APOGEE;
|
||||
}
|
||||
},
|
||||
ALTITUDE(trans.get("RecoveryDevice.DeployEvent.ALTITUDE")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean isActivationEvent(DeploymentConfiguration config, FlightEvent e, RocketComponent source) {
|
||||
if (e.getType() != FlightEvent.Type.ALTITUDE)
|
||||
return false;
|
||||
|
||||
double alt = config.deployAltitude;
|
||||
Pair<Double, Double> altitude = (Pair<Double, Double>) e.getData();
|
||||
|
||||
return (altitude.getU() >= alt) && (altitude.getV() <= alt);
|
||||
}
|
||||
},
|
||||
LOWER_STAGE_SEPARATION(trans.get("RecoveryDevice.DeployEvent.LOWER_STAGE_SEPARATION")) {
|
||||
@Override
|
||||
public boolean isActivationEvent(DeploymentConfiguration config, 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")) {
|
||||
@Override
|
||||
public boolean isActivationEvent(DeploymentConfiguration config, FlightEvent e, RocketComponent source) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
private final String description;
|
||||
|
||||
DeployEvent(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public abstract boolean isActivationEvent(DeploymentConfiguration config, FlightEvent e, RocketComponent source);
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return description;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,12 +1,14 @@
|
||||
package net.sf.openrocket.rocketcomponent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.material.Material;
|
||||
import net.sf.openrocket.preset.ComponentPreset;
|
||||
import net.sf.openrocket.simulation.FlightEvent;
|
||||
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
import net.sf.openrocket.util.MathUtil;
|
||||
import net.sf.openrocket.util.Pair;
|
||||
|
||||
|
||||
/**
|
||||
@ -24,78 +26,9 @@ import net.sf.openrocket.util.Pair;
|
||||
public abstract class RecoveryDevice extends MassObject {
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
public static enum DeployEvent {
|
||||
LAUNCH(trans.get("RecoveryDevice.DeployEvent.LAUNCH")) {
|
||||
@Override
|
||||
public boolean isActivationEvent(FlightEvent e, RocketComponent source) {
|
||||
return e.getType() == FlightEvent.Type.LAUNCH;
|
||||
}
|
||||
},
|
||||
EJECTION(trans.get("RecoveryDevice.DeployEvent.EJECTION")) {
|
||||
@Override
|
||||
public boolean isActivationEvent(FlightEvent e, RocketComponent source) {
|
||||
if (e.getType() != FlightEvent.Type.EJECTION_CHARGE)
|
||||
return false;
|
||||
RocketComponent charge = e.getSource();
|
||||
return charge.getStageNumber() == source.getStageNumber();
|
||||
}
|
||||
},
|
||||
APOGEE(trans.get("RecoveryDevice.DeployEvent.APOGEE")) {
|
||||
@Override
|
||||
public boolean isActivationEvent(FlightEvent e, RocketComponent source) {
|
||||
return e.getType() == FlightEvent.Type.APOGEE;
|
||||
}
|
||||
},
|
||||
ALTITUDE(trans.get("RecoveryDevice.DeployEvent.ALTITUDE")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean isActivationEvent(FlightEvent e, RocketComponent source) {
|
||||
if (e.getType() != FlightEvent.Type.ALTITUDE)
|
||||
return false;
|
||||
|
||||
double alt = ((RecoveryDevice) source).getDeployAltitude();
|
||||
Pair<Double, Double> altitude = (Pair<Double, Double>) e.getData();
|
||||
|
||||
return (altitude.getU() >= alt) && (altitude.getV() <= alt);
|
||||
}
|
||||
},
|
||||
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")) {
|
||||
@Override
|
||||
public boolean isActivationEvent(FlightEvent e, RocketComponent source) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
private final String description;
|
||||
|
||||
DeployEvent(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public abstract boolean isActivationEvent(FlightEvent e, RocketComponent source);
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return description;
|
||||
}
|
||||
|
||||
}
|
||||
private Map<String,DeploymentConfiguration> deploymentConfigurations = new HashMap<String,DeploymentConfiguration>();
|
||||
|
||||
|
||||
private DeployEvent deployEvent = DeployEvent.EJECTION;
|
||||
private double deployAltitude = 200;
|
||||
private double deployDelay = 0;
|
||||
private DeploymentConfiguration defaultDeploymentConfig = new DeploymentConfiguration();
|
||||
|
||||
private double cd = Parachute.DEFAULT_CD;
|
||||
private boolean cdAutomatic = true;
|
||||
@ -175,44 +108,61 @@ public abstract class RecoveryDevice extends MassObject {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public DeployEvent getDeployEvent() {
|
||||
return deployEvent;
|
||||
/**
|
||||
* Return the deployment configuration for this configurationId or null if using default.
|
||||
*
|
||||
* @param configID
|
||||
* @return
|
||||
*/
|
||||
public DeploymentConfiguration getDeploymentConfiguration( String configID ) {
|
||||
DeploymentConfiguration config = deploymentConfigurations.get(configID);
|
||||
return config;
|
||||
}
|
||||
|
||||
public void setDeployEvent(DeployEvent deployEvent) {
|
||||
if (this.deployEvent == deployEvent)
|
||||
public DeploymentConfiguration getDefaultDeploymentConfiguration() {
|
||||
return defaultDeploymentConfig;
|
||||
}
|
||||
|
||||
public void setDeploymentConfiguration( String configID, DeploymentConfiguration config ) {
|
||||
deploymentConfigurations.put(configID, config);
|
||||
}
|
||||
|
||||
public DeployEvent getDefaultDeployEvent() {
|
||||
return defaultDeploymentConfig.getDeployEvent();
|
||||
}
|
||||
|
||||
public void setDefaultDeployEvent(DeployEvent deployEvent) {
|
||||
if (this.defaultDeploymentConfig.getDeployEvent() == deployEvent)
|
||||
return;
|
||||
this.deployEvent = deployEvent;
|
||||
this.defaultDeploymentConfig.setDeployEvent(deployEvent);
|
||||
fireComponentChangeEvent(ComponentChangeEvent.EVENT_CHANGE);
|
||||
}
|
||||
|
||||
|
||||
public double getDeployAltitude() {
|
||||
return deployAltitude;
|
||||
public double getDefaultDeployAltitude() {
|
||||
return defaultDeploymentConfig.getDeployAltitude();
|
||||
}
|
||||
|
||||
public void setDeployAltitude(double deployAltitude) {
|
||||
if (MathUtil.equals(this.deployAltitude, deployAltitude))
|
||||
public void setDefaultDeployAltitude(double deployAltitude) {
|
||||
if (MathUtil.equals(getDefaultDeployAltitude(), deployAltitude))
|
||||
return;
|
||||
this.deployAltitude = deployAltitude;
|
||||
if (getDeployEvent() == DeployEvent.ALTITUDE)
|
||||
defaultDeploymentConfig.setDeployAltitude(deployAltitude);
|
||||
if (getDefaultDeployEvent() == DeployEvent.ALTITUDE)
|
||||
fireComponentChangeEvent(ComponentChangeEvent.EVENT_CHANGE);
|
||||
else
|
||||
fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
|
||||
}
|
||||
|
||||
|
||||
public double getDeployDelay() {
|
||||
return deployDelay;
|
||||
public double getDefaultDeployDelay() {
|
||||
return defaultDeploymentConfig.getDeployDelay();
|
||||
}
|
||||
|
||||
public void setDeployDelay(double delay) {
|
||||
public void setDefaultDeployDelay(double delay) {
|
||||
delay = MathUtil.max(delay, 0);
|
||||
if (MathUtil.equals(this.deployDelay, delay))
|
||||
if (MathUtil.equals(getDefaultDeployDelay(), delay))
|
||||
return;
|
||||
this.deployDelay = delay;
|
||||
defaultDeploymentConfig.setDeployDelay(delay);
|
||||
fireComponentChangeEvent(ComponentChangeEvent.EVENT_CHANGE);
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ import net.sf.openrocket.motor.MotorId;
|
||||
import net.sf.openrocket.motor.MotorInstance;
|
||||
import net.sf.openrocket.motor.MotorInstanceConfiguration;
|
||||
import net.sf.openrocket.rocketcomponent.Configuration;
|
||||
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
|
||||
import net.sf.openrocket.rocketcomponent.LaunchLug;
|
||||
import net.sf.openrocket.rocketcomponent.MotorMount;
|
||||
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
|
||||
@ -42,6 +43,8 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
||||
private SimulationStepper currentStepper;
|
||||
|
||||
private SimulationStatus status;
|
||||
|
||||
private String flightConfigurationId;
|
||||
|
||||
|
||||
@Override
|
||||
@ -53,6 +56,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
||||
|
||||
// Set up rocket configuration
|
||||
Configuration configuration = setupConfiguration(simulationConditions);
|
||||
flightConfigurationId = configuration.getMotorConfigurationID();
|
||||
MotorInstanceConfiguration motorConfiguration = setupMotorConfiguration(configuration);
|
||||
if (motorConfiguration.getMotorIDs().isEmpty()) {
|
||||
throw new MotorIgnitionException("No motors defined in the simulation.");
|
||||
@ -371,10 +375,14 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
||||
RocketComponent c = rci.next();
|
||||
if (!(c instanceof RecoveryDevice))
|
||||
continue;
|
||||
if (((RecoveryDevice) c).getDeployEvent().isActivationEvent(event, c)) {
|
||||
DeploymentConfiguration deployConfig = ((RecoveryDevice) c).getDeploymentConfiguration(flightConfigurationId);
|
||||
if ( deployConfig == null ) {
|
||||
deployConfig = ((RecoveryDevice) c).getDefaultDeploymentConfiguration();
|
||||
}
|
||||
if (deployConfig.isActivationEvent(event, c)) {
|
||||
// Delay event by at least 1ms to allow stage separation to occur first
|
||||
addEvent(new FlightEvent(FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT,
|
||||
event.getTime() + Math.max(0.001, ((RecoveryDevice) c).getDeployDelay()), c));
|
||||
event.getTime() + Math.max(0.001, deployConfig.getDeployDelay()), c));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user