major optimization updates
[debian/openrocket] / src / net / sf / openrocket / optimization / services / DefaultSimulationModifierService.java
index 977cd1866dc5d8242a86ad4b09231705bdfa8f99..565330aae1b25d7f36ee4a7408b6aca0e23b96d0 100644 (file)
@@ -7,21 +7,41 @@ import java.util.List;
 import java.util.Map;
 
 import net.sf.openrocket.document.OpenRocketDocument;
+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.GenericComponentModifier;
 import net.sf.openrocket.rocketcomponent.BodyTube;
+import net.sf.openrocket.rocketcomponent.EllipticalFinSet;
+import net.sf.openrocket.rocketcomponent.FinSet;
+import net.sf.openrocket.rocketcomponent.FreeformFinSet;
+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.RecoveryDevice.DeployEvent;
 import net.sf.openrocket.rocketcomponent.Rocket;
 import net.sf.openrocket.rocketcomponent.RocketComponent;
+import net.sf.openrocket.rocketcomponent.Streamer;
 import net.sf.openrocket.rocketcomponent.Transition;
+import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
 import net.sf.openrocket.startup.Application;
 import net.sf.openrocket.unit.UnitGroup;
+import net.sf.openrocket.util.BugException;
+import net.sf.openrocket.util.Reflection;
+import net.sf.openrocket.util.Reflection.Method;
 
 public class DefaultSimulationModifierService implements SimulationModifierService {
        
        private static final Translator trans = Application.getTranslator();
        
+       private static final double DEFAULT_RANGE_MULTIPLIER = 2.0;
+       
+
        private static final Map<Class<?>, List<ModifierDefinition>> definitions = new HashMap<Class<?>, List<ModifierDefinition>>();
        static {
                //addModifier("optimization.modifier.", unitGroup, multiplier, componentClass, methodName);
@@ -33,23 +53,56 @@ public class DefaultSimulationModifierService implements SimulationModifierServi
                 */
 
                addModifier("optimization.modifier.nosecone.length", UnitGroup.UNITS_LENGTH, 1.0, NoseCone.class, "Length");
-               addModifier("optimization.modifier.nosecone.diameter", UnitGroup.UNITS_LENGTH, 2.0, NoseCone.class, "AftRadius");
-               addModifier("optimization.modifier.nosecone.thickness", UnitGroup.UNITS_LENGTH, 1.0, NoseCone.class, "Thickness");
+               addModifier("optimization.modifier.nosecone.diameter", UnitGroup.UNITS_LENGTH, 2.0, NoseCone.class, "AftRadius", "isAftRadiusAutomatic");
+               addModifier("optimization.modifier.nosecone.thickness", UnitGroup.UNITS_LENGTH, 1.0, NoseCone.class, "Thickness", "isFilled");
                
                addModifier("optimization.modifier.transition.length", UnitGroup.UNITS_LENGTH, 1.0, Transition.class, "Length");
-               addModifier("optimization.modifier.transition.forediameter", UnitGroup.UNITS_LENGTH, 2.0, Transition.class, "ForeRadius");
-               addModifier("optimization.modifier.transition.aftdiameter", UnitGroup.UNITS_LENGTH, 2.0, Transition.class, "AftRadius");
-               addModifier("optimization.modifier.transition.thickness", UnitGroup.UNITS_LENGTH, 1.0, Transition.class, "Thickness");
+               addModifier("optimization.modifier.transition.forediameter", UnitGroup.UNITS_LENGTH, 2.0, Transition.class, "ForeRadius", "isForeRadiusAutomatic");
+               addModifier("optimization.modifier.transition.aftdiameter", UnitGroup.UNITS_LENGTH, 2.0, Transition.class, "AftRadius", "isAftRadiusAutomatic");
+               addModifier("optimization.modifier.transition.thickness", UnitGroup.UNITS_LENGTH, 1.0, Transition.class, "Thickness", "isFilled");
                
                addModifier("optimization.modifier.bodytube.length", UnitGroup.UNITS_LENGTH, 1.0, BodyTube.class, "Length");
-               addModifier("optimization.modifier.bodytube.outerDiameter", UnitGroup.UNITS_LENGTH, 2.0, BodyTube.class, "OuterRadius");
-               addModifier("optimization.modifier.bodytube.thickness", UnitGroup.UNITS_LENGTH, 1.0, BodyTube.class, "Thickness");
+               addModifier("optimization.modifier.bodytube.outerDiameter", UnitGroup.UNITS_LENGTH, 2.0, BodyTube.class, "OuterRadius", "isOuterRadiusAutomatic");
+               addModifier("optimization.modifier.bodytube.thickness", UnitGroup.UNITS_LENGTH, 1.0, BodyTube.class, "Thickness", "isFilled");
+               
+               addModifier("optimization.modifier.trapezoidfinset.rootChord", UnitGroup.UNITS_LENGTH, 1.0, TrapezoidFinSet.class, "RootChord");
+               addModifier("optimization.modifier.trapezoidfinset.tipChord", UnitGroup.UNITS_LENGTH, 1.0, TrapezoidFinSet.class, "TipChord");
+               addModifier("optimization.modifier.trapezoidfinset.sweep", UnitGroup.UNITS_LENGTH, 1.0, TrapezoidFinSet.class, "Sweep");
+               addModifier("optimization.modifier.trapezoidfinset.height", UnitGroup.UNITS_LENGTH, 1.0, TrapezoidFinSet.class, "Height");
+               addModifier("optimization.modifier.finset.cant", UnitGroup.UNITS_ANGLE, 1.0, TrapezoidFinSet.class, "CantAngle");
+               
+               addModifier("optimization.modifier.ellipticalfinset.length", UnitGroup.UNITS_LENGTH, 1.0, EllipticalFinSet.class, "Length");
+               addModifier("optimization.modifier.ellipticalfinset.height", UnitGroup.UNITS_LENGTH, 1.0, EllipticalFinSet.class, "Height");
+               addModifier("optimization.modifier.finset.cant", UnitGroup.UNITS_ANGLE, 1.0, EllipticalFinSet.class, "CantAngle");
+               
+               addModifier("optimization.modifier.finset.cant", UnitGroup.UNITS_ANGLE, 1.0, FreeformFinSet.class, "CantAngle");
+               
+               addModifier("optimization.modifier.launchlug.length", UnitGroup.UNITS_LENGTH, 1.0, LaunchLug.class, "Length");
+               addModifier("optimization.modifier.launchlug.outerDiameter", UnitGroup.UNITS_LENGTH, 2.0, LaunchLug.class, "OuterRadius");
+               addModifier("optimization.modifier.launchlug.thickness", UnitGroup.UNITS_LENGTH, 1.0, LaunchLug.class, "Thickness");
                
 
+               addModifier("optimization.modifier.masscomponent.mass", UnitGroup.UNITS_MASS, 1.0, MassComponent.class, "ComponentMass");
+               
+               addModifier("optimization.modifier.parachute.diameter", UnitGroup.UNITS_LENGTH, 1.0, Parachute.class, "Diameter");
+               addModifier("optimization.modifier.parachute.coefficient", UnitGroup.UNITS_NONE, 1.0, Parachute.class, "CD");
+               
+               addModifier("optimization.modifier.streamer.length", UnitGroup.UNITS_LENGTH, 1.0, Streamer.class, "StripLength");
+               addModifier("optimization.modifier.streamer.width", UnitGroup.UNITS_LENGTH, 1.0, Streamer.class, "StripWidth");
+               addModifier("optimization.modifier.streamer.aspectRatio", UnitGroup.UNITS_NONE, 1.0, Streamer.class, "AspectRatio");
+               addModifier("optimization.modifier.streamer.coefficient", UnitGroup.UNITS_NONE, 1.0, Streamer.class, "CD", "isCDAutomatic");
+               
+       }
+       
+       private static void addModifier(String modifierNameKey, UnitGroup unitGroup, double multiplier,
+                       Class<? extends RocketComponent> componentClass, String methodName) {
+               addModifier(modifierNameKey, unitGroup, multiplier, componentClass, methodName, null);
        }
        
        private static void addModifier(String modifierNameKey, UnitGroup unitGroup, double multiplier,
-                               Class<? extends RocketComponent> componentClass, String methodName) {
+                               Class<? extends RocketComponent> componentClass, String methodName, String autoMethod) {
+               
+               String modifierDescriptionKey = modifierNameKey + ".desc";
                
                List<ModifierDefinition> list = definitions.get(componentClass);
                if (list == null) {
@@ -57,7 +110,8 @@ public class DefaultSimulationModifierService implements SimulationModifierServi
                        definitions.put(componentClass, list);
                }
                
-               ModifierDefinition definition = new ModifierDefinition(modifierNameKey, unitGroup, multiplier, componentClass, methodName);
+               ModifierDefinition definition = new ModifierDefinition(modifierNameKey, modifierDescriptionKey, unitGroup,
+                               multiplier, componentClass, methodName, autoMethod);
                list.add(definition);
        }
        
@@ -69,29 +123,182 @@ public class DefaultSimulationModifierService implements SimulationModifierServi
                List<SimulationModifier> modifiers = new ArrayList<SimulationModifier>();
                
                Rocket rocket = document.getRocket();
+               
+               // Simulation is used to calculate default min/max values
+               Simulation simulation = new Simulation(rocket);
+               simulation.getConfiguration().setMotorConfigurationID(null);
+               
                for (RocketComponent c : rocket) {
                        
                        // Attribute modifiers
                        List<ModifierDefinition> list = definitions.get(c.getClass());
                        if (list != null) {
                                for (ModifierDefinition def : list) {
+                                       
+                                       // Ignore modifier if value is set to automatic
+                                       if (def.autoMethod != null) {
+                                               Method m = Reflection.findMethod(c.getClass(), def.autoMethod);
+                                               if ((Boolean) m.invoke(c)) {
+                                                       continue;
+                                               }
+                                       }
+                                       
                                        SimulationModifier mod = new GenericComponentModifier(
-                                                       trans.get(def.modifierNameKey), c, def.unitGroup, def.multiplier, def.componentClass,
-                                                       c.getID(), def.methodName);
+                                                       trans.get(def.modifierNameKey), trans.get(def.modifierDescriptionKey), c, def.unitGroup,
+                                                       def.multiplier, def.componentClass, c.getID(), def.methodName);
+                                       setDefaultMinMax(mod, simulation);
                                        modifiers.add(mod);
                                }
                        }
                        
-                       // TODO: HIGH: Conditional modifiers (overrides)
+
+                       // Add override modifiers if mass/CG is overridden
+                       if (c.isMassOverridden()) {
+                               SimulationModifier mod = new GenericComponentModifier(
+                                               trans.get("optimization.modifier.rocketcomponent.overrideMass"),
+                                               trans.get("optimization.modifier.rocketcomponent.overrideMass.desc"),
+                                               c, UnitGroup.UNITS_MASS,
+                                               1.0, c.getClass(), c.getID(), "OverrideMass");
+                               setDefaultMinMax(mod, simulation);
+                               modifiers.add(mod);
+                       }
+                       if (c.isCGOverridden()) {
+                               SimulationModifier mod = new GenericComponentModifier(
+                                               trans.get("optimization.modifier.rocketcomponent.overrideCG"),
+                                               trans.get("optimization.modifier.rocketcomponent.overrideCG.desc"),
+                                               c, UnitGroup.UNITS_LENGTH,
+                                               1.0, c.getClass(), c.getID(), "OverrideCGX");
+                               mod.setMinValue(0);
+                               mod.setMaxValue(c.getLength());
+                               modifiers.add(mod);
+                       }
+                       
+
+                       // Conditional motor mount parameters
+                       if (c instanceof MotorMount) {
+                               MotorMount mount = (MotorMount) c;
+                               if (mount.isMotorMount()) {
+                                       
+                                       SimulationModifier mod = new GenericComponentModifier(
+                                                       trans.get("optimization.modifier.motormount.overhang"),
+                                                       trans.get("optimization.modifier.motormount.overhang.desc"),
+                                                       c, UnitGroup.UNITS_LENGTH,
+                                                       1.0, c.getClass(), c.getID(), "MotorOverhang");
+                                       setDefaultMinMax(mod, simulation);
+                                       modifiers.add(mod);
+                                       
+                                       mod = new GenericComponentModifier(
+                                                       trans.get("optimization.modifier.motormount.delay"),
+                                                       trans.get("optimization.modifier.motormount.delay.desc"),
+                                                       c, UnitGroup.UNITS_SHORT_TIME,
+                                                       1.0, c.getClass(), c.getID(), "IgnitionDelay");
+                                       mod.setMinValue(0);
+                                       mod.setMaxValue(5);
+                                       modifiers.add(mod);
+                                       
+                               }
+                       }
                        
-                       // TODO: Transition / Nose cone shape parameter (conditional)
+
+                       // Inner component positioning
+                       if (c instanceof InternalComponent) {
+                               RocketComponent parent = c.getParent();
+                               SimulationModifier mod = new GenericComponentModifier(
+                                               trans.get("optimization.modifier.internalcomponent.position"),
+                                               trans.get("optimization.modifier.internalcomponent.position.desc"),
+                                               c, UnitGroup.UNITS_LENGTH,
+                                               1.0, c.getClass(), c.getID(), "PositionValue");
+                               mod.setMinValue(0);
+                               mod.setMaxValue(parent.getLength());
+                               modifiers.add(mod);
+                       }
+                       
+
+                       // Custom min/max for fin set position
+                       if (c instanceof FinSet) {
+                               RocketComponent parent = c.getParent();
+                               SimulationModifier mod = new GenericComponentModifier(
+                                               trans.get("optimization.modifier.finset.position"),
+                                               trans.get("optimization.modifier.finset.position.desc"),
+                                               c, UnitGroup.UNITS_LENGTH,
+                                               1.0, c.getClass(), c.getID(), "PositionValue");
+                               mod.setMinValue(0);
+                               mod.setMaxValue(parent.getLength());
+                               modifiers.add(mod);
+                       }
+                       
+
+                       // Custom min/max for launch lug position
+                       if (c instanceof LaunchLug) {
+                               RocketComponent parent = c.getParent();
+                               SimulationModifier mod = new GenericComponentModifier(
+                                               trans.get("optimization.modifier.launchlug.position"),
+                                               trans.get("optimization.modifier.launchlug.position.desc"),
+                                               c, UnitGroup.UNITS_LENGTH,
+                                               1.0, c.getClass(), c.getID(), "PositionValue");
+                               mod.setMinValue(0);
+                               mod.setMaxValue(parent.getLength());
+                               modifiers.add(mod);
+                       }
+                       
+
+                       // 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(), "DeployDelay");
+                               mod.setMinValue(0);
+                               mod.setMaxValue(10);
+                               modifiers.add(mod);
+                               
+                               if (device.getDeployEvent() == 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(), "DeployAltitude");
+                                       setDefaultMinMax(mod, simulation);
+                                       modifiers.add(mod);
+                               }
+                       }
+                       
+
+                       // Conditional shape parameter of Transition
+                       if (c instanceof Transition) {
+                               Transition transition = (Transition) c;
+                               Transition.Shape shape = transition.getType();
+                               if (shape.usesParameter()) {
+                                       SimulationModifier mod = new GenericComponentModifier(
+                                                       trans.get("optimization.modifier." + c.getClass().getSimpleName().toLowerCase() + ".shapeparameter"),
+                                                       trans.get("optimization.modifier." + c.getClass().getSimpleName().toLowerCase() + ".shapeparameter.desc"),
+                                                       c, UnitGroup.UNITS_NONE,
+                                                       1.0, c.getClass(), c.getID(), "ShapeParameter");
+                                       mod.setMinValue(shape.minParameter());
+                                       mod.setMaxValue(shape.maxParameter());
+                                       modifiers.add(mod);
+                               }
+                       }
                }
                
                return modifiers;
        }
        
        
-
+       private void setDefaultMinMax(SimulationModifier mod, Simulation simulation) {
+               try {
+                       double current = mod.getCurrentSIValue(simulation);
+                       mod.setMinValue(current / DEFAULT_RANGE_MULTIPLIER);
+                       mod.setMaxValue(current * DEFAULT_RANGE_MULTIPLIER);
+               } catch (OptimizationException e) {
+                       throw new BugException("Simulation modifier threw exception", e);
+               }
+       }
+       
+       
        /*
         * String modifierName, Object relatedObject, UnitGroup unitGroup,
                        double multiplier, Class<? extends RocketComponent> componentClass, String componentId, String methodName
@@ -99,20 +306,23 @@ public class DefaultSimulationModifierService implements SimulationModifierServi
 
        private static class ModifierDefinition {
                private final String modifierNameKey;
+               private final String modifierDescriptionKey;
                private final UnitGroup unitGroup;
                private final double multiplier;
                private final Class<? extends RocketComponent> componentClass;
                private final String methodName;
+               private final String autoMethod;
                
                
-               public ModifierDefinition(String modifierNameKey, UnitGroup unitGroup, double multiplier,
-                               Class<? extends RocketComponent> componentClass, String methodName) {
-                       super();
+               public ModifierDefinition(String modifierNameKey, String modifierDescriptionKey, UnitGroup unitGroup,
+                               double multiplier, Class<? extends RocketComponent> componentClass, String methodName, String autoMethod) {
                        this.modifierNameKey = modifierNameKey;
+                       this.modifierDescriptionKey = modifierDescriptionKey;
                        this.unitGroup = unitGroup;
                        this.multiplier = multiplier;
                        this.componentClass = componentClass;
                        this.methodName = methodName;
+                       this.autoMethod = autoMethod;
                }
                
        }