1 package net.sf.openrocket.simulation.listeners.example;
6 import net.sf.openrocket.aerodynamics.AerodynamicCalculator;
7 import net.sf.openrocket.aerodynamics.AerodynamicForces;
8 import net.sf.openrocket.aerodynamics.FlightConditions;
9 import net.sf.openrocket.motor.MotorId;
10 import net.sf.openrocket.motor.MotorInstance;
11 import net.sf.openrocket.motor.MotorInstanceConfiguration;
12 import net.sf.openrocket.rocketcomponent.MotorMount;
13 import net.sf.openrocket.rocketcomponent.RocketComponent;
14 import net.sf.openrocket.simulation.FlightDataBranch;
15 import net.sf.openrocket.simulation.FlightDataType;
16 import net.sf.openrocket.simulation.SimulationStatus;
17 import net.sf.openrocket.simulation.exception.SimulationException;
18 import net.sf.openrocket.simulation.listeners.AbstractSimulationListener;
19 import net.sf.openrocket.unit.UnitGroup;
20 import net.sf.openrocket.util.ArrayList;
21 import net.sf.openrocket.util.Coordinate;
22 import net.sf.openrocket.util.PolyInterpolator;
24 public class DampingMoment extends AbstractSimulationListener {
26 private static final FlightDataType type = FlightDataType.getType("Damping moment coefficient", "Cdm", UnitGroup.UNITS_COEFFICIENT);
27 private static final FlightDataType[] typeList = {type};
29 public String getName(){
30 return "Damping moment listener";
34 * Return a list of any flight data types this listener creates.
36 public FlightDataType[] getFlightDataTypes(){
41 public FlightConditions postFlightConditions(SimulationStatus status, FlightConditions flightConditions) throws SimulationException {
43 // Save it as a flightdatatype
45 //status.getFlightData().setValue(type, aerodynamicPart + propulsivePart);
46 status.getFlightData().setValue(type, calculate(status, flightConditions));
48 return flightConditions;
51 private double calculate(SimulationStatus status, FlightConditions flightConditions){
53 // Work out the propulsive/jet damping part of the moment.
55 // dm/dt = (thrust - ma)/v
56 FlightDataBranch data = status.getFlightData();
58 List<Double> mpAll = data.get(FlightDataType.TYPE_PROPELLANT_MASS);
59 List<Double> time = data.get(FlightDataType.TYPE_TIME);
60 if (mpAll == null || time == null){
64 int len = mpAll.size();
66 // This isn't as accurate as I would like
67 double mdot=Double.NaN;
69 // Using polynomial interpolator for derivative. Doesn't help much
70 //double[] x = { time.get(len-5), time.get(len-4), time.get(len-3), time.get(len-2), time.get(len-1) };
71 //double[] y = { mpAll.get(len-5), mpAll.get(len-4), mpAll.get(len-3), mpAll.get(len-2), mpAll.get(len-1) };
72 //PolyInterpolator interp = new PolyInterpolator(x);
73 //double[] coeff = interp.interpolator(y);
75 //mdot = (interp.eval(x[4], coeff) - interp.eval(x[4]-dt, coeff))/dt;
77 mdot = (mpAll.get(len-1) - mpAll.get(len-2)) / (time.get(len-1) - time.get(len-2));
80 double cg = data.getLast(FlightDataType.TYPE_CG_LOCATION);
82 // find the maximum distance from nose to nozzle.
83 double nozzleDistance = 0;
84 for (MotorId id: status.getMotorConfiguration().getMotorIDs()){
85 MotorInstanceConfiguration config = status.getMotorConfiguration();
86 Coordinate position = config.getMotorPosition(id);
88 double x = position.x + config.getMotorInstance(id).getParentMotor().getLength();
89 if (x > nozzleDistance){
94 // now can get the propulsive part
95 double propulsivePart = mdot * Math.pow(nozzleDistance - cg, 2);
97 // Work out the aerodynamic part of the moment.
98 double aerodynamicPart = 0;
100 AerodynamicCalculator aerocalc = status.getSimulationConditions().getAerodynamicCalculator();
102 // Must go through each component ...
103 Map<RocketComponent, AerodynamicForces> forces = aerocalc.getForceAnalysis(status.getConfiguration(), flightConditions, null);
104 for (Map.Entry<RocketComponent, AerodynamicForces> entry : forces.entrySet()){
106 RocketComponent comp = entry.getKey();
108 if (!comp.isAerodynamic()) continue;
110 //System.out.println(comp.toString());
112 double CNa = entry.getValue().getCNa(); //?
113 double Cp = entry.getValue().getCP().length();
114 double z = comp.getPositionValue(); //?
116 aerodynamicPart += CNa*Math.pow(z-Cp, 2);
119 double v = flightConditions.getVelocity();
120 double rho = flightConditions.getAtmosphericConditions().getDensity();
121 double ar = flightConditions.getRefArea();
123 aerodynamicPart = aerodynamicPart * .5 * rho * v * ar;
125 return aerodynamicPart + propulsivePart;