2001-12-06 18:13:24 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
|
2001-12-01 06:22:24 +00:00
|
|
|
#include "Atmosphere.hpp"
|
|
|
|
#include "Math.hpp"
|
|
|
|
#include "Propeller.hpp"
|
|
|
|
namespace yasim {
|
|
|
|
|
|
|
|
Propeller::Propeller(float radius, float v, float omega,
|
2001-12-06 18:13:24 +00:00
|
|
|
float rho, float power)
|
2001-12-01 06:22:24 +00:00
|
|
|
{
|
|
|
|
// Initialize numeric constants:
|
2001-12-06 18:13:24 +00:00
|
|
|
_lambdaPeak = Math::pow(5.0, -1.0/4.0);
|
2002-05-10 23:35:06 +00:00
|
|
|
_beta = 1.0f/(Math::pow(5.0f, -1.0f/4.0f) - Math::pow(5.0f, -5.0f/4.0f));
|
2001-12-01 06:22:24 +00:00
|
|
|
|
|
|
|
_r = radius;
|
2002-05-10 23:35:06 +00:00
|
|
|
_etaC = 0.85f; // make this settable?
|
2001-12-01 06:22:24 +00:00
|
|
|
|
2001-12-07 20:00:59 +00:00
|
|
|
_j0 = v/(omega*_lambdaPeak);
|
|
|
|
_baseJ0 = _j0;
|
2001-12-01 06:22:24 +00:00
|
|
|
|
|
|
|
float V2 = v*v + (_r*omega)*(_r*omega);
|
2001-12-07 20:00:59 +00:00
|
|
|
_f0 = 2*_etaC*power/(rho*v*V2);
|
2001-12-01 06:22:24 +00:00
|
|
|
|
2001-12-06 18:13:24 +00:00
|
|
|
_matchTakeoff = false;
|
2003-05-16 17:27:17 +00:00
|
|
|
_manual = false;
|
|
|
|
_proppitch = 0;
|
2004-07-20 22:17:58 +00:00
|
|
|
_propfeather = 0;
|
2001-12-06 18:13:24 +00:00
|
|
|
}
|
2001-12-01 06:22:24 +00:00
|
|
|
|
2001-12-06 18:13:24 +00:00
|
|
|
void Propeller::setTakeoff(float omega0, float power0)
|
|
|
|
{
|
|
|
|
// Takeoff thrust coefficient at lambda==0
|
|
|
|
_matchTakeoff = true;
|
|
|
|
float V2 = _r*omega0 * _r*omega0;
|
2001-12-07 20:00:59 +00:00
|
|
|
float gamma = _etaC * _beta / _j0;
|
2001-12-06 18:13:24 +00:00
|
|
|
float torque = power0 / omega0;
|
|
|
|
float density = Atmosphere::getStdDensity(0);
|
2002-05-10 23:35:06 +00:00
|
|
|
_tc0 = (torque * gamma) / (0.5f * density * V2 * _f0);
|
2001-12-06 18:13:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Propeller::modPitch(float mod)
|
|
|
|
{
|
2001-12-07 20:00:59 +00:00
|
|
|
_j0 *= mod;
|
2002-05-10 23:35:06 +00:00
|
|
|
if(_j0 < 0.25f*_baseJ0) _j0 = 0.25f*_baseJ0;
|
|
|
|
if(_j0 > 4*_baseJ0) _j0 = 4*_baseJ0;
|
2001-12-01 06:22:24 +00:00
|
|
|
}
|
|
|
|
|
2003-05-16 17:27:17 +00:00
|
|
|
void Propeller::setManualPitch()
|
|
|
|
{
|
|
|
|
_manual = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Propeller::setPropPitch(float proppitch)
|
|
|
|
{
|
|
|
|
// makes only positive range of axis effective.
|
|
|
|
_proppitch = Math::clamp(proppitch, 0, 1);
|
|
|
|
}
|
2001-12-06 18:13:24 +00:00
|
|
|
|
2004-07-20 22:17:58 +00:00
|
|
|
void Propeller::setPropFeather(int state)
|
|
|
|
{
|
|
|
|
// 0 = normal, 1 = feathered
|
|
|
|
_propfeather = (state != 0);
|
|
|
|
}
|
|
|
|
|
2001-12-01 06:22:24 +00:00
|
|
|
void Propeller::calc(float density, float v, float omega,
|
|
|
|
float* thrustOut, float* torqueOut)
|
|
|
|
{
|
2004-05-01 00:25:56 +00:00
|
|
|
// For manual pitch, exponentially modulate the J0 value between
|
|
|
|
// 0.25 and 4. A prop pitch of 0.5 results in no change from the
|
|
|
|
// base value.
|
|
|
|
if (_manual)
|
2004-05-01 15:18:27 +00:00
|
|
|
_j0 = _baseJ0 * Math::pow(2, 2 - 4*_proppitch);
|
2004-05-01 00:25:56 +00:00
|
|
|
|
2001-12-01 06:22:24 +00:00
|
|
|
float tipspd = _r*omega;
|
|
|
|
float V2 = v*v + tipspd*tipspd;
|
|
|
|
|
2004-05-01 00:25:56 +00:00
|
|
|
// Sanify
|
2001-12-01 06:22:24 +00:00
|
|
|
if(v < 0) v = 0;
|
2002-05-23 19:47:19 +00:00
|
|
|
if(omega < 0.001) omega = 0.001;
|
|
|
|
|
2004-05-01 00:25:56 +00:00
|
|
|
float J = v/omega; // Advance ratio
|
|
|
|
float lambda = J/_j0; // Unitless scalar advance ratio
|
2001-12-01 06:22:24 +00:00
|
|
|
|
2004-05-01 00:25:56 +00:00
|
|
|
// There's an undefined point at lambda == 1.
|
|
|
|
if(lambda == 1.0f) lambda = 0.9999f;
|
2001-12-01 06:22:24 +00:00
|
|
|
|
2004-05-01 00:25:56 +00:00
|
|
|
float l4 = lambda*lambda; l4 = l4*l4; // lambda^4
|
|
|
|
float gamma = (_etaC*_beta/_j0)*(1-l4); // thrust/torque ratio
|
2001-12-06 18:13:24 +00:00
|
|
|
|
2004-05-01 00:25:56 +00:00
|
|
|
// Compute a thrust coefficient, with clamping at very low
|
|
|
|
// lambdas (fast propeller / slow aircraft).
|
2001-12-06 18:13:24 +00:00
|
|
|
float tc = (1 - lambda) / (1 - _lambdaPeak);
|
|
|
|
if(_matchTakeoff && tc > _tc0) tc = _tc0;
|
|
|
|
|
2002-05-10 23:35:06 +00:00
|
|
|
float thrust = 0.5f * density * V2 * _f0 * tc;
|
2004-05-01 00:25:56 +00:00
|
|
|
float torque = thrust/gamma;
|
|
|
|
if(lambda > 1) {
|
|
|
|
// This is the negative thrust / windmilling regime. Throw
|
|
|
|
// out the efficiency graph approach and instead simply
|
|
|
|
// extrapolate the existing linear thrust coefficient and a
|
|
|
|
// torque coefficient that crosses the axis at a preset
|
|
|
|
// windmilling speed. The tau0 value is an analytically
|
|
|
|
// calculated (i.e. don't mess with it) value for a torque
|
|
|
|
// coefficient at lamda==1.
|
|
|
|
float tau0 = (0.25f * _j0) / (_etaC * _beta * (1 - _lambdaPeak));
|
|
|
|
float lambdaWM = 1.2f; // lambda of zero torque (windmilling)
|
|
|
|
torque = tau0 - tau0 * (lambda - 1) / (lambdaWM - 1);
|
|
|
|
torque *= 0.5f * density * V2 * _f0;
|
2001-12-01 06:22:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*thrustOut = thrust;
|
|
|
|
*torqueOut = torque;
|
|
|
|
}
|
|
|
|
|
|
|
|
}; // namespace yasim
|