package net.sf.openrocket.optimization.rocketoptimization.parameters; import java.util.Arrays; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.sf.openrocket.document.Simulation; 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.SimulationCalculationException; 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; /** * 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 Logger log = LoggerFactory.getLogger(SimulationBasedParameter.class); @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 (SimulationCalculationException e) { // Calculation errors 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]; } }