![]() |
JSBSim Flight Dynamics Model 1.0 (23 February 2013)
An Open Source Flight Dynamics and Control Software Library in C++
|
FGPropeller models a propeller given the tabular data for Ct and Cp, indexed by the advance ratio "J". More...
#include <FGPropeller.h>
Inheritance diagram for FGPropeller:
Collaboration diagram for FGPropeller:Public Member Functions | |
| FGPropeller (FGFDMExec *exec, Element *el, int num=0) | |
| Constructor for FGPropeller. | |
| ~FGPropeller () | |
| Destructor for FGPropeller - deletes the FGTable objects. | |
| double | Calculate (double EnginePower) |
| Calculates and returns the thrust produced by this propeller. | |
| int | GetConstantSpeed (void) const |
| double | GetCpFactor (void) const |
| Retrieves the coefficient of power multiplier. | |
| FGTable * | GetCpMachTable (void) const |
| Retrieves propeller power Mach effects factor. | |
| FGTable * | GetCPowerTable (void) const |
| Retrieves propeller power table. | |
| double | GetCtFactor (void) const |
| Retrieves the coefficient of thrust multiplier. | |
| FGTable * | GetCThrustTable (void) const |
| Retrieves propeller thrust table. | |
| FGTable * | GetCtMachTable (void) const |
| Retrieves propeller thrust Mach effects factor. | |
| double | GetDiameter (void) const |
| Retrieves the propeller diameter. | |
| double | GetEngineRPM (void) const |
| Calculates the RPMs of the engine based on gear ratio. | |
| bool | GetFeather (void) const |
| double | GetHelicalTipMach (void) const |
| double | GetInducedVelocity (void) const |
| double | GetIxx (void) const |
| Retrieves the propeller moment of inertia. | |
| FGColumnVector3 | GetPFactor (void) const |
| double | GetPitch (void) const |
| Retrieves the pitch of the propeller in degrees. | |
| double | GetPowerRequired (void) |
| Retrieves the power required (or "absorbed") by the propeller - i.e. | |
| bool | GetReverse (void) const |
| double | GetReverseCoef (void) const |
| double | GetRPM (void) const |
| Retrieves the RPMs of the propeller. | |
| double | GetThrustCoefficient (void) const |
| string | GetThrusterLabels (int id, const string &delimeter) |
| string | GetThrusterValues (int id, const string &delimeter) |
| double | GetTorque (void) const |
| Retrieves the Torque in foot-pounds (Don't you love the English system?) | |
| bool | IsVPitch (void) const |
| Returns true of this propeller is variable pitch. | |
| void | SetAdvance (double advance) |
| void | SetConstantSpeed (int mode) |
| Sets propeller into constant speed mode, or manual pitch mode. | |
| void | SetCpFactor (double cpf) |
| Sets coefficient of power multiplier. | |
| void | SetCtFactor (double ctf) |
| Sets coefficient of thrust multiplier. | |
| void | SetEngineRPM (double rpm) |
| Sets the Revolutions Per Minute for the propeller using the engine gear ratio. | |
| void | SetFeather (bool f) |
| void | SetInducedVelocity (double Vi) |
| void | SetPFactor (double pf) |
| Sets the P-Factor constant. | |
| void | SetPitch (double pitch) |
| This commands the pitch of the blade to change to the value supplied. | |
| void | SetReverse (bool r) |
| void | SetReverseCoef (double c) |
| void | SetRPM (double rpm) |
| Sets the Revolutions Per Minute for the propeller. | |
| void | SetSense (double s) |
| Sets the rotation sense of the propeller. | |
<sense> {1 | -1} </sense>
<propeller name="{string}">
<ixx> {number} </ixx>
<diameter unit="IN"> {number} </diameter>
<numblades> {number} </numblades>
<gearratio> {number} </gearratio>
<minpitch> {number} </minpitch>
<maxpitch> {number} </maxpitch>
<minrpm> {number} </minrpm>
<maxrpm> {number} </maxrpm>
<constspeed> {number} </constspeed>
<reversepitch> {number} </reversepitch>
<p_factor> {number} </p_factor>
<ct_factor> {number} </ct_factor>
<cp_factor> {number} </cp_factor>
<table name="C_THRUST" type="internal">
<tableData>
{numbers}
</tableData>
</table>
<table name="C_POWER" type="internal">
<tableData>
{numbers}
</tableData>
</table>
<table name="CT_MACH" type="internal">
<tableData>
{numbers}
</tableData>
</table>
<table name="CP_MACH" type="internal">
<tableData>
{numbers}
</tableData>
</table>
</propeller>
<ixx> - Propeller rotational inertia.
<diameter> - Propeller disk diameter.
<numblades> - Number of blades.
<gearratio> - Ratio of (engine rpm) / (prop rpm).
<minpitch> - Minimum blade pitch angle.
<maxpitch> - Maximum blade pitch angle.
<minrpm> - Minimum rpm target for constant speed propeller.
<maxrpm> - Maximum rpm target for constant speed propeller.
<constspeed> - 1 = constant speed mode, 0 = manual pitch mode.
<reversepitch> - Blade pitch angle for reverse.
<sense> - Direction of rotation (1=clockwise as viewed from cockpit,
-1=anti-clockwise as viewed from cockpit). Sense is
specified in the parent tag of the propeller.
<p_factor> - P factor.
<ct_factor> - A multiplier for the coefficients of thrust.
<cp_factor> - A multiplier for the coefficients of power.
Two tables are needed. One for coefficient of thrust (Ct) and one for coefficient of power (Cp).
Two tables are optional. They apply a factor to Ct and Cp based on the helical tip Mach.
Several references were helpful, here:
Definition at line 154 of file FGPropeller.h.
| FGPropeller | ( | FGFDMExec * | exec, |
| Element * | el, | ||
| int | num = 0 |
||
| ) |
| exec | a pointer to the main executive object |
| el | a pointer to the thruster config file XML element |
| num | the number of this propeller |
Definition at line 60 of file FGPropeller.cpp.
References Element::FindElement(), Element::FindElementValueAsNumber(), Element::FindElementValueAsNumberConvertTo(), Element::FindNextElement(), Element::GetAttributeValue(), Element::GetDataAsNumber(), FGPropeller::GetEngineRPM(), Element::GetParent(), FGFDMExec::GetPropertyManager(), FGPropeller::GetRPM(), FGPropeller::SetConstantSpeed(), FGPropeller::SetCpFactor(), FGPropeller::SetCtFactor(), FGPropeller::SetSense(), and FGPropertyManager::Tie().
: FGThruster(exec, prop_element, num) { string token; Element *table_element, *local_element; string name=""; FGPropertyManager* PropertyManager = exec->GetPropertyManager(); MaxPitch = MinPitch = P_Factor = Pitch = Advance = MinRPM = MaxRPM = 0.0; Sense = 1; // default clockwise rotation ReversePitch = 0.0; Reversed = false; Feathered = false; Reverse_coef = 0.0; GearRatio = 1.0; CtFactor = CpFactor = 1.0; ConstantSpeed = 0; cThrust = cPower = CtMach = CpMach = 0; Vinduced = 0.0; if (prop_element->FindElement("ixx")) Ixx = prop_element->FindElementValueAsNumberConvertTo("ixx", "SLUG*FT2"); if (prop_element->FindElement("diameter")) Diameter = prop_element->FindElementValueAsNumberConvertTo("diameter", "FT"); if (prop_element->FindElement("numblades")) numBlades = (int)prop_element->FindElementValueAsNumber("numblades"); if (prop_element->FindElement("gearratio")) GearRatio = prop_element->FindElementValueAsNumber("gearratio"); if (prop_element->FindElement("minpitch")) MinPitch = prop_element->FindElementValueAsNumber("minpitch"); if (prop_element->FindElement("maxpitch")) MaxPitch = prop_element->FindElementValueAsNumber("maxpitch"); if (prop_element->FindElement("minrpm")) MinRPM = prop_element->FindElementValueAsNumber("minrpm"); if (prop_element->FindElement("maxrpm")) { MaxRPM = prop_element->FindElementValueAsNumber("maxrpm"); ConstantSpeed = 1; } if (prop_element->FindElement("constspeed")) ConstantSpeed = (int)prop_element->FindElementValueAsNumber("constspeed"); if (prop_element->FindElement("reversepitch")) ReversePitch = prop_element->FindElementValueAsNumber("reversepitch"); while((table_element = prop_element->FindNextElement("table")) != 0) { name = table_element->GetAttributeValue("name"); try { if (name == "C_THRUST") { cThrust = new FGTable(PropertyManager, table_element); } else if (name == "C_POWER") { cPower = new FGTable(PropertyManager, table_element); } else if (name == "CT_MACH") { CtMach = new FGTable(PropertyManager, table_element); } else if (name == "CP_MACH") { CpMach = new FGTable(PropertyManager, table_element); } else { cerr << "Unknown table type: " << name << " in propeller definition." << endl; } } catch (std::string str) { throw("Error loading propeller table:" + name + ". " + str); } } if( (cPower == 0) || (cThrust == 0)){ cerr << "Propeller configuration must contain C_THRUST and C_POWER tables!" << endl; } local_element = prop_element->GetParent()->FindElement("sense"); if (local_element) { double Sense = local_element->GetDataAsNumber(); SetSense(Sense >= 0.0 ? 1.0 : -1.0); } local_element = prop_element->GetParent()->FindElement("p_factor"); if (local_element) { P_Factor = local_element->GetDataAsNumber(); } if (P_Factor < 0) { cerr << "P-Factor value in propeller configuration file must be greater than zero" << endl; } if (prop_element->FindElement("ct_factor")) SetCtFactor( prop_element->FindElementValueAsNumber("ct_factor") ); if (prop_element->FindElement("cp_factor")) SetCpFactor( prop_element->FindElementValueAsNumber("cp_factor") ); Type = ttPropeller; RPM = 0; vTorque.InitMatrix(); D4 = Diameter*Diameter*Diameter*Diameter; D5 = D4*Diameter; Pitch = MinPitch; string property_name, base_property_name; base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNum); property_name = base_property_name + "/engine-rpm"; PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetEngineRPM ); property_name = base_property_name + "/advance-ratio"; PropertyManager->Tie( property_name.c_str(), &J ); property_name = base_property_name + "/blade-angle"; PropertyManager->Tie( property_name.c_str(), &Pitch ); property_name = base_property_name + "/thrust-coefficient"; PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetThrustCoefficient ); property_name = base_property_name + "/propeller-rpm"; PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetRPM ); property_name = base_property_name + "/helical-tip-Mach"; PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetHelicalTipMach ); property_name = base_property_name + "/constant-speed-mode"; PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetConstantSpeed, &FGPropeller::SetConstantSpeed ); property_name = base_property_name + "/prop-induced-velocity_fps"; PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetInducedVelocity, &FGPropeller::SetInducedVelocity ); Debug(0); }
Here is the call graph for this function:| double Calculate | ( | double | EnginePower | ) | [virtual] |
Given the excess power available from the engine (in foot-pounds), the thrust is calculated, as well as the current RPM. The RPM is calculated by integrating the torque provided by the engine over what the propeller "absorbs" (essentially the "drag" of the propeller).
| PowerAvailable | this is the excess power provided by the engine to accelerate the prop. It could be negative, dictating that the propeller would be slowed. |
Reimplemented from FGThruster.
Definition at line 195 of file FGPropeller.cpp.
References FGPropeller::GetPowerRequired(), FGColumnVector3::Magnitude(), and FGMatrix33::Transposed().
{
FGColumnVector3 localAeroVel = Transform().Transposed() * in.AeroUVW;
double omega, PowerAvailable;
double Vel = localAeroVel(eU);
double rho = in.Density;
double RPS = RPM/60.0;
// Calculate helical tip Mach
double Area = 0.25*Diameter*Diameter*M_PI;
double Vtip = RPS * Diameter * M_PI;
HelicalTipMach = sqrt(Vtip*Vtip + Vel*Vel) / in.Soundspeed;
PowerAvailable = EnginePower - GetPowerRequired();
if (RPS > 0.0) J = Vel / (Diameter * RPS); // Calculate J normally
else J = Vel / Diameter;
if (MaxPitch == MinPitch) { // Fixed pitch prop
ThrustCoeff = cThrust->GetValue(J);
} else { // Variable pitch prop
ThrustCoeff = cThrust->GetValue(J, Pitch);
}
// Apply optional scaling factor to Ct (default value = 1)
ThrustCoeff *= CtFactor;
// Apply optional Mach effects from CT_MACH table
if (CtMach) ThrustCoeff *= CtMach->GetValue(HelicalTipMach);
Thrust = ThrustCoeff*RPS*RPS*D4*rho;
// Induced velocity in the propeller disk area. This formula is obtained
// from momentum theory - see B. W. McCormick, "Aerodynamics, Aeronautics,
// and Flight Mechanics" 1st edition, eqn. 6.15 (propeller analysis chapter).
// Since Thrust and Vel can both be negative we need to adjust this formula
// To handle sign (direction) separately from magnitude.
double Vel2sum = Vel*abs(Vel) + 2.0*Thrust/(rho*Area);
if( Vel2sum > 0.0)
Vinduced = 0.5 * (-Vel + sqrt(Vel2sum));
else
Vinduced = 0.5 * (-Vel - sqrt(-Vel2sum));
// We need to drop the case where the downstream velocity is opposite in
// direction to the aircraft velocity. For example, in such a case, the
// direction of the airflow on the tail would be opposite to the airflow on
// the wing tips. When such complicated airflows occur, the momentum theory
// breaks down and the formulas above are no longer applicable
// (see H. Glauert, "The Elements of Airfoil and Airscrew Theory",
// 2nd edition, ยง16.3, pp. 219-221)
if ((Vel+2.0*Vinduced)*Vel < 0.0) {
// The momentum theory is no longer applicable so let's assume the induced
// saturates to -0.5*Vel so that the total velocity Vel+2*Vinduced equals 0.
Vinduced = -0.5*Vel;
}
// P-factor is simulated by a shift of the acting location of the thrust.
// The shift is a multiple of the angle between the propeller shaft axis
// and the relative wind that goes through the propeller disk.
if (P_Factor > 0.0001) {
double tangentialVel = localAeroVel.Magnitude(eV, eW);
if (tangentialVel > 0.0001) {
double angle = atan2(tangentialVel, localAeroVel(eU));
double factor = Sense * P_Factor * angle / tangentialVel;
SetActingLocationY( GetLocationY() + factor * localAeroVel(eW));
SetActingLocationZ( GetLocationZ() + factor * localAeroVel(eV));
}
}
omega = RPS*2.0*M_PI;
vFn(eX) = Thrust;
// The Ixx value and rotation speed given below are for rotation about the
// natural axis of the engine. The transform takes place in the base class
// FGForce::GetBodyForces() function.
vH(eX) = Ixx*omega*Sense;
vH(eY) = 0.0;
vH(eZ) = 0.0;
if (omega > 0.0) ExcessTorque = PowerAvailable / omega;
else ExcessTorque = PowerAvailable / 1.0;
RPM = (RPS + ((ExcessTorque / Ixx) / (2.0 * M_PI)) * deltaT) * 60.0;
if (RPM < 0.0) RPM = 0.0; // Engine won't turn backwards
// Transform Torque and momentum first, as PQR is used in this
// equation and cannot be transformed itself.
vMn = in.PQR*(Transform()*vH) + Transform()*vTorque;
return Thrust; // return thrust in pounds
}
Here is the call graph for this function:| double GetPowerRequired | ( | void | ) | [virtual] |
the power required to keep spinning the propeller at the current velocity, air density, and rotational rate.
Reimplemented from FGThruster.
Definition at line 296 of file FGPropeller.cpp.
Referenced by FGPropeller::Calculate().
{
double cPReq, J;
double rho = in.Density;
double Vel = in.AeroUVW(eU);
double RPS = RPM / 60.0;
if (RPS != 0.0) J = Vel / (Diameter * RPS);
else J = Vel / Diameter;
if (MaxPitch == MinPitch) { // Fixed pitch prop
cPReq = cPower->GetValue(J);
} else { // Variable pitch prop
if (ConstantSpeed != 0) { // Constant Speed Mode
// do normal calculation when propeller is neither feathered nor reversed
// Note: This method of feathering and reversing was added to support the
// turboprop model. It's left here for backward compatablity, but
// now feathering and reversing should be done in Manual Pitch Mode.
if (!Feathered) {
if (!Reversed) {
double rpmReq = MinRPM + (MaxRPM - MinRPM) * Advance;
double dRPM = rpmReq - RPM;
// The pitch of a variable propeller cannot be changed when the RPMs are
// too low - the oil pump does not work.
if (RPM > 200) Pitch -= dRPM * deltaT;
if (Pitch < MinPitch) Pitch = MinPitch;
else if (Pitch > MaxPitch) Pitch = MaxPitch;
} else { // Reversed propeller
// when reversed calculate propeller pitch depending on throttle lever position
// (beta range for taxing full reverse for braking)
double PitchReq = MinPitch - ( MinPitch - ReversePitch ) * Reverse_coef;
// The pitch of a variable propeller cannot be changed when the RPMs are
// too low - the oil pump does not work.
if (RPM > 200) Pitch += (PitchReq - Pitch) / 200;
if (RPM > MaxRPM) {
Pitch += (MaxRPM - RPM) / 50;
if (Pitch < ReversePitch) Pitch = ReversePitch;
else if (Pitch > MaxPitch) Pitch = MaxPitch;
}
}
} else { // Feathered propeller
// ToDo: Make feathered and reverse settings done via FGKinemat
Pitch += (MaxPitch - Pitch) / 300; // just a guess (about 5 sec to fully feathered)
}
} else { // Manual Pitch Mode, pitch is controlled externally
}
cPReq = cPower->GetValue(J, Pitch);
}
// Apply optional scaling factor to Cp (default value = 1)
cPReq *= CpFactor;
// Apply optional Mach effects from CP_MACH table
if (CpMach) cPReq *= CpMach->GetValue(HelicalTipMach);
double local_RPS = RPS < 0.01 ? 0.01 : RPS;
PowerRequired = cPReq*local_RPS*RPS*local_RPS*D5*rho;
vTorque(eX) = -Sense*PowerRequired / (local_RPS*2.0*M_PI);
return PowerRequired;
}
Here is the caller graph for this function:| void SetPitch | ( | double | pitch | ) | [inline] |
This call is meant to be issued either from the cockpit or by the flight control system (perhaps to maintain constant RPM for a constant-speed propeller). This value will be limited to be within whatever is specified in the config file for Max and Min pitch. It is also one of the lookup indices to the power and thrust tables for variable-pitch propellers.
| pitch | the pitch of the blade in degrees. |
Reimplemented from FGForce.
Definition at line 187 of file FGPropeller.h.
{Pitch = pitch;}
| void SetRPM | ( | double | rpm | ) | [inline, virtual] |
Normally the propeller instance will calculate its own rotational velocity, given the Torque produced by the engine and integrating over time using the standard equation for rotational acceleration "a": a = Q/I , where Q is Torque and I is moment of inertia for the propeller.
| rpm | the rotational velocity of the propeller |
Reimplemented from FGThruster.
Definition at line 172 of file FGPropeller.h.
{RPM = rpm;}
| void SetSense | ( | double | s | ) | [inline] |
| s | this value should be +/- 1 ONLY. +1 indicates clockwise rotation as viewed by someone standing behind the engine looking forward into the direction of flight. |
Definition at line 207 of file FGPropeller.h.
Referenced by FGPropeller::FGPropeller().
{ Sense = s;}
Here is the caller graph for this function: