- Implemented a DampingMoment simulation listener example
[debian/openrocket] / core / src / net / sf / openrocket / simulation / listeners / example / DampingMoment.java
1 package net.sf.openrocket.simulation.listeners.example;
2
3 import java.util.List;
4 import java.util.Map;
5
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;
23
24 public class DampingMoment extends AbstractSimulationListener {
25         
26         private static final FlightDataType type = FlightDataType.getType("Damping moment coefficient", "Cdm", UnitGroup.UNITS_COEFFICIENT);
27         private static final FlightDataType[] typeList = {type};
28         
29         public String getName(){
30                 return "Damping moment listener";
31         }
32         
33         /**
34          * Return a list of any flight data types this listener creates.
35          */
36         public FlightDataType[] getFlightDataTypes(){
37                 return typeList;
38         }
39         
40         @Override
41         public FlightConditions postFlightConditions(SimulationStatus status, FlightConditions flightConditions) throws SimulationException {
42                 
43                 // Save it as a flightdatatype
44                 
45                 //status.getFlightData().setValue(type, aerodynamicPart + propulsivePart);
46                 status.getFlightData().setValue(type, calculate(status, flightConditions));
47
48                 return flightConditions;
49         }
50         
51         private double calculate(SimulationStatus status, FlightConditions flightConditions){
52                 
53                 // Work out the propulsive/jet damping part of the moment.
54                 
55                 // dm/dt = (thrust - ma)/v
56                 FlightDataBranch data = status.getFlightData();
57                 
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){
61                         return Double.NaN;
62                 }
63                 
64                 int len = mpAll.size();
65                 
66                 // This isn't as accurate as I would like
67                 double mdot=Double.NaN;
68                 if (len > 2){
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);
74                         //double dt = .01;
75                         //mdot = (interp.eval(x[4], coeff) - interp.eval(x[4]-dt, coeff))/dt; 
76                                                 
77                         mdot = (mpAll.get(len-1) - mpAll.get(len-2)) / (time.get(len-1) - time.get(len-2));
78                 }
79                 
80                 double cg = data.getLast(FlightDataType.TYPE_CG_LOCATION);
81                 
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);
87                         
88                         double x = position.x + config.getMotorInstance(id).getParentMotor().getLength();
89                         if (x > nozzleDistance){
90                                 nozzleDistance = x;
91                         }                       
92                 }
93                 
94                 // now can get the propulsive part
95                 double propulsivePart = mdot * Math.pow(nozzleDistance - cg, 2);
96                 
97                 // Work out the aerodynamic part of the moment.
98                 double aerodynamicPart = 0;
99                 
100                 AerodynamicCalculator aerocalc = status.getSimulationConditions().getAerodynamicCalculator();
101                 
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()){
105                         
106                         RocketComponent comp = entry.getKey();
107                         
108                         if (!comp.isAerodynamic()) continue;
109                         
110                         //System.out.println(comp.toString());
111                         
112                         double CNa = entry.getValue().getCNa(); //?
113                         double Cp = entry.getValue().getCP().length();
114                         double z = comp.getPositionValue(); //?
115                         
116                         aerodynamicPart += CNa*Math.pow(z-Cp, 2);
117                 }
118                 
119                 double v = flightConditions.getVelocity();
120                 double rho = flightConditions.getAtmosphericConditions().getDensity();
121                 double ar = flightConditions.getRefArea();
122                 
123                 aerodynamicPart = aerodynamicPart * .5 * rho * v * ar;
124                 
125                 return aerodynamicPart + propulsivePart;
126         
127         }
128         
129 }