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);
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") );
if(a->hasAttribute("alphaout0"))
_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;
_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;
_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);
_translift=value;
}
+void Rotor::setSharedFlapHinge(bool s)
+{
+ _shared_flap_hinge=s;
+}
+
void Rotor::setC2(float value)
{
_c2=value;
_rotor_rpm=value;
}
+void Rotor::setPhiNull(float value)
+{
+ _phi_null=value;
+}
+
void Rotor::setRelLenHinge(float value)
{
_rel_len_hinge=value;
{
lval = Math::clamp(lval, -1, 1);
int i;
+ _collective=_min_pitch+(lval+1)/2*(_max_pitch-_min_pitch);
for(i=0; i<_rotorparts.size(); i++) {
- ((Rotorpart*)_rotorparts.get(i))->setCollective(lval);
+ ((Rotorpart*)_rotorparts.get(i))->setCollective(_collective);
}
- _collective=_min_pitch+(lval+1)/2*(_max_pitch-_min_pitch);
}
void Rotor::setCyclicele(float lval,float rval)
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;
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);
//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));
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
}
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();
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);
private:
float _torque;
float _omega,_omegan,_omegarel,_ddt_omega,_omegarelneu;
+ float _phi_null;
float _chord;
float _taper;
float _airfoil_incidence_no_lift;
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);
float getOverallStall()
{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);
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];
float _cyclicele;
float _cyclic_factor;
float _rotor_correction_factor;
+ float _phi;
+ bool _shared_flap_hinge;
};
std::ostream & operator<<(std::ostream & out, /*const*/ Rotor& r);
_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);
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;
_omega=value;
}
+void Rotorpart::setPhi(float value)
+{
+ _phi=value;
+}
+
void Rotorpart::setOmegaN(float value)
{
_omegan=value;
_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)
{
_rellenhinge=f;
}
+void Rotorpart::setSharedFlapHinge(bool s)
+{
+ _shared_flap_hinge=s;
+}
+
void Rotorpart::setC2(float f)
{
_c2=f;
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.
*_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)
//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);
}
//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);
- _incidence=(col+cyc)-_delta3*_alphaalt;
+ 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
//float beta=_relamp*cyc+col;
//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.)
iv( _directionofcentripetalforce)
iv( _directionofrotorpart)
i( _centripetalforce)
- i( _maxpitch)
- i( _minpitch)
- i( _maxcyclic)
- i( _mincyclic)
i( _cyclic)
i( _collective)
i( _delta3)
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();
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);
float _directionofcentripetalforce[3];
float _directionofrotorpart[3];
float _centripetalforce;
- float _maxpitch;
- float _minpitch;
- float _maxcyclic;
- float _mincyclic;
float _cyclic;
float _collective;
float _delta3;
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