]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/models/propulsion/FGRotor.h
Andreas Gaeb: fix #222 (JSBSIm reset problems)
[flightgear.git] / src / FDM / JSBSim / models / propulsion / FGRotor.h
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Header:       FGRotor.h
4  Author:       T. Kreitler
5  Date started: 08/24/00
6
7  ------------- Copyright (C) 2010  T. Kreitler (t.kreitler@web.de) -------------
8
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
12  version.
13
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
17  details.
18
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.
22
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.
25
26 HISTORY
27 --------------------------------------------------------------------------------
28 01/01/10  T.Kreitler test implementation
29 01/10/11  T.Kreitler changed to single rotor model
30
31 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
32 SENTRY
33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
34
35 #ifndef FGROTOR_H
36 #define FGROTOR_H
37
38 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
39 INCLUDES
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
41
42 #include "FGThruster.h"
43
44 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
45 DEFINITIONS
46 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
47
48 #define ID_ROTOR "$Id: FGRotor.h,v 1.8 2011/01/17 22:09:59 jberndt Exp $"
49
50 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
51 FORWARD DECLARATIONS
52 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
53
54 namespace JSBSim {
55
56 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57 CLASS DOCUMENTATION
58 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
59
60 /** Models a helicopter rotor.
61
62
63 <h3>Configuration File Format</h3>
64 @code
65 <rotor name="{string}">
66   <diameter unit="{LENGTH}"> {number} </diameter>
67   <numblades> {number} </numblades>
68   <gearratio> {number} </gearratio>
69   <nominalrpm> {number} </nominalrpm>
70   <chord unit="{LENGTH}"> {number} </chord>
71   <liftcurveslope Xunit="1/RAD"> {number} </liftcurveslope>
72   <twist unit="{ANGLE}"> {number} </twist>
73   <hingeoffset unit="{LENGTH}"> {number} </hingeoffset>
74   <flappingmoment unit="{MOMENT}"> {number} </flappingmoment>
75   <massmoment Xunit="SLUG*FT"> {number} </massmoment>
76   <polarmoment unit="{MOMENT}"> {number} </polarmoment>
77   <inflowlag> {number} </inflowlag>
78   <tiplossfactor> {number} </tiplossfactor>
79
80   <controlmap> {MAIN|TAIL|TANDEM} </controlmap>
81   <ExternalRPM> {number} </ExternalRPM>
82
83   <groundeffectexp> {number} </groundeffectexp>
84   <groundeffectshift unit="{LENGTH}"> {number} </groundeffectshift>
85 </rotor>
86
87 //  LENGTH means any of the supported units, same for ANGLE and MOMENT.
88 //  Xunit-attributes are a hint for currently unsupported units, so
89 //  values must be provided accordingly.
90
91 @endcode
92
93 <h3>Configuration Parameters:</h3>
94
95   Brief description and the symbol frequently found in the literature.
96
97 <pre>
98     \<diameter>           - Rotor disk diameter (2x R).
99     \<numblades>          - Number of blades (b).
100     \<gearratio>          - Ratio of (engine rpm) / (rotor rpm), usually > 1.
101     \<nominalrpm>         - RPM at which the rotor usally operates. 
102     \<chord>              - Blade chord, (c).
103     \<liftcurveslope>     - Slope of curve of section lift against section angle of attack,
104                              per rad (a).
105     \<twist>              - Blade twist from root to tip, (theta_1).
106     \<hingeoffset>        - Rotor flapping-hinge offset (e).
107     \<flappingmoment>     - Flapping moment of inertia (I_b).
108     \<massmoment>         - Blade mass moment. Mass of a single blade times the blade's
109                              cg-distance from the hub, optional.
110     \<polarmoment>        - Moment of inertia for the whole rotor disk, optional.
111     \<inflowlag>          - Rotor inflow time constant, sec. Smaller values yield to
112                               quicker responses to control input (defaults to 0.2).
113     \<tiplossfactor>      - Tip-loss factor. The Blade fraction that produces lift.
114                               Value usually ranges between 0.95 - 1.0, optional (B).
115
116     \<controlmap>         - Defines the control inputs used (see notes).
117     \<ExternalRPM>        - Links the rotor to another rotor, or an user controllable property.
118
119     Experimental properties
120     
121     \<groundeffectexp>    - Exponent for ground effect approximation. Values usually range from 0.04
122                             for large rotors to 0.1 for smaller ones. As a rule of thumb the effect 
123                             vanishes at a height 2-3 times the rotor diameter.
124                               formula used: exp ( - groundeffectexp * (height+groundeffectshift) )
125                             Omitting or setting to 0.0 disables the effect calculation.
126     \<groundeffectshift>  - Further adjustment of ground effect, approx. hub height or slightly above. 
127
128 </pre>
129
130 <h3>Notes:</h3>  
131
132   <h4>- Controls -</h4>
133
134     The behavior of the rotor is controlled/influenced by following inputs.<ul>
135       <li> The power provided by the engine. This is handled by the regular engine controls.</li>
136       <li> The collective control input. This is read from the <tt>fdm</tt> property 
137            <tt>propulsion/engine[x]/collective-ctrl-rad</tt>. See below for tail rotor</li>
138       <li> The lateral cyclic input. Read from
139            <tt>propulsion/engine[x]/lateral-ctrl-rad</tt>.</li>
140       <li> The longitudinal cyclic input. Read from 
141            <tt>propulsion/engine[x]/longitudinal-ctrl-rad</tt>.</li>
142       <li> The tail collective (aka antitorque, aka pedal) control input. Read from
143            <tt>propulsion/engine[x]/antitorque-ctrl-rad</tt> or 
144            <tt>propulsion/engine[x]/tail-collective-ctrl-rad</tt>.</li> 
145
146     </ul>
147
148   <h4>- Tail/tandem rotor -</h4>
149
150     Providing <tt>\<ExternalRPM\> 0 \</ExternalRPM\></tt> the tail rotor's RPM
151     is linked to to the main (=first, =0) rotor, and specifing
152     <tt>\<controlmap\> TAIL \</controlmap\></tt> tells this rotor to read the
153     collective input from <tt>propulsion/engine[1]/antitorque-ctrl-rad</tt>
154     (The TAIL-map ignores lateral and longitudinal input). The rotor needs to be 
155     attached to a dummy engine, e.g. an 1HP electrical engine.
156     A tandem rotor is setup analogous. 
157
158   <h4>- Sense -</h4>
159
160     The 'sense' parameter from the thruster is interpreted as follows, sense=1 means
161     counter clockwise rotation of the main rotor, as viewed from above. This is as a far
162     as I know more popular than clockwise rotation, which is defined by setting sense to
163     -1. Concerning coaxial designs - by setting 'sense' to zero, a Kamov-style rotor is
164     modeled (i.e. the rotor produces no torque).
165
166   <h4>- Engine issues -</h4>
167
168     Currently the rotor can only be driven with piston and electrical engines. An adaption
169     for the turboprop engine might become available in the future.
170     In order to keep the rotor speed constant, use of a RPM-Governor system is 
171     encouraged (see examples).
172
173   <h4>- Development hints -</h4>
174
175     Setting <tt>\<ExternalRPM> -1 \</ExternalRPM></tt> the rotor's RPM is controlled  by
176     the <tt>propulsion/engine[x]/x-rpm-dict</tt> property. This feature can be useful
177     when developing a FDM.
178   
179
180 <h3>References:</h3>  
181
182     <dl>    
183     <dt>/SH79/</dt><dd>Shaugnessy, J. D., Deaux, Thomas N., and Yenni, Kenneth R.,
184               "Development and Validation of a Piloted Simulation of a 
185               Helicopter and External Sling Load",  NASA TP-1285, 1979.</dd>
186     <dt>/BA41/</dt><dd>Bailey,F.J.,Jr., "A Simplified Theoretical Method of Determining
187               the Characteristics of a Lifting Rotor in Forward Flight", NACA Rep.716, 1941.</dd>
188     <dt>/AM50/</dt><dd>Amer, Kenneth B.,"Theory of Helicopter Damping in Pitch or Roll and a
189               Comparison With Flight Measurements", NACA TN-2136, 1950.</dd>
190     <dt>/TA77/</dt><dd>Talbot, Peter D., Corliss, Lloyd D., "A Mathematical Force and Moment
191               Model of a UH-1H Helicopter for Flight Dynamics Simulations", NASA TM-73,254, 1977.</dd>   
192     </dl>
193
194     @author Thomas Kreitler
195     @version $Id: FGRotor.h,v 1.8 2011/01/17 22:09:59 jberndt Exp $
196   */
197
198
199
200 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
201 CLASS DECLARATION
202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
203
204 class FGRotor :  public FGThruster {
205
206   enum eCtrlMapping {eMainCtrl=0, eTailCtrl, eTandemCtrl};
207
208 public:
209
210   /** Constructor for FGRotor.
211       @param exec a pointer to the main executive object
212       @param rotor_element a pointer to the thruster config file XML element
213       @param num the number of this rotor */
214   FGRotor(FGFDMExec *exec, Element* rotor_element, int num);
215
216   /// Destructor for FGRotor
217   ~FGRotor();
218
219   /** Returns the power required by the rotor. Well, to achieve this the rotor
220       is cycled through the whole machinery, yielding to a new state.
221       (hmm, sort of a huge side effect)
222   */
223   double GetPowerRequired(void);
224
225   /** Returns the scalar thrust of the rotor, and adjusts the RPM value. */
226   double Calculate(double PowerAvailable);
227
228
229   /// Retrieves the RPMs of the rotor.
230   double GetRPM(void) const { return RPM; }
231   
232   // void   SetRPM(double rpm) { RPM = rpm; }
233   
234   /// Retrieves the RPMs of the Engine, as seen from this rotor.
235   double GetEngineRPM(void) const { return GearRatio*RPM; } // bit of a hack.
236   /// Tells the rotor's gear ratio, usually the engine asks for this.
237   double GetGearRatio(void) { return GearRatio; }
238   /// Retrieves the thrust of the rotor.
239   double GetThrust(void) const { return Thrust; }
240
241   /// Retrieves the rotor's coning angle 
242   double GetA0(void) const { return a0; }
243   /// Retrieves the longitudinal flapping angle with respect to the rotor shaft
244   double GetA1(void) const { return a1s; }
245   /// Retrieves the lateral flapping angle with respect to the rotor shaft
246   double GetB1(void) const { return b1s; }
247
248   /// Retrieves the inflow ratio
249   double GetLambda(void) const { return lambda; }
250   /// Retrieves the tip-speed (aka advance) ratio
251   double GetMu(void) const { return mu; }
252   /// Retrieves the induced inflow ratio
253   double GetNu(void) const { return nu; }
254   /// Retrieves the induced velocity
255   double GetVi(void) const { return v_induced; }
256   /// Retrieves the thrust coefficient
257   double GetCT(void) const { return C_T; }
258   /// Retrieves the torque
259   double GetTorque(void) const { return Torque; }
260   
261   /// Downwash angle - currently only valid for a rotor that spins horizontally
262   double GetThetaDW(void) const { return theta_downwash; }
263   /// Downwash angle - currently only valid for a rotor that spins horizontally
264   double GetPhiDW(void) const { return phi_downwash; }
265
266   /// Retrieves the collective control input in radians.
267   double GetCollectiveCtrl(void) const { return CollectiveCtrl; }
268   /// Retrieves the lateral control input in radians.
269   double GetLateralCtrl(void) const { return LateralCtrl; }
270   /// Retrieves the longitudinal control input in radians.
271   double GetLongitudinalCtrl(void) const { return LongitudinalCtrl; }
272
273   /// Sets the collective control input in radians.
274   void SetCollectiveCtrl(double c) { CollectiveCtrl = c; }
275   /// Sets the lateral control input in radians.
276   void SetLateralCtrl(double c) { LateralCtrl = c; }
277   /// Sets the longitudinal control input in radians.
278   void SetLongitudinalCtrl(double c) { LongitudinalCtrl = c; }
279
280   // Stubs. Only main rotor RPM is returned
281   string GetThrusterLabels(int id, string delimeter);
282   string GetThrusterValues(int id, string delimeter);
283
284 private:
285
286   // assist in parameter retrieval
287   double ConfigValueConv( Element* e, const string& ename, double default_val=0.0, 
288                                       const string& unit = "", bool tell=false);
289
290   double ConfigValue( Element* e, const string& ename, double default_val=0.0,
291                                   bool tell=false);
292
293   void Configure(Element* rotor_element);
294
295   // true entry points
296   void CalcStatePart1(void);
297   void CalcStatePart2(double PowerAvailable);
298
299   // rotor dynamics
300   void calc_flow_and_thrust(double theta_0, double Uw, double Ww, double flow_scale = 1.0);
301   void calc_coning_angle(double theta_0);
302   void calc_flapping_angles(double theta_0, const FGColumnVector3 &pqr_fus_w);
303   void calc_drag_and_side_forces(double theta_0);
304   void calc_torque(double theta_0);
305
306   // transformations
307   FGColumnVector3 hub_vel_body2ca( const FGColumnVector3 &uvw, const FGColumnVector3 &pqr, 
308                                    double a_ic = 0.0 , double b_ic = 0.0 );
309   FGColumnVector3 fus_angvel_body2ca( const FGColumnVector3 &pqr);
310   FGColumnVector3 body_forces(double a_ic = 0.0 , double b_ic = 0.0 );
311   FGColumnVector3 body_moments(double a_ic = 0.0 , double b_ic = 0.0 );
312
313   // interface
314   bool BindModel(void);
315   void Debug(int from);
316
317   // environment
318   double dt;
319   double rho;
320   Filter damp_hagl;
321
322   // configuration parameters
323   double Radius;
324   int    BladeNum;
325
326   double Sense;
327   double NominalRPM;
328   int    ExternalRPM;
329   int    RPMdefinition;
330   FGPropertyManager* ExtRPMsource;
331
332   double BladeChord;
333   double LiftCurveSlope;
334   double BladeTwist;
335   double HingeOffset;
336   double BladeFlappingMoment;
337   double BladeMassMoment;
338   double PolarMoment;
339   double InflowLag;
340   double TipLossB;
341
342   double GroundEffectExp;
343   double GroundEffectShift;
344
345   // derived parameters
346   double LockNumberByRho;
347   double Solidity; // aka sigma
348   double R[5]; // Radius powers
349   double B[5]; // TipLossB powers
350
351   // Some of the calculations require shaft axes. So the
352   // thruster orientation (Tbo, with b for body) needs to be
353   // expressed/represented in helicopter shaft coordinates (Hsr).
354   FGMatrix33 InvTransform;
355   FGMatrix33 TboToHsr;
356   FGMatrix33 HsrToTbo;
357
358   // dynamic values
359   double RPM;
360   double Omega;          // must be > 0 
361   double beta_orient;    // rotor orientation angle (rad)
362   double a0;             // coning angle (rad)
363   double a_1, b_1, a_dw; // flapping angles
364   double a1s, b1s;       // cyclic flapping relative to shaft axes, /SH79/ eqn(43)
365   double H_drag, J_side; // Forces
366
367   double Torque;
368   double C_T;        // rotor thrust coefficient
369   double lambda;     // inflow ratio
370   double mu;         // tip-speed ratio 
371   double nu;         // induced inflow ratio
372   double v_induced;  // induced velocity, always positive [ft/s]
373
374   double theta_downwash;
375   double phi_downwash;
376
377   // control
378   eCtrlMapping ControlMap;
379   double CollectiveCtrl;
380   double LateralCtrl;
381   double LongitudinalCtrl;
382
383 };
384
385 }
386 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
387 #endif