1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7 ------------- Copyright (C) 2010 T. Kreitler (t.kreitler@web.de) -------------
9 This program is free software; you can redistribute it and/or modify it under
10 the terms of the GNU Lesser General Public License as published by the Free Software
11 Foundation; either version 2 of the License, or (at your option) any later
14 This program is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
19 You should have received a copy of the GNU Lesser General Public License along with
20 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21 Place - Suite 330, Boston, MA 02111-1307, USA.
23 Further information about the GNU Lesser General Public License can also be found on
24 the world wide web at http://www.gnu.org.
27 --------------------------------------------------------------------------------
28 01/01/10 T.Kreitler test implementation
29 01/10/11 T.Kreitler changed to single rotor model
30 03/06/11 T.Kreitler added brake, clutch, and experimental free-wheeling-unit
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
39 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
43 #include "FGThruster.h"
45 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
47 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
49 #define ID_ROTOR "$Id: FGRotor.h,v 1.12 2011/10/15 21:30:28 jentron Exp $"
51 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
57 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
59 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
61 /** Models a helicopter rotor.
64 <h3>Configuration File Format</h3>
66 <rotor name="{string}">
67 <diameter unit="{LENGTH}"> {number} </diameter>
68 <numblades> {number} </numblades>
69 <gearratio> {number} </gearratio>
70 <nominalrpm> {number} </nominalrpm>
71 <minrpm> {number} </minrpm>
72 <maxrpm> {number} </maxrpm>
73 <chord unit="{LENGTH}"> {number} </chord>
74 <liftcurveslope Xunit="1/RAD"> {number} </liftcurveslope>
75 <twist unit="{ANGLE}"> {number} </twist>
76 <hingeoffset unit="{LENGTH}"> {number} </hingeoffset>
77 <flappingmoment unit="{MOMENT}"> {number} </flappingmoment>
78 <massmoment Xunit="SLUG*FT"> {number} </massmoment>
79 <polarmoment unit="{MOMENT}"> {number} </polarmoment>
80 <inflowlag> {number} </inflowlag>
81 <tiplossfactor> {number} </tiplossfactor>
82 <maxbrakepower unit="{POWER}"> {number} </maxbrakepower>
83 <gearloss unit="{POWER}"> {number} </gearloss>
84 <gearmoment unit="{MOMENT}"> {number} </gearmoment>
86 <controlmap> {MAIN|TAIL|TANDEM} </controlmap>
87 <ExternalRPM> {number} </ExternalRPM>
89 <groundeffectexp> {number} </groundeffectexp>
90 <groundeffectshift unit="{LENGTH}"> {number} </groundeffectshift>
92 <freewheelthresh> {number} </freewheelthresh>
95 // LENGTH means any of the supported units, same for ANGLE and MOMENT.
96 // Xunit-attributes are a hint for currently unsupported units, so
97 // values must be provided accordingly.
101 <h3>Configuration Parameters:</h3>
103 Brief description and the symbol frequently found in the literature.
106 \<diameter> - Rotor disk diameter (2x R).
107 \<numblades> - Number of blades (b).
108 \<gearratio> - Ratio of (engine rpm) / (rotor rpm), usually > 1.
109 \<nominalrpm> - RPM at which the rotor usally operates.
110 \<minrpm> - Lowest RPM used in the model, optional and defaults to 1.
111 \<maxrpm> - Largest RPM used in the model, optional and defaults to 2 x nominalrpm.
112 \<chord> - Blade chord, (c).
113 \<liftcurveslope> - Slope of curve of section lift against section angle of attack,
115 \<twist> - Blade twist from root to tip, (theta_1).
116 \<hingeoffset> - Rotor flapping-hinge offset (e).
117 \<flappingmoment> - Flapping moment of inertia (I_b).
118 \<massmoment> - Blade mass moment. Mass of a single blade times the blade's
119 cg-distance from the hub, optional.
120 \<polarmoment> - Moment of inertia for the whole rotor disk, optional.
121 \<inflowlag> - Rotor inflow time constant, sec. Smaller values yield to quicker
122 responses (typical values for main rotor: 0.1 - 0.2 s).
123 \<tiplossfactor> - Tip-loss factor. The Blade fraction that produces lift.
124 Value usually ranges between 0.95 - 1.0, optional (B).
126 \<maxbrakepower> - Rotor brake, 20-30 hp should work for a mid size helicopter.
127 \<gearloss> - Friction in gear, 0.2% to 3% of the engine power, optional (see notes).
128 \<gearmoment> - Approximation for the moment of inertia of the gear (and engine),
129 defaults to 0.1 * polarmoment, optional.
131 \<controlmap> - Defines the control inputs used (see notes).
133 \<ExternalRPM> - Links the rotor to another rotor, or an user controllable property.
135 Experimental properties
137 \<groundeffectexp> - Exponent for ground effect approximation. Values usually range from 0.04
138 for large rotors to 0.1 for smaller ones. As a rule of thumb the effect
139 vanishes at a height 2-3 times the rotor diameter.
140 formula used: exp ( - groundeffectexp * (height+groundeffectshift) )
141 Omitting or setting to 0.0 disables the effect calculation.
142 \<groundeffectshift> - Further adjustment of ground effect, approx. hub height or slightly above.
148 <h4>- Controls -</h4>
150 The behavior of the rotor is controlled/influenced by following inputs.<ul>
151 <li> The power provided by the engine. This is handled by the regular engine controls.</li>
152 <li> The collective control input. This is read from the <tt>fdm</tt> property
153 <tt>propulsion/engine[x]/collective-ctrl-rad</tt>. See below for tail rotor</li>
154 <li> The lateral cyclic input. Read from
155 <tt>propulsion/engine[x]/lateral-ctrl-rad</tt>.</li>
156 <li> The longitudinal cyclic input. Read from
157 <tt>propulsion/engine[x]/longitudinal-ctrl-rad</tt>.</li>
158 <li> The tail collective (aka antitorque, aka pedal) control input. Read from
159 <tt>propulsion/engine[x]/antitorque-ctrl-rad</tt> or
160 <tt>propulsion/engine[x]/tail-collective-ctrl-rad</tt>.</li>
164 <h4>- Tail/tandem rotor -</h4>
166 Providing <tt>\<ExternalRPM\> 0 \</ExternalRPM\></tt> the tail rotor's RPM
167 is linked to to the main (=first, =0) rotor, and specifing
168 <tt>\<controlmap\> TAIL \</controlmap\></tt> tells this rotor to read the
169 collective input from <tt>propulsion/engine[1]/antitorque-ctrl-rad</tt>
170 (The TAIL-map ignores lateral and longitudinal input). The rotor needs to be
171 attached to a dummy engine, e.g. an 1HP electrical engine.
172 A tandem rotor is setup analogous.
176 The 'sense' parameter from the thruster is interpreted as follows, sense=1 means
177 counter clockwise rotation of the main rotor, as viewed from above. This is as a far
178 as I know more popular than clockwise rotation, which is defined by setting sense to
179 -1. Concerning coaxial designs - by setting 'sense' to zero, a Kamov-style rotor is
180 modeled (i.e. the rotor produces no torque).
182 <h4>- Engine issues -</h4>
184 In order to keep the rotor/engine speed constant, use of a RPM-Governor system is
185 encouraged (see examples).
187 In case the model requires the manual use of a clutch the <tt>\<gearloss\></tt>
188 property might need attention.<ul>
190 <li> Electrical: here the gear-loss should be rather large to keep the engine
191 controllable when the clutch is open (although full throttle might still make it
193 <li> Piston: this engine model already has some internal friction loss and also
194 looses power if it spins too high. Here the gear-loss could be set to 0.25%
195 of the engine power (which is also the approximated default).</li>
196 <li> Turboprop: Here the default value might be a bit too small. Also it's advisable
197 to adjust the power table for rpm values that are far beyond the nominal value.</li>
201 <h4>- Development hints -</h4>
203 Setting <tt>\<ExternalRPM> -1 \</ExternalRPM></tt> the rotor's RPM is controlled by
204 the <tt>propulsion/engine[x]/x-rpm-dict</tt> property. This feature can be useful
205 when developing a FDM.
211 <dt>/SH79/</dt><dd>Shaugnessy, J. D., Deaux, Thomas N., and Yenni, Kenneth R.,
212 "Development and Validation of a Piloted Simulation of a
213 Helicopter and External Sling Load", NASA TP-1285, 1979.</dd>
214 <dt>/BA41/</dt><dd>Bailey,F.J.,Jr., "A Simplified Theoretical Method of Determining
215 the Characteristics of a Lifting Rotor in Forward Flight", NACA Rep.716, 1941.</dd>
216 <dt>/AM50/</dt><dd>Amer, Kenneth B.,"Theory of Helicopter Damping in Pitch or Roll and a
217 Comparison With Flight Measurements", NACA TN-2136, 1950.</dd>
218 <dt>/TA77/</dt><dd>Talbot, Peter D., Corliss, Lloyd D., "A Mathematical Force and Moment
219 Model of a UH-1H Helicopter for Flight Dynamics Simulations", NASA TM-73,254, 1977.</dd>
220 <dt>/GE49/</dt><dd>Gessow, Alfred, Amer, Kenneth B. "An Introduction to the Physical
221 Aspects of Helicopter Stability", NACA TN-1982, 1949.</dd>
224 @author Thomas Kreitler
225 @version $Id: FGRotor.h,v 1.12 2011/10/15 21:30:28 jentron Exp $
230 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
234 class FGTransmission : public FGJSBBase {
237 FGTransmission(FGFDMExec *exec, int num);
240 void Calculate(double EnginePower, double ThrusterTorque, double dt);
242 void SetMaxBrakePower(double x) {MaxBrakePower=x;}
243 double GetMaxBrakePower() const {return MaxBrakePower;}
244 void SetEngineFriction(double x) {EngineFriction=x;}
245 double GetEngineFriction() const {return EngineFriction;}
246 void SetEngineMoment(double x) {EngineMoment=x;}
247 double GetEngineMoment() const {return EngineMoment;}
248 void SetThrusterMoment(double x) {ThrusterMoment=x;}
249 double GetThrusterMoment() const {return ThrusterMoment;}
251 double GetFreeWheelTransmission() const {return FreeWheelTransmission;}
252 double GetEngineRPM() {return EngineRPM;}
253 double GetThrusterRPM() {return ThrusterRPM;}
255 double GetBrakeCtrl() const {return BrakeCtrlNorm;}
256 void SetBrakeCtrl(double x) {BrakeCtrlNorm=x;}
257 void SetClutchCtrlNorm(double x) {ClutchCtrlNorm=x;}
260 bool BindModel(int num);
261 // void Debug(int from);
263 inline double omega_to_rpm(double w) {return w * 9.54929658551372014613302580235;} // omega/(2.0*PI) * 60.0
264 inline double rpm_to_omega(double r) {return r * .104719755119659774615421446109;} // (rpm/60.0)*2.0*PI
267 double FreeWheelTransmission; // state, 0: free, 1:locked
269 double ThrusterMoment;
270 double EngineMoment; // estimated MOI of gear and engine, influences acceleration
271 double EngineFriction; // estimated friction in gear and possibly engine
273 double ClutchCtrlNorm; // also in FGThruster.h
274 double BrakeCtrlNorm;
275 double MaxBrakePower;
279 FGPropertyManager* PropertyManager;
283 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
285 class FGRotor : public FGThruster {
287 enum eCtrlMapping {eMainCtrl=0, eTailCtrl, eTandemCtrl};
291 /** Constructor for FGRotor.
292 @param exec a pointer to the main executive object
293 @param rotor_element a pointer to the thruster config file XML element
294 @param num the number of this rotor */
295 FGRotor(FGFDMExec *exec, Element* rotor_element, int num);
297 /// Destructor for FGRotor
300 /** Returns the power required by the rotor. */
301 double GetPowerRequired(void)const { return PowerRequired; }
303 /** Returns the scalar thrust of the rotor, and adjusts the RPM value. */
304 double Calculate(double EnginePower);
307 /// Retrieves the RPMs of the rotor.
308 double GetRPM(void) const { return RPM; }
309 void SetRPM(double rpm) { RPM = rpm; }
311 /// Retrieves the RPMs of the Engine, as seen from this rotor.
312 double GetEngineRPM(void) const {return EngineRPM;} //{ return GearRatio*RPM; }
313 void SetEngineRPM(double rpm) {EngineRPM = rpm;} //{ RPM = rpm/GearRatio; }
314 /// Tells the rotor's gear ratio, usually the engine asks for this.
315 double GetGearRatio(void) { return GearRatio; }
316 /// Retrieves the thrust of the rotor.
317 double GetThrust(void) const { return Thrust; }
319 /// Retrieves the rotor's coning angle
320 double GetA0(void) const { return a0; }
321 /// Retrieves the longitudinal flapping angle with respect to the rotor shaft
322 double GetA1(void) const { return a1s; }
323 /// Retrieves the lateral flapping angle with respect to the rotor shaft
324 double GetB1(void) const { return b1s; }
326 /// Retrieves the inflow ratio
327 double GetLambda(void) const { return lambda; }
328 /// Retrieves the tip-speed (aka advance) ratio
329 double GetMu(void) const { return mu; }
330 /// Retrieves the induced inflow ratio
331 double GetNu(void) const { return nu; }
332 /// Retrieves the induced velocity
333 double GetVi(void) const { return v_induced; }
334 /// Retrieves the thrust coefficient
335 double GetCT(void) const { return C_T; }
336 /// Retrieves the torque
337 double GetTorque(void) const { return Torque; }
339 /// Downwash angle - currently only valid for a rotor that spins horizontally
340 double GetThetaDW(void) const { return theta_downwash; }
341 /// Downwash angle - currently only valid for a rotor that spins horizontally
342 double GetPhiDW(void) const { return phi_downwash; }
344 /// Retrieves the collective control input in radians.
345 double GetCollectiveCtrl(void) const { return CollectiveCtrl; }
346 /// Retrieves the lateral control input in radians.
347 double GetLateralCtrl(void) const { return LateralCtrl; }
348 /// Retrieves the longitudinal control input in radians.
349 double GetLongitudinalCtrl(void) const { return LongitudinalCtrl; }
351 /// Sets the collective control input in radians.
352 void SetCollectiveCtrl(double c) { CollectiveCtrl = c; }
353 /// Sets the lateral control input in radians.
354 void SetLateralCtrl(double c) { LateralCtrl = c; }
355 /// Sets the longitudinal control input in radians.
356 void SetLongitudinalCtrl(double c) { LongitudinalCtrl = c; }
358 // Stubs. Only main rotor RPM is returned
359 string GetThrusterLabels(int id, string delimeter);
360 string GetThrusterValues(int id, string delimeter);
364 // assist in parameter retrieval
365 double ConfigValueConv( Element* e, const string& ename, double default_val=0.0,
366 const string& unit = "", bool tell=false);
368 double ConfigValue( Element* e, const string& ename, double default_val=0.0,
371 void Configure(Element* rotor_element);
373 void CalcRotorState(void);
376 void calc_flow_and_thrust(double theta_0, double Uw, double Ww, double flow_scale = 1.0);
377 void calc_coning_angle(double theta_0);
378 void calc_flapping_angles(double theta_0, const FGColumnVector3 &pqr_fus_w);
379 void calc_drag_and_side_forces(double theta_0);
380 void calc_torque(double theta_0);
383 FGColumnVector3 hub_vel_body2ca( const FGColumnVector3 &uvw, const FGColumnVector3 &pqr,
384 double a_ic = 0.0 , double b_ic = 0.0 );
385 FGColumnVector3 fus_angvel_body2ca( const FGColumnVector3 &pqr);
386 FGColumnVector3 body_forces(double a_ic = 0.0 , double b_ic = 0.0 );
387 FGColumnVector3 body_moments(double a_ic = 0.0 , double b_ic = 0.0 );
390 bool BindModel(void);
391 void Debug(int from);
398 // configuration parameters
409 FGPropertyManager* ExtRPMsource;
410 double SourceGearRatio;
413 double LiftCurveSlope;
416 double BladeFlappingMoment;
417 double BladeMassMoment;
422 double GroundEffectExp;
423 double GroundEffectShift;
425 // derived parameters
426 double LockNumberByRho;
427 double Solidity; // aka sigma
428 double R[5]; // Radius powers
429 double B[5]; // TipLossB powers
431 // Some of the calculations require shaft axes. So the
432 // thruster orientation (Tbo, with b for body) needs to be
433 // expressed/represented in helicopter shaft coordinates (Hsr).
434 FGMatrix33 InvTransform;
440 double Omega; // must be > 0
441 double beta_orient; // rotor orientation angle (rad)
442 double a0; // coning angle (rad)
443 double a_1, b_1, a_dw; // flapping angles
444 double a1s, b1s; // cyclic flapping relative to shaft axes, /SH79/ eqn(43)
445 double H_drag, J_side; // Forces
448 double C_T; // rotor thrust coefficient
449 double lambda; // inflow ratio
450 double mu; // tip-speed ratio
451 double nu; // induced inflow ratio
452 double v_induced; // induced velocity, always positive [ft/s]
454 double theta_downwash;
458 eCtrlMapping ControlMap;
459 double CollectiveCtrl;
461 double LongitudinalCtrl;
463 // interaction with engine
464 FGTransmission *Transmission;
466 double MaxBrakePower;
473 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%