1
0
Fork 0

Removed orphaned 10520d engine modeling code. Thanks goes to Phil

Schubert for getting the ball rolling with engine modeling in
flightgear.  The existing engine modeling code is derived from
his initial efforts.
This commit is contained in:
curt 2002-02-24 21:41:02 +00:00
parent c923f27f16
commit 3ca8643632
5 changed files with 0 additions and 1148 deletions

View file

@ -1,459 +0,0 @@
// Module: 10520c.c
// Author: Phil Schubert
// Date started: 12/03/99
// Purpose: Models a Continental IO-520-M Engine
// Called by: FGSimExec
//
// Copyright (C) 1999 Philip L. Schubert (philings@ozemail.com.au)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
// Further information about the GNU General Public License can also
// be found on the world wide web at http://www.gnu.org.
//
// FUNCTIONAL DESCRIPTION
// ------------------------------------------------------------------------
// Models a Continental IO-520-M engine. This engine is used in Cessna
// 210, 310, Beechcraft Bonaza and Baron C55. The equations used below
// were determined by a first and second order curve fits using Excel.
// The data is from the Cessna Aircraft Corporations Engine and Flight
// Computer for C310. Part Number D3500-13
//
// ARGUMENTS
// ------------------------------------------------------------------------
//
//
// HISTORY
// ------------------------------------------------------------------------
// 12/03/99 PLS Created
// 07/03/99 PLS Added Calculation of Density, and Prop_Torque
// 07/03/99 PLS Restructered Variables to allow easier implementation
// of Classes
// 15/03/99 PLS Added Oil Pressure, Oil Temperature and CH Temp
// ------------------------------------------------------------------------
// INCLUDES
// ------------------------------------------------------------------------
#include <simgear/compiler.h>
#include <iostream>
#include <math.h>
#include "10520d.hxx"
SG_USING_STD(cout);
SG_USING_STD(endl);
// ------------------------------------------------------------------------
// CODE
// ------------------------------------------------------------------------
// Calculate Engine RPM based on Propellor Lever Position
float FGEngine::Calc_Engine_RPM (float LeverPosition)
{
// Calculate RPM as set by Prop Lever Position. Assumes engine
// will run at 1000 RPM at full course
float RPM = LeverPosition * (Max_RPM - Min_RPM) /100 + Min_RPM ;
if ( RPM >= Max_RPM ) {
RPM = Max_RPM;
}
return RPM;
}
// Calculate Manifold Pressure based on Throttle lever Position
static float Calc_Manifold_Pressure ( float LeverPosn, float MaxMan)
{
float Inches;
// if ( x < = 0 ) {
// x = 0.00001;
// }
Inches = LeverPosn * MaxMan / 100;
return Inches;
}
// set initial default values
void FGEngine::init() {
// Control and environment inputs
IAS = 0;
Throttle_Lever_Pos = 75;
Propeller_Lever_Pos = 75;
Mixture_Lever_Pos = 100;
// Engine Specific Variables used by this program that have limits.
// Will be set in a parameter file to be read in to create
// and instance for each engine.
Max_Manifold_Pressure = 29.50;
Max_RPM = 2700;
Min_RPM = 1000;
Max_Fuel_Flow = 130;
Mag_Derate_Percent = 5;
MaxHP = 285;
Gear_Ratio = 1;
// Initialise Engine Variables used by this instance
Percentage_Power = 0;
Manifold_Pressure = 29.00; // Inches
RPM = 500;
Fuel_Flow = 0; // lbs/hour
Torque = 0;
CHT = 370;
Mixture = 14;
Oil_Pressure = 0; // PSI
Oil_Temp = 85; // Deg C
HP = 0;
RPS = 0;
Torque_Imbalance = 0;
Desired_RPM = 0;
// Initialise Propellor Variables used by this instance
FGProp1_Angular_V = 0;
FGProp1_Coef_Drag = 0.6;
FGProp1_Torque = 0;
FGProp1_Thrust = 0;
FGProp1_RPS = 0;
FGProp1_Coef_Lift = 0.1;
Alpha1 = 13.5;
FGProp1_Blade_Angle = 13.5;
FGProp_Fine_Pitch_Stop = 13.5;
FGProp_Course_Pitch_Stop = 55;
// Other internal values
Rho = 0.002378;
}
// Calculate Oil Pressure
static float Oil_Press (float Oil_Temp, float Engine_RPM)
{
float Oil_Pressure = 0; //PSI
float Oil_Press_Relief_Valve = 60; //PSI
float Oil_Press_RPM_Max = 1800;
float Design_Oil_Temp = 85; //Celsius
float Oil_Viscosity_Index = 0.25; // PSI/Deg C
float Temp_Deviation = 0; // Deg C
Oil_Pressure = (Oil_Press_Relief_Valve / Oil_Press_RPM_Max) * Engine_RPM;
// Pressure relief valve opens at Oil_Press_Relief_Valve PSI setting
if (Oil_Pressure >= Oil_Press_Relief_Valve)
{
Oil_Pressure = Oil_Press_Relief_Valve;
}
// Now adjust pressure according to Temp which affects the viscosity
Oil_Pressure += (Design_Oil_Temp - Oil_Temp) * Oil_Viscosity_Index;
return Oil_Pressure;
}
// Calculate Cylinder Head Temperature
static float Calc_CHT (float Fuel_Flow, float Mixture, float IAS)
{
float CHT = 350;
return CHT;
}
// Calculate Density Ratio
static float Density_Ratio ( float x )
{
float y = ((3E-10 * x * x) - (3E-05 * x) + 0.9998);
return y;
}
// Calculate Air Density - Rho
static float Density ( float x )
{
float y = ((9E-08 * x * x) - (7E-08 * x) + 0.0024);
return y;
}
// Calculate Speed in FPS given Knots CAS
static float IAS_to_FPS (float ias)
{
return ias * 1.68888888;
}
// update the engine model based on current control positions
void FGEngine::update() {
// Declare local variables
int num = 0; // Not used. Counting variables
int num2 = 100; // Not used.
float ManXRPM = 0;
float Vo = 0;
float V1 = 0;
// Set up the new variables
float Blade_Station = 30;
float Rho = 0.002378;
float FGProp_Area = 1.405/3;
float PI = 3.1428571;
// Input Variables
// float IAS = 0;
// 0 = Closed, 100 = Fully Open
// float Throttle_Lever_Pos = 75;
// 0 = Full Course 100 = Full Fine
// float Propeller_Lever_Pos = 75;
// 0 = Idle Cut Off 100 = Full Rich
// float Mixture_Lever_Pos = 100;
// Environmental Variables
// Temp Variation from ISA (Deg F)
float FG_ISA_VAR = 0;
// Pressure Altitude 1000's of Feet
float FG_Pressure_Ht = 0;
// Parameters that alter the operation of the engine.
// Yes = 1. Is there Fuel Available. Calculated elsewhere
int Fuel_Available = 1;
// Off = 0. Reduces power by 3 % for same throttle setting
int Alternate_Air_Pos =0;
// 1 = On. Reduces power by 5 % for same power lever settings
int Magneto_Left = 1;
// 1 = On. Ditto, Both of the above though do not alter fuel flow
int Magneto_Right = 1;
// There needs to be a section in here to trap silly values, like
// 0, otherwise they will crash the calculations
// cout << " Number of Iterations ";
// cin >> num2;
// cout << endl;
// cout << " Throttle % ";
// cin >> Throttle_Lever_Pos;
// cout << endl;
// cout << " Prop % ";
// cin >> Propeller_Lever_Pos;
// cout << endl;
//==================================================================
// Engine & Environmental Inputs from elsewhere
// Calculate Air Density (Rho) - In FG this is calculated in
// FG_Atomoshere.cxx
Rho = Density(FG_Pressure_Ht); // In FG FG_Pressure_Ht is "h"
// cout << "Rho = " << Rho << endl;
// Calculate Manifold Pressure (Engine 1) as set by throttle opening
Manifold_Pressure =
Calc_Manifold_Pressure( Throttle_Lever_Pos, Max_Manifold_Pressure );
cout << "manifold pressure = " << Manifold_Pressure << endl;
RPM = Calc_Engine_RPM(Propeller_Lever_Pos);
// cout << "Engine RPM = " << RPM << endl;
Desired_RPM = RPM;
cout << "Desired RPM = " << Desired_RPM << endl;
//==================================================================
// Engine Power & Torque Calculations
// Loop until stable - required for testing only
for (num = 0; num < num2; num++) {
// cout << endl << "====================" << endl;
// cout << "MP Inches = " << Manifold_Pressure << "\t";
// cout << " RPM = " << RPM << "\t";
// For a given Manifold Pressure and RPM calculate the % Power
// Multiply Manifold Pressure by RPM
ManXRPM = Manifold_Pressure * RPM;
// cout << ManXRPM << endl;
// Calculate % Power
Percentage_Power = (+ 7E-09 * ManXRPM * ManXRPM)
+ ( + 7E-04 * ManXRPM) - 0.1218;
// cout << "percent power = " << Percentage_Power << "%" << "\t";
// Adjust for Temperature - Temperature above Standard decrease
// power % by 7/120 per degree F increase, and incease power for
// temps below at the same ratio
Percentage_Power = Percentage_Power - (FG_ISA_VAR * 7 /120);
// cout << " adjusted T = " << Percentage_Power << "%" << "\t";
// Adjust for Altitude. In this version a linear variation is
// used. Decrease 1% for each 1000' increase in Altitde
Percentage_Power = Percentage_Power + (FG_Pressure_Ht * 12/10000);
// cout << " adjusted A = " << Percentage_Power << "%" << "\t";
// Now Calculate Fuel Flow based on % Power Best Power Mixture
Fuel_Flow = Percentage_Power * Max_Fuel_Flow / 100.0;
// cout << Fuel_Flow << " lbs/hr"<< endl;
// Now Derate engine for the effects of Bad/Switched off magnetos
if (Magneto_Left == 0 && Magneto_Right == 0) {
// cout << "Both OFF\n";
Percentage_Power = 0;
} else if (Magneto_Left && Magneto_Right) {
// cout << "Both On ";
} else if (Magneto_Left == 0 || Magneto_Right== 0) {
// cout << "1 Magneto Failed ";
Percentage_Power = Percentage_Power *
((100.0 - Mag_Derate_Percent)/100.0);
}
// cout << "Final engine % power = " << Percentage_Power << "%" << endl;
// Calculate Engine Horsepower
HP = Percentage_Power * MaxHP / 100.0;
// Calculate Engine Torque
Torque = HP * 5252 / RPM;
// cout << Torque << "Ft/lbs" << "\t";
// Calculate Cylinder Head Temperature
CHT = Calc_CHT( Fuel_Flow, Mixture, IAS);
// cout << "Cylinder Head Temp (F) = " << CHT << endl;
// Calculate Oil Pressure
Oil_Pressure = Oil_Press( Oil_Temp, RPM );
// cout << "Oil Pressure (PSI) = " << Oil_Pressure << endl;
//==============================================================
// Now do the Propellor Calculations
// Revs per second
FGProp1_RPS = RPM * Gear_Ratio / 60.0;
// cout << FGProp1_RPS << " RPS" << endl;
//Radial Flow Vector (V2) Ft/sec at Ref Blade Station (usually 30")
FGProp1_Angular_V = FGProp1_RPS * 2 * PI * (Blade_Station / 12);
// cout << "Angular Velocity " << FGProp1_Angular_V << endl;
// Axial Flow Vector (Vo) Ft/sec
// Some further work required here to allow for inflow at low speeds
// Vo = (IAS + 20) * 1.688888;
Vo = IAS_to_FPS(IAS + 20);
// cout << "Feet/sec = " << Vo << endl;
// cout << Vo << "Axial Velocity" << endl;
// Relative Velocity (V1)
V1 = sqrt((FGProp1_Angular_V * FGProp1_Angular_V) +
(Vo * Vo));
// cout << "Relative Velocity " << V1 << endl;
if ( FGProp1_Blade_Angle >= FGProp_Course_Pitch_Stop ) {
FGProp1_Blade_Angle = FGProp_Course_Pitch_Stop;
}
// cout << FGProp1_Blade_Angle << " Prop Blade Angle" << endl;
// Blade Angle of Attack (Alpha1)
Alpha1 = FGProp1_Blade_Angle -(atan(Vo / FGProp1_Angular_V) * (180/PI));
// cout << Alpha1 << " Alpha1" << endl;
// cout << " Alpha1 = " << Alpha1
// << " Blade angle = " << FGProp1_Blade_Angle
// << " Vo = " << Vo
// << " FGProp1_Angular_V = " << FGProp1_Angular_V << endl;
// Calculate Coefficient of Drag at Alpha1
FGProp1_Coef_Drag = (0.0005 * (Alpha1 * Alpha1)) + (0.0003 * Alpha1)
+ 0.0094;
// cout << FGProp1_Coef_Drag << " Coef Drag" << endl;
// Calculate Coefficient of Lift at Alpha1
FGProp1_Coef_Lift = -(0.0026 * (Alpha1 * Alpha1)) + (0.1027 * Alpha1)
+ 0.2295;
// cout << FGProp1_Coef_Lift << " Coef Lift " << endl;
// Covert Alplha1 to Radians
// Alpha1 = Alpha1 * PI / 180;
// Calculate Prop Torque
FGProp1_Torque = (0.5 * Rho * (V1 * V1) * FGProp_Area
* ((FGProp1_Coef_Lift * sin(Alpha1 * PI / 180))
+ (FGProp1_Coef_Drag * cos(Alpha1 * PI / 180))))
* (Blade_Station/12);
// cout << "Prop Torque = " << FGProp1_Torque << endl;
// Calculate Prop Thrust
// cout << " V1 = " << V1 << " Alpha1 = " << Alpha1 << endl;
FGProp1_Thrust = 0.5 * Rho * (V1 * V1) * FGProp_Area
* ((FGProp1_Coef_Lift * cos(Alpha1 * PI / 180))
- (FGProp1_Coef_Drag * sin(Alpha1 * PI / 180)));
// cout << " Prop Thrust = " << FGProp1_Thrust << endl;
// End of Propeller Calculations
//==============================================================
Torque_Imbalance = FGProp1_Torque - Torque;
// cout << Torque_Imbalance << endl;
if (Torque_Imbalance > 20) {
RPM -= 14.5;
// FGProp1_RPM -= 25;
FGProp1_Blade_Angle -= 0.75;
}
if (FGProp1_Blade_Angle < FGProp_Fine_Pitch_Stop) {
FGProp1_Blade_Angle = FGProp_Fine_Pitch_Stop;
}
if (Torque_Imbalance < -20) {
RPM += 14.5;
// FGProp1_RPM += 25;
FGProp1_Blade_Angle += 0.75;
}
if (RPM >= 2700) {
RPM = 2700;
}
// cout << FGEng1_RPM << " Blade_Angle " << FGProp1_Blade_Angle << endl << endl;
}
}
// Functions
// Calculate Oil Temperature
static float Oil_Temp (float Fuel_Flow, float Mixture, float IAS)
{
float Oil_Temp = 85;
return (Oil_Temp);
}

View file

@ -1,142 +0,0 @@
// Module: 10520c.c
// Author: Phil Schubert
// Date started: 12/03/99
// Purpose: Models a Continental IO-520-M Engine
// Called by: FGSimExec
//
// Copyright (C) 1999 Philip L. Schubert (philings@ozemail.com.au)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
// Further information about the GNU General Public License can also
// be found on the world wide web at http://www.gnu.org.
//
// FUNCTIONAL DESCRIPTION
// ------------------------------------------------------------------------
// Models a Continental IO-520-M engine. This engine is used in Cessna
// 210, 310, Beechcraft Bonaza and Baron C55. The equations used below
// were determined by a first and second order curve fits using Excel.
// The data is from the Cessna Aircraft Corporations Engine and Flight
// Computer for C310. Part Number D3500-13
//
// ARGUMENTS
// ------------------------------------------------------------------------
//
//
// HISTORY
// ------------------------------------------------------------------------
// 12/03/99 PLS Created
// 07/03/99 PLS Added Calculation of Density, and Prop_Torque
// 07/03/99 PLS Restructered Variables to allow easier implementation
// of Classes
// 15/03/99 PLS Added Oil Pressure, Oil Temperature and CH Temp
// ------------------------------------------------------------------------
// INCLUDES
// ------------------------------------------------------------------------
#ifndef _10520D_HXX_
#define _10520D_HXX_
#include <iostream>
#include <math.h>
class FGEngine {
private:
// Control and environment inputs
float IAS;
// 0 = Closed, 100 = Fully Open
float Throttle_Lever_Pos;
// 0 = Full Course 100 = Full Fine
float Propeller_Lever_Pos;
// 0 = Idle Cut Off 100 = Full Rich
float Mixture_Lever_Pos;
// Engine Specific Variables used by this program that have limits.
// Will be set in a parameter file to be read in to create
// and instance for each engine.
float Max_Manifold_Pressure;
float Max_RPM;
float Min_RPM;
float Max_Fuel_Flow;
float Mag_Derate_Percent;
float MaxHP;
float Gear_Ratio;
// Initialise Engine Variables used by this instance
float Percentage_Power;
float Manifold_Pressure; // Inches
float RPM;
float Fuel_Flow; // lbs/hour
float Torque;
float CHT;
float Mixture;
float Oil_Pressure; // PSI
float Oil_Temp; // Deg C
float HP;
float RPS;
float Torque_Imbalance;
float Desired_RPM;
// Initialise Propellor Variables used by this instance
float FGProp1_Angular_V;
float FGProp1_Coef_Drag;
float FGProp1_Torque;
float FGProp1_Thrust;
float FGProp1_RPS;
float FGProp1_Coef_Lift;
float Alpha1;
float FGProp1_Blade_Angle;
float FGProp_Fine_Pitch_Stop;
float FGProp_Course_Pitch_Stop;
// Other internal values
float Rho;
// Calculate Engine RPM based on Propellor Lever Position
float Calc_Engine_RPM (float Position);
public:
// set initial default values
void init();
// update the engine model based on current control positions
void update();
inline void set_IAS( float value ) { IAS = value; }
inline void set_Throttle_Lever_Pos( float value ) {
Throttle_Lever_Pos = value;
}
inline void set_Propeller_Lever_Pos( float value ) {
Propeller_Lever_Pos = value;
}
inline void set_Mixture_Lever_Pos( float value ) {
Mixture_Lever_Pos = value;
}
// accessors
inline float get_RPM() const { return RPM; }
inline float get_FGProp1_Thrust() const { return FGProp1_Thrust; }
inline float get_Rho() const { return Rho; }
};
#endif // _10520D_HXX_

View file

@ -53,14 +53,6 @@ libJSBSim_a_SOURCES = \
# noinst_PROGRAMS = testJSBsim
# testJSBsim_SOURCES = JSBSim.dcpp
# testJSBsim_LDADD = libJSBSim.a filtersjb/libfiltersjb.a
# demo_SOURCES = demo.cxx
# demo_LDADD = libJSBSim.a filtersjb/libfiltersjb.a
if OLD_AUTOMAKE
INCLUDES += -I$(top_srcdir) -I$(top_srcdir)/src
DEFS += -DFGFS

View file

@ -14,10 +14,6 @@ libFlight_a_SOURCES = \
MagicCarpet.cxx MagicCarpet.hxx \
NullFDM.cxx NullFDM.hxx
bin_PROGRAMS = pstest
pstest_SOURCES = ps-10520c.cxx
if OLD_AUTOMAKE
INCLUDES += -I$(top_srcdir) -I$(top_srcdir)/src
else

View file

@ -1,535 +0,0 @@
// Module: 10520c.c
// Author: Phil Schubert
// Date started: 12/03/99
// Purpose: Models a Continental IO-520-M Engine
// Called by: FGSimExec
//
// Copyright (C) 1999 Philip L. Schubert (philip@zedley.com)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
// Further information about the GNU General Public License can also
// be found on the world wide web at http://www.gnu.org.
//
// FUNCTIONAL DESCRIPTION
// ------------------------------------------------------------------------
// Models a Continental IO-520-M engine. This engine is used in Cessna
// 210, 310, Beechcraft Bonaza and Baron C55. The equations used below
// were determined by a first and second order curve fits using Excel.
// The data is from the Cessna Aircraft Corporations Engine and Flight
// Computer for C310. Part Number D3500-13
//
// ARGUMENTS
// ------------------------------------------------------------------------
//
//
// HISTORY
// ------------------------------------------------------------------------
// 12/03/99 PLS Created
// 07/03/99 PLS Added Calculation of Density, and Prop_Torque
// 07/03/99 PLS Restructered Variables to allow easier implementation
// of Classes
// 15/03/99 PLS Added Oil Pressure
// 19/8/2000 PLS Updated E-mail address - This version compiles
// 19/8/2000 PLS Set Max Prop blade angle to prevent prop exeeding 90
// ------------------------------------------------------------------------
// INCLUDES
// ------------------------------------------------------------------------
#include <simgear/compiler.h>
#include <math.h>
#include STL_IOSTREAM
#if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
SG_USING_STD(cout);
SG_USING_STD(endl);
#endif
// ------------------------------------------------------------------------
// CODE
// ------------------------------------------------------------------------
// prototype definitions
// These should be in a header file 10520c.h
float Density (float x);
void ShowRho (float x);
float IAS_to_FPS (float x);
void ShowFPS(float x);
float Get_Throttle (float x);
void Show_Throttle (float x);
float Manifold_Pressure (float x, float z);
void Show_Manifold_Pressure (float x);
float CHT (float Fuel_Flow, float Mixture, float IAS);
void Show_CHT (float x);
float Oil_Temp (float x, float y);
void Show_Oil_Temp (float x);
float Oil_Press (float Oil_Temp, float Engine_RPM);
void Show_Oil_Press (float x);
int main()
{
// Declare local variables
int num = 0; // Not used. Counting variables
int num2 = 100; // Not used.
float ManXRPM = 0;
float Vo = 0;
float V1 = 0;
// Set up the new variables
float Blade_Station = 30;
float Rho = 0.002378;
float FGProp_Area = 1.405/3;
float PI = 3.1428571;
// Input Variables
float IAS = 0;
cout << "Enter IAS ";
// cin >> IAS;
IAS = 85;
cout << endl;
// 0 = Closed, 100 = Fully Open
float FGEng1_Throttle_Lever_Pos = 75;
// 0 = Full Course 100 = Full Fine
float FGEng1_Propeller_Lever_Pos = 75;
// 0 = Idle Cut Off 100 = Full Rich
float FGEng1_Mixture_Lever_Pos = 100;
// Environmental Variables
// Temp Variation from ISA (Deg F)
float FG_ISA_VAR = 0;
// Pressure Altitude 1000's of Feet
float FG_Pressure_Ht = 0;
// Parameters that alter the operation of the engine.
// Yes = 1. Is there Fuel Available. Calculated elsewhere
int FGEng1_Fuel_Available = 1;
// Off = 0. Reduces power by 3 % for same throttle setting
int FGEng1_Alternate_Air_Pos =0;
// 1 = On. Reduces power by 5 % for same power lever settings
int FGEng1_Magneto_Left = 1;
// 1 = On. Ditto, Both of the above though do not alter fuel flow
int FGEng1_Magneto_Right = 1;
// There needs to be a section in here to trap silly values, like
// 0, otherwise they will crash the calculations
// Engine Specific Variables used by this program that have limits.
// Will be set in a parameter file to be read in to create
// and instance for each engine.
float FGEng_Max_Manifold_Pressure = 29.50;
float FGEng_Max_RPM = 2700;
float FGEng_Min_RPM = 1000;
float FGEng_Max_Fuel_Flow = 130;
float FGEng_Mag_Derate_Percent = 5;
float FGEng_MaxHP = 285;
float FGEng_Gear_Ratio = 1;
// Initialise Engine Variables used by this instance
float FGEng1_Percentage_Power = 0;
float FGEng1_Manifold_Pressure = 29.00; // Inches
float FGEng1_RPM = 500;
float FGEng1_Fuel_Flow = 0; // lbs/hour
float FGEng1_Torque = 0;
float FGEng1_CHT = 370;
float FGEng1_Mixture = 14;
float FGEng1_Oil_Pressure = 0; // PSI
float FGEng1_Oil_Temp = 85; // Deg C
float FGEng1_HP = 0;
float FGEng1_RPS = 0;
float Torque_Imbalance = 0;
float FGEng1_Desired_RPM = 0;
// Initialise Propellor Variables used by this instance
float FGProp1_Angular_V = 0;
float FGProp1_Coef_Drag = 0.6;
float FGProp1_Torque = 0;
float FGProp1_Thrust = 0;
float FGProp1_RPS = 0;
float FGProp1_Coef_Lift = 0.1;
float Alpha1 = 13.5;
float FGProp1_Blade_Angle = 13.5;
float FGProp_Fine_Pitch_Stop = 13.5;
float FGProp_Course_Pitch_Stop = 55;
// cout << "Enter Blade Angle ";
// cin >> FGProp1_Blade_Angle;
// cout << endl;
cout << " Number of Iterations ";
// cin >> num2;
num2 = 100;
cout << endl;
cout << " Throttle % ";
// cin >> FGEng1_Throttle_Lever_Pos;
FGEng1_Throttle_Lever_Pos = 50;
cout << endl;
cout << " Prop % ";
// cin >> FGEng1_Propeller_Lever_Pos;
FGEng1_Propeller_Lever_Pos = 100;
cout << endl;
//==================================================================
// Engine & Environmental Inputs from elsewhere
// Calculate Air Density (Rho) - In FG this is calculated in
// FG_Atomoshere.cxx
Rho = Density(FG_Pressure_Ht); // In FG FG_Pressure_Ht is "h"
ShowRho(Rho);
// Calculate Manifold Pressure (Engine 1) as set by throttle opening
FGEng1_Manifold_Pressure = Manifold_Pressure(FGEng1_Throttle_Lever_Pos,
FGEng1_Manifold_Pressure );
Show_Manifold_Pressure(FGEng1_Manifold_Pressure);
// Calculate Desired RPM as set by Prop Lever Position.
// Actual engine RPM may be different
// The governed max RPM at 100% Prop Lever Position = FGEng_MaxRPM
// The governed minimum RPM at 0% Prop Lever Position = FGEng_Min_RPM
// The actual minimum RPM of the engine can be < FGEng_Min_RPM if there is insufficient
// engine torque to counter act the propeller torque at FGProp_Fine_Pitch_Stop
FGEng1_RPM = (FGEng1_Propeller_Lever_Pos * (FGEng_Max_RPM - FGEng_Min_RPM) /100)
+ FGEng_Min_RPM ;
// * ((FGEng_Max_RPM + FGEng_Min_RPM) / 100);
if (FGEng1_RPM >= 2700) {
FGEng1_RPM = 2700;
}
FGEng1_Desired_RPM = FGEng1_RPM;
cout << "Desired RPM = " << FGEng1_Desired_RPM << endl;
//==================================================================
// Engine Power & Torque Calculations
// Loop until stable - required for testing only
for (num = 1; num < num2; num++) {
cout << endl << "====================" << endl;
cout << "MP Inches = " << FGEng1_Manifold_Pressure << "\t";
cout << FGEng1_RPM << " RPM" << "\t";
// For a givem Manifold Pressure and RPM calculate the % Power
// Multiply Manifold Pressure by RPM
ManXRPM = FGEng1_Manifold_Pressure * FGEng1_RPM;
cout << ManXRPM << endl;
// Calculate % Power
FGEng1_Percentage_Power = (+ 7E-09 * ManXRPM * ManXRPM)
+ ( + 7E-04 * ManXRPM) - 0.1218;
cout << "percent power = " << FGEng1_Percentage_Power << "%" << "\t";
// Adjust for Temperature - Temperature above Standard decrease
// power % by 7/120 per degree F increase, and incease power for
// temps below at the same ratio
FGEng1_Percentage_Power = FGEng1_Percentage_Power - (FG_ISA_VAR * 7 /120);
cout << " adjusted T = " << FGEng1_Percentage_Power << "%" << "\t";
// Adjust for Altitude. In this version a linear variation is
// used. Decrease 1% for each 1000' increase in Altitde
FGEng1_Percentage_Power = FGEng1_Percentage_Power
+ (FG_Pressure_Ht * 12/10000);
cout << " adjusted A = " << FGEng1_Percentage_Power << "%" << "\t";
// Now Calculate Fuel Flow based on % Power Best Power Mixture
FGEng1_Fuel_Flow = FGEng1_Percentage_Power
* FGEng_Max_Fuel_Flow / 100;
// cout << FGEng1_Fuel_Flow << " lbs/hr"<< endl;
// Now Derate engine for the effects of Bad/Switched off magnetos
if (FGEng1_Magneto_Left == 0 && FGEng1_Magneto_Right == 0) {
// cout << "Both OFF\n";
FGEng1_Percentage_Power = 0;
} else if (FGEng1_Magneto_Left && FGEng1_Magneto_Right) {
// cout << "Both On ";
} else if (FGEng1_Magneto_Left == 0 || FGEng1_Magneto_Right== 0) {
// cout << "1 Magneto Failed ";
FGEng1_Percentage_Power = FGEng1_Percentage_Power *
((100 - FGEng_Mag_Derate_Percent)/100);
// cout << FGEng1_Percentage_Power << "%" << "\t";
}
// Calculate Engine Horsepower
FGEng1_HP = FGEng1_Percentage_Power * FGEng_MaxHP/100;
// Calculate Engine Torque
FGEng1_Torque = FGEng1_HP * 5252 / FGEng1_RPM;
cout << FGEng1_Torque << "Ft/lbs" << "\t";
// Calculate Cylinder Head Temperature
FGEng1_CHT = CHT (FGEng1_Fuel_Flow, FGEng1_Mixture, IAS);
// Show_CHT (FGEng1_CHT);
// Calculate Oil Pressure
FGEng1_Oil_Pressure = Oil_Press (FGEng1_Oil_Temp, FGEng1_RPM);
// Show_Oil_Press(FGEng1_Oil_Pressure);
//==============================================================
// Now do the Propellor Calculations
// Revs per second
FGProp1_RPS = FGEng1_RPM * FGEng_Gear_Ratio/60;
// cout << FGProp1_RPS << " RPS" << endl;
//Radial Flow Vector (V2) Ft/sec at Ref Blade Station (usually 30")
FGProp1_Angular_V = FGProp1_RPS * 2 * PI * (Blade_Station / 12);
cout << "Angular Velocity " << FGProp1_Angular_V << endl;
// Axial Flow Vector (Vo) Ft/sec
// Some further work required here to allow for inflow at low speeds
// Vo = (IAS + 20) * 1.688888;
Vo = IAS_to_FPS(IAS + 20);
// ShowFPS ( Vo );
// cout << Vo << "Axial Velocity" << endl;
// Relative Velocity (V1)
V1 = sqrt((FGProp1_Angular_V * FGProp1_Angular_V) +
(Vo * Vo));
cout << "Relative Velocity " << V1 << endl;
if ( FGProp1_Blade_Angle >= FGProp_Course_Pitch_Stop ) {
FGProp1_Blade_Angle = FGProp_Course_Pitch_Stop;
}
cout << FGProp1_Blade_Angle << " Prop Blade Angle" << endl;
// Blade Angle of Attack (Alpha1)
Alpha1 = FGProp1_Blade_Angle -(atan(Vo / FGProp1_Angular_V) * (180/PI));
// cout << Alpha1 << " Alpha1" << endl;
cout << " Alpha1 = " << Alpha1
<< " Blade angle = " << FGProp1_Blade_Angle
<< " Vo = " << Vo
<< " FGProp1_Angular_V = " << FGProp1_Angular_V << endl;
// Calculate Coefficient of Drag at Alpha1
FGProp1_Coef_Drag = (0.0005 * (Alpha1 * Alpha1)) + (0.0003 * Alpha1)
+ 0.0094;
// cout << FGProp1_Coef_Drag << " Coef Drag" << endl;
// Calculate Coefficient of Lift at Alpha1
FGProp1_Coef_Lift = -(0.0026 * (Alpha1 * Alpha1)) + (0.1027 * Alpha1)
+ 0.2295;
// cout << FGProp1_Coef_Lift << " Coef Lift " << endl;
// Covert Alplha1 to Radians
// Alpha1 = Alpha1 * PI / 180;
// Calculate Prop Torque
FGProp1_Torque = (0.5 * Rho * (V1 * V1) * FGProp_Area
* ((FGProp1_Coef_Lift * sin(Alpha1 * PI / 180))
+ (FGProp1_Coef_Drag * cos(Alpha1 * PI / 180))))
* (Blade_Station/12);
cout << "Prop Torque = " << FGProp1_Torque << endl;
// Calculate Prop Thrust
FGProp1_Thrust = 0.5 * Rho * (V1 * V1) * FGProp_Area
* ((FGProp1_Coef_Lift * cos(Alpha1 * PI / 180))
- (FGProp1_Coef_Drag * sin(Alpha1 * PI / 180)));
cout << " Prop Thrust = " << FGProp1_Thrust << endl;
// End of Propeller Calculations
//==============================================================
Torque_Imbalance = FGProp1_Torque - FGEng1_Torque;
// cout << Torque_Imbalance << endl;
if (Torque_Imbalance > 20) {
FGEng1_RPM -= 14.5;
// FGProp1_RPM -= 25;
FGProp1_Blade_Angle -= 0.75;
}
if (FGProp1_Blade_Angle < FGProp_Fine_Pitch_Stop) {
FGProp1_Blade_Angle = FGProp_Fine_Pitch_Stop;
}
if (Torque_Imbalance < -20) {
FGEng1_RPM += 14.5;
// FGProp1_RPM += 25;
FGProp1_Blade_Angle += 0.75;
}
if (FGEng1_RPM >= 2700) {
FGEng1_RPM = 2700;
}
// cout << FGEng1_RPM << " Blade_Angle " << FGProp1_Blade_Angle << endl << endl;
}
return (0);
}
// Functions
// Calculate Air Density - Rho
float Density ( float x )
{
float y ;
y = ((9E-08 * x * x) - (7E-08 * x) + 0.0024);
return(y);
}
// Show Air Density Calculations
void ShowRho (float x)
{
cout << "Rho = ";
cout << x << endl;
}
// Calculate Speed in FPS given Knots CAS
float IAS_to_FPS (float x)
{
float y;
y = x * 1.68888888;
return (y);
}
// Show Feet per Second
void ShowFPS (float x)
{
cout << "Feet/sec = ";
cout << x << endl;
}
// Calculate Manifold Pressure based on Throttle lever Position
float Manifold_Pressure ( float x, float z)
{
float y;
// if ( x < = 0 )
// {
// x = 0.00001;
// }
y = x * z / 100;
return (y);
}
// Show Manifold Pressure
void Show_Manifold_Pressure (float x)
{
cout << "Manifold Pressure = ";
cout << x << endl;
}
// Calculate Oil Temperature
float Oil_Temp (float Fuel_Flow, float Mixture, float IAS)
{
float Oil_Temp = 85;
return (Oil_Temp);
}
// Show Oil Temperature
void Show_Oil_Temp (float x)
{
cout << "Oil Temperature (F) = ";
cout << x << endl;
}
// Calculate Oil Pressure
float Oil_Press (float Oil_Temp, float Engine_RPM)
{
float Oil_Pressure = 0; //PSI
float Oil_Press_Relief_Valve = 60; //PSI
float Oil_Press_RPM_Max = 1800;
float Design_Oil_Temp = 85; //Celsius
float Oil_Viscosity_Index = 0.25; // PSI/Deg C
float Temp_Deviation = 0; // Deg C
Oil_Pressure = (Oil_Press_Relief_Valve / Oil_Press_RPM_Max) * Engine_RPM;
// Pressure relief valve opens at Oil_Press_Relief_Valve PSI setting
if (Oil_Pressure >= Oil_Press_Relief_Valve)
{
Oil_Pressure = Oil_Press_Relief_Valve;
}
// Now adjust pressure according to Temp which affects the viscosity
Oil_Pressure += (Design_Oil_Temp - Oil_Temp) * Oil_Viscosity_Index;
return (Oil_Pressure);
}
// Show Oil Pressure
void Show_Oil_Press (float x)
{
cout << "Oil Pressure (PSI) = ";
cout << x << endl;
}
// Calculate Cylinder Head Temperature
float CHT (float Fuel_Flow, float Mixture, float IAS)
{
float CHT = 350;
return (CHT);
}
// Show Cyl Head Temperature
void Show_CHT (float x)
{
cout << "CHT (F) = ";
cout << x << endl;
}