39#include "FGPropeller.h"
40#include "input_output/FGXMLElement.h"
41#include "input_output/FGLog.h"
54 Element *table_element, *local_element;
58 MaxPitch = MinPitch = P_Factor = Pitch = Advance = MinRPM = MaxRPM = 0.0;
65 CtFactor = CpFactor = 1.0;
67 cThrust = cPower = CtMach = CpMach = 0;
73 Sense_multiplier = 1.0;
76 Sense_multiplier = -1.0;
101 if (name ==
"C_THRUST") {
102 cThrust =
new FGTable(PropertyManager, table_element);
103 }
else if (name ==
"C_POWER") {
104 cPower =
new FGTable(PropertyManager, table_element);
105 }
else if (name ==
"CT_MACH") {
106 CtMach =
new FGTable(PropertyManager, table_element);
107 }
else if (name ==
"CP_MACH") {
108 CpMach =
new FGTable(PropertyManager, table_element);
111 log <<
"Unknown table type: " << name <<
" in propeller definition.\n";
115 err <<
"Error loading propeller table:" << name <<
". " << e.what() <<
"\n";
119 if( (cPower ==
nullptr) || (cThrust ==
nullptr)){
121 err <<
"Propeller configuration must contain C_THRUST and C_POWER tables!\n";
128 SetSense(Sense >= 0.0 ? 1.0 : -1.0);
136 err <<
"P-Factor value in propeller configuration file must be greater than zero\n";
146 vTorque.InitMatrix();
147 D4 = Diameter*Diameter*Diameter*Diameter;
151 string property_name, base_property_name;
152 base_property_name = CreateIndexedPropertyName(
"propulsion/engine", EngineNum);
153 property_name = base_property_name +
"/engine-rpm";
155 property_name = base_property_name +
"/advance-ratio";
156 PropertyManager->Tie( property_name.c_str(), &J );
157 property_name = base_property_name +
"/blade-angle";
158 PropertyManager->Tie( property_name.c_str(), &Pitch );
159 property_name = base_property_name +
"/thrust-coefficient";
161 property_name = base_property_name +
"/propeller-rpm";
163 property_name = base_property_name +
"/helical-tip-Mach";
165 property_name = base_property_name +
"/constant-speed-mode";
168 property_name = base_property_name +
"/prop-induced-velocity_fps";
171 property_name = base_property_name +
"/propeller-power-ftlbps";
172 PropertyManager->Tie( property_name.c_str(), &PowerRequired );
173 property_name = base_property_name +
"/propeller-torque-ftlb";
175 property_name = base_property_name +
"/propeller-sense";
176 PropertyManager->Tie( property_name.c_str(), &Sense );
197 FGThruster::ResetToIC();
221 double omega, PowerAvailable;
223 double Vel = localAeroVel(eU);
224 double rho = in.Density;
225 double RPS = RPM/60.0;
228 double Area = 0.25*Diameter*Diameter*M_PI;
229 double Vtip = RPS * Diameter * M_PI;
230 HelicalTipMach = sqrt(Vtip*Vtip + Vel*Vel) / in.Soundspeed;
232 if (RPS > 0.01) J = Vel / (Diameter * RPS);
233 else J = Vel / Diameter;
237 if (MaxPitch == MinPitch) {
240 ThrustCoeff = cThrust->
GetValue(J, Pitch);
244 ThrustCoeff *= CtFactor;
247 if (CtMach) ThrustCoeff *= CtMach->
GetValue(HelicalTipMach);
249 Thrust = ThrustCoeff*RPS*RPS*D4*rho;
256 double Vel2sum = Vel*abs(Vel) + 2.0*Thrust/(rho*Area);
259 Vinduced = 0.5 * (-Vel + sqrt(Vel2sum));
261 Vinduced = 0.5 * (-Vel - sqrt(-Vel2sum));
266 if (P_Factor > 0.0001) {
267 double tangentialVel = localAeroVel.
Magnitude(eV, eW);
269 if (tangentialVel > 0.0001) {
273 double angle = atan2(tangentialVel, Vel+Vinduced);
274 double factor = Sense * P_Factor * angle / tangentialVel;
275 SetActingLocationY( GetLocationY() + factor * localAeroVel(eW));
276 SetActingLocationZ( GetLocationZ() + factor * localAeroVel(eV));
280 omega = RPS*2.0*M_PI;
283 vTorque(eX) = -Sense*EnginePower / max(0.01, omega);
291 if (omega > 0.01) ExcessTorque = PowerAvailable / omega;
292 else ExcessTorque = PowerAvailable / 1.0;
294 RPM = (RPS + ((ExcessTorque / Ixx) / (2.0 * M_PI)) * in.TotalDeltaT) * 60.0;
296 if (RPM < 0.0) RPM = 0.0;
300 vMn = in.PQRi*(mT*vH) + mT*vTorque;
311 if (MaxPitch == MinPitch) {
316 if (ConstantSpeed != 0) {
325 double rpmReq = MinRPM + (MaxRPM - MinRPM) * Advance;
326 double dRPM = rpmReq - RPM;
329 if (RPM > 200) Pitch -= dRPM * in.TotalDeltaT;
330 if (Pitch < MinPitch) Pitch = MinPitch;
331 else if (Pitch > MaxPitch) Pitch = MaxPitch;
337 double PitchReq = MinPitch - ( MinPitch - ReversePitch ) * Reverse_coef;
340 if (RPM > 200) Pitch += (PitchReq - Pitch) / 200;
342 Pitch += (MaxRPM - RPM) / 50;
343 if (Pitch < ReversePitch) Pitch = ReversePitch;
344 else if (Pitch > MaxPitch) Pitch = MaxPitch;
350 Pitch += (MaxPitch - Pitch) / 300;
364 if (CpMach) cPReq *= CpMach->
GetValue(HelicalTipMach);
366 double RPS = RPM / 60.0;
367 double local_RPS = RPS < 0.01 ? 0.01 : RPS;
369 PowerRequired = cPReq*local_RPS*local_RPS*local_RPS*D5*in.Density;
371 return PowerRequired;
380 double p_pitch = Thrust * Sense * (GetActingLocationZ() - GetLocationZ()) / 12.0;
382 double p_yaw = Thrust * Sense * (GetActingLocationY() - GetLocationY()) / 12.0;
391 std::ostringstream buf;
393 buf << Name <<
" Torque (engine " <<
id <<
")" << delimeter
394 << Name <<
" PFactor Pitch (engine " <<
id <<
")" << delimeter
395 << Name <<
" PFactor Yaw (engine " <<
id <<
")" << delimeter
396 << Name <<
" Thrust (engine " <<
id <<
" in lbs)" << delimeter;
398 buf << Name <<
" Pitch (engine " <<
id <<
")" << delimeter;
399 buf << Name <<
" RPM (engine " <<
id <<
")";
408 std::ostringstream buf;
411 buf << vTorque(eX) << delimeter
412 << vPFactor(ePitch) << delimeter
413 << vPFactor(eYaw) << delimeter
414 << Thrust << delimeter;
416 buf << Pitch << delimeter;
441void FGPropeller::Debug(
int from)
443 if (debug_lvl <= 0)
return;
448 log <<
"\n Propeller Name: " << Name <<
"\n";
449 log <<
" IXX = " << Ixx <<
"\n";
450 log <<
" Diameter = " << Diameter <<
" ft." <<
"\n";
451 log <<
" Number of Blades = " << numBlades <<
"\n";
452 log <<
" Gear Ratio = " << GearRatio <<
"\n";
453 log <<
" Minimum Pitch = " << MinPitch <<
"\n";
454 log <<
" Maximum Pitch = " << MaxPitch <<
"\n";
455 log <<
" Minimum RPM = " << MinRPM <<
"\n";
456 log <<
" Maximum RPM = " << MaxRPM <<
"\n";
459 if (debug_lvl & 2 ) {
460 FGLogging log(LogLevel::DEBUG);
461 if (from == 0) log <<
"Instantiated: FGPropeller\n";
462 if (from == 1) log <<
"Destroyed: FGPropeller\n";
464 if (debug_lvl & 4 ) {
466 if (debug_lvl & 8 ) {
468 if (debug_lvl & 16) {
470 if (debug_lvl & 64) {
Element * FindElement(const std::string &el="")
Searches for a specified element.
double GetAttributeValueAsNumber(const std::string &key)
Retrieves an attribute value as a double precision real number.
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
Element * GetParent(void)
Returns a pointer to the parent of an element.
double FindElementValueAsNumberConvertTo(const std::string &el, const std::string &target_units)
Searches for the named element and converts and returns the data belonging to it.
Element * FindNextElement(const std::string &el="")
Searches for the next element as specified.
double GetDataAsNumber(void)
Converts the element data to a number.
bool HasAttribute(const std::string &key)
Determines if an element has the supplied attribute.
double FindElementValueAsNumber(const std::string &el="")
Searches for the named element and returns the data belonging to it as a number.
This class implements a 3 element column vector.
double Magnitude(void) const
Length of the vector.
Encapsulates the JSBSim simulation executive.
std::shared_ptr< FGPropertyManager > GetPropertyManager(void) const
Returns a pointer to the property manager object.
Handles matrix math operations.
FGMatrix33 Transposed(void) const
Transposed matrix.
void SetInducedVelocity(double Vi)
Set the propeller induced velocity.
~FGPropeller()
Destructor for FGPropeller - deletes the FGTable objects.
double Calculate(double EnginePower)
Calculates and returns the thrust produced by this propeller.
double GetPowerRequired(void)
Retrieves the power required (or "absorbed") by the propeller - i.e.
int GetConstantSpeed(void) const
Returns a non-zero value if the propeller is constant speed.
double GetRPM(void) const
Retrieves the RPMs of the propeller.
std::string GetThrusterValues(int id, const std::string &delimeter)
Generate the values for the thruster standard CSV output.
void ResetToIC(void)
Reset the initial conditions.
void SetCtFactor(double ctf)
Sets coefficient of thrust multiplier.
void SetConstantSpeed(int mode)
Sets propeller into constant speed mode, or manual pitch mode.
FGColumnVector3 GetPFactor(void) const
Retrieves the P-Factor constant.
void SetCpFactor(double cpf)
Sets coefficient of power multiplier.
double GetInducedVelocity(void) const
Get the propeller induced velocity.
void SetSense(double s)
Sets the rotation sense of the propeller.
double GetHelicalTipMach(void) const
Retrieves the Mach number at the propeller tips.
std::string GetThrusterLabels(int id, const std::string &delimeter)
Generate the labels for the thruster standard CSV output.
double GetTorque(void) const
Retrieves the Torque in foot-pounds (Don't you love the English system?)
double GetEngineRPM(void) const
Calculates the RPMs of the engine based on gear ratio.
FGPropeller(FGFDMExec *exec, Element *el, int num=0)
Constructor for FGPropeller.
bool IsVPitch(void) const
Returns true of this propeller is variable pitch.
double GetThrustCoefficient(void) const
Retrieves the thrust coefficient.
double GetValue(void) const
Get the current table value.
Base class for specific thrusting devices such as propellers, nozzles, etc.
Main namespace for the JSBSim Flight Dynamics Model.