57 Element *table_element, *local_element;
61 MaxPitch = MinPitch = P_Factor = Pitch = Advance = MinRPM = MaxRPM = 0.0;
68 CtFactor = CpFactor = 1.0;
70 cThrust = cPower = CtMach = CpMach = 0;
76 Sense_multiplier = 1.0;
79 Sense_multiplier = -1.0;
94 MaxRPM = prop_element->FindElementValueAsNumber(
"maxrpm");
102 name = table_element->GetAttributeValue(
"name");
104 if (name ==
"C_THRUST") {
105 cThrust = new FGTable(PropertyManager, table_element);
106 } else if (name ==
"C_POWER") {
107 cPower = new FGTable(PropertyManager, table_element);
108 } else if (name ==
"CT_MACH") {
109 CtMach = new FGTable(PropertyManager, table_element);
110 } else if (name ==
"CP_MACH") {
111 CpMach = new FGTable(PropertyManager, table_element);
113 cerr <<
"Unknown table type: " << name <<
" in propeller definition." << endl;
115 } catch (std::string& str) {
116 throw(
"Error loading propeller table:" +
name +
". " + str);
119 if( (cPower == 0) || (cThrust == 0)){
120 cerr <<
"Propeller configuration must contain C_THRUST and C_POWER tables!" << endl;
123 local_element = prop_element->GetParent()->FindElement(
"sense");
125 double Sense = local_element->GetDataAsNumber();
126 SetSense(Sense >= 0.0 ? 1.0 : -1.0);
128 local_element = prop_element->GetParent()->FindElement(
"p_factor");
130 P_Factor = local_element->GetDataAsNumber();
133 cerr <<
"P-Factor value in propeller configuration file must be greater than zero" << endl;
135 if (prop_element->FindElement(
"ct_factor"))
136 SetCtFactor( prop_element->FindElementValueAsNumber(
"ct_factor") );
137 if (prop_element->FindElement(
"cp_factor"))
138 SetCpFactor( prop_element->FindElementValueAsNumber(
"cp_factor") );
142 vTorque.InitMatrix();
143 D4 = Diameter*Diameter*Diameter*Diameter;
147 string property_name, base_property_name;
148 base_property_name = CreateIndexedPropertyName(
"propulsion/engine", EngineNum);
149 property_name = base_property_name +
"/engine-rpm";
151 property_name = base_property_name +
"/advance-ratio";
152 PropertyManager->Tie( property_name.c_str(), &J );
153 property_name = base_property_name +
"/blade-angle";
154 PropertyManager->Tie( property_name.c_str(), &Pitch );
155 property_name = base_property_name +
"/thrust-coefficient";
157 property_name = base_property_name +
"/propeller-rpm";
159 property_name = base_property_name +
"/helical-tip-Mach";
161 property_name = base_property_name +
"/constant-speed-mode";
164 property_name = base_property_name +
"/prop-induced-velocity_fps";
167 property_name = base_property_name +
"/propeller-power-ftlbps";
168 PropertyManager->Tie( property_name.c_str(), &PowerRequired );
169 property_name = base_property_name +
"/propeller-torque-ftlb";
171 property_name = base_property_name +
"/propeller-sense";
172 PropertyManager->Tie( property_name.c_str(), &Sense );
217 double omega, PowerAvailable;
219 double Vel = localAeroVel(
eU);
220 double rho =
in.Density;
221 double RPS = RPM/60.0;
224 double Area = 0.25*Diameter*Diameter*
M_PI;
225 double Vtip = RPS * Diameter *
M_PI;
226 HelicalTipMach = sqrt(Vtip*Vtip + Vel*Vel) /
in.Soundspeed;
228 if (RPS > 0.01) J = Vel / (Diameter * RPS);
229 else J = Vel / Diameter;
233 if (MaxPitch == MinPitch) {
243 if (CtMach)
ThrustCoeff *= CtMach->GetValue(HelicalTipMach);
252 double Vel2sum = Vel*abs(Vel) + 2.0*
Thrust/(rho*Area);
255 Vinduced = 0.5 * (-Vel + sqrt(Vel2sum));
257 Vinduced = 0.5 * (-Vel - sqrt(-Vel2sum));
262 if (P_Factor > 0.0001) {
265 if (tangentialVel > 0.0001) {
269 double angle = atan2(tangentialVel, Vel+Vinduced);
270 double factor = Sense * P_Factor * angle / tangentialVel;
276 omega = RPS*2.0*
M_PI;
279 vTorque(
eX) = -Sense*EnginePower / max(0.01, omega);
287 if (omega > 0.01) ExcessTorque = PowerAvailable / omega;
288 else ExcessTorque = PowerAvailable / 1.0;
290 RPM = (RPS + ((ExcessTorque / Ixx) / (2.0 *
M_PI)) *
in.TotalDeltaT) * 60.0;
292 if (RPM < 0.0) RPM = 0.0;
307 if (MaxPitch == MinPitch) {
308 cPReq = cPower->GetValue(J);
312 if (ConstantSpeed != 0) {
321 double rpmReq = MinRPM + (MaxRPM - MinRPM) * Advance;
322 double dRPM = rpmReq - RPM;
325 if (RPM > 200) Pitch -= dRPM *
in.TotalDeltaT;
326 if (Pitch < MinPitch) Pitch = MinPitch;
327 else if (Pitch > MaxPitch) Pitch = MaxPitch;
333 double PitchReq = MinPitch - ( MinPitch - ReversePitch ) * Reverse_coef;
336 if (RPM > 200) Pitch += (PitchReq - Pitch) / 200;
338 Pitch += (MaxRPM - RPM) / 50;
339 if (Pitch < ReversePitch) Pitch = ReversePitch;
340 else if (Pitch > MaxPitch) Pitch = MaxPitch;
346 Pitch += (MaxPitch - Pitch) / 300;
353 cPReq = cPower->GetValue(J, Pitch);
360 if (CpMach) cPReq *= CpMach->GetValue(HelicalTipMach);
362 double RPS = RPM / 60.0;
363 double local_RPS = RPS < 0.01 ? 0.01 : RPS;