1
0
Fork 0

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:
mfranz 2007-05-09 20:36:43 +00:00
parent b51292d9db
commit 7b05646ed0
5 changed files with 96 additions and 72 deletions

View file

@ -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") );

View file

@ -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);

View file

@ -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);

View file

@ -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)

View file

@ -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