Convert DampingMoment listener to simulation extension
This commit is contained in:
parent
c3d2d5fc16
commit
17a4f1ffdb
@ -0,0 +1,147 @@
|
||||
package net.sf.openrocket.simulation.extension.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.sf.openrocket.aerodynamics.AerodynamicCalculator;
|
||||
import net.sf.openrocket.aerodynamics.AerodynamicForces;
|
||||
import net.sf.openrocket.aerodynamics.FlightConditions;
|
||||
import net.sf.openrocket.aerodynamics.WarningSet;
|
||||
import net.sf.openrocket.motor.MotorConfiguration;
|
||||
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.simulation.FlightDataBranch;
|
||||
import net.sf.openrocket.simulation.FlightDataType;
|
||||
import net.sf.openrocket.simulation.SimulationConditions;
|
||||
import net.sf.openrocket.simulation.SimulationStatus;
|
||||
import net.sf.openrocket.simulation.exception.SimulationException;
|
||||
import net.sf.openrocket.simulation.extension.AbstractSimulationExtension;
|
||||
import net.sf.openrocket.simulation.listeners.AbstractSimulationListener;
|
||||
import net.sf.openrocket.unit.UnitGroup;
|
||||
|
||||
public class DampingMoment extends AbstractSimulationExtension {
|
||||
private static final Logger log = LoggerFactory.getLogger(DampingMoment.class);
|
||||
|
||||
// Save it as a FlightDataType
|
||||
private static final FlightDataType cdm = FlightDataType.getType("Damping moment coefficient", "Cdm", UnitGroup.UNITS_COEFFICIENT);
|
||||
private static final ArrayList<FlightDataType> types = new ArrayList<FlightDataType>();
|
||||
|
||||
DampingMoment() {
|
||||
types.add(cdm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FlightDataType> getFlightDataTypes() {
|
||||
return types;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(SimulationConditions conditions) throws SimulationException {
|
||||
log.debug("initializing...");
|
||||
conditions.getSimulationListenerList().add(new DampingMomentListener());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Damping Moment Coeficient(Cdm)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Calculate damping moment coefficient after every simulation step and publish to FlightData as Cdm";
|
||||
}
|
||||
|
||||
private class DampingMomentListener extends AbstractSimulationListener {
|
||||
|
||||
@Override
|
||||
public FlightConditions postFlightConditions(SimulationStatus status, FlightConditions flightConditions) throws SimulationException {
|
||||
|
||||
//status.getFlightData().setValue(cdm, aerodynamicPart + propulsivePart);
|
||||
status.getFlightData().setValue(cdm, calculate(status, flightConditions));
|
||||
|
||||
return flightConditions;
|
||||
}
|
||||
|
||||
private double calculate(SimulationStatus status, FlightConditions flightConditions) {
|
||||
|
||||
// Work out the propulsive/jet damping part of the moment.
|
||||
|
||||
// dm/dt = (thrust - ma)/v
|
||||
FlightDataBranch data = status.getFlightData();
|
||||
|
||||
List<Double> mpAll = data.get(FlightDataType.TYPE_MOTOR_MASS);
|
||||
List<Double> time = data.get(FlightDataType.TYPE_TIME);
|
||||
if (mpAll == null || time == null) {
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
int len = mpAll.size();
|
||||
|
||||
// This isn't as accurate as I would like
|
||||
double mdot = Double.NaN;
|
||||
if (len > 2) {
|
||||
// Using polynomial interpolator for derivative. Doesn't help much
|
||||
//double[] x = { time.get(len-5), time.get(len-4), time.get(len-3), time.get(len-2), time.get(len-1) };
|
||||
//double[] y = { mpAll.get(len-5), mpAll.get(len-4), mpAll.get(len-3), mpAll.get(len-2), mpAll.get(len-1) };
|
||||
//PolyInterpolator interp = new PolyInterpolator(x);
|
||||
//double[] coeff = interp.interpolator(y);
|
||||
//double dt = .01;
|
||||
//mdot = (interp.eval(x[4], coeff) - interp.eval(x[4]-dt, coeff))/dt;
|
||||
|
||||
mdot = (mpAll.get(len - 1) - mpAll.get(len - 2)) / (time.get(len - 1) - time.get(len - 2));
|
||||
}
|
||||
|
||||
double cg = data.getLast(FlightDataType.TYPE_CG_LOCATION);
|
||||
|
||||
// find the maximum distance from nose to nozzle.
|
||||
double nozzleDistance = 0;
|
||||
FlightConfiguration config = status.getConfiguration();
|
||||
for (MotorConfiguration inst : config.getActiveMotors()) {
|
||||
double x_position= inst.getX();
|
||||
double x = x_position + inst.getMotor().getLaunchCGx();
|
||||
if (x > nozzleDistance) {
|
||||
nozzleDistance = x;
|
||||
}
|
||||
}
|
||||
|
||||
// now can get the propulsive part
|
||||
double propulsivePart = mdot * Math.pow(nozzleDistance - cg, 2);
|
||||
|
||||
// Work out the aerodynamic part of the moment.
|
||||
double aerodynamicPart = 0;
|
||||
|
||||
AerodynamicCalculator aerocalc = status.getSimulationConditions().getAerodynamicCalculator();
|
||||
|
||||
// Must go through each component ...
|
||||
Map<RocketComponent, AerodynamicForces> forces = aerocalc.getForceAnalysis(status.getConfiguration(), flightConditions, status.getWarnings());
|
||||
for (Map.Entry<RocketComponent, AerodynamicForces> entry : forces.entrySet()) {
|
||||
|
||||
RocketComponent comp = entry.getKey();
|
||||
|
||||
if (!comp.isAerodynamic())
|
||||
continue;
|
||||
|
||||
//System.out.println(comp.toString());
|
||||
|
||||
double CNa = entry.getValue().getCNa(); //?
|
||||
double Cp = entry.getValue().getCP().length();
|
||||
double z = comp.getAxialOffset();
|
||||
|
||||
aerodynamicPart += CNa * Math.pow(z - Cp, 2);
|
||||
}
|
||||
|
||||
double v = flightConditions.getVelocity();
|
||||
double rho = flightConditions.getAtmosphericConditions().getDensity();
|
||||
double ar = flightConditions.getRefArea();
|
||||
|
||||
aerodynamicPart = aerodynamicPart * .5 * rho * v * ar;
|
||||
|
||||
return aerodynamicPart + propulsivePart;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package net.sf.openrocket.simulation.extension.impl;
|
||||
|
||||
import net.sf.openrocket.plugin.Plugin;
|
||||
import net.sf.openrocket.simulation.extension.AbstractSimulationExtensionProvider;
|
||||
|
||||
@Plugin
|
||||
public class DampingMomentProvider extends AbstractSimulationExtensionProvider {
|
||||
|
||||
public DampingMomentProvider() {
|
||||
super(DampingMoment.class, "Post-step flight conditions", "Damping Moment Coefficient (Cdm)");
|
||||
}
|
||||
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
package net.sf.openrocket.simulation.listeners.example;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sf.openrocket.aerodynamics.AerodynamicCalculator;
|
||||
import net.sf.openrocket.aerodynamics.AerodynamicForces;
|
||||
import net.sf.openrocket.aerodynamics.FlightConditions;
|
||||
import net.sf.openrocket.aerodynamics.WarningSet;
|
||||
import net.sf.openrocket.motor.MotorConfiguration;
|
||||
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.simulation.FlightDataBranch;
|
||||
import net.sf.openrocket.simulation.FlightDataType;
|
||||
import net.sf.openrocket.simulation.SimulationStatus;
|
||||
import net.sf.openrocket.simulation.exception.SimulationException;
|
||||
import net.sf.openrocket.simulation.listeners.AbstractSimulationListener;
|
||||
import net.sf.openrocket.unit.UnitGroup;
|
||||
|
||||
public class DampingMoment extends AbstractSimulationListener {
|
||||
|
||||
private static final FlightDataType type = FlightDataType.getType("Damping moment coefficient", "Cdm", UnitGroup.UNITS_COEFFICIENT);
|
||||
|
||||
// unused
|
||||
//private static final FlightDataType[] typeList = { type };
|
||||
|
||||
@Override
|
||||
public FlightConditions postFlightConditions(SimulationStatus status, FlightConditions flightConditions) throws SimulationException {
|
||||
|
||||
// Save it as a flightdatatype
|
||||
|
||||
//status.getFlightData().setValue(type, aerodynamicPart + propulsivePart);
|
||||
status.getFlightData().setValue(type, calculate(status, flightConditions));
|
||||
|
||||
return flightConditions;
|
||||
}
|
||||
|
||||
private double calculate(SimulationStatus status, FlightConditions flightConditions) {
|
||||
|
||||
// Work out the propulsive/jet damping part of the moment.
|
||||
|
||||
// dm/dt = (thrust - ma)/v
|
||||
FlightDataBranch data = status.getFlightData();
|
||||
|
||||
List<Double> mpAll = data.get(FlightDataType.TYPE_MOTOR_MASS);
|
||||
List<Double> time = data.get(FlightDataType.TYPE_TIME);
|
||||
if (mpAll == null || time == null) {
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
int len = mpAll.size();
|
||||
|
||||
// This isn't as accurate as I would like
|
||||
double mdot = Double.NaN;
|
||||
if (len > 2) {
|
||||
// Using polynomial interpolator for derivative. Doesn't help much
|
||||
//double[] x = { time.get(len-5), time.get(len-4), time.get(len-3), time.get(len-2), time.get(len-1) };
|
||||
//double[] y = { mpAll.get(len-5), mpAll.get(len-4), mpAll.get(len-3), mpAll.get(len-2), mpAll.get(len-1) };
|
||||
//PolyInterpolator interp = new PolyInterpolator(x);
|
||||
//double[] coeff = interp.interpolator(y);
|
||||
//double dt = .01;
|
||||
//mdot = (interp.eval(x[4], coeff) - interp.eval(x[4]-dt, coeff))/dt;
|
||||
|
||||
mdot = (mpAll.get(len - 1) - mpAll.get(len - 2)) / (time.get(len - 1) - time.get(len - 2));
|
||||
}
|
||||
|
||||
double cg = data.getLast(FlightDataType.TYPE_CG_LOCATION);
|
||||
|
||||
// find the maximum distance from nose to nozzle.
|
||||
double nozzleDistance = 0;
|
||||
FlightConfiguration config = status.getConfiguration();
|
||||
for (MotorConfiguration inst : config.getActiveMotors()) {
|
||||
double x_position= inst.getX();
|
||||
double x = x_position + inst.getMotor().getLaunchCGx();
|
||||
if (x > nozzleDistance) {
|
||||
nozzleDistance = x;
|
||||
}
|
||||
}
|
||||
|
||||
// now can get the propulsive part
|
||||
double propulsivePart = mdot * Math.pow(nozzleDistance - cg, 2);
|
||||
|
||||
// Work out the aerodynamic part of the moment.
|
||||
double aerodynamicPart = 0;
|
||||
|
||||
AerodynamicCalculator aerocalc = status.getSimulationConditions().getAerodynamicCalculator();
|
||||
|
||||
// Must go through each component ...
|
||||
Map<RocketComponent, AerodynamicForces> forces = aerocalc.getForceAnalysis(status.getConfiguration(), flightConditions, status.getWarnings());
|
||||
for (Map.Entry<RocketComponent, AerodynamicForces> entry : forces.entrySet()) {
|
||||
|
||||
RocketComponent comp = entry.getKey();
|
||||
|
||||
if (!comp.isAerodynamic())
|
||||
continue;
|
||||
|
||||
//System.out.println(comp.toString());
|
||||
|
||||
double CNa = entry.getValue().getCNa(); //?
|
||||
double Cp = entry.getValue().getCP().length();
|
||||
double z = comp.getAxialOffset();
|
||||
|
||||
aerodynamicPart += CNa * Math.pow(z - Cp, 2);
|
||||
}
|
||||
|
||||
double v = flightConditions.getVelocity();
|
||||
double rho = flightConditions.getAtmosphericConditions().getDensity();
|
||||
double ar = flightConditions.getRefArea();
|
||||
|
||||
aerodynamicPart = aerodynamicPart * .5 * rho * v * ar;
|
||||
|
||||
return aerodynamicPart + propulsivePart;
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user