+void Rotorgear::initRotorIteration(float *lrot,float dt)
+{
+ int i;
+ float omegarel;
+ if (!_rotors.size()) return;
+ Rotor* r0 = (Rotor*)_rotors.get(0);
+ omegarel= r0->getOmegaRelNeu();
+ for(i=0; i<_rotors.size(); i++) {
+ Rotor* r = (Rotor*)_rotors.get(i);
+ r->inititeration(dt,omegarel,0,lrot);
+ }
+}
+
+void Rotorgear::calcForces(float* torqueOut)
+{
+ int i,j;
+ torqueOut[0]=torqueOut[1]=torqueOut[2]=0;
+ // check,<if the engine can handle the torque of the rotors.
+ // If not reduce the torque to the fueselage and change rotational
+ // speed of the rotors instead
+ if (_rotors.size())
+ {
+ float omegarel,omegan;
+ Rotor* r0 = (Rotor*)_rotors.get(0);
+ omegarel= r0->getOmegaRel();
+
+ float total_torque_of_inertia=0;
+ float total_torque=0;
+ for(i=0; i<_rotors.size(); i++) {
+ Rotor* r = (Rotor*)_rotors.get(i);
+ omegan=r->getOmegan();
+ total_torque_of_inertia+=r->getTorqueOfInertia()*omegan*omegan;
+ //FIXME: this is constant, so this can be done in compile
+
+ total_torque+=r->getTorque()*omegan;
+ }
+ float max_torque_of_engine=0;
+ // SGPropertyNode * node=fgGetNode("/rotors/gear", true);
+ if (_engineon)
+ {
+ max_torque_of_engine=_max_power_engine*_max_rel_torque;
+ float df=_target_rel_rpm-omegarel;
+ df/=_engine_prop_factor;
+ df = Math::clamp(df, 0, 1);
+ max_torque_of_engine = df * _max_power_engine*_max_rel_torque;
+ }
+ total_torque*=-1;
+ _ddt_omegarel=0;
+ float rel_torque_engine=1;
+ if (total_torque<=0)
+ rel_torque_engine=0;
+ else
+ if (max_torque_of_engine>0)
+ rel_torque_engine=1/max_torque_of_engine*total_torque;
+ else
+ rel_torque_engine=0;
+
+ //add the rotor brake and the gear fritcion
+ float dt=0.1f;
+ if (r0->_rotorparts.size()) dt=((Rotorpart*)r0->_rotorparts.get(0))->getDt();
+
+ float rotor_brake_torque;
+ rotor_brake_torque=_rotorbrake*_max_power_rotor_brake+_rotorgear_friction;
+ //clamp it to the value you need to stop the rotor
+ //to avod accelerate the rotor to neagtive rpm:
+ rotor_brake_torque=Math::clamp(rotor_brake_torque,0,
+ total_torque_of_inertia/dt*omegarel);
+ max_torque_of_engine-=rotor_brake_torque;
+
+ //change the rotation of the rotors
+ if ((max_torque_of_engine<total_torque) //decreasing rotation
+ ||((max_torque_of_engine>total_torque)&&(omegarel<_target_rel_rpm))
+ //increasing rotation due to engine
+ ||(total_torque<0) ) //increasing rotation due to autorotation
+ {
+ _ddt_omegarel=(max_torque_of_engine-total_torque)/total_torque_of_inertia;
+ if(max_torque_of_engine>total_torque)
+ {
+ //check if the acceleration is due to the engine. If yes,
+ //the engine self limits the accel.
+ float lim1=-total_torque/total_torque_of_inertia;
+ //accel. by autorotation
+
+ if (lim1<_engine_accel_limit) lim1=_engine_accel_limit;
+ //if the accel by autorotation greater than the max. engine
+ //accel, then this is the limit, if not: the engine is the limit
+ if (_ddt_omegarel>lim1) _ddt_omegarel=lim1;
+ }
+ if (_ddt_omegarel>5.5)_ddt_omegarel=5.5;
+ //clamp it to avoid overflow. Should never be reached
+ if (_ddt_omegarel<-5.5)_ddt_omegarel=-5.5;
+
+ if (_max_power_engine<0.001) {omegarel=1;_ddt_omegarel=0;}
+ //for debug: negative or no maxpower will result
+ //in permanet 100% rotation
+
+ omegarel+=dt*_ddt_omegarel;
+
+ if (omegarel>2.5) omegarel=2.5;
+ //clamp it to avoid overflow. Should never be reached
+ if (omegarel<-.5) omegarel=-.5;
+
+ r0->setOmegaRelNeu(omegarel);
+ //calculate the torque, which is needed to accelerate the rotors.
+ //Add this additional torque to the body
+ for(j=0; j<_rotors.size(); j++) {
+ Rotor* r = (Rotor*)_rotors.get(j);
+ for(i=0; i<r->_rotorparts.size(); i++) {
+ // float torque_scalar=0;
+ Rotorpart* rp = (Rotorpart*)r->_rotorparts.get(i);
+ float torque[3];
+ rp->getAccelTorque(_ddt_omegarel,torque);
+ Math::add3(torque,torqueOut,torqueOut);
+ }
+ }
+ }
+ _total_torque_on_engine=total_torque+_ddt_omegarel*total_torque_of_inertia;
+ }
+}
+
+void Rotorgear::addRotor(Rotor* rotor)
+{
+ _rotors.add(rotor);
+ _in_use = 1;
+}
+
+void Rotorgear::compile()
+{
+ // float wgt = 0;
+ for(int j=0; j<_rotors.size(); j++) {
+ Rotor* r = (Rotor*)_rotors.get(j);
+ r->compile();
+ }
+}
+
+void Rotorgear::getDownWash(float *pos, float * v_heli, float *downwash)
+{
+ float tmp[3];
+ downwash[0]=downwash[1]=downwash[2]=0;
+ for(int i=0; i<_rotors.size(); i++) {
+ Rotor* ro = (Rotor*)_rotors.get(i);
+ ro->getDownWash(pos,v_heli,tmp);
+ Math::add3(downwash,tmp,downwash); // + downwash
+ }
+}
+
+void Rotorgear::setParameter(char *parametername, float value)
+{
+#define p(a,b) if (strcmp(parametername,#a)==0) _##a = (value * (b)); else
+ p(max_power_engine,1000)
+ p(engine_prop_factor,1)
+ p(yasimdragfactor,1)
+ p(yasimliftfactor,1)
+ p(max_power_rotor_brake,1000)
+ p(rotorgear_friction,1000)
+ p(engine_accel_limit,0.01)
+ SG_LOG(SG_INPUT, SG_ALERT,
+ "internal error in parameter set up for rotorgear: '"
+ << parametername <<"'" << endl);
+#undef p
+}
+int Rotorgear::getValueforFGSet(int j,char *text,float *f)
+{
+ if (j==0)
+ {
+ sprintf(text,"/rotors/gear/total-torque");
+ *f=_total_torque_on_engine;
+ } else return 0;
+ return j+1;
+}
+Rotorgear::Rotorgear()
+{
+ _in_use=0;
+ _engineon=0;
+ _rotorbrake=0;
+ _max_power_rotor_brake=1;
+ _rotorgear_friction=1;
+ _max_power_engine=1000*450;
+ _engine_prop_factor=0.05f;
+ _yasimdragfactor=1;
+ _yasimliftfactor=1;
+ _ddt_omegarel=0;
+ _engine_accel_limit=0.05f;
+ _total_torque_on_engine=0;
+ _target_rel_rpm=1;
+ _max_rel_torque=1;
+}
+
+Rotorgear::~Rotorgear()
+{
+ for(int i=0; i<_rotors.size(); i++)
+ delete (Rotor*)_rotors.get(i);
+}
+