Maik JUSTUS:
"minor update for the rotor FDM. It results in a more realistic calculation of the phase shift of rotor and therefor in a little bit more realistic flight behavior. (Additionally you can modify the initial position of the rotor and some (not finished) modifications for the jet ranger rotor)."
This commit is contained in:
parent
b51292d9db
commit
7b05646ed0
5 changed files with 96 additions and 72 deletions
|
@ -708,6 +708,7 @@ Rotor* FGFDM::parseRotor(XMLAttributes* a, const char* type)
|
|||
w->setTranslift(attrf(a, "translift", 0.05));
|
||||
w->setC2(attrf(a, "dragfactor", 1));
|
||||
w->setStepspersecond(attrf(a, "stepspersecond", 120));
|
||||
w->setPhiNull((attrf(a, "phi0", 0))*YASIM_PI/180);
|
||||
w->setRPM(attrf(a, "rpm", 424));
|
||||
w->setRelLenHinge(attrf(a, "rellenflaphinge", 0.07));
|
||||
w->setAlpha0((attrf(a, "flap0", -5))*YASIM_PI/180);
|
||||
|
@ -717,12 +718,10 @@ Rotor* FGFDM::parseRotor(XMLAttributes* a, const char* type)
|
|||
w->setTeeterdamp(attrf(a,"teeterdamp",.0001));
|
||||
w->setMaxteeterdamp(attrf(a,"maxteeterdamp",1000));
|
||||
w->setRelLenTeeterHinge(attrf(a,"rellenteeterhinge",0.01));
|
||||
void setAlphamin(float f);
|
||||
void setAlphamax(float f);
|
||||
void setAlpha0factor(float f);
|
||||
|
||||
if(attrb(a,"ccw"))
|
||||
w->setCcw(1);
|
||||
if(attrb(a,"sharedflaphinge"))
|
||||
w->setSharedFlapHinge(true);
|
||||
|
||||
if(a->hasAttribute("name"))
|
||||
w->setName(a->getValue("name") );
|
||||
|
|
|
@ -67,6 +67,7 @@ Rotor::Rotor()
|
|||
_normal_with_yaw_roll[2]=1;
|
||||
_number_of_blades=4;
|
||||
_omega=_omegan=_omegarel=_omegarelneu=0;
|
||||
_phi_null=0;
|
||||
_ddt_omega=0;
|
||||
_pitch_a=0;
|
||||
_pitch_b=0;
|
||||
|
@ -75,6 +76,7 @@ Rotor::Rotor()
|
|||
_no_torque=0;
|
||||
_rel_blade_center=.7;
|
||||
_rel_len_hinge=0.01;
|
||||
_shared_flap_hinge=false;
|
||||
_rellenteeterhinge=0.01;
|
||||
_rotor_rpm=442;
|
||||
_sim_blades=0;
|
||||
|
@ -149,8 +151,8 @@ void Rotor::inititeration(float dt,float omegarel,float ddt_omegarel,float *rot)
|
|||
_ddt_omega=_omegan*ddt_omegarel;
|
||||
int i;
|
||||
for(i=0; i<_rotorparts.size(); i++) {
|
||||
float s = Math::sin(2*pi*i/_number_of_parts);
|
||||
float c = Math::cos(2*pi*i/_number_of_parts);
|
||||
float s = Math::sin(float(2*pi*i/_number_of_parts+(_phi-pi/2.)*(_ccw?1:-1)));
|
||||
float c = Math::cos(float(2*pi*i/_number_of_parts+(_phi-pi/2.)*(_ccw?1:-1)));
|
||||
Rotorpart* r = (Rotorpart*)_rotorparts.get(i);
|
||||
r->setOmega(_omega);
|
||||
r->setDdtOmega(_ddt_omega);
|
||||
|
@ -522,6 +524,11 @@ void Rotor::setTranslift(float value)
|
|||
_translift=value;
|
||||
}
|
||||
|
||||
void Rotor::setSharedFlapHinge(bool s)
|
||||
{
|
||||
_shared_flap_hinge=s;
|
||||
}
|
||||
|
||||
void Rotor::setC2(float value)
|
||||
{
|
||||
_c2=value;
|
||||
|
@ -537,6 +544,11 @@ void Rotor::setRPM(float value)
|
|||
_rotor_rpm=value;
|
||||
}
|
||||
|
||||
void Rotor::setPhiNull(float value)
|
||||
{
|
||||
_phi_null=value;
|
||||
}
|
||||
|
||||
void Rotor::setRelLenHinge(float value)
|
||||
{
|
||||
_rel_len_hinge=value;
|
||||
|
@ -635,10 +647,10 @@ void Rotor::setCollective(float lval)
|
|||
{
|
||||
lval = Math::clamp(lval, -1, 1);
|
||||
int i;
|
||||
for(i=0; i<_rotorparts.size(); i++) {
|
||||
((Rotorpart*)_rotorparts.get(i))->setCollective(lval);
|
||||
}
|
||||
_collective=_min_pitch+(lval+1)/2*(_max_pitch-_min_pitch);
|
||||
for(i=0; i<_rotorparts.size(); i++) {
|
||||
((Rotorpart*)_rotorparts.get(i))->setCollective(_collective);
|
||||
}
|
||||
}
|
||||
|
||||
void Rotor::setCyclicele(float lval,float rval)
|
||||
|
@ -919,11 +931,17 @@ void Rotor::compile()
|
|||
float omega=_rotor_rpm/60*2*pi;
|
||||
_omegan=omega;
|
||||
float omega0=omega*Math::sqrt(1/(1-_rel_len_hinge));
|
||||
_delta*=pitchaforce/(_pitch_a*omega*lentocenter*2*rotorpartmass);
|
||||
float delta_theoretical=pitchaforce/(_pitch_a*omega*lentocenter*2*rotorpartmass);
|
||||
_delta*=delta_theoretical;
|
||||
|
||||
float phi=Math::atan2(2*omega*_delta,omega0*omega0-omega*omega);
|
||||
float relamp=(omega*omega/(2*_delta*Math::sqrt(sqr(omega0*omega0-omega*omega)
|
||||
+4*_delta*_delta*omega*omega)))*_cyclic_factor;
|
||||
float relamp_theoretical=(omega*omega/(2*delta_theoretical*Math::sqrt(sqr(omega0*omega0-omega*omega)
|
||||
+4*delta_theoretical*delta_theoretical*omega*omega)))*_cyclic_factor;
|
||||
_phi=Math::acos(_rel_len_hinge);
|
||||
SG_LOG(SG_GENERAL, SG_ALERT,
|
||||
"phi: " << _phi*180/3.14 << " delta3: " << _delta3 << "(" << Math::atan(_delta3)*180/3.14 << ")" <<endl);
|
||||
_phi-=Math::atan(_delta3);
|
||||
if (!_no_torque)
|
||||
{
|
||||
torque0=_power_at_pitch_0/_number_of_parts*1000/omega;
|
||||
|
@ -945,13 +963,19 @@ void Rotor::compile()
|
|||
float lpos[3],lforceattac[3],lspeed[3],dirzentforce[3];
|
||||
float s = Math::sin(2*pi*i/_number_of_parts);
|
||||
float c = Math::cos(2*pi*i/_number_of_parts);
|
||||
float direction[3],nextdirection[3],help[3];
|
||||
float sp = Math::sin(float(2*pi*i/_number_of_parts-pi/2.+_phi));
|
||||
float cp = Math::cos(float(2*pi*i/_number_of_parts-pi/2.+_phi));
|
||||
float direction[3],nextdirection[3],help[3],direction90deg[3];
|
||||
Math::mul3(c ,directions[0],help);
|
||||
Math::mul3(s ,directions[1],direction);
|
||||
Math::add3(help,direction,direction);
|
||||
|
||||
Math::mul3(c ,directions[1],help);
|
||||
Math::mul3(s ,directions[2],nextdirection);
|
||||
Math::mul3(s ,directions[2],direction90deg);
|
||||
Math::add3(help,direction90deg,direction90deg);
|
||||
|
||||
Math::mul3(cp ,directions[1],help);
|
||||
Math::mul3(sp ,directions[2],nextdirection);
|
||||
Math::add3(help,nextdirection,nextdirection);
|
||||
|
||||
Math::mul3(lentocenter,direction,lpos);
|
||||
|
@ -960,17 +984,12 @@ void Rotor::compile()
|
|||
//nextdirection: +90deg (gyro)!!!
|
||||
|
||||
Math::add3(lforceattac,_base,lforceattac);
|
||||
Math::mul3(speed,nextdirection,lspeed);
|
||||
Math::mul3(speed,direction90deg,lspeed);
|
||||
Math::mul3(1,nextdirection,dirzentforce);
|
||||
|
||||
|
||||
float maxcyclic=(i&1)?_maxcyclicele:_maxcyclicail;
|
||||
float mincyclic=(i&1)?_mincyclicele:_mincyclicail;
|
||||
|
||||
Rotorpart* rp=rps[i]=newRotorpart(lpos, lforceattac, _normal,
|
||||
lspeed,dirzentforce,zentforce,pitchaforce, _max_pitch,_min_pitch,
|
||||
mincyclic,maxcyclic,_delta3,rotorpartmass,_translift,
|
||||
_rel_len_hinge,lentocenter);
|
||||
lspeed,dirzentforce,zentforce,pitchaforce,_delta3,rotorpartmass,
|
||||
_translift,_rel_len_hinge,lentocenter);
|
||||
int k = i*4/_number_of_parts;
|
||||
rp->setAlphaoutput(_alphaoutput[k&1?k:(_ccw?k^2:k)],0);
|
||||
rp->setAlphaoutput(_alphaoutput[4+(k&1?k:(_ccw?k^2:k))],1+(k>1));
|
||||
|
@ -1083,7 +1102,7 @@ void Rotor::compile()
|
|||
rps[0]->setOmega(0);
|
||||
writeInfo();
|
||||
}
|
||||
std::ostream & operator<<(std::ostream & out, /*const*/ Rotor& r)
|
||||
std::ostream & operator<<(std::ostream & out, Rotor& r)
|
||||
{
|
||||
#define i(x) << #x << ":" << r.x << endl
|
||||
#define iv(x) << #x << ":" << r.x[0] << ";" << r.x[1] << ";" <<r.x[2] << ";" << endl
|
||||
|
@ -1192,7 +1211,6 @@ void Rotor:: writeInfo()
|
|||
}
|
||||
Rotorpart* Rotor::newRotorpart(float* pos, float *posforceattac, float *normal,
|
||||
float* speed,float *dirzentforce, float zentforce,float maxpitchforce,
|
||||
float maxpitch, float minpitch, float mincyclic,float maxcyclic,
|
||||
float delta3,float mass,float translift,float rellenhinge,float len)
|
||||
{
|
||||
Rotorpart *r = new Rotorpart();
|
||||
|
@ -1202,17 +1220,15 @@ Rotorpart* Rotor::newRotorpart(float* pos, float *posforceattac, float *normal,
|
|||
r->setPositionForceAttac(posforceattac);
|
||||
r->setSpeed(speed);
|
||||
r->setDirectionofZentipetalforce(dirzentforce);
|
||||
r->setMaxpitch(maxpitch);
|
||||
r->setMinpitch(minpitch);
|
||||
r->setMaxcyclic(maxcyclic);
|
||||
r->setMincyclic(mincyclic);
|
||||
r->setDelta3(delta3);
|
||||
r->setDynamic(_dynamic);
|
||||
r->setTranslift(_translift);
|
||||
r->setC2(_c2);
|
||||
r->setWeight(mass);
|
||||
r->setRelLenHinge(rellenhinge);
|
||||
r->setSharedFlapHinge(_shared_flap_hinge);
|
||||
r->setOmegaN(_omegan);
|
||||
r->setPhi(_phi_null);
|
||||
r->setAlpha0(_alpha0);
|
||||
r->setAlphamin(_alphamin);
|
||||
r->setAlphamax(_alphamax);
|
||||
|
|
|
@ -19,6 +19,7 @@ class Rotor {
|
|||
private:
|
||||
float _torque;
|
||||
float _omega,_omegan,_omegarel,_ddt_omega,_omegarelneu;
|
||||
float _phi_null;
|
||||
float _chord;
|
||||
float _taper;
|
||||
float _airfoil_incidence_no_lift;
|
||||
|
@ -64,6 +65,7 @@ public:
|
|||
void setC2(float value);
|
||||
void setStepspersecond(float steps);
|
||||
void setRPM(float value);
|
||||
void setPhiNull(float value);
|
||||
void setRelLenHinge(float value);
|
||||
void setBase(float* base); // in local coordinates
|
||||
void getPosition(float* out);
|
||||
|
@ -112,11 +114,10 @@ public:
|
|||
{if (_stall_v2sum !=0 ) return _stall_sum/_stall_v2sum; else return 0;}
|
||||
float getAirfoilIncidenceNoLift() {return _airfoil_incidence_no_lift;}
|
||||
|
||||
|
||||
Vector _rotorparts;
|
||||
void findGroundEffectAltitude(Ground * ground_cb,State *s);
|
||||
void writeInfo();
|
||||
|
||||
void setSharedFlapHinge(bool s);
|
||||
|
||||
private:
|
||||
void strncpy(char *dest,const char *src,int maxlen);
|
||||
|
@ -127,7 +128,6 @@ private:
|
|||
int iteration=0,float a0=-1,float a1=-1,float a2=-1,float a3=-1);
|
||||
Rotorpart* newRotorpart(float* pos, float *posforceattac, float *normal,
|
||||
float* speed,float *dirzentforce, float zentforce,float maxpitchforce,
|
||||
float maxpitch, float minpitch, float mincyclic,float maxcyclic,
|
||||
float delta3,float mass,float translift,float rellenhinge,float len);
|
||||
float _base[3];
|
||||
float _groundeffectpos[4][3];
|
||||
|
@ -199,6 +199,8 @@ private:
|
|||
float _cyclicele;
|
||||
float _cyclic_factor;
|
||||
float _rotor_correction_factor;
|
||||
float _phi;
|
||||
bool _shared_flap_hinge;
|
||||
};
|
||||
std::ostream & operator<<(std::ostream & out, /*const*/ Rotor& r);
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ Rotorpart::Rotorpart()
|
|||
_cyclic=0;
|
||||
_collective=0;
|
||||
_rellenhinge=0;
|
||||
_shared_flap_hinge=false;
|
||||
_dt=0;
|
||||
#define set3(x,a,b,c) x[0]=a;x[1]=b;x[2]=c;
|
||||
set3 (_speed,1,0,0);
|
||||
|
@ -23,10 +24,6 @@ Rotorpart::Rotorpart()
|
|||
set3 (_last_torque,0,0,0);
|
||||
#undef set3
|
||||
_centripetalforce=1;
|
||||
_maxpitch=.02;
|
||||
_minpitch=0;
|
||||
_maxcyclic=0.02;
|
||||
_mincyclic=-0.02;
|
||||
_delta3=0.5;
|
||||
_cyclic=0;
|
||||
_collective=-1;
|
||||
|
@ -187,6 +184,11 @@ void Rotorpart::setOmega(float value)
|
|||
_omega=value;
|
||||
}
|
||||
|
||||
void Rotorpart::setPhi(float value)
|
||||
{
|
||||
_phi=value;
|
||||
}
|
||||
|
||||
void Rotorpart::setOmegaN(float value)
|
||||
{
|
||||
_omegan=value;
|
||||
|
@ -202,25 +204,6 @@ void Rotorpart::setZentipetalForce(float f)
|
|||
_centripetalforce=f;
|
||||
}
|
||||
|
||||
void Rotorpart::setMinpitch(float f)
|
||||
{
|
||||
_minpitch=f;
|
||||
}
|
||||
|
||||
void Rotorpart::setMaxpitch(float f)
|
||||
{
|
||||
_maxpitch=f;
|
||||
}
|
||||
|
||||
void Rotorpart::setMaxcyclic(float f)
|
||||
{
|
||||
_maxcyclic=f;
|
||||
}
|
||||
|
||||
void Rotorpart::setMincyclic(float f)
|
||||
{
|
||||
_mincyclic=f;
|
||||
}
|
||||
|
||||
void Rotorpart::setDelta3(float f)
|
||||
{
|
||||
|
@ -247,6 +230,11 @@ void Rotorpart::setRelLenHinge(float f)
|
|||
_rellenhinge=f;
|
||||
}
|
||||
|
||||
void Rotorpart::setSharedFlapHinge(bool s)
|
||||
{
|
||||
_shared_flap_hinge=s;
|
||||
}
|
||||
|
||||
void Rotorpart::setC2(float f)
|
||||
{
|
||||
_c2=f;
|
||||
|
@ -378,9 +366,6 @@ float Rotorpart::calculateAlpha(float* v_rel_air, float rho,
|
|||
if((_nextrp==NULL)||(_lastrp==NULL)||(_rotor==NULL))
|
||||
return 0.0;//not initialized. Can happen during startupt of flightgear
|
||||
if (returnlift!=NULL) *returnlift=0;
|
||||
/*float flap_omega=(_nextrp->getrealAlpha()-_lastrp->getrealAlpha())
|
||||
*_omega / pi*_rotor->getNumberOfParts()/4; hier mal die alte version probieren?
|
||||
*/
|
||||
float flap_omega=(_next90rp->getrealAlpha()-_last90rp->getrealAlpha())
|
||||
*_omega / pi;
|
||||
float local_width=_diameter*(1-_rel_len_blade_start)/2.
|
||||
|
@ -432,7 +417,7 @@ float Rotorpart::calculateAlpha(float* v_rel_air, float rho,
|
|||
*_rotor_correction_factor-_rotor->getAirfoilIncidenceNoLift();
|
||||
ias = incidence_of_airspeed;
|
||||
float lift_wo_cyc = _rotor->getLiftCoef(incidence_of_airspeed
|
||||
-cyc*_rotor_correction_factor,v_local_scalar)
|
||||
-cyc*_rotor_correction_factor*prantl_factor,v_local_scalar)
|
||||
* v_local_scalar * v_local_scalar * A *rho *0.5;
|
||||
float lift_with_cyc =
|
||||
_rotor->getLiftCoef(incidence_of_airspeed,v_local_scalar)
|
||||
|
@ -464,8 +449,31 @@ float Rotorpart::calculateAlpha(float* v_rel_air, float rho,
|
|||
//as above, use 1st order approximation
|
||||
//float alpha=Math::atan2(lift_moment,_centripetalforce * _len);
|
||||
float alpha;
|
||||
alpha=lift_moment/(_centripetalforce * _len - _mass * _len * 9.81 /_alpha0);
|
||||
//centripetalforce is >=0 and _alpha0<-0.01
|
||||
if (_shared_flap_hinge)
|
||||
{
|
||||
float div=0;
|
||||
if (Math::abs(_alphaalt) >1e-6)
|
||||
div=(_centripetalforce * _len - _mass * _len * 9.81 /_alpha0*(_alphaalt+_oppositerp->getAlphaAlt())/(2.0*_alphaalt));
|
||||
if (Math::abs(div)>1e-6)
|
||||
alpha=lift_moment/div;
|
||||
else if(Math::abs(_alphaalt+_oppositerp->getAlphaAlt())>1e-6)
|
||||
{
|
||||
float div=(_centripetalforce * _len - _mass * _len * 9.81 *0.5)*(_alphaalt+_oppositerp->getAlphaAlt());
|
||||
if (Math::abs(div)>1e-6)
|
||||
alpha=_oppositerp->getAlphaAlt()+lift_moment/div*_alphaalt;
|
||||
}
|
||||
else
|
||||
alpha=_alphaalt;
|
||||
}
|
||||
else
|
||||
{
|
||||
float div=(_centripetalforce * _len - _mass * _len * 9.81 /_alpha0);
|
||||
if (Math::abs(div)>1e-6)
|
||||
alpha=lift_moment/div;
|
||||
else
|
||||
alpha=_alphaalt;
|
||||
}
|
||||
|
||||
return (alpha);
|
||||
}
|
||||
|
||||
|
@ -490,9 +498,11 @@ void Rotorpart::calcForce(float* v, float rho, float* out, float* torque,
|
|||
//Angle of blade which would produce no vertical force (where the
|
||||
//effective incidence is zero)
|
||||
|
||||
//float cyc=_mincyclic+(_cyclic+1)/2*(_maxcyclic-_mincyclic);
|
||||
float cyc=_cyclic;
|
||||
float col=_minpitch+(_collective+1)/2*(_maxpitch-_minpitch);
|
||||
float col=_collective;
|
||||
if (_shared_flap_hinge)
|
||||
_incidence=(col+cyc)-_delta3*0.5*(_alphaalt-_oppositerp->getAlphaAlt());
|
||||
else
|
||||
_incidence=(col+cyc)-_delta3*_alphaalt;
|
||||
//the incidence of the rotorblade due to control input reduced by the
|
||||
//delta3 effect, see README.YASIM
|
||||
|
@ -503,6 +513,7 @@ void Rotorpart::calcForce(float* v, float rho, float* out, float* torque,
|
|||
//the new flapping angle will be the old flapping angle
|
||||
//+ factor *(alpha - "old flapping angle")
|
||||
alpha=calculateAlpha(v,rho,_incidence,cyc,0,&scalar_torque);
|
||||
alpha=Math::clamp(alpha,_alphamin,_alphamax);
|
||||
//the incidence is a function of alpha (if _delta* != 0)
|
||||
//Therefore missing: wrap this function in an integrator
|
||||
//(runge kutta e. g.)
|
||||
|
@ -564,10 +575,6 @@ std::ostream & operator<<(std::ostream & out, const Rotorpart& rp)
|
|||
iv( _directionofcentripetalforce)
|
||||
iv( _directionofrotorpart)
|
||||
i( _centripetalforce)
|
||||
i( _maxpitch)
|
||||
i( _minpitch)
|
||||
i( _maxcyclic)
|
||||
i( _mincyclic)
|
||||
i( _cyclic)
|
||||
i( _collective)
|
||||
i( _delta3)
|
||||
|
|
|
@ -60,6 +60,7 @@ namespace yasim {
|
|||
void setTorque(float torque_max_force,float torque_no_force);
|
||||
void setOmega(float value);
|
||||
void setOmegaN(float value);
|
||||
void setPhi(float value);
|
||||
void setDdtOmega(float value);
|
||||
float getIncidence();
|
||||
float getPhi();
|
||||
|
@ -72,6 +73,8 @@ namespace yasim {
|
|||
void setRotor(Rotor *rotor);
|
||||
void setTorqueOfInertia(float toi);
|
||||
void writeInfo(std::ostringstream &buffer);
|
||||
void setSharedFlapHinge(bool s);
|
||||
float getAlphaAlt() {return _alphaalt;}
|
||||
|
||||
private:
|
||||
void strncpy(char *dest,const char *src,int maxlen);
|
||||
|
@ -88,10 +91,6 @@ namespace yasim {
|
|||
float _directionofcentripetalforce[3];
|
||||
float _directionofrotorpart[3];
|
||||
float _centripetalforce;
|
||||
float _maxpitch;
|
||||
float _minpitch;
|
||||
float _maxcyclic;
|
||||
float _mincyclic;
|
||||
float _cyclic;
|
||||
float _collective;
|
||||
float _delta3;
|
||||
|
@ -119,6 +118,7 @@ namespace yasim {
|
|||
char _alphaoutputbuf[2][256];
|
||||
int _alpha2type;
|
||||
float _rotor_correction_factor;
|
||||
bool _shared_flap_hinge;
|
||||
};
|
||||
std::ostream & operator<<(std::ostream & out, const Rotorpart& rp);
|
||||
}; // namespace yasim
|
||||
|
|
Loading…
Reference in a new issue