41 #include "FGPropeller.h" 42 #include "input_output/FGXMLElement.h" 48 IDENT(IdSrc,
"$Id: FGPropeller.cpp,v 1.59 2017/02/26 12:09:46 bcoconni Exp $");
49 IDENT(IdHdr,ID_PROPELLER);
63 Element *table_element, *local_element;
67 MaxPitch = MinPitch = P_Factor = Pitch = Advance = MinRPM = MaxRPM = 0.0;
74 CtFactor = CpFactor = 1.0;
76 cThrust = cPower = CtMach = CpMach = 0;
82 Sense_multiplier = 1.0;
85 Sense_multiplier = -1.0;
110 if (name ==
"C_THRUST") {
111 cThrust =
new FGTable(PropertyManager, table_element);
112 }
else if (name ==
"C_POWER") {
113 cPower =
new FGTable(PropertyManager, table_element);
114 }
else if (name ==
"CT_MACH") {
115 CtMach =
new FGTable(PropertyManager, table_element);
116 }
else if (name ==
"CP_MACH") {
117 CpMach =
new FGTable(PropertyManager, table_element);
119 cerr <<
"Unknown table type: " << name <<
" in propeller definition." << endl;
121 }
catch (std::string& str) {
122 throw(
"Error loading propeller table:" + name +
". " + str);
125 if( (cPower == 0) || (cThrust == 0)){
126 cerr <<
"Propeller configuration must contain C_THRUST and C_POWER tables!" << endl;
132 SetSense(Sense >= 0.0 ? 1.0 : -1.0);
139 cerr <<
"P-Factor value in propeller configuration file must be greater than zero" << endl;
148 vTorque.InitMatrix();
150 D4 = Diameter*Diameter*Diameter*Diameter;
154 string property_name, base_property_name;
155 base_property_name = CreateIndexedPropertyName(
"propulsion/engine", EngineNum);
156 property_name = base_property_name +
"/engine-rpm";
158 property_name = base_property_name +
"/advance-ratio";
159 PropertyManager->
Tie( property_name.c_str(), &J );
160 property_name = base_property_name +
"/blade-angle";
161 PropertyManager->
Tie( property_name.c_str(), &Pitch );
162 property_name = base_property_name +
"/thrust-coefficient";
164 property_name = base_property_name +
"/propeller-rpm";
166 property_name = base_property_name +
"/helical-tip-Mach";
168 property_name = base_property_name +
"/constant-speed-mode";
171 property_name = base_property_name +
"/prop-induced-velocity_fps";
194 FGThruster::ResetToIC();
212 double omega, PowerAvailable;
214 double Vel = localAeroVel(eU) + Vinduced;
215 double rho = in.Density;
216 double RPS = RPM/60.0;
219 double Area = 0.25*Diameter*Diameter*M_PI;
220 double Vtip = RPS * Diameter * M_PI;
221 HelicalTipMach = sqrt(Vtip*Vtip + Vel*Vel) / in.Soundspeed;
223 if (RPS > 0.0) J = Vel / (Diameter * RPS);
224 else J = Vel / Diameter;
228 if (MaxPitch == MinPitch) {
229 ThrustCoeff = cThrust->GetValue(J);
231 ThrustCoeff = cThrust->GetValue(J, Pitch);
235 ThrustCoeff *= CtFactor;
238 if (CtMach) ThrustCoeff *= CtMach->GetValue(HelicalTipMach);
240 Thrust = ThrustCoeff*RPS*RPS*D4*rho;
247 double Vel2sum = Vel*abs(Vel) + 2.0*Thrust/(rho*Area);
250 Vinduced = 0.5 * (-Vel + sqrt(Vel2sum));
252 Vinduced = 0.5 * (-Vel - sqrt(-Vel2sum));
257 if (P_Factor > 0.0001) {
258 double tangentialVel = localAeroVel.
Magnitude(eV, eW);
260 if (tangentialVel > 0.0001) {
261 double angle = atan2(tangentialVel, localAeroVel(eU));
262 double factor = Sense * P_Factor * angle / tangentialVel;
263 SetActingLocationY( GetLocationY() + factor * localAeroVel(eW));
264 SetActingLocationZ( GetLocationZ() + factor * localAeroVel(eV));
268 omega = RPS*2.0*M_PI;
276 vH(eX) = Ixx*omega*Sense*Sense_multiplier;
278 if (omega > 0.0) ExcessTorque = PowerAvailable / omega;
279 else ExcessTorque = PowerAvailable / 1.0;
281 RPM = (RPS + ((ExcessTorque / Ixx) / (2.0 * M_PI)) * in.TotalDeltaT) * 60.0;
283 if (RPM < 0.0) RPM = 0.0;
287 vMn = in.PQRi*(Transform()*vH) + Transform()*vTorque;
298 if (MaxPitch == MinPitch) {
299 cPReq = cPower->GetValue(J);
303 if (ConstantSpeed != 0) {
312 double rpmReq = MinRPM + (MaxRPM - MinRPM) * Advance;
313 double dRPM = rpmReq - RPM;
316 if (RPM > 200) Pitch -= dRPM * in.TotalDeltaT;
317 if (Pitch < MinPitch) Pitch = MinPitch;
318 else if (Pitch > MaxPitch) Pitch = MaxPitch;
324 double PitchReq = MinPitch - ( MinPitch - ReversePitch ) * Reverse_coef;
327 if (RPM > 200) Pitch += (PitchReq - Pitch) / 200;
329 Pitch += (MaxRPM - RPM) / 50;
330 if (Pitch < ReversePitch) Pitch = ReversePitch;
331 else if (Pitch > MaxPitch) Pitch = MaxPitch;
337 Pitch += (MaxPitch - Pitch) / 300;
344 cPReq = cPower->GetValue(J, Pitch);
351 if (CpMach) cPReq *= CpMach->GetValue(HelicalTipMach);
353 double RPS = RPM / 60.0;
354 double local_RPS = RPS < 0.01 ? 0.01 : RPS;
356 PowerRequired = cPReq*local_RPS*local_RPS*local_RPS*D5*in.Density;
357 vTorque(eX) = -Sense*PowerRequired / (local_RPS*2.0*M_PI);
359 return PowerRequired;
366 double px=0.0, py, pz;
368 py = Thrust * Sense * (GetActingLocationY() - GetLocationY()) / 12.0;
369 pz = Thrust * Sense * (GetActingLocationZ() - GetLocationZ()) / 12.0;
378 std::ostringstream buf;
380 buf << Name <<
" Torque (engine " <<
id <<
")" << delimeter
381 << Name <<
" PFactor Pitch (engine " <<
id <<
")" << delimeter
382 << Name <<
" PFactor Yaw (engine " <<
id <<
")" << delimeter
383 << Name <<
" Thrust (engine " <<
id <<
" in lbs)" << delimeter;
385 buf << Name <<
" Pitch (engine " <<
id <<
")" << delimeter;
386 buf << Name <<
" RPM (engine " <<
id <<
")";
395 std::ostringstream buf;
398 buf << vTorque(eX) << delimeter
399 << vPFactor(ePitch) << delimeter
400 << vPFactor(eYaw) << delimeter
401 << Thrust << delimeter;
403 buf << Pitch << delimeter;
428 void FGPropeller::Debug(
int from)
430 if (debug_lvl <= 0)
return;
434 cout <<
"\n Propeller Name: " << Name << endl;
435 cout <<
" IXX = " << Ixx << endl;
436 cout <<
" Diameter = " << Diameter <<
" ft." << endl;
437 cout <<
" Number of Blades = " << numBlades << endl;
438 cout <<
" Gear Ratio = " << GearRatio << endl;
439 cout <<
" Minimum Pitch = " << MinPitch << endl;
440 cout <<
" Maximum Pitch = " << MaxPitch << endl;
441 cout <<
" Minimum RPM = " << MinRPM << endl;
442 cout <<
" Maximum RPM = " << MaxRPM << endl;
464 if (debug_lvl & 2 ) {
465 if (from == 0) cout <<
"Instantiated: FGPropeller" << endl;
466 if (from == 1) cout <<
"Destroyed: FGPropeller" << endl;
468 if (debug_lvl & 4 ) {
470 if (debug_lvl & 8 ) {
472 if (debug_lvl & 16) {
474 if (debug_lvl & 64) {
476 cout << IdSrc << endl;
477 cout << IdHdr << endl;
~FGPropeller()
Destructor for FGPropeller - deletes the FGTable objects.
Element * GetParent(void)
Returns a pointer to the parent of an element.
double GetEngineRPM(void) const
Calculates the RPMs of the engine based on gear ratio.
double GetRPM(void) const
Retrieves the RPMs of the propeller.
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
double GetPowerRequired(void)
Retrieves the power required (or "absorbed") by the propeller - i.e.
void SetConstantSpeed(int mode)
Sets propeller into constant speed mode, or manual pitch mode.
bool HasAttribute(const std::string &key)
Determines if an element has the supplied attribute.
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. ...
void SetCpFactor(double cpf)
Sets coefficient of power multiplier.
Element * FindElement(const std::string &el="")
Searches for a specified element.
double FindElementValueAsNumber(const std::string &el="")
Searches for the named element and returns the data belonging to it as a number.
bool IsVPitch(void) const
Returns true of this propeller is variable pitch.
Base class for specific thrusting devices such as propellers, nozzles, etc.
double Calculate(double EnginePower)
Calculates and returns the thrust produced by this propeller.
double GetThrustCoefficient(void) const
Retrieves the thrust coefficient.
FGPropertyManager * GetPropertyManager(void)
Returns a pointer to the property manager object.
double GetInducedVelocity(void) const
Get the propeller induced velocity.
std::string GetThrusterLabels(int id, const std::string &delimeter)
Generate the labels for the thruster standard CSV output.
void Tie(const std::string &name, bool *pointer, bool useDefault=true)
Tie a property to an external bool variable.
double GetDataAsNumber(void)
Converts the element data to a number.
void SetSense(double s)
Sets the rotation sense of the propeller.
double GetAttributeValueAsNumber(const std::string &key)
Retrieves an attribute value as a double precision real number.
std::string GetThrusterValues(int id, const std::string &delimeter)
Generate the values for the thruster standard CSV output.
void SetInducedVelocity(double Vi)
Set the propeller induced velocity.
This class implements a 3 element column vector.
double GetHelicalTipMach(void) const
Retrieves the Mach number at the propeller tips.
int GetConstantSpeed(void) const
Returns a non-zero value if the propeller is constant speed.
Element * FindNextElement(const std::string &el="")
Searches for the next element as specified.
FGMatrix33 Transposed(void) const
Transposed matrix.
double Magnitude(void) const
Length of the vector.
void SetCtFactor(double ctf)
Sets coefficient of thrust multiplier.
FGColumnVector3 GetPFactor(void) const
Retrieves the P-Factor constant.
void ResetToIC(void)
Reset the initial conditions.
Encapsulates the JSBSim simulation executive.