2008-06-02 21:07:35 +00:00
|
|
|
#include <ostream>
|
|
|
|
|
2003-11-25 18:50:47 +00:00
|
|
|
#include <simgear/debug/logstream.hxx>
|
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
#include "Math.hpp"
|
|
|
|
#include "Rotorpart.hpp"
|
2006-08-14 21:59:44 +00:00
|
|
|
#include "Rotor.hpp"
|
2003-10-16 14:40:13 +00:00
|
|
|
#include <stdio.h>
|
2006-08-14 21:59:44 +00:00
|
|
|
#include <string.h>
|
2003-10-16 14:40:13 +00:00
|
|
|
namespace yasim {
|
2008-06-02 21:07:35 +00:00
|
|
|
using std::endl;
|
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
const float pi=3.14159;
|
2006-08-14 21:59:44 +00:00
|
|
|
float _help = 0;
|
2003-10-16 14:40:13 +00:00
|
|
|
Rotorpart::Rotorpart()
|
|
|
|
{
|
2006-08-14 21:59:44 +00:00
|
|
|
_compiled=0;
|
2003-10-16 14:40:13 +00:00
|
|
|
_cyclic=0;
|
|
|
|
_collective=0;
|
|
|
|
_rellenhinge=0;
|
2007-05-09 20:36:43 +00:00
|
|
|
_shared_flap_hinge=false;
|
2003-10-16 14:40:13 +00:00
|
|
|
_dt=0;
|
2006-08-14 21:59:44 +00:00
|
|
|
#define set3(x,a,b,c) x[0]=a;x[1]=b;x[2]=c;
|
2003-10-16 14:40:13 +00:00
|
|
|
set3 (_speed,1,0,0);
|
2007-01-17 20:30:34 +00:00
|
|
|
set3 (_directionofcentripetalforce,1,0,0);
|
2006-08-14 21:59:44 +00:00
|
|
|
set3 (_directionofrotorpart,0,1,0);
|
|
|
|
set3 (_direction_of_movement,1,0,0);
|
|
|
|
set3 (_last_torque,0,0,0);
|
|
|
|
#undef set3
|
2007-01-17 20:30:34 +00:00
|
|
|
_centripetalforce=1;
|
2003-10-16 14:40:13 +00:00
|
|
|
_delta3=0.5;
|
|
|
|
_cyclic=0;
|
2006-08-14 21:59:44 +00:00
|
|
|
_collective=-1;
|
2003-10-16 14:40:13 +00:00
|
|
|
_relamp=1;
|
|
|
|
_mass=10;
|
|
|
|
_incidence = 0;
|
|
|
|
_alpha=0;
|
|
|
|
_alphamin=-.1;
|
|
|
|
_alphamax= .1;
|
|
|
|
_alpha0=-.05;
|
|
|
|
_alpha0factor=1;
|
|
|
|
_alphaoutputbuf[0][0]=0;
|
|
|
|
_alphaoutputbuf[1][0]=0;
|
|
|
|
_alpha2type=0;
|
|
|
|
_alphaalt=0;
|
|
|
|
_lastrp=0;
|
|
|
|
_nextrp=0;
|
|
|
|
_oppositerp=0;
|
2006-09-14 18:18:33 +00:00
|
|
|
_last90rp=0;
|
|
|
|
_next90rp=0;
|
2003-10-16 14:40:13 +00:00
|
|
|
_translift=0;
|
|
|
|
_dynamic=100;
|
|
|
|
_c2=0;
|
|
|
|
_torque_max_force=0;
|
|
|
|
_torque_no_force=0;
|
|
|
|
_omega=0;
|
|
|
|
_omegan=1;
|
2006-08-14 21:59:44 +00:00
|
|
|
_ddt_omega=0;
|
2003-10-16 14:40:13 +00:00
|
|
|
_phi=0;
|
|
|
|
_len=1;
|
2006-08-14 21:59:44 +00:00
|
|
|
_rotor=NULL;
|
|
|
|
_twist=0;
|
|
|
|
_number_of_segments=1;
|
|
|
|
_rel_len_where_incidence_is_measured=0.7;
|
|
|
|
_diameter=10;
|
|
|
|
_torque_of_inertia=0;
|
|
|
|
_rel_len_blade_start=0;
|
2006-09-14 18:18:33 +00:00
|
|
|
_torque=0;
|
|
|
|
_rotor_correction_factor=0.6;
|
2007-05-25 21:15:59 +00:00
|
|
|
_direction=0;
|
|
|
|
_balance=1;
|
2003-10-16 14:40:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Rotorpart::inititeration(float dt,float *rot)
|
|
|
|
{
|
2006-08-14 21:59:44 +00:00
|
|
|
_dt=dt;
|
|
|
|
_phi+=_omega*dt;
|
|
|
|
while (_phi>(2*pi)) _phi-=2*pi;
|
|
|
|
while (_phi<(0 )) _phi+=2*pi;
|
|
|
|
float a=Math::dot3(rot,_normal);
|
|
|
|
if(a>0)
|
2003-10-16 14:40:13 +00:00
|
|
|
_alphaalt=_alpha*Math::cos(a)
|
2006-09-14 18:18:33 +00:00
|
|
|
+_next90rp->getrealAlpha()*Math::sin(a);
|
2006-08-14 21:59:44 +00:00
|
|
|
else
|
2003-10-16 14:40:13 +00:00
|
|
|
_alphaalt=_alpha*Math::cos(a)
|
2006-09-14 18:18:33 +00:00
|
|
|
+_last90rp->getrealAlpha()*Math::sin(-a);
|
2006-08-14 21:59:44 +00:00
|
|
|
//calculate the rotation of the fuselage, determine
|
|
|
|
//the part in the same direction as alpha
|
|
|
|
//and add it ro _alphaalt
|
|
|
|
//alpha is rotation about "normal cross dirofzentf"
|
2003-10-16 14:40:13 +00:00
|
|
|
|
2006-08-14 21:59:44 +00:00
|
|
|
float dir[3];
|
2007-01-17 20:30:34 +00:00
|
|
|
Math::cross3(_directionofcentripetalforce,_normal,dir);
|
2006-08-14 21:59:44 +00:00
|
|
|
a=Math::dot3(rot,dir);
|
|
|
|
_alphaalt -= a;
|
|
|
|
_alphaalt= Math::clamp(_alphaalt,_alphamin,_alphamax);
|
2007-05-25 21:15:59 +00:00
|
|
|
|
|
|
|
//unbalance
|
|
|
|
float b;
|
|
|
|
b=_rotor->getBalance();
|
|
|
|
float s =Math::sin(_phi+_direction);
|
|
|
|
float c =Math::cos(_phi+_direction);
|
|
|
|
if (s>0)
|
|
|
|
_balance=(b>0)?(1.-s*(1.-b)):(1.-s)*(1.+b);
|
|
|
|
else
|
|
|
|
_balance=(b>0)?1.:1.+b;
|
2006-08-14 21:59:44 +00:00
|
|
|
}
|
2003-10-16 14:40:13 +00:00
|
|
|
|
2006-08-14 21:59:44 +00:00
|
|
|
void Rotorpart::setRotor(Rotor *rotor)
|
|
|
|
{
|
|
|
|
_rotor=rotor;
|
|
|
|
}
|
2003-10-16 14:40:13 +00:00
|
|
|
|
2006-08-14 21:59:44 +00:00
|
|
|
void Rotorpart::setParameter(char *parametername, float value)
|
|
|
|
{
|
|
|
|
#define p(a) if (strcmp(parametername,#a)==0) _##a = value; else
|
2003-10-16 14:40:13 +00:00
|
|
|
|
2006-08-14 21:59:44 +00:00
|
|
|
p(twist)
|
|
|
|
p(number_of_segments)
|
|
|
|
p(rel_len_where_incidence_is_measured)
|
|
|
|
p(rel_len_blade_start)
|
2006-09-14 18:18:33 +00:00
|
|
|
p(rotor_correction_factor)
|
|
|
|
SG_LOG(SG_INPUT, SG_ALERT,
|
|
|
|
"internal error in parameter set up for rotorpart: '"
|
|
|
|
<< parametername <<"'" << endl);
|
2006-08-14 21:59:44 +00:00
|
|
|
#undef p
|
2003-10-16 14:40:13 +00:00
|
|
|
}
|
2006-08-14 21:59:44 +00:00
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
void Rotorpart::setTorque(float torque_max_force,float torque_no_force)
|
|
|
|
{
|
|
|
|
_torque_max_force=torque_max_force;
|
|
|
|
_torque_no_force=torque_no_force;
|
|
|
|
}
|
|
|
|
|
2006-08-14 21:59:44 +00:00
|
|
|
void Rotorpart::setTorqueOfInertia(float toi)
|
|
|
|
{
|
|
|
|
_torque_of_inertia=toi;
|
|
|
|
}
|
2003-10-16 14:40:13 +00:00
|
|
|
|
|
|
|
void Rotorpart::setWeight(float value)
|
|
|
|
{
|
2006-08-14 21:59:44 +00:00
|
|
|
_mass=value;
|
2003-10-16 14:40:13 +00:00
|
|
|
}
|
2006-08-14 21:59:44 +00:00
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
float Rotorpart::getWeight(void)
|
|
|
|
{
|
2006-08-14 21:59:44 +00:00
|
|
|
return(_mass/.453); //_mass is in kg, returns pounds
|
2003-10-16 14:40:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Rotorpart::setPosition(float* p)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i=0; i<3; i++) _pos[i] = p[i];
|
|
|
|
}
|
2006-08-14 21:59:44 +00:00
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
float Rotorpart::getIncidence()
|
|
|
|
{
|
|
|
|
return(_incidence);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Rotorpart::getPosition(float* out)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i=0; i<3; i++) out[i] = _pos[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
void Rotorpart::setPositionForceAttac(float* p)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i=0; i<3; i++) _posforceattac[i] = p[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
void Rotorpart::getPositionForceAttac(float* out)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i=0; i<3; i++) out[i] = _posforceattac[i];
|
|
|
|
}
|
2006-08-14 21:59:44 +00:00
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
void Rotorpart::setSpeed(float* p)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i=0; i<3; i++) _speed[i] = p[i];
|
2006-08-14 21:59:44 +00:00
|
|
|
Math::unit3(_speed,_direction_of_movement);
|
2003-10-16 14:40:13 +00:00
|
|
|
}
|
2006-08-14 21:59:44 +00:00
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
void Rotorpart::setDirectionofZentipetalforce(float* p)
|
|
|
|
{
|
|
|
|
int i;
|
2007-01-17 20:30:34 +00:00
|
|
|
for(i=0; i<3; i++) _directionofcentripetalforce[i] = p[i];
|
2003-10-16 14:40:13 +00:00
|
|
|
}
|
|
|
|
|
2006-08-14 21:59:44 +00:00
|
|
|
void Rotorpart::setDirectionofRotorPart(float* p)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i=0; i<3; i++) _directionofrotorpart[i] = p[i];
|
|
|
|
}
|
|
|
|
|
2007-05-25 21:15:59 +00:00
|
|
|
void Rotorpart::setDirection(float direction)
|
|
|
|
{
|
|
|
|
_direction=direction;
|
|
|
|
}
|
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
void Rotorpart::setOmega(float value)
|
|
|
|
{
|
2006-08-14 21:59:44 +00:00
|
|
|
_omega=value;
|
2003-10-16 14:40:13 +00:00
|
|
|
}
|
2006-08-14 21:59:44 +00:00
|
|
|
|
2007-05-09 20:36:43 +00:00
|
|
|
void Rotorpart::setPhi(float value)
|
|
|
|
{
|
|
|
|
_phi=value;
|
|
|
|
}
|
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
void Rotorpart::setOmegaN(float value)
|
|
|
|
{
|
2006-08-14 21:59:44 +00:00
|
|
|
_omegan=value;
|
2003-10-16 14:40:13 +00:00
|
|
|
}
|
|
|
|
|
2006-08-14 21:59:44 +00:00
|
|
|
void Rotorpart::setDdtOmega(float value)
|
|
|
|
{
|
|
|
|
_ddt_omega=value;
|
|
|
|
}
|
2003-10-16 14:40:13 +00:00
|
|
|
|
|
|
|
void Rotorpart::setZentipetalForce(float f)
|
|
|
|
{
|
2007-01-17 20:30:34 +00:00
|
|
|
_centripetalforce=f;
|
2003-10-16 14:40:13 +00:00
|
|
|
}
|
2006-08-14 21:59:44 +00:00
|
|
|
|
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
void Rotorpart::setDelta3(float f)
|
|
|
|
{
|
|
|
|
_delta3=f;
|
|
|
|
}
|
2006-08-14 21:59:44 +00:00
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
void Rotorpart::setRelamp(float f)
|
|
|
|
{
|
|
|
|
_relamp=f;
|
|
|
|
}
|
2006-08-14 21:59:44 +00:00
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
void Rotorpart::setTranslift(float f)
|
|
|
|
{
|
|
|
|
_translift=f;
|
|
|
|
}
|
2006-08-14 21:59:44 +00:00
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
void Rotorpart::setDynamic(float f)
|
|
|
|
{
|
|
|
|
_dynamic=f;
|
|
|
|
}
|
2006-08-14 21:59:44 +00:00
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
void Rotorpart::setRelLenHinge(float f)
|
|
|
|
{
|
|
|
|
_rellenhinge=f;
|
|
|
|
}
|
2006-08-14 21:59:44 +00:00
|
|
|
|
2007-05-09 20:36:43 +00:00
|
|
|
void Rotorpart::setSharedFlapHinge(bool s)
|
|
|
|
{
|
|
|
|
_shared_flap_hinge=s;
|
|
|
|
}
|
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
void Rotorpart::setC2(float f)
|
|
|
|
{
|
|
|
|
_c2=f;
|
|
|
|
}
|
2006-08-14 21:59:44 +00:00
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
void Rotorpart::setAlpha0(float f)
|
|
|
|
{
|
2007-01-17 20:30:34 +00:00
|
|
|
if (f>-0.01) f=-0.01; //half a degree bending
|
2003-10-16 14:40:13 +00:00
|
|
|
_alpha0=f;
|
|
|
|
}
|
2006-08-14 21:59:44 +00:00
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
void Rotorpart::setAlphamin(float f)
|
|
|
|
{
|
|
|
|
_alphamin=f;
|
|
|
|
}
|
2006-08-14 21:59:44 +00:00
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
void Rotorpart::setAlphamax(float f)
|
|
|
|
{
|
|
|
|
_alphamax=f;
|
|
|
|
}
|
2006-08-14 21:59:44 +00:00
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
void Rotorpart::setAlpha0factor(float f)
|
|
|
|
{
|
|
|
|
_alpha0factor=f;
|
|
|
|
}
|
|
|
|
|
2006-08-14 21:59:44 +00:00
|
|
|
void Rotorpart::setDiameter(float f)
|
|
|
|
{
|
|
|
|
_diameter=f;
|
|
|
|
}
|
2003-10-16 14:40:13 +00:00
|
|
|
|
|
|
|
float Rotorpart::getPhi()
|
|
|
|
{
|
2006-08-14 21:59:44 +00:00
|
|
|
return(_phi);
|
2003-10-16 14:40:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
float Rotorpart::getAlpha(int i)
|
|
|
|
{
|
2006-08-14 21:59:44 +00:00
|
|
|
i=i&1;
|
2003-10-16 14:40:13 +00:00
|
|
|
|
2006-08-14 21:59:44 +00:00
|
|
|
if (i==0)
|
2006-09-14 18:18:33 +00:00
|
|
|
return _alpha*180/pi;//in Grad = 1
|
2006-08-14 21:59:44 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (_alpha2type==1) //yaw or roll
|
|
|
|
return (getAlpha(0)-_oppositerp->getAlpha(0))/2;
|
|
|
|
else //collective
|
|
|
|
return (getAlpha(0)+_oppositerp->getAlpha(0)+
|
2006-09-14 18:18:33 +00:00
|
|
|
_next90rp->getAlpha(0)+_last90rp->getAlpha(0))/4;
|
2006-08-14 21:59:44 +00:00
|
|
|
}
|
2003-10-16 14:40:13 +00:00
|
|
|
}
|
|
|
|
float Rotorpart::getrealAlpha(void)
|
|
|
|
{
|
|
|
|
return _alpha;
|
|
|
|
}
|
2006-08-14 21:59:44 +00:00
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
void Rotorpart::setAlphaoutput(char *text,int i)
|
|
|
|
{
|
2006-08-14 21:59:44 +00:00
|
|
|
strncpy(_alphaoutputbuf[i>0],text,255);
|
|
|
|
if (i>0) _alpha2type=i;
|
2003-10-16 14:40:13 +00:00
|
|
|
}
|
2006-08-14 21:59:44 +00:00
|
|
|
|
2003-10-16 14:40:13 +00:00
|
|
|
char* Rotorpart::getAlphaoutput(int i)
|
|
|
|
{
|
|
|
|
return _alphaoutputbuf[i&1];
|
|
|
|
}
|
|
|
|
|
|
|
|
void Rotorpart::setLen(float value)
|
|
|
|
{
|
2006-08-14 21:59:44 +00:00
|
|
|
_len=value;
|
2003-10-16 14:40:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Rotorpart::setNormal(float* p)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i=0; i<3; i++) _normal[i] = p[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
void Rotorpart::getNormal(float* out)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i=0; i<3; i++) out[i] = _normal[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
void Rotorpart::setCollective(float pos)
|
|
|
|
{
|
|
|
|
_collective = pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Rotorpart::setCyclic(float pos)
|
|
|
|
{
|
|
|
|
_cyclic = pos;
|
|
|
|
}
|
|
|
|
|
2006-08-14 21:59:44 +00:00
|
|
|
void Rotorpart::setlastnextrp(Rotorpart*lastrp,Rotorpart*nextrp,
|
2006-09-14 18:18:33 +00:00
|
|
|
Rotorpart *oppositerp,Rotorpart*last90rp,Rotorpart*next90rp)
|
2003-10-16 14:40:13 +00:00
|
|
|
{
|
2006-08-14 21:59:44 +00:00
|
|
|
_lastrp=lastrp;
|
|
|
|
_nextrp=nextrp;
|
|
|
|
_oppositerp=oppositerp;
|
2006-09-14 18:18:33 +00:00
|
|
|
_last90rp=last90rp;
|
|
|
|
_next90rp=next90rp;
|
2003-10-16 14:40:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Rotorpart::strncpy(char *dest,const char *src,int maxlen)
|
|
|
|
{
|
2006-08-14 21:59:44 +00:00
|
|
|
int n=0;
|
|
|
|
while(src[n]&&n<(maxlen-1))
|
|
|
|
{
|
|
|
|
dest[n]=src[n];
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
dest[n]=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate the flapping angle, where zentripetal force and
|
|
|
|
//lift compensate each other
|
|
|
|
float Rotorpart::calculateAlpha(float* v_rel_air, float rho,
|
|
|
|
float incidence, float cyc, float alphaalt, float *torque,
|
|
|
|
float *returnlift)
|
|
|
|
{
|
|
|
|
float moment[3],v_local[3],v_local_scalar,lift_moment,v_flap[3],v_help[3];
|
|
|
|
float ias;//nur f. dgb
|
|
|
|
int i,n;
|
|
|
|
for (i=0;i<3;i++)
|
|
|
|
moment[i]=0;
|
2007-05-15 21:30:33 +00:00
|
|
|
float relgrav = Math::dot3(_normal,_rotor->getGravDirection());
|
|
|
|
lift_moment=-_mass*_len*9.81*relgrav;
|
2006-08-14 21:59:44 +00:00
|
|
|
*torque=0;//
|
|
|
|
if((_nextrp==NULL)||(_lastrp==NULL)||(_rotor==NULL))
|
|
|
|
return 0.0;//not initialized. Can happen during startupt of flightgear
|
|
|
|
if (returnlift!=NULL) *returnlift=0;
|
2006-09-14 18:18:33 +00:00
|
|
|
float flap_omega=(_next90rp->getrealAlpha()-_last90rp->getrealAlpha())
|
2006-08-14 21:59:44 +00:00
|
|
|
*_omega / pi;
|
|
|
|
float local_width=_diameter*(1-_rel_len_blade_start)/2.
|
|
|
|
/(float (_number_of_segments));
|
|
|
|
for (n=0;n<_number_of_segments;n++)
|
|
|
|
{
|
|
|
|
float rel = (n+.5)/(float (_number_of_segments));
|
|
|
|
float r= _diameter *0.5 *(rel*(1-_rel_len_blade_start)
|
|
|
|
+_rel_len_blade_start);
|
2006-09-14 18:18:33 +00:00
|
|
|
float local_incidence=incidence+_twist *rel -
|
|
|
|
_twist *_rel_len_where_incidence_is_measured;
|
2006-08-14 21:59:44 +00:00
|
|
|
float local_chord = _rotor->getChord()*rel+_rotor->getChord()
|
|
|
|
*_rotor->getTaper()*(1-rel);
|
|
|
|
float A = local_chord * local_width;
|
|
|
|
//calculate the local air speed and the incidence to this speed;
|
|
|
|
Math::mul3(_omega * r , _direction_of_movement , v_local);
|
|
|
|
|
|
|
|
// add speed component due to flapping
|
|
|
|
Math::mul3(flap_omega * r,_normal,v_flap);
|
|
|
|
Math::add3(v_flap,v_local,v_local);
|
|
|
|
Math::sub3(v_rel_air,v_local,v_local);
|
|
|
|
//v_local is now the total airspeed at the blade
|
|
|
|
//apparent missing: calculating the local_wind = v_rel_air at
|
|
|
|
//every point of the rotor. It differs due to aircraft-rotation
|
|
|
|
//it is considered in v_flap
|
|
|
|
|
|
|
|
//substract now the component of the air speed parallel to
|
|
|
|
//the blade;
|
2006-09-14 18:18:33 +00:00
|
|
|
Math::mul3(Math::dot3(v_local,_directionofrotorpart),
|
2006-08-14 21:59:44 +00:00
|
|
|
_directionofrotorpart,v_help);
|
|
|
|
Math::sub3(v_local,v_help,v_local);
|
|
|
|
|
|
|
|
//split into direction and magnitude
|
|
|
|
v_local_scalar=Math::mag3(v_local);
|
|
|
|
if (v_local_scalar!=0)
|
2006-09-14 18:18:33 +00:00
|
|
|
//Math::unit3(v_local,v_help);
|
|
|
|
Math::mul3(1/v_local_scalar,v_local,v_help);
|
2006-08-14 21:59:44 +00:00
|
|
|
float incidence_of_airspeed = Math::asin(Math::clamp(
|
2006-09-14 18:18:33 +00:00
|
|
|
Math::dot3(v_help,_normal),-1,1)) + local_incidence;
|
|
|
|
ias = incidence_of_airspeed;
|
|
|
|
|
|
|
|
//reduce the ias (Prantl factor)
|
|
|
|
float prantl_factor=2/pi*Math::acos(Math::exp(
|
|
|
|
-_rotor->getNumberOfBlades()/2.*(1-rel)
|
|
|
|
*Math::sqrt(1+1/Math::sqr(Math::tan(
|
|
|
|
pi/2-Math::abs(incidence_of_airspeed-local_incidence))))));
|
|
|
|
incidence_of_airspeed = (incidence_of_airspeed+
|
|
|
|
_rotor->getAirfoilIncidenceNoLift())*prantl_factor
|
|
|
|
*_rotor_correction_factor-_rotor->getAirfoilIncidenceNoLift();
|
2006-08-14 21:59:44 +00:00
|
|
|
ias = incidence_of_airspeed;
|
2006-09-14 18:18:33 +00:00
|
|
|
float lift_wo_cyc = _rotor->getLiftCoef(incidence_of_airspeed
|
2007-05-09 20:36:43 +00:00
|
|
|
-cyc*_rotor_correction_factor*prantl_factor,v_local_scalar)
|
2006-08-14 21:59:44 +00:00
|
|
|
* v_local_scalar * v_local_scalar * A *rho *0.5;
|
|
|
|
float lift_with_cyc =
|
|
|
|
_rotor->getLiftCoef(incidence_of_airspeed,v_local_scalar)
|
|
|
|
* v_local_scalar * v_local_scalar *A *rho*0.5;
|
|
|
|
float lift=lift_wo_cyc+_relamp*(lift_with_cyc-lift_wo_cyc);
|
|
|
|
//take into account that the rotor is a resonant system where
|
|
|
|
//the cyclic input hase increased result
|
|
|
|
float drag = -_rotor->getDragCoef(incidence_of_airspeed,v_local_scalar)
|
|
|
|
* v_local_scalar * v_local_scalar * A *rho*0.5;
|
|
|
|
float angle = incidence_of_airspeed - incidence;
|
|
|
|
//angle between blade movement caused by rotor-rotation and the
|
|
|
|
//total movement of the blade
|
|
|
|
|
|
|
|
lift_moment += r*(lift * Math::cos(angle)
|
|
|
|
- drag * Math::sin(angle));
|
|
|
|
*torque += r*(drag * Math::cos(angle)
|
|
|
|
+ lift * Math::sin(angle));
|
|
|
|
if (returnlift!=NULL) *returnlift+=lift;
|
|
|
|
}
|
2007-07-31 15:51:04 +00:00
|
|
|
//use 1st order approximation for alpha
|
2007-01-17 20:30:34 +00:00
|
|
|
//float alpha=Math::atan2(lift_moment,_centripetalforce * _len);
|
2006-09-14 18:18:33 +00:00
|
|
|
float alpha;
|
2007-05-09 20:36:43 +00:00
|
|
|
if (_shared_flap_hinge)
|
|
|
|
{
|
|
|
|
float div=0;
|
|
|
|
if (Math::abs(_alphaalt) >1e-6)
|
2007-05-15 21:30:33 +00:00
|
|
|
div=(_centripetalforce * _len - _mass * _len * 9.81 * relgrav /_alpha0*(_alphaalt+_oppositerp->getAlphaAlt())/(2.0*_alphaalt));
|
2007-05-09 20:36:43 +00:00
|
|
|
if (Math::abs(div)>1e-6)
|
2007-06-23 06:41:17 +00:00
|
|
|
{
|
2007-05-09 20:36:43 +00:00
|
|
|
alpha=lift_moment/div;
|
2007-06-23 06:41:17 +00:00
|
|
|
}
|
2007-05-09 20:36:43 +00:00
|
|
|
else if(Math::abs(_alphaalt+_oppositerp->getAlphaAlt())>1e-6)
|
|
|
|
{
|
2007-05-15 21:30:33 +00:00
|
|
|
float div=(_centripetalforce * _len - _mass * _len * 9.81 *0.5 * relgrav)*(_alphaalt+_oppositerp->getAlphaAlt());
|
2007-05-09 20:36:43 +00:00
|
|
|
if (Math::abs(div)>1e-6)
|
2007-06-23 06:41:17 +00:00
|
|
|
{
|
2007-05-09 20:36:43 +00:00
|
|
|
alpha=_oppositerp->getAlphaAlt()+lift_moment/div*_alphaalt;
|
2007-06-23 06:41:17 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
alpha=_alphaalt;
|
2007-05-09 20:36:43 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
alpha=_alphaalt;
|
2007-06-23 06:41:17 +00:00
|
|
|
if (_omega/_omegan<0.2)
|
|
|
|
{
|
|
|
|
float frac = 0.001+_omega/_omegan*4.995;
|
|
|
|
alpha=Math::clamp(alpha,_alphamin,_alphamax);
|
|
|
|
alpha=_alphaalt*(1-frac)+frac*alpha;
|
|
|
|
}
|
2007-05-09 20:36:43 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
float div=(_centripetalforce * _len - _mass * _len * 9.81 /_alpha0);
|
|
|
|
if (Math::abs(div)>1e-6)
|
|
|
|
alpha=lift_moment/div;
|
|
|
|
else
|
|
|
|
alpha=_alphaalt;
|
|
|
|
}
|
|
|
|
|
2006-08-14 21:59:44 +00:00
|
|
|
return (alpha);
|
2003-10-16 14:40:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate the aerodynamic force given a wind vector v (in the
|
|
|
|
// aircraft's "local" coordinates) and an air density rho. Returns a
|
|
|
|
// torque about the Y axis, too.
|
2006-08-14 21:59:44 +00:00
|
|
|
void Rotorpart::calcForce(float* v, float rho, float* out, float* torque,
|
|
|
|
float* torque_scalar)
|
2003-10-16 14:40:13 +00:00
|
|
|
{
|
2006-08-14 21:59:44 +00:00
|
|
|
if (_compiled!=1)
|
2003-10-16 14:40:13 +00:00
|
|
|
{
|
2006-08-14 21:59:44 +00:00
|
|
|
for (int i=0;i<3;i++)
|
|
|
|
torque[i]=out[i]=0;
|
|
|
|
*torque_scalar=0;
|
|
|
|
return;
|
2003-10-16 14:40:13 +00:00
|
|
|
}
|
2007-01-17 20:30:34 +00:00
|
|
|
_centripetalforce=_mass*_len*_omega*_omega;
|
2006-08-14 21:59:44 +00:00
|
|
|
float vrel[3],vreldir[3];
|
|
|
|
Math::sub3(_speed,v,vrel);
|
2007-01-17 20:30:34 +00:00
|
|
|
float scalar_torque=0;
|
2006-08-14 21:59:44 +00:00
|
|
|
Math::unit3(vrel,vreldir);//direction of blade-movement rel. to air
|
|
|
|
//Angle of blade which would produce no vertical force (where the
|
|
|
|
//effective incidence is zero)
|
|
|
|
|
2006-09-14 18:18:33 +00:00
|
|
|
float cyc=_cyclic;
|
2007-05-09 20:36:43 +00:00
|
|
|
float col=_collective;
|
|
|
|
if (_shared_flap_hinge)
|
|
|
|
_incidence=(col+cyc)-_delta3*0.5*(_alphaalt-_oppositerp->getAlphaAlt());
|
|
|
|
else
|
|
|
|
_incidence=(col+cyc)-_delta3*_alphaalt;
|
2006-08-14 21:59:44 +00:00
|
|
|
//the incidence of the rotorblade due to control input reduced by the
|
|
|
|
//delta3 effect, see README.YASIM
|
2006-09-14 18:18:33 +00:00
|
|
|
//float beta=_relamp*cyc+col;
|
2006-08-14 21:59:44 +00:00
|
|
|
//the incidence of the rotorblade which is used for the calculation
|
|
|
|
|
|
|
|
float alpha,factor; //alpha is the flapping angle
|
|
|
|
//the new flapping angle will be the old flapping angle
|
|
|
|
//+ factor *(alpha - "old flapping angle")
|
2007-01-17 20:30:34 +00:00
|
|
|
alpha=calculateAlpha(v,rho,_incidence,cyc,0,&scalar_torque);
|
2007-05-09 20:36:43 +00:00
|
|
|
alpha=Math::clamp(alpha,_alphamin,_alphamax);
|
2007-01-17 20:30:34 +00:00
|
|
|
//the incidence is a function of alpha (if _delta* != 0)
|
|
|
|
//Therefore missing: wrap this function in an integrator
|
|
|
|
//(runge kutta e. g.)
|
2003-10-16 14:40:13 +00:00
|
|
|
|
2007-01-17 20:30:34 +00:00
|
|
|
factor=_dt*_dynamic;
|
|
|
|
if (factor>1) factor=1;
|
2003-10-16 14:40:13 +00:00
|
|
|
|
2006-08-14 21:59:44 +00:00
|
|
|
float dirblade[3];
|
2007-01-17 20:30:34 +00:00
|
|
|
Math::cross3(_normal,_directionofcentripetalforce,dirblade);
|
2006-08-14 21:59:44 +00:00
|
|
|
float vblade=Math::abs(Math::dot3(dirblade,v));
|
|
|
|
|
|
|
|
alpha=_alphaalt+(alpha-_alphaalt)*factor;
|
|
|
|
_alpha=alpha;
|
2006-09-14 18:18:33 +00:00
|
|
|
float meancosalpha=(1*Math::cos(_last90rp->getrealAlpha())
|
|
|
|
+1*Math::cos(_next90rp->getrealAlpha())
|
2006-08-14 21:59:44 +00:00
|
|
|
+1*Math::cos(_oppositerp->getrealAlpha())
|
|
|
|
+1*Math::cos(alpha))/4;
|
2006-09-14 18:18:33 +00:00
|
|
|
float schwenkfactor=1-(Math::cos(_lastrp->getrealAlpha())-meancosalpha)*_rotor->getNumberOfParts()/4;
|
2006-08-14 21:59:44 +00:00
|
|
|
|
|
|
|
//missing: consideration of rellenhinge
|
2007-05-25 21:15:59 +00:00
|
|
|
|
|
|
|
//add the unbalance
|
|
|
|
_centripetalforce*=_balance;
|
|
|
|
scalar_torque*=_balance;
|
|
|
|
|
2007-01-17 20:30:34 +00:00
|
|
|
float xforce = Math::cos(alpha)*_centripetalforce;
|
|
|
|
float zforce = schwenkfactor*Math::sin(alpha)*_centripetalforce;
|
2006-08-14 21:59:44 +00:00
|
|
|
*torque_scalar=scalar_torque;
|
|
|
|
scalar_torque+= 0*_ddt_omega*_torque_of_inertia;
|
|
|
|
float thetorque = scalar_torque;
|
|
|
|
int i;
|
|
|
|
float f=_rotor->getCcw()?1:-1;
|
|
|
|
for(i=0; i<3; i++) {
|
|
|
|
_last_torque[i]=torque[i] = f*_normal[i]*thetorque;
|
|
|
|
out[i] = _normal[i]*zforce*_rotor->getLiftFactor()
|
2007-01-17 20:30:34 +00:00
|
|
|
+_directionofcentripetalforce[i]*xforce;
|
2006-08-14 21:59:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Rotorpart::getAccelTorque(float relaccel,float *t)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
float f=_rotor->getCcw()?1:-1;
|
|
|
|
for(i=0; i<3; i++) {
|
2006-09-14 18:18:33 +00:00
|
|
|
t[i]=f*-1* _normal[i]*relaccel*_omegan* _torque_of_inertia;// *_omeagan ?
|
2006-08-14 21:59:44 +00:00
|
|
|
_rotor->addTorque(-relaccel*_omegan* _torque_of_inertia);
|
|
|
|
}
|
|
|
|
}
|
2006-09-14 18:18:33 +00:00
|
|
|
std::ostream & operator<<(std::ostream & out, const Rotorpart& rp)
|
|
|
|
{
|
|
|
|
#define i(x) << #x << ":" << rp.x << endl
|
|
|
|
#define iv(x) << #x << ":" << rp.x[0] << ";" << rp.x[1] << ";" <<rp.x[2] << ";" << endl
|
|
|
|
out << "Writing Info on Rotorpart " << endl
|
|
|
|
i( _dt)
|
|
|
|
iv( _last_torque)
|
|
|
|
i( _compiled)
|
|
|
|
iv( _pos) // position in local coords
|
|
|
|
iv( _posforceattac) // position in local coords
|
|
|
|
iv( _normal) //direcetion of the rotation axis
|
|
|
|
i( _torque_max_force)
|
|
|
|
i( _torque_no_force)
|
|
|
|
iv( _speed)
|
|
|
|
iv( _direction_of_movement)
|
2007-01-17 20:30:34 +00:00
|
|
|
iv( _directionofcentripetalforce)
|
2006-09-14 18:18:33 +00:00
|
|
|
iv( _directionofrotorpart)
|
2007-01-17 20:30:34 +00:00
|
|
|
i( _centripetalforce)
|
2006-09-14 18:18:33 +00:00
|
|
|
i( _cyclic)
|
|
|
|
i( _collective)
|
|
|
|
i( _delta3)
|
|
|
|
i( _dynamic)
|
|
|
|
i( _translift)
|
|
|
|
i( _c2)
|
|
|
|
i( _mass)
|
|
|
|
i( _alpha)
|
|
|
|
i( _alphaalt)
|
|
|
|
i( _alphamin) i(_alphamax) i(_alpha0) i(_alpha0factor)
|
|
|
|
i( _rellenhinge)
|
|
|
|
i( _relamp)
|
|
|
|
i( _omega) i(_omegan) i(_ddt_omega)
|
|
|
|
i( _phi)
|
|
|
|
i( _len)
|
|
|
|
i( _incidence)
|
|
|
|
i( _twist) //outer incidence = inner inner incidence + _twist
|
|
|
|
i( _number_of_segments)
|
|
|
|
i( _rel_len_where_incidence_is_measured)
|
|
|
|
i( _rel_len_blade_start)
|
|
|
|
i( _diameter)
|
|
|
|
i( _torque_of_inertia)
|
|
|
|
i( _torque)
|
|
|
|
i (_alphaoutputbuf[0])
|
|
|
|
i (_alphaoutputbuf[1])
|
|
|
|
i( _alpha2type)
|
|
|
|
i(_rotor_correction_factor)
|
|
|
|
<< endl;
|
|
|
|
#undef i
|
|
|
|
#undef iv
|
|
|
|
return out;
|
|
|
|
}
|
2003-10-16 14:40:13 +00:00
|
|
|
}; // namespace yasim
|