diff --git a/core/src/net/sf/openrocket/gui/dialogs/optimization/GeneralOptimizationDialog.java b/core/src/net/sf/openrocket/gui/dialogs/optimization/GeneralOptimizationDialog.java index 9f4e75470..767c50f38 100644 --- a/core/src/net/sf/openrocket/gui/dialogs/optimization/GeneralOptimizationDialog.java +++ b/core/src/net/sf/openrocket/gui/dialogs/optimization/GeneralOptimizationDialog.java @@ -98,7 +98,7 @@ import net.sf.openrocket.util.TextUtil; import com.itextpdf.text.Font; /** - * General rocket optimization dialog. + * General rocket optimization dialog. * * @author Sampo Niskanen */ diff --git a/core/src/net/sf/openrocket/optimization/rocketoptimization/SimulationModifier.java b/core/src/net/sf/openrocket/optimization/rocketoptimization/SimulationModifier.java index 1989ea074..b85751ae3 100644 --- a/core/src/net/sf/openrocket/optimization/rocketoptimization/SimulationModifier.java +++ b/core/src/net/sf/openrocket/optimization/rocketoptimization/SimulationModifier.java @@ -89,7 +89,7 @@ public interface SimulationModifier extends ChangeSource { public double getCurrentScaledValue(Simulation simulation) throws OptimizationException; - + /** * Modify the specified simulation to the corresponding parameter value. * @@ -99,6 +99,13 @@ public interface SimulationModifier extends ChangeSource { */ public void modify(Simulation simulation, double scaledValue) throws OptimizationException; + /** + * Called once at the start of the optimization. + * This method can be used to ensure the simulation or rocket are properly configured. + * + * @param simulation + */ + public void initialize(Simulation simulation) throws OptimizationException; /** * Compare whether this SimulationModifier is equivalent to another simulation modifier. diff --git a/core/src/net/sf/openrocket/optimization/rocketoptimization/modifiers/AbstractSimulationModifier.java b/core/src/net/sf/openrocket/optimization/rocketoptimization/modifiers/AbstractSimulationModifier.java index 20bfcd03e..32f237365 100644 --- a/core/src/net/sf/openrocket/optimization/rocketoptimization/modifiers/AbstractSimulationModifier.java +++ b/core/src/net/sf/openrocket/optimization/rocketoptimization/modifiers/AbstractSimulationModifier.java @@ -76,6 +76,10 @@ public abstract class AbstractSimulationModifier implements SimulationModifier { return toScaledValue(value); } + @Override + public void initialize(Simulation simulation) throws OptimizationException { + // Default is no-op. + } /** diff --git a/core/src/net/sf/openrocket/optimization/rocketoptimization/modifiers/FlightConfigurationModifier.java b/core/src/net/sf/openrocket/optimization/rocketoptimization/modifiers/FlightConfigurationModifier.java new file mode 100644 index 000000000..d25ed55f0 --- /dev/null +++ b/core/src/net/sf/openrocket/optimization/rocketoptimization/modifiers/FlightConfigurationModifier.java @@ -0,0 +1,77 @@ +package net.sf.openrocket.optimization.rocketoptimization.modifiers; + +import java.util.Locale; + +import net.sf.openrocket.document.Simulation; +import net.sf.openrocket.optimization.general.OptimizationException; +import net.sf.openrocket.rocketcomponent.FlightConfigurableParameter; +import net.sf.openrocket.rocketcomponent.FlightConfiguration; +import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.unit.UnitGroup; +import net.sf.openrocket.util.BugException; +import net.sf.openrocket.util.Reflection.Method; + +public class FlightConfigurationModifier> extends GenericModifier { + + private final Class componentClass; + private final String componentId; + private final Method configGetter; + + + /** + * Sole constructor. + * + * @param modifierName the name of this modifier (returned by {@link #getName()}) + * @param modifierDescription the description of this modifier (returned by {@link #getDescription()}) + * @param relatedObject the related object (returned by {@link #getRelatedObject()}) + * @param unitGroup the unit group (returned by {@link #getUnitGroup()}) + * @param multiplier the multiplier by which the value returned by the getter is multiplied + * to obtain the desired value + * @param componentClass the RocketComponent class type that is being modified + * @param componentId the ID of the component to modify + * @param configName the name of the configuration object (base name of the getter) + * @param flightConfigClass the class of the FlightConfigurableParameter + * @param methodName the base name of the getter/setter methods (without "get"/"set") + */ + public FlightConfigurationModifier( + String modifierName, + String modifierDescription, + Object relatedObject, + UnitGroup unitGroup, + double multiplier, + Class componentClass, + String componentId, + String configName, + Class flightConfigClass, + String methodName) { + super(modifierName, modifierDescription, relatedObject, unitGroup, multiplier, flightConfigClass, methodName); + + this.componentClass = componentClass; + this.componentId = componentId; + + try { + configName = configName.substring(0, 1).toUpperCase(Locale.ENGLISH) + configName.substring(1); + configGetter = new Method(componentClass.getMethod("get" + configName)); + } catch (SecurityException e) { + throw new BugException("Trying to find method get/set" + configName + " in class " + componentClass, e); + } catch (NoSuchMethodException e) { + throw new BugException("Trying to find method get/set" + configName + " in class " + componentClass, e); + } + + } + + + @Override + protected E getModifiedObject(Simulation simulation) throws OptimizationException { + + RocketComponent c = simulation.getRocket().findComponent(componentId); + if (c == null) { + throw new OptimizationException("Could not find component of type " + componentClass.getSimpleName() + + " with correct ID"); + } + + FlightConfiguration configs = (FlightConfiguration) configGetter.invoke(c); + return configs.get(simulation.getConfiguration().getFlightConfigurationID()); + } + +} diff --git a/core/src/net/sf/openrocket/optimization/services/DefaultSimulationModifierService.java b/core/src/net/sf/openrocket/optimization/services/DefaultSimulationModifierService.java index a04a3c1b1..d2c8f5524 100644 --- a/core/src/net/sf/openrocket/optimization/services/DefaultSimulationModifierService.java +++ b/core/src/net/sf/openrocket/optimization/services/DefaultSimulationModifierService.java @@ -12,17 +12,22 @@ import net.sf.openrocket.document.Simulation; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.optimization.general.OptimizationException; import net.sf.openrocket.optimization.rocketoptimization.SimulationModifier; +import net.sf.openrocket.optimization.rocketoptimization.modifiers.FlightConfigurationModifier; import net.sf.openrocket.optimization.rocketoptimization.modifiers.GenericComponentModifier; import net.sf.openrocket.rocketcomponent.BodyTube; +import net.sf.openrocket.rocketcomponent.DeploymentConfiguration; +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; +import net.sf.openrocket.rocketcomponent.IgnitionConfiguration; import net.sf.openrocket.rocketcomponent.InternalComponent; import net.sf.openrocket.rocketcomponent.LaunchLug; import net.sf.openrocket.rocketcomponent.MassComponent; 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.Rocket; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.Streamer; @@ -186,15 +191,20 @@ public class DefaultSimulationModifierService implements SimulationModifierServi setDefaultMinMax(mod, simulation); modifiers.add(mod); - mod = new GenericComponentModifier( + mod = new FlightConfigurationModifier( trans.get("optimization.modifier.motormount.delay"), trans.get("optimization.modifier.motormount.delay.desc"), c, UnitGroup.UNITS_SHORT_TIME, - 1.0, c.getClass(), c.getID(), "DefaultIgnitionDelay"); + 1.0, + c.getClass(), + c.getID(), + "IgnitionConfiguration", + IgnitionConfiguration.class, + "IgnitionDelay"); + mod.setMinValue(0); mod.setMaxValue(5); modifiers.add(mod); - } } @@ -241,31 +251,48 @@ public class DefaultSimulationModifierService implements SimulationModifierServi } - // FIXME: Reimplement for flight-configuration controlled modifiers - // Recovery device deployment altitude and delay - // if (c instanceof RecoveryDevice) { - // RecoveryDevice device = (RecoveryDevice) c; - // - // SimulationModifier mod = new GenericComponentModifier( - // trans.get("optimization.modifier.recoverydevice.deployDelay"), - // trans.get("optimization.modifier.recoverydevice.deployDelay.desc"), - // c, UnitGroup.UNITS_SHORT_TIME, - // 1.0, c.getClass(), c.getID(), "DefaultDeployDelay"); - // mod.setMinValue(0); - // mod.setMaxValue(10); - // modifiers.add(mod); - // - // if (device.getDefaultDeployEvent() == DeployEvent.ALTITUDE) { - // mod = new GenericComponentModifier( - // trans.get("optimization.modifier.recoverydevice.deployAltitude"), - // trans.get("optimization.modifier.recoverydevice.deployAltitude.desc"), - // c, UnitGroup.UNITS_DISTANCE, - // 1.0, c.getClass(), c.getID(), "DefaultDeployAltitude"); - // setDefaultMinMax(mod, simulation); - // modifiers.add(mod); - // } - // } + if (c instanceof RecoveryDevice) { + RecoveryDevice device = (RecoveryDevice) c; + + SimulationModifier mod = new FlightConfigurationModifier( + trans.get("optimization.modifier.recoverydevice.deployDelay"), + trans.get("optimization.modifier.recoverydevice.deployDelay.desc"), + c, + UnitGroup.UNITS_SHORT_TIME, + 1.0, + c.getClass(), + c.getID(), + "DeploymentConfiguration", + DeploymentConfiguration.class, + "DeployDelay"); + + mod.setMinValue(0); + mod.setMaxValue(10); + modifiers.add(mod); + + mod = new FlightConfigurationModifier( + trans.get("optimization.modifier.recoverydevice.deployAltitude"), + trans.get("optimization.modifier.recoverydevice.deployAltitude.desc"), + c, + UnitGroup.UNITS_DISTANCE, + 1.0, + c.getClass(), + c.getID(), + "DeploymentConfiguration", + DeploymentConfiguration.class, + "DeployAltitude") { + + @Override + public void initialize(Simulation simulation) throws OptimizationException { + DeploymentConfiguration config = getModifiedObject(simulation); + config.setDeployEvent(DeployEvent.APOGEE); + } + + }; + setDefaultMinMax(mod, simulation); + modifiers.add(mod); + } // Conditional shape parameter of Transition @@ -288,7 +315,6 @@ public class DefaultSimulationModifierService implements SimulationModifierServi return modifiers; } - private void setDefaultMinMax(SimulationModifier mod, Simulation simulation) { try { double current = mod.getCurrentSIValue(simulation);