Search in sources :

Example 1 with Aircraft

use of com.chrisali.javaflightsim.simulation.aircraft.Aircraft in project j6dof-flight-sim by chris-ali.

the class Trimming method trimSim.

/**
 * Trims an aircraft longitudinally for a forward velocity and altitude specified in
 *
 * <p> SimConfig/InitialConditions.txt </p>
 *
 * by setting the elevator, throttle and pitch attitude. These values are calculated by statically equating forces and moments.
 * If unable to reach a given trim condition, the method will return the maximum values for each control and pitch attitude.
 * These values are then saved to
 *
 * <p> SimConfig/InitialConditions.txt </p>
 * and
 * <p> SimConfig/InitialControls.txt </p>
 *
 * as long as the test mode boolean flag is false; otherwise the results will be displayed in the console
 *
 * @param configuration
 * @param testMode
 */
public static void trimSim(SimulationConfiguration configuration, boolean testMode) {
    Aircraft aircraft = FileUtilities.readAircraftConfiguration(configuration.getSelectedAircraft());
    aero = new Aerodynamics(aircraft);
    initialConditions = configuration.getInitialConditions();
    initialControls = configuration.getInitialControls();
    environmentParams = Environment.getAndUpdateEnvironmentParams(new double[] { 0, 0, initialConditions.get(InitialConditions.INITD) });
    double alphaMin = -0.18, alphaMax = 0.18, throttleMin = 0.0, throttleMax = 1.0, alphaTrim = 0.0, thetaTrim = 0.0, elevTrim = 0.0, throttleTrim = 0.0, wVelocityTrim = 0.0, lift = 0.0, drag = 0.0, totalThrust = 0.0, zForce = 100.0;
    double trueAirspeed = Math.sqrt(Math.pow(initialConditions.get(InitialConditions.INITU), 2) + Math.pow(initialConditions.get(InitialConditions.INITW), 2));
    double weight = aircraft.getMassProperty(MassProperties.TOTAL_MASS) * Environment.getGravity();
    double q = environmentParams.get(EnvironmentParameters.RHO) * Math.pow(trueAirspeed, 2) / 2;
    double s = aircraft.getWingGeometry(WingGeometry.S_WING);
    int counter = 0;
    logger.debug("Finding trim pitch and elevator...");
    do {
        alphaTrim = (alphaMin + alphaMax) / 2;
        // Break out of loop if trim condition not satisfied after 100 attempts
        if (counter == 100) {
            logger.error("Unable to trim elevator and pitch for given conditions!");
            break;
        }
        // =============================================== Pitch ================================================================
        // Calculate trim pitch by using (theta = alpha + FPA)
        // FPA is zero in level flight
        thetaTrim = alphaTrim + 0;
        double[] windParameters = new double[] { trueAirspeed, 0, alphaTrim };
        double CL_alpha = aero.calculateInterpStabDer(windParameters, initialControls, StabilityDerivatives.CL_ALPHA);
        double CL_0 = aero.calculateInterpStabDer(windParameters, initialControls, StabilityDerivatives.CL_0);
        lift = q * s * ((CL_alpha * alphaTrim) + CL_0);
        double CD_alpha = aero.calculateInterpStabDer(windParameters, initialControls, StabilityDerivatives.CD_ALPHA);
        double CD_0 = aero.calculateInterpStabDer(windParameters, initialControls, StabilityDerivatives.CD_0);
        drag = q * s * ((CD_alpha * alphaTrim) + CD_0);
        // Calculate zForce to find trim alpha to zero forces
        zForce = (-lift * Math.cos(alphaTrim)) - (drag * Math.sin(alphaTrim)) + (weight * Math.cos(thetaTrim));
        if (zForce > 0)
            alphaMin = alphaTrim;
        else
            alphaMax = alphaTrim;
        // Recalculate w velocity for new angle of attack
        wVelocityTrim = windParameters[0] * Math.sin(alphaTrim);
        // ==================================================== Elevator ========================================================
        // Calculate trim elevator, limiting if necessary
        double CM_alpha = aero.calculateInterpStabDer(windParameters, initialControls, StabilityDerivatives.CM_ALPHA);
        double CM_d_elev = aircraft.getStabilityDerivative(StabilityDerivatives.CM_D_ELEV).getValue();
        double CM_0 = aircraft.getStabilityDerivative(StabilityDerivatives.CM_0).getValue();
        elevTrim = (CM_0 + (CM_alpha * alphaTrim)) / CM_d_elev;
        elevTrim = elevTrim > FlightControl.ELEVATOR.getMaximum() ? FlightControl.ELEVATOR.getMaximum() : elevTrim < FlightControl.ELEVATOR.getMinimum() ? FlightControl.ELEVATOR.getMinimum() : elevTrim;
        counter++;
    } while (Math.abs(zForce) > 1);
    logger.debug("...done!");
    // ==================================================== Throttle ============================================================
    Set<Engine> engines = aircraft.getEngines();
    drag = (drag * Math.cos(alphaTrim)) - (lift * Math.sin(alphaTrim)) + (weight * Math.sin(thetaTrim));
    counter = 0;
    logger.debug("Finding trim throttle...");
    do {
        throttleTrim = (throttleMin + throttleMax) / 2;
        // Break out of loop if trim condition not satisfied after 100 attempts
        if (counter == 100) {
            logger.error("Unable to trim throttle for given conditions!");
            break;
        }
        initialControls.put(FlightControl.THROTTLE_1, throttleTrim);
        initialControls.put(FlightControl.THROTTLE_2, throttleTrim);
        initialControls.put(FlightControl.THROTTLE_3, throttleTrim);
        initialControls.put(FlightControl.THROTTLE_4, throttleTrim);
        // Get total thrust, equate it with drag of aircraft to find trim throttle
        totalThrust = 0.0;
        for (Engine engine : engines) {
            engine.updateEngineState(initialControls, environmentParams, new double[] { trueAirspeed, 0, 0 });
            totalThrust += engine.getEngineThrust()[0];
        }
        if (totalThrust < drag)
            throttleMin = throttleTrim;
        else
            throttleMax = throttleTrim;
        counter++;
    } while (Math.abs(totalThrust - drag) > 1);
    logger.debug("...done!");
    // Update initialControls and initialConditions
    initialConditions.put(InitialConditions.INITTHETA, thetaTrim);
    initialConditions.put(InitialConditions.INITW, wVelocityTrim);
    initialControls.put(FlightControl.ELEVATOR, -elevTrim);
    initialControls.put(FlightControl.AILERON, 0.0);
    initialControls.put(FlightControl.RUDDER, 0.0);
    logger.debug("Finished trimming aircraft!");
    logger.debug(String.format("Trim controls are: \nElevator: %.4f rad\nThrottle: %.4f", elevTrim, throttleTrim));
    logger.debug(String.format("Trim states are: \nW Velocity: %3.4f ft/sec\nTheta: %.4f rad\nAlpha: %.4f rad", wVelocityTrim, thetaTrim, alphaTrim));
    // In test mode do not write any config settings to files
    if (!testMode) {
        logger.debug("Updating initial conditions and initial flight controls...");
        configuration.setInitialConditions(initialConditions);
        configuration.setInitialControls(initialControls);
        configuration.save();
    } else {
        logger.debug(Trimming.outputTrimValues());
    }
}
Also used : Aerodynamics(com.chrisali.javaflightsim.simulation.aircraft.Aerodynamics) Aircraft(com.chrisali.javaflightsim.simulation.aircraft.Aircraft) Engine(com.chrisali.javaflightsim.simulation.propulsion.Engine)

Example 2 with Aircraft

use of com.chrisali.javaflightsim.simulation.aircraft.Aircraft in project j6dof-flight-sim by chris-ali.

the class ReadWriteJsonTest method WriteThenReadJsonAircraftTest.

@Test
public void WriteThenReadJsonAircraftTest() {
    String aircraftName = "TwinNavion";
    Aircraft aircraft = FileUtilities.readAircraftConfiguration(aircraftName);
    String assertion = "Property to serialize should not be null";
    assertNotNull(assertion, aircraft);
    assertEquals("Names should be equal", aircraftName, aircraft.getName());
    assertNotNull(assertion, aircraft.getMassProps());
    assertNotNull(assertion, aircraft.getWingGeometry());
    assertNotNull(assertion, aircraft.getStabDerivs());
    assertNotNull(assertion, aircraft.getGroundReaction());
    assertNotNull(assertion, aircraft.getEngines());
    for (Engine engine : aircraft.getEngines()) {
        assertNotNull(assertion, engine);
    }
    aircraft.save();
    Aircraft readAircraft = FileUtilities.readAircraftConfiguration(aircraftName);
    assertion = "Deserialized property should not be null";
    assertNotNull(assertion, readAircraft);
    assertEquals("Names should be equal", aircraftName, readAircraft.getName());
    assertNotNull(assertion, readAircraft.getMassProps());
    assertNotNull(assertion, readAircraft.getWingGeometry());
    assertNotNull(assertion, readAircraft.getStabDerivs());
    assertNotNull(assertion, readAircraft.getGroundReaction());
    assertNotNull(assertion, readAircraft.getEngines());
    for (Engine engine : readAircraft.getEngines()) {
        assertNotNull(assertion, engine);
    }
}
Also used : Aircraft(com.chrisali.javaflightsim.simulation.aircraft.Aircraft) Engine(com.chrisali.javaflightsim.simulation.propulsion.Engine) Test(org.junit.Test)

Aggregations

Aircraft (com.chrisali.javaflightsim.simulation.aircraft.Aircraft)2 Engine (com.chrisali.javaflightsim.simulation.propulsion.Engine)2 Aerodynamics (com.chrisali.javaflightsim.simulation.aircraft.Aerodynamics)1 Test (org.junit.Test)1