Implement tumbling based on the mathematics in techdoc.pdf. Change the

conditions to transistion to tumbling to include aoa>30.
This commit is contained in:
kruland2607 2013-02-18 12:09:15 -06:00
parent b99a704eb6
commit 526131a64c
3 changed files with 60 additions and 22 deletions

View File

@ -194,13 +194,17 @@ public class BasicEventSimulationEngine implements SimulationEngine {
}
// Check for Tumbling
// FIXME - need to test things like no longer stable.
// Conditions for transision are:
// apogee reached
// and is not already tumbling
// and not stable (cg > cp)
// and aoa > 30
if (status.isApogeeReached() && !status.isTumbling() ) {
int last_data_index = status.getFlightData().getLength() -1;
double cp = status.getFlightData().get(FlightDataType.TYPE_CP_LOCATION).get(last_data_index);
double cg = status.getFlightData().get(FlightDataType.TYPE_CG_LOCATION).get(last_data_index);
if( cg > cp ) {
double cp = status.getFlightData().getLast(FlightDataType.TYPE_CP_LOCATION);
double cg = status.getFlightData().getLast(FlightDataType.TYPE_CG_LOCATION);
double aoa = status.getFlightData().getLast(FlightDataType.TYPE_AOA);
if( cg > cp && aoa > 30 ) {
addEvent( new FlightEvent(FlightEvent.Type.TUMBLE,status.getSimulationTime()));
}
status.setTumbling(true);

View File

@ -1,42 +1,77 @@
package net.sf.openrocket.simulation;
import java.util.Iterator;
import net.sf.openrocket.aerodynamics.AerodynamicForces;
import net.sf.openrocket.aerodynamics.FlightConditions;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.motor.MotorInstanceConfiguration;
import net.sf.openrocket.rocketcomponent.Configuration;
import net.sf.openrocket.rocketcomponent.FinSet;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.SymmetricComponent;
public class BasicTumbleStatus extends SimulationStatus {
private double tumbleCd;
// Magic constants from techdoc.pdf
private final static double cDFin = 1.42;
private final static double cDBt = 0.56;
// Fin efficiency. Index is number of fins. The 0th entry is arbitrary and used to
// offset the indexes so finEff[1] is the coefficient for one fin from the table in techdoc.pdf
private final static double[] finEff = { 0.0, 0.5, 1.0, 1.41, 1.81, 1.73, 1.90, 1.85 };
private double drag;
public BasicTumbleStatus(Configuration configuration,
MotorInstanceConfiguration motorConfiguration,
SimulationConditions simulationConditions) {
super(configuration, motorConfiguration, simulationConditions);
computeTumbleCd();
computeTumbleDrag();
}
public BasicTumbleStatus(SimulationStatus orig) {
super(orig);
if ( orig instanceof BasicTumbleStatus ) {
this.tumbleCd = ((BasicTumbleStatus) orig).tumbleCd;
this.drag = ((BasicTumbleStatus) orig).drag;
}
}
public double getTumbleCd( ) {
return tumbleCd;
public double getTumbleDrag( ) {
return drag;
}
public void computeTumbleCd() {
// FIXME - probably want to compute the overall CD more accurately. Perhaps average
// CD over three AoA: 0, 90, 180. In any case, using barrowman to compute this Cd is
// completely wrong.
WarningSet warnings = new WarningSet();
FlightConditions cond = new FlightConditions(this.getConfiguration());
cond.setAOA(Math.PI);
AerodynamicForces forces = this.getSimulationConditions().getAerodynamicCalculator().getAerodynamicForces(this.getConfiguration(), cond, warnings);
tumbleCd = forces.getCD();
public void computeTumbleDrag() {
// Computed based on Sampo's experimentation as documented in the pdf.
// compute the fin and body tube projected areas
double aFins = 0.0;
double aBt = 0.0;
Rocket r = this.getConfiguration().getRocket();
Iterator<RocketComponent> componentIterator = r.iterator();
while ( componentIterator.hasNext() ) {
RocketComponent component = componentIterator.next();
if ( ! component.isAerodynamic() ) {
continue;
}
if ( component instanceof FinSet ) {
double finComponent = ((FinSet)component).getFinArea();
int finCount = ((FinSet)component).getFinCount();
// check bounds on finCount.
if ( finCount >= finEff.length ) {
finCount = finEff.length-1;
}
aFins += finComponent * finEff[finCount];
} else if (component instanceof SymmetricComponent ){
aBt += ((SymmetricComponent) component) .getComponentPlanformArea();
}
}
drag = ( cDFin * aFins + cDBt * aBt );
}
}

View File

@ -18,7 +18,6 @@ public class BasicTumbleStepper extends AbstractSimulationStepper {
@Override
public void step(SimulationStatus status, double maxTimeStep) throws SimulationException {
double refArea = status.getConfiguration().getReferenceArea();
// Get the atmospheric conditions
AtmosphericConditions atmosphere = modelAtmosphericConditions(status);
@ -30,11 +29,11 @@ public class BasicTumbleStepper extends AbstractSimulationStepper {
// Get total CD
double mach = airSpeed.length() / atmosphere.getMachSpeed();
double totalCD = ((BasicTumbleStatus)status).getTumbleCd();
double tumbleDrag = ((BasicTumbleStatus)status).getTumbleDrag();
// Compute drag force
double dynP = (0.5 * atmosphere.getDensity() * airSpeed.length2());
double dragForce = totalCD * dynP * refArea;
double dragForce = tumbleDrag * dynP;
MassData massData = calculateMassData(status);
double mass = massData.getCG().weight;