optimization updates
authorplaa <plaa@180e2498-e6e9-4542-8430-84ac67f01cd8>
Wed, 10 Aug 2011 05:08:47 +0000 (05:08 +0000)
committerplaa <plaa@180e2498-e6e9-4542-8430-84ac67f01cd8>
Wed, 10 Aug 2011 05:08:47 +0000 (05:08 +0000)
git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@149 180e2498-e6e9-4542-8430-84ac67f01cd8

13 files changed:
l10n/messages.properties
src/net/sf/openrocket/gui/dialogs/optimization/OptimizationPlotDialog.java
src/net/sf/openrocket/optimization/general/multidim/MultidirectionalSearchOptimizer.java
src/net/sf/openrocket/optimization/rocketoptimization/parameters/DeploymentVelocityParameter.java [new file with mode: 0644]
src/net/sf/openrocket/optimization/rocketoptimization/parameters/GroundHitVelocityParameter.java
src/net/sf/openrocket/optimization/rocketoptimization/parameters/LandingDistanceParameter.java
src/net/sf/openrocket/optimization/rocketoptimization/parameters/MaximumAccelerationParameter.java
src/net/sf/openrocket/optimization/rocketoptimization/parameters/MaximumAltitudeParameter.java
src/net/sf/openrocket/optimization/rocketoptimization/parameters/MaximumVelocityParameter.java
src/net/sf/openrocket/optimization/rocketoptimization/parameters/SimulationBasedParameter.java [new file with mode: 0644]
src/net/sf/openrocket/optimization/rocketoptimization/parameters/TotalFlightTimeParameter.java [new file with mode: 0644]
src/net/sf/openrocket/optimization/services/DefaultOptimizableParameterService.java
src/net/sf/openrocket/simulation/listeners/system/RecoveryDeviceDeploymentEndListener.java [new file with mode: 0644]

index 8d71278d96412cbce1a9c4b0c2f23da14fb31a01..692248a1eaf1b4de8f14124c08307cb14253f753 100644 (file)
@@ -1479,3 +1479,6 @@ MaximumAccelerationParameter.name = Maximum acceleration
 StabilityParameter.name = Stability
 GroundHitVelocityParameter.name = Ground hit speed
 LandingDistanceParameter.name = Landing distance
+TotalFlightTimeParameter.name = Total flight time
+DeploymentVelocityParameter.name = Velocity at parachute deployment
+
index da91712a5e42e853c06654f297885b11698f8769..c3f9c0cbf9855836a82cbc230f0d7f56a691ce05 100644 (file)
@@ -57,7 +57,8 @@ public class OptimizationPlotDialog extends JDialog {
        private static final LogHelper log = Application.getLogger();
        private static final Translator trans = Application.getTranslator();
        
-
+       // FIXME:  Set range to optimization range
+       
        private static final LinearInterpolator RED = new LinearInterpolator(
                        new double[] { 0.0, 1.0 }, new double[] { 0.0, 1.0 }
                        );
@@ -165,7 +166,6 @@ public class OptimizationPlotDialog extends JDialog {
                tooltipGenerator.addToolTipSeries(tooltips);
                lineRenderer.setBaseToolTipGenerator(tooltipGenerator);
                
-
                XYPlot plot = chart.getXYPlot();
                
                plot.setDataset(0, new XYSeriesCollection(series));
@@ -255,6 +255,14 @@ public class OptimizationPlotDialog extends JDialog {
                                true, // Tooltips
                                false); // Urls
                
+
+               chart.getXYPlot().getDomainAxis().setRange(xUnit.toUnit(modX.getMinValue()),
+                               xUnit.toUnit(modX.getMaxValue()));
+               
+               chart.getXYPlot().getRangeAxis().setRange(yUnit.toUnit(modY.getMinValue()),
+                               yUnit.toUnit(modY.getMaxValue()));
+               
+
                PaintScale paintScale = new GradientScale(min, max);
                
                XYShapeRenderer shapeRenderer = new XYShapeRenderer();
index 76d2f301ac8aabbabb69f31b0d2d63290f842dcf..d50618a32e2779c226323e4f465aaa81c422e012 100644 (file)
@@ -111,6 +111,9 @@ public class MultidirectionalSearchOptimizer implements FunctionOptimizer, Stati
                                        functionExecutor.compute(expansion);
                                
                                // Check reflection acceptance
+                               System.err.println("stepsize = " + step);
+                               System.err.println("Simplex    = " + simplex);
+                               System.err.println("Reflection = " + reflection);
                                log.debug("Computing reflection");
                                functionExecutor.waitFor(reflection);
                                
@@ -188,11 +191,13 @@ public class MultidirectionalSearchOptimizer implements FunctionOptimizer, Stati
                                                } else {
                                                        log.debug("Coordinate search unsuccessful, halving step.");
                                                        step /= 2;
+                                                       simplexComputed = false;
                                                        reductionFallback++;
                                                }
                                        } else {
                                                log.debug("Coordinate search not used, halving step.");
                                                step /= 2;
+                                               simplexComputed = false;
                                                reductionFallback++;
                                        }
                                        
@@ -223,8 +228,11 @@ public class MultidirectionalSearchOptimizer implements FunctionOptimizer, Stati
        private void createReflection(List<Point> base, List<Point> reflection) {
                Point current = base.get(0);
                reflection.clear();
+               
+               /*  new = - (old - current) + current = 2*current - old  */
                for (int i = 1; i < base.size(); i++) {
-                       Point p = current.mul(2).sub(base.get(i));
+                       Point p = base.get(i);
+                       p = current.mul(2).sub(p);
                        reflection.add(p);
                }
        }
@@ -242,6 +250,9 @@ public class MultidirectionalSearchOptimizer implements FunctionOptimizer, Stati
                Point current = base.get(0);
                for (int i = 1; i < base.size(); i++) {
                        Point p = base.get(i);
+                       
+                       /* new = (old - current)*0.5 + current = old*0.5 + current*0.5 = (old + current)*0.5 */
+
                        p = p.add(current).mul(0.5);
                        base.set(i, p);
                }
diff --git a/src/net/sf/openrocket/optimization/rocketoptimization/parameters/DeploymentVelocityParameter.java b/src/net/sf/openrocket/optimization/rocketoptimization/parameters/DeploymentVelocityParameter.java
new file mode 100644 (file)
index 0000000..0add664
--- /dev/null
@@ -0,0 +1,40 @@
+package net.sf.openrocket.optimization.rocketoptimization.parameters;
+
+import net.sf.openrocket.l10n.Translator;
+import net.sf.openrocket.simulation.FlightData;
+import net.sf.openrocket.simulation.FlightDataType;
+import net.sf.openrocket.simulation.listeners.SimulationListener;
+import net.sf.openrocket.simulation.listeners.system.RecoveryDeviceDeploymentEndListener;
+import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.unit.UnitGroup;
+
+/**
+ * An optimization parameter that computes the total flight time.
+ * 
+ * @author Sampo Niskanen <sampo.niskanen@iki.fi>
+ */
+public class DeploymentVelocityParameter extends SimulationBasedParameter {
+       
+       private static final Translator trans = Application.getTranslator();
+       
+       @Override
+       public String getName() {
+               return trans.get("name");
+       }
+       
+       @Override
+       protected SimulationListener[] getSimulationListeners() {
+               return new SimulationListener[] { new RecoveryDeviceDeploymentEndListener() };
+       }
+       
+       @Override
+       protected double getResultValue(FlightData simulatedData) {
+               return simulatedData.getBranch(0).getLast(FlightDataType.TYPE_VELOCITY_TOTAL);
+       }
+       
+       @Override
+       public UnitGroup getUnitGroup() {
+               return UnitGroup.UNITS_VELOCITY;
+       }
+       
+}
index 124fe65bf6c5d18d459c961f4ce0dd8e202e3f12..4effe72b4e35b38430c1d88b44d2150677bc9557 100644 (file)
@@ -1,16 +1,8 @@
 package net.sf.openrocket.optimization.rocketoptimization.parameters;
 
-import net.sf.openrocket.document.Simulation;
 import net.sf.openrocket.l10n.Translator;
-import net.sf.openrocket.logging.LogHelper;
-import net.sf.openrocket.optimization.general.OptimizationException;
-import net.sf.openrocket.optimization.rocketoptimization.OptimizableParameter;
+import net.sf.openrocket.simulation.FlightData;
 import net.sf.openrocket.simulation.FlightDataType;
-import net.sf.openrocket.simulation.exception.MotorIgnitionException;
-import net.sf.openrocket.simulation.exception.SimulationCancelledException;
-import net.sf.openrocket.simulation.exception.SimulationException;
-import net.sf.openrocket.simulation.exception.SimulationLaunchException;
-import net.sf.openrocket.simulation.listeners.system.InterruptListener;
 import net.sf.openrocket.startup.Application;
 import net.sf.openrocket.unit.UnitGroup;
 
@@ -19,9 +11,8 @@ import net.sf.openrocket.unit.UnitGroup;
  * 
  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
  */
-public class GroundHitVelocityParameter implements OptimizableParameter {
+public class GroundHitVelocityParameter extends SimulationBasedParameter {
        
-       private static final LogHelper log = Application.getLogger();
        private static final Translator trans = Application.getTranslator();
        
        @Override
@@ -30,25 +21,8 @@ public class GroundHitVelocityParameter implements OptimizableParameter {
        }
        
        @Override
-       public double computeValue(Simulation simulation) throws OptimizationException, InterruptedException {
-               try {
-                       log.debug("Running simulation to evaluate ground hit speed");
-                       simulation.simulate(new InterruptListener());
-                       double value = simulation.getSimulatedData().getBranch(0).getLast(FlightDataType.TYPE_VELOCITY_TOTAL);
-                       log.debug("Ground hit speed was " + value);
-                       return value;
-               } catch (MotorIgnitionException e) {
-                       // A problem with motor ignition will cause optimization to fail
-                       throw new OptimizationException(e);
-               } catch (SimulationLaunchException e) {
-                       // Other launch exceptions result in zero altitude
-                       return Double.NaN;
-               } catch (SimulationCancelledException e) {
-                       throw (InterruptedException) new InterruptedException("Optimization was interrupted").initCause(e);
-               } catch (SimulationException e) {
-                       // Other exceptions fail
-                       throw new OptimizationException(e);
-               }
+       protected double getResultValue(FlightData simulatedData) {
+               return simulatedData.getBranch(0).getLast(FlightDataType.TYPE_VELOCITY_TOTAL);
        }
        
        @Override
@@ -56,4 +30,5 @@ public class GroundHitVelocityParameter implements OptimizableParameter {
                return UnitGroup.UNITS_VELOCITY;
        }
        
+
 }
index c5dc0061be63812b71d07ab61e1cba96924ad7cd..cb387d714e7d285dd029375a9f3eb8c44f388820 100644 (file)
@@ -1,16 +1,8 @@
 package net.sf.openrocket.optimization.rocketoptimization.parameters;
 
-import net.sf.openrocket.document.Simulation;
 import net.sf.openrocket.l10n.Translator;
-import net.sf.openrocket.logging.LogHelper;
-import net.sf.openrocket.optimization.general.OptimizationException;
-import net.sf.openrocket.optimization.rocketoptimization.OptimizableParameter;
+import net.sf.openrocket.simulation.FlightData;
 import net.sf.openrocket.simulation.FlightDataType;
-import net.sf.openrocket.simulation.exception.MotorIgnitionException;
-import net.sf.openrocket.simulation.exception.SimulationCancelledException;
-import net.sf.openrocket.simulation.exception.SimulationException;
-import net.sf.openrocket.simulation.exception.SimulationLaunchException;
-import net.sf.openrocket.simulation.listeners.system.InterruptListener;
 import net.sf.openrocket.startup.Application;
 import net.sf.openrocket.unit.UnitGroup;
 
@@ -19,9 +11,8 @@ import net.sf.openrocket.unit.UnitGroup;
  * 
  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
  */
-public class LandingDistanceParameter implements OptimizableParameter {
+public class LandingDistanceParameter extends SimulationBasedParameter {
        
-       private static final LogHelper log = Application.getLogger();
        private static final Translator trans = Application.getTranslator();
        
        @Override
@@ -30,25 +21,8 @@ public class LandingDistanceParameter implements OptimizableParameter {
        }
        
        @Override
-       public double computeValue(Simulation simulation) throws OptimizationException, InterruptedException {
-               try {
-                       log.debug("Running simulation to evaluate rocket landing distance");
-                       simulation.simulate(new InterruptListener());
-                       double value = simulation.getSimulatedData().getBranch(0).getLast(FlightDataType.TYPE_POSITION_XY);
-                       log.debug("Landing distance was " + value);
-                       return value;
-               } catch (MotorIgnitionException e) {
-                       // A problem with motor ignition will cause optimization to fail
-                       throw new OptimizationException(e);
-               } catch (SimulationLaunchException e) {
-                       // Other launch exceptions result in zero altitude
-                       return Double.NaN;
-               } catch (SimulationCancelledException e) {
-                       throw (InterruptedException) new InterruptedException("Optimization was interrupted").initCause(e);
-               } catch (SimulationException e) {
-                       // Other exceptions fail
-                       throw new OptimizationException(e);
-               }
+       protected double getResultValue(FlightData simulatedData) {
+               return simulatedData.getBranch(0).getLast(FlightDataType.TYPE_POSITION_XY);
        }
        
        @Override
index 7b007aa2642578ec864c8429961c55de548e2eed..eb6e7a61aed1f96d10011bb7f995dedb4b4a6674 100644 (file)
@@ -1,17 +1,10 @@
 package net.sf.openrocket.optimization.rocketoptimization.parameters;
 
-import net.sf.openrocket.document.Simulation;
 import net.sf.openrocket.l10n.Translator;
-import net.sf.openrocket.logging.LogHelper;
-import net.sf.openrocket.optimization.general.OptimizationException;
-import net.sf.openrocket.optimization.rocketoptimization.OptimizableParameter;
+import net.sf.openrocket.simulation.FlightData;
 import net.sf.openrocket.simulation.FlightDataType;
-import net.sf.openrocket.simulation.exception.MotorIgnitionException;
-import net.sf.openrocket.simulation.exception.SimulationCancelledException;
-import net.sf.openrocket.simulation.exception.SimulationException;
-import net.sf.openrocket.simulation.exception.SimulationLaunchException;
+import net.sf.openrocket.simulation.listeners.SimulationListener;
 import net.sf.openrocket.simulation.listeners.system.ApogeeEndListener;
-import net.sf.openrocket.simulation.listeners.system.InterruptListener;
 import net.sf.openrocket.startup.Application;
 import net.sf.openrocket.unit.UnitGroup;
 
@@ -20,9 +13,8 @@ import net.sf.openrocket.unit.UnitGroup;
  * 
  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
  */
-public class MaximumAccelerationParameter implements OptimizableParameter {
+public class MaximumAccelerationParameter extends SimulationBasedParameter {
        
-       private static final LogHelper log = Application.getLogger();
        private static final Translator trans = Application.getTranslator();
        
        @Override
@@ -31,25 +23,13 @@ public class MaximumAccelerationParameter implements OptimizableParameter {
        }
        
        @Override
-       public double computeValue(Simulation simulation) throws OptimizationException, InterruptedException {
-               try {
-                       log.debug("Running simulation to evaluate maximum acceleration");
-                       simulation.simulate(new ApogeeEndListener(), new InterruptListener());
-                       double value = simulation.getSimulatedData().getBranch(0).getMaximum(FlightDataType.TYPE_ACCELERATION_TOTAL);
-                       log.debug("Maximum acceleration was " + value);
-                       return value;
-               } catch (MotorIgnitionException e) {
-                       // A problem with motor ignition will cause optimization to fail
-                       throw new OptimizationException(e);
-               } catch (SimulationLaunchException e) {
-                       // Other launch exceptions result in zero velocity
-                       return Double.NaN;
-               } catch (SimulationCancelledException e) {
-                       throw (InterruptedException) new InterruptedException("Optimization was interrupted").initCause(e);
-               } catch (SimulationException e) {
-                       // Other exceptions fail
-                       throw new OptimizationException(e);
-               }
+       protected SimulationListener[] getSimulationListeners() {
+               return new SimulationListener[] { new ApogeeEndListener() };
+       }
+       
+       @Override
+       protected double getResultValue(FlightData simulatedData) {
+               return simulatedData.getBranch(0).getMaximum(FlightDataType.TYPE_ACCELERATION_TOTAL);
        }
        
        @Override
index 7498ed118665f15884479f545f36754678447332..f427d7fca533253498d8f196f918a925e43947d6 100644 (file)
@@ -1,17 +1,10 @@
 package net.sf.openrocket.optimization.rocketoptimization.parameters;
 
-import net.sf.openrocket.document.Simulation;
 import net.sf.openrocket.l10n.Translator;
-import net.sf.openrocket.logging.LogHelper;
-import net.sf.openrocket.optimization.general.OptimizationException;
-import net.sf.openrocket.optimization.rocketoptimization.OptimizableParameter;
+import net.sf.openrocket.simulation.FlightData;
 import net.sf.openrocket.simulation.FlightDataType;
-import net.sf.openrocket.simulation.exception.MotorIgnitionException;
-import net.sf.openrocket.simulation.exception.SimulationCancelledException;
-import net.sf.openrocket.simulation.exception.SimulationException;
-import net.sf.openrocket.simulation.exception.SimulationLaunchException;
+import net.sf.openrocket.simulation.listeners.SimulationListener;
 import net.sf.openrocket.simulation.listeners.system.ApogeeEndListener;
-import net.sf.openrocket.simulation.listeners.system.InterruptListener;
 import net.sf.openrocket.startup.Application;
 import net.sf.openrocket.unit.UnitGroup;
 
@@ -20,9 +13,8 @@ import net.sf.openrocket.unit.UnitGroup;
  * 
  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
  */
-public class MaximumAltitudeParameter implements OptimizableParameter {
+public class MaximumAltitudeParameter extends SimulationBasedParameter {
        
-       private static final LogHelper log = Application.getLogger();
        private static final Translator trans = Application.getTranslator();
        
        @Override
@@ -31,24 +23,13 @@ public class MaximumAltitudeParameter implements OptimizableParameter {
        }
        
        @Override
-       public double computeValue(Simulation simulation) throws OptimizationException, InterruptedException {
-               try {
-                       log.debug("Running simulation to evaluate apogee altitude");
-                       simulation.simulate(new ApogeeEndListener(), new InterruptListener());
-                       log.debug("Maximum altitude was " + simulation.getSimulatedData().getBranch(0).getMaximum(FlightDataType.TYPE_ALTITUDE));
-                       return simulation.getSimulatedData().getBranch(0).getMaximum(FlightDataType.TYPE_ALTITUDE);
-               } catch (MotorIgnitionException e) {
-                       // A problem with motor ignition will cause optimization to fail
-                       throw new OptimizationException(e);
-               } catch (SimulationLaunchException e) {
-                       // Other launch exceptions result in zero altitude
-                       return 0.0;
-               } catch (SimulationCancelledException e) {
-                       throw (InterruptedException) new InterruptedException("Optimization was interrupted").initCause(e);
-               } catch (SimulationException e) {
-                       // Other exceptions fail
-                       throw new OptimizationException(e);
-               }
+       protected SimulationListener[] getSimulationListeners() {
+               return new SimulationListener[] { new ApogeeEndListener() };
+       }
+       
+       @Override
+       protected double getResultValue(FlightData simulatedData) {
+               return simulatedData.getBranch(0).getMaximum(FlightDataType.TYPE_ALTITUDE);
        }
        
        @Override
index 229df474ad3ad5be10c0a3c587685e0201ac94c2..3062e4b8e7fb0f0a9c5f407d08e59d6018614826 100644 (file)
@@ -1,17 +1,10 @@
 package net.sf.openrocket.optimization.rocketoptimization.parameters;
 
-import net.sf.openrocket.document.Simulation;
 import net.sf.openrocket.l10n.Translator;
-import net.sf.openrocket.logging.LogHelper;
-import net.sf.openrocket.optimization.general.OptimizationException;
-import net.sf.openrocket.optimization.rocketoptimization.OptimizableParameter;
+import net.sf.openrocket.simulation.FlightData;
 import net.sf.openrocket.simulation.FlightDataType;
-import net.sf.openrocket.simulation.exception.MotorIgnitionException;
-import net.sf.openrocket.simulation.exception.SimulationCancelledException;
-import net.sf.openrocket.simulation.exception.SimulationException;
-import net.sf.openrocket.simulation.exception.SimulationLaunchException;
+import net.sf.openrocket.simulation.listeners.SimulationListener;
 import net.sf.openrocket.simulation.listeners.system.ApogeeEndListener;
-import net.sf.openrocket.simulation.listeners.system.InterruptListener;
 import net.sf.openrocket.startup.Application;
 import net.sf.openrocket.unit.UnitGroup;
 
@@ -20,9 +13,8 @@ import net.sf.openrocket.unit.UnitGroup;
  * 
  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
  */
-public class MaximumVelocityParameter implements OptimizableParameter {
+public class MaximumVelocityParameter extends SimulationBasedParameter {
        
-       private static final LogHelper log = Application.getLogger();
        private static final Translator trans = Application.getTranslator();
        
        @Override
@@ -31,25 +23,13 @@ public class MaximumVelocityParameter implements OptimizableParameter {
        }
        
        @Override
-       public double computeValue(Simulation simulation) throws OptimizationException, InterruptedException {
-               try {
-                       log.debug("Running simulation to evaluate maximum velocity");
-                       simulation.simulate(new ApogeeEndListener(), new InterruptListener());
-                       double value = simulation.getSimulatedData().getBranch(0).getMaximum(FlightDataType.TYPE_VELOCITY_TOTAL);
-                       log.debug("Maximum velocity was " + value);
-                       return value;
-               } catch (MotorIgnitionException e) {
-                       // A problem with motor ignition will cause optimization to fail
-                       throw new OptimizationException(e);
-               } catch (SimulationLaunchException e) {
-                       // Other launch exceptions result in zero velocity
-                       return Double.NaN;
-               } catch (SimulationCancelledException e) {
-                       throw (InterruptedException) new InterruptedException("Optimization was interrupted").initCause(e);
-               } catch (SimulationException e) {
-                       // Other exceptions fail
-                       throw new OptimizationException(e);
-               }
+       protected SimulationListener[] getSimulationListeners() {
+               return new SimulationListener[] { new ApogeeEndListener() };
+       }
+       
+       @Override
+       protected double getResultValue(FlightData simulatedData) {
+               return simulatedData.getBranch(0).getMaximum(FlightDataType.TYPE_VELOCITY_TOTAL);
        }
        
        @Override
diff --git a/src/net/sf/openrocket/optimization/rocketoptimization/parameters/SimulationBasedParameter.java b/src/net/sf/openrocket/optimization/rocketoptimization/parameters/SimulationBasedParameter.java
new file mode 100644 (file)
index 0000000..807be94
--- /dev/null
@@ -0,0 +1,78 @@
+package net.sf.openrocket.optimization.rocketoptimization.parameters;
+
+import java.util.Arrays;
+
+import net.sf.openrocket.document.Simulation;
+import net.sf.openrocket.logging.LogHelper;
+import net.sf.openrocket.optimization.general.OptimizationException;
+import net.sf.openrocket.optimization.rocketoptimization.OptimizableParameter;
+import net.sf.openrocket.simulation.FlightData;
+import net.sf.openrocket.simulation.exception.MotorIgnitionException;
+import net.sf.openrocket.simulation.exception.SimulationCancelledException;
+import net.sf.openrocket.simulation.exception.SimulationException;
+import net.sf.openrocket.simulation.exception.SimulationLaunchException;
+import net.sf.openrocket.simulation.listeners.SimulationListener;
+import net.sf.openrocket.simulation.listeners.system.InterruptListener;
+import net.sf.openrocket.startup.Application;
+
+/**
+ * An abstract optimization parameter that simulates a rocket flight and obtains
+ * a value from the simulation result.
+ * 
+ * @author Sampo Niskanen <sampo.niskanen@iki.fi>
+ */
+public abstract class SimulationBasedParameter implements OptimizableParameter {
+       
+       private static final LogHelper log = Application.getLogger();
+       
+       @Override
+       public double computeValue(Simulation simulation) throws OptimizationException, InterruptedException {
+               try {
+                       log.debug("Running simulation for " + getName());
+                       
+                       SimulationListener[] listeners = getSimulationListeners();
+                       listeners = Arrays.copyOf(listeners, listeners.length + 1);
+                       listeners[listeners.length - 1] = new InterruptListener();
+                       simulation.simulate(listeners);
+                       
+                       double value = getResultValue(simulation.getSimulatedData());
+                       log.debug("Parameter '" + getName() + " was " + value);
+                       return value;
+               } catch (MotorIgnitionException e) {
+                       // A problem with motor ignition will cause optimization to fail
+                       throw new OptimizationException(e);
+               } catch (SimulationLaunchException e) {
+                       // Other launch exceptions result in illegal value
+                       return Double.NaN;
+               } catch (SimulationCancelledException e) {
+                       // Simulation cancellation stops the optimization
+                       throw (InterruptedException) new InterruptedException("Optimization was interrupted").initCause(e);
+               } catch (SimulationException e) {
+                       // Other exceptions fail
+                       throw new OptimizationException(e);
+               }
+       }
+       
+       
+       /**
+        * Return the optimization parameter from the simulation flight data.
+        * 
+        * @param simulatedData         the simulated data.
+        * @return                                      the optimization parameter.
+        */
+       protected abstract double getResultValue(FlightData simulatedData);
+       
+       /**
+        * Return an array of simulation listeners to provide to the simulation.
+        * This may include a listener that stops the simulation after the necessary value
+        * has been computed.
+        * <p>
+        * This array should NOT contain InterruptListener, it will be added implicitly.
+        * 
+        * @return      an array of simulation listeners to include.
+        */
+       protected SimulationListener[] getSimulationListeners() {
+               return new SimulationListener[0];
+       }
+       
+}
diff --git a/src/net/sf/openrocket/optimization/rocketoptimization/parameters/TotalFlightTimeParameter.java b/src/net/sf/openrocket/optimization/rocketoptimization/parameters/TotalFlightTimeParameter.java
new file mode 100644 (file)
index 0000000..560227a
--- /dev/null
@@ -0,0 +1,33 @@
+package net.sf.openrocket.optimization.rocketoptimization.parameters;
+
+import net.sf.openrocket.l10n.Translator;
+import net.sf.openrocket.simulation.FlightData;
+import net.sf.openrocket.simulation.FlightDataType;
+import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.unit.UnitGroup;
+
+/**
+ * An optimization parameter that computes the total flight time.
+ * 
+ * @author Sampo Niskanen <sampo.niskanen@iki.fi>
+ */
+public class TotalFlightTimeParameter extends SimulationBasedParameter {
+       
+       private static final Translator trans = Application.getTranslator();
+       
+       @Override
+       public String getName() {
+               return trans.get("name");
+       }
+       
+       @Override
+       protected double getResultValue(FlightData simulatedData) {
+               return simulatedData.getBranch(0).getLast(FlightDataType.TYPE_TIME);
+       }
+       
+       @Override
+       public UnitGroup getUnitGroup() {
+               return UnitGroup.UNITS_FLIGHT_TIME;
+       }
+       
+}
index 65b9ab987066d5f50bbffaef03e3c5e430494da1..7eadfb6a1dcea35aea3f7e0c1c653b3c59cfadc4 100644 (file)
@@ -6,12 +6,14 @@ import java.util.List;
 
 import net.sf.openrocket.document.OpenRocketDocument;
 import net.sf.openrocket.optimization.rocketoptimization.OptimizableParameter;
+import net.sf.openrocket.optimization.rocketoptimization.parameters.DeploymentVelocityParameter;
 import net.sf.openrocket.optimization.rocketoptimization.parameters.GroundHitVelocityParameter;
 import net.sf.openrocket.optimization.rocketoptimization.parameters.LandingDistanceParameter;
 import net.sf.openrocket.optimization.rocketoptimization.parameters.MaximumAccelerationParameter;
 import net.sf.openrocket.optimization.rocketoptimization.parameters.MaximumAltitudeParameter;
 import net.sf.openrocket.optimization.rocketoptimization.parameters.MaximumVelocityParameter;
 import net.sf.openrocket.optimization.rocketoptimization.parameters.StabilityParameter;
+import net.sf.openrocket.optimization.rocketoptimization.parameters.TotalFlightTimeParameter;
 
 /**
  * Default implementation for optimization parameter service.
@@ -31,6 +33,8 @@ public class DefaultOptimizableParameterService implements OptimizableParameterS
                list.add(new StabilityParameter(true));
                list.add(new GroundHitVelocityParameter());
                list.add(new LandingDistanceParameter());
+               list.add(new TotalFlightTimeParameter());
+               list.add(new DeploymentVelocityParameter());
                
                return list;
        }
diff --git a/src/net/sf/openrocket/simulation/listeners/system/RecoveryDeviceDeploymentEndListener.java b/src/net/sf/openrocket/simulation/listeners/system/RecoveryDeviceDeploymentEndListener.java
new file mode 100644 (file)
index 0000000..b6bac33
--- /dev/null
@@ -0,0 +1,29 @@
+package net.sf.openrocket.simulation.listeners.system;
+
+import net.sf.openrocket.rocketcomponent.RecoveryDevice;
+import net.sf.openrocket.simulation.FlightEvent;
+import net.sf.openrocket.simulation.SimulationStatus;
+import net.sf.openrocket.simulation.exception.SimulationException;
+import net.sf.openrocket.simulation.listeners.AbstractSimulationListener;
+
+
+/**
+ * A simulation listeners that ends the simulation when apogee is reached.
+ * 
+ * @author Sampo Niskanen <sampo.niskanen@iki.fi>
+ */
+public class RecoveryDeviceDeploymentEndListener extends AbstractSimulationListener {
+       
+       public static final RecoveryDeviceDeploymentEndListener INSTANCE = new RecoveryDeviceDeploymentEndListener();
+       
+       @Override
+       public boolean recoveryDeviceDeployment(SimulationStatus status, RecoveryDevice recoveryDevice) throws SimulationException {
+               status.getEventQueue().add(new FlightEvent(FlightEvent.Type.SIMULATION_END, status.getSimulationTime()));
+               return true;
+       }
+       
+       @Override
+       public boolean isSystemListener() {
+               return true;
+       }
+}