/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGRotor.h
- Author: Jon S. Berndt
+ Author: T. Kreitler
Date started: 08/24/00
- ------------- Copyright (C) 2000 Jon S. Berndt (jsb@hal-pc.org) -------------
+ ------------- Copyright (C) 2010 T. Kreitler (t.kreitler@web.de) -------------
This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
+ the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
- You should have received a copy of the GNU General Public License along with
+ You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA.
- Further information about the GNU General Public License can also be found on
+ Further information about the GNU Lesser General Public License can also be found on
the world wide web at http://www.gnu.org.
HISTORY
--------------------------------------------------------------------------------
-08/24/00 JSB Created
+01/01/10 T.Kreitler test implementation
+01/10/11 T.Kreitler changed to single rotor model
+03/06/11 T.Kreitler added brake, clutch, and experimental free-wheeling-unit
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_ROTOR "$Id$"
+#define ID_ROTOR "$Id: FGRotor.h,v 1.9 2011/03/10 01:35:25 dpculp Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-/** Models a rotor (such as for a helicopter); NOT YET IMPLEMENTED.
+/** Models a helicopter rotor.
+
+
+<h3>Configuration File Format</h3>
+@code
+<rotor name="{string}">
+ <diameter unit="{LENGTH}"> {number} </diameter>
+ <numblades> {number} </numblades>
+ <gearratio> {number} </gearratio>
+ <nominalrpm> {number} </nominalrpm>
+ <chord unit="{LENGTH}"> {number} </chord>
+ <liftcurveslope Xunit="1/RAD"> {number} </liftcurveslope>
+ <twist unit="{ANGLE}"> {number} </twist>
+ <hingeoffset unit="{LENGTH}"> {number} </hingeoffset>
+ <flappingmoment unit="{MOMENT}"> {number} </flappingmoment>
+ <massmoment Xunit="SLUG*FT"> {number} </massmoment>
+ <polarmoment unit="{MOMENT}"> {number} </polarmoment>
+ <inflowlag> {number} </inflowlag>
+ <tiplossfactor> {number} </tiplossfactor>
+ <maxbrakepower unit="{POWER}"> {number} </maxbrakepower>
+
+ <controlmap> {MAIN|TAIL|TANDEM} </controlmap>
+ <ExternalRPM> {number} </ExternalRPM>
+
+ <groundeffectexp> {number} </groundeffectexp>
+ <groundeffectshift unit="{LENGTH}"> {number} </groundeffectshift>
+
+ <freewheelthresh> {number} </freewheelthresh>
+</rotor>
+
+// LENGTH means any of the supported units, same for ANGLE and MOMENT.
+// Xunit-attributes are a hint for currently unsupported units, so
+// values must be provided accordingly.
+
+@endcode
+
+<h3>Configuration Parameters:</h3>
+
+ Brief description and the symbol frequently found in the literature.
+
+<pre>
+ \<diameter> - Rotor disk diameter (2x R).
+ \<numblades> - Number of blades (b).
+ \<gearratio> - Ratio of (engine rpm) / (rotor rpm), usually > 1.
+ \<nominalrpm> - RPM at which the rotor usally operates.
+ \<chord> - Blade chord, (c).
+ \<liftcurveslope> - Slope of curve of section lift against section angle of attack,
+ per rad (a).
+ \<twist> - Blade twist from root to tip, (theta_1).
+ \<hingeoffset> - Rotor flapping-hinge offset (e).
+ \<flappingmoment> - Flapping moment of inertia (I_b).
+ \<massmoment> - Blade mass moment. Mass of a single blade times the blade's
+ cg-distance from the hub, optional.
+ \<polarmoment> - Moment of inertia for the whole rotor disk, optional.
+ \<inflowlag> - Rotor inflow time constant, sec. Smaller values yield to quicker
+ responses (typical values for main rotor: 0.1 - 0.2 s).
+ \<tiplossfactor> - Tip-loss factor. The Blade fraction that produces lift.
+ Value usually ranges between 0.95 - 1.0, optional (B).
+ \<maxbrakepower> - Rotor brake, 20-30 hp should work for a mid size helicopter.
+
+ \<controlmap> - Defines the control inputs used (see notes).
+ \<ExternalRPM> - Links the rotor to another rotor, or an user controllable property.
+
+ Experimental properties
+
+ \<groundeffectexp> - Exponent for ground effect approximation. Values usually range from 0.04
+ for large rotors to 0.1 for smaller ones. As a rule of thumb the effect
+ vanishes at a height 2-3 times the rotor diameter.
+ formula used: exp ( - groundeffectexp * (height+groundeffectshift) )
+ Omitting or setting to 0.0 disables the effect calculation.
+ \<groundeffectshift> - Further adjustment of ground effect, approx. hub height or slightly above.
+
+ \<freewheelthresh> - Ratio of thruster power to engine power. The FWU will release when above
+ the threshold. The value shouldn't be too close to 1.0, 1.5 seems ok.
+ 0 disables this feature, which is also the default.
+
+</pre>
+
+<h3>Notes:</h3>
+
+ <h4>- Controls -</h4>
+
+ The behavior of the rotor is controlled/influenced by following inputs.<ul>
+ <li> The power provided by the engine. This is handled by the regular engine controls.</li>
+ <li> The collective control input. This is read from the <tt>fdm</tt> property
+ <tt>propulsion/engine[x]/collective-ctrl-rad</tt>. See below for tail rotor</li>
+ <li> The lateral cyclic input. Read from
+ <tt>propulsion/engine[x]/lateral-ctrl-rad</tt>.</li>
+ <li> The longitudinal cyclic input. Read from
+ <tt>propulsion/engine[x]/longitudinal-ctrl-rad</tt>.</li>
+ <li> The tail collective (aka antitorque, aka pedal) control input. Read from
+ <tt>propulsion/engine[x]/antitorque-ctrl-rad</tt> or
+ <tt>propulsion/engine[x]/tail-collective-ctrl-rad</tt>.</li>
+
+ </ul>
+
+ <h4>- Tail/tandem rotor -</h4>
+
+ Providing <tt>\<ExternalRPM\> 0 \</ExternalRPM\></tt> the tail rotor's RPM
+ is linked to to the main (=first, =0) rotor, and specifing
+ <tt>\<controlmap\> TAIL \</controlmap\></tt> tells this rotor to read the
+ collective input from <tt>propulsion/engine[1]/antitorque-ctrl-rad</tt>
+ (The TAIL-map ignores lateral and longitudinal input). The rotor needs to be
+ attached to a dummy engine, e.g. an 1HP electrical engine.
+ A tandem rotor is setup analogous.
+
+ <h4>- Sense -</h4>
+
+ The 'sense' parameter from the thruster is interpreted as follows, sense=1 means
+ counter clockwise rotation of the main rotor, as viewed from above. This is as a far
+ as I know more popular than clockwise rotation, which is defined by setting sense to
+ -1. Concerning coaxial designs - by setting 'sense' to zero, a Kamov-style rotor is
+ modeled (i.e. the rotor produces no torque).
+
+ <h4>- Engine issues -</h4>
+
+ In order to keep the rotor speed constant, use of a RPM-Governor system is
+ encouraged (see examples).
+
+ <h4>- Development hints -</h4>
+
+ Setting <tt>\<ExternalRPM> -1 \</ExternalRPM></tt> the rotor's RPM is controlled by
+ the <tt>propulsion/engine[x]/x-rpm-dict</tt> property. This feature can be useful
+ when developing a FDM.
+
+
+<h3>References:</h3>
+
+ <dl>
+ <dt>/SH79/</dt><dd>Shaugnessy, J. D., Deaux, Thomas N., and Yenni, Kenneth R.,
+ "Development and Validation of a Piloted Simulation of a
+ Helicopter and External Sling Load", NASA TP-1285, 1979.</dd>
+ <dt>/BA41/</dt><dd>Bailey,F.J.,Jr., "A Simplified Theoretical Method of Determining
+ the Characteristics of a Lifting Rotor in Forward Flight", NACA Rep.716, 1941.</dd>
+ <dt>/AM50/</dt><dd>Amer, Kenneth B.,"Theory of Helicopter Damping in Pitch or Roll and a
+ Comparison With Flight Measurements", NACA TN-2136, 1950.</dd>
+ <dt>/TA77/</dt><dd>Talbot, Peter D., Corliss, Lloyd D., "A Mathematical Force and Moment
+ Model of a UH-1H Helicopter for Flight Dynamics Simulations", NASA TM-73,254, 1977.</dd>
+ <dt>/GE49/</dt><dd>Gessow, Alfred, Amer, Kenneth B. "An Introduction to the Physical
+ Aspects of Helicopter Stability", NACA TN-1982, 1949.</dd>
+ </dl>
+
+ @author Thomas Kreitler
+ @version $Id: FGRotor.h,v 1.9 2011/03/10 01:35:25 dpculp Exp $
*/
+
+
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-class FGRotor : public FGThruster {
+class FGRotor : public FGThruster {
+
+ enum eCtrlMapping {eMainCtrl=0, eTailCtrl, eTandemCtrl};
public:
- FGRotor(FGFDMExec *FDMExec);
+
+ /** Constructor for FGRotor.
+ @param exec a pointer to the main executive object
+ @param rotor_element a pointer to the thruster config file XML element
+ @param num the number of this rotor */
+ FGRotor(FGFDMExec *exec, Element* rotor_element, int num);
+
+ /// Destructor for FGRotor
~FGRotor();
- double Calculate(double);
+ /** Returns the power required by the rotor. */
+ double GetPowerRequired(void)const { return PowerRequired; }
+
+ /** Returns the scalar thrust of the rotor, and adjusts the RPM value. */
+ double Calculate(double EnginePower);
+
+
+ /// Retrieves the RPMs of the rotor.
+ double GetRPM(void) const { return RPM; }
+
+ // void SetRPM(double rpm) { RPM = rpm; }
+
+ /// Retrieves the RPMs of the Engine, as seen from this rotor.
+ double GetEngineRPM(void) const { return GearRatio*RPM; } // bit of a hack.
+ /// Tells the rotor's gear ratio, usually the engine asks for this.
+ double GetGearRatio(void) { return GearRatio; }
+ /// Retrieves the thrust of the rotor.
+ double GetThrust(void) const { return Thrust; }
+
+ /// Retrieves the rotor's coning angle
+ double GetA0(void) const { return a0; }
+ /// Retrieves the longitudinal flapping angle with respect to the rotor shaft
+ double GetA1(void) const { return a1s; }
+ /// Retrieves the lateral flapping angle with respect to the rotor shaft
+ double GetB1(void) const { return b1s; }
+
+ /// Retrieves the inflow ratio
+ double GetLambda(void) const { return lambda; }
+ /// Retrieves the tip-speed (aka advance) ratio
+ double GetMu(void) const { return mu; }
+ /// Retrieves the induced inflow ratio
+ double GetNu(void) const { return nu; }
+ /// Retrieves the induced velocity
+ double GetVi(void) const { return v_induced; }
+ /// Retrieves the thrust coefficient
+ double GetCT(void) const { return C_T; }
+ /// Retrieves the torque
+ double GetTorque(void) const { return Torque; }
+ /// Retrieves the state of the free-wheeling-unit (FWU).
+ double GetFreeWheelTransmission(void) const { return FreeWheelTransmission; }
+
+ /// Downwash angle - currently only valid for a rotor that spins horizontally
+ double GetThetaDW(void) const { return theta_downwash; }
+ /// Downwash angle - currently only valid for a rotor that spins horizontally
+ double GetPhiDW(void) const { return phi_downwash; }
+
+ /// Retrieves the collective control input in radians.
+ double GetCollectiveCtrl(void) const { return CollectiveCtrl; }
+ /// Retrieves the lateral control input in radians.
+ double GetLateralCtrl(void) const { return LateralCtrl; }
+ /// Retrieves the longitudinal control input in radians.
+ double GetLongitudinalCtrl(void) const { return LongitudinalCtrl; }
+ /// Retrieves the normalized brake control input.
+ double GetBrakeCtrl(void) const { return BrakeCtrlNorm; }
+
+ /// Sets the collective control input in radians.
+ void SetCollectiveCtrl(double c) { CollectiveCtrl = c; }
+ /// Sets the lateral control input in radians.
+ void SetLateralCtrl(double c) { LateralCtrl = c; }
+ /// Sets the longitudinal control input in radians.
+ void SetLongitudinalCtrl(double c) { LongitudinalCtrl = c; }
+ /// Sets the normalized brake control input.
+ void SetBrakeCtrl(double c) { BrakeCtrlNorm = c; }
+
+ // Stubs. Only main rotor RPM is returned
string GetThrusterLabels(int id, string delimeter);
string GetThrusterValues(int id, string delimeter);
private:
+
+ // assist in parameter retrieval
+ double ConfigValueConv( Element* e, const string& ename, double default_val=0.0,
+ const string& unit = "", bool tell=false);
+
+ double ConfigValue( Element* e, const string& ename, double default_val=0.0,
+ bool tell=false);
+
+ void Configure(Element* rotor_element);
+
+ // true entry points
+ void CalcStatePart1(void);
+ void CalcStatePart2(double PowerAvailable);
+
+ // rotor dynamics
+ void calc_flow_and_thrust(double theta_0, double Uw, double Ww, double flow_scale = 1.0);
+ void calc_coning_angle(double theta_0);
+ void calc_flapping_angles(double theta_0, const FGColumnVector3 &pqr_fus_w);
+ void calc_drag_and_side_forces(double theta_0);
+ void calc_torque(double theta_0);
+
+ void calc_freewheel_state(double pwr_in, double pwr_out);
+
+ // transformations
+ FGColumnVector3 hub_vel_body2ca( const FGColumnVector3 &uvw, const FGColumnVector3 &pqr,
+ double a_ic = 0.0 , double b_ic = 0.0 );
+ FGColumnVector3 fus_angvel_body2ca( const FGColumnVector3 &pqr);
+ FGColumnVector3 body_forces(double a_ic = 0.0 , double b_ic = 0.0 );
+ FGColumnVector3 body_moments(double a_ic = 0.0 , double b_ic = 0.0 );
+
+ // interface
+ bool BindModel(void);
void Debug(int from);
+
+ // environment
+ double dt;
+ double rho;
+ Filter damp_hagl;
+
+ // configuration parameters
+ double Radius;
+ int BladeNum;
+
+ double Sense;
+ double NominalRPM;
+ int ExternalRPM;
+ int RPMdefinition;
+ FGPropertyManager* ExtRPMsource;
+
+ double BladeChord;
+ double LiftCurveSlope;
+ double BladeTwist;
+ double HingeOffset;
+ double BladeFlappingMoment;
+ double BladeMassMoment;
+ double PolarMoment;
+ double InflowLag;
+ double TipLossB;
+
+ double GroundEffectExp;
+ double GroundEffectShift;
+
+ // derived parameters
+ double LockNumberByRho;
+ double Solidity; // aka sigma
+ double R[5]; // Radius powers
+ double B[5]; // TipLossB powers
+
+ // Some of the calculations require shaft axes. So the
+ // thruster orientation (Tbo, with b for body) needs to be
+ // expressed/represented in helicopter shaft coordinates (Hsr).
+ FGMatrix33 InvTransform;
+ FGMatrix33 TboToHsr;
+ FGMatrix33 HsrToTbo;
+
+ // dynamic values
+ double RPM;
+ double Omega; // must be > 0
+ double beta_orient; // rotor orientation angle (rad)
+ double a0; // coning angle (rad)
+ double a_1, b_1, a_dw; // flapping angles
+ double a1s, b1s; // cyclic flapping relative to shaft axes, /SH79/ eqn(43)
+ double H_drag, J_side; // Forces
+
+ double Torque;
+ double C_T; // rotor thrust coefficient
+ double lambda; // inflow ratio
+ double mu; // tip-speed ratio
+ double nu; // induced inflow ratio
+ double v_induced; // induced velocity, always positive [ft/s]
+
+ double theta_downwash;
+ double phi_downwash;
+
+ // control
+ eCtrlMapping ControlMap;
+ double CollectiveCtrl;
+ double LateralCtrl;
+ double LongitudinalCtrl;
+
+ double BrakeCtrlNorm, MaxBrakePower;
+
+ // free-wheeling-unit (FWU)
+ int FreeWheelPresent; // 'installed' or not
+ double FreeWheelThresh; // when to release
+ Filter FreeWheelLag;
+ double FreeWheelTransmission; // state, 0: free, 1:locked
+
+
};
+
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif