StabilityParameter.name = Stability
GroundHitVelocityParameter.name = Ground hit speed
LandingDistanceParameter.name = Landing distance
+TotalFlightTimeParameter.name = Total flight time
+DeploymentVelocityParameter.name = Velocity at parachute deployment
+
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 }
);
tooltipGenerator.addToolTipSeries(tooltips);
lineRenderer.setBaseToolTipGenerator(tooltipGenerator);
-
XYPlot plot = chart.getXYPlot();
plot.setDataset(0, new XYSeriesCollection(series));
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();
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);
} 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++;
}
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);
}
}
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);
}
--- /dev/null
+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;
+ }
+
+}
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;
*
* @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
}
@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
return UnitGroup.UNITS_VELOCITY;
}
+
}
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;
*
* @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
}
@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
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;
*
* @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
}
@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
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;
*
* @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
}
@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
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;
*
* @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
}
@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
--- /dev/null
+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];
+ }
+
+}
--- /dev/null
+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;
+ }
+
+}
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.
list.add(new StabilityParameter(true));
list.add(new GroundHitVelocityParameter());
list.add(new LandingDistanceParameter());
+ list.add(new TotalFlightTimeParameter());
+ list.add(new DeploymentVelocityParameter());
return list;
}
--- /dev/null
+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;
+ }
+}