JSBSim Flight Dynamics Model 1.0 (23 February 2013)
An Open Source Flight Dynamics and Control Software Library in C++

FGRotor Class Reference

Models a helicopter rotor. More...

#include <FGRotor.h>

Inheritance diagram for FGRotor:
Collaboration diagram for FGRotor:

List of all members.

Public Member Functions

 FGRotor (FGFDMExec *exec, Element *rotor_element, int num)
 Constructor for FGRotor.
 ~FGRotor ()
 Destructor for FGRotor.
double Calculate (double EnginePower)
 Returns the scalar thrust of the rotor, and adjusts the RPM value.
double GetA0 (void) const
 Retrieves the rotor's coning angle.
double GetA1 (void) const
 Retrieves the longitudinal flapping angle with respect to the rotor shaft.
double GetB1 (void) const
 Retrieves the lateral flapping angle with respect to the rotor shaft.
double GetCollectiveCtrl (void) const
 Retrieves the collective control input in radians.
double GetCT (void) const
 Retrieves the thrust coefficient.
double GetEngineRPM (void) const
 Retrieves the RPMs of the Engine, as seen from this rotor.
double GetGearRatio (void)
 Tells the rotor's gear ratio, usually the engine asks for this.
double GetGroundEffectScaleNorm (void) const
 Retrieves the ground effect scaling factor.
double GetLambda (void) const
 Retrieves the inflow ratio.
double GetLateralCtrl (void) const
 Retrieves the lateral control input in radians.
double GetLongitudinalCtrl (void) const
 Retrieves the longitudinal control input in radians.
double GetMu (void) const
 Retrieves the tip-speed (aka advance) ratio.
double GetNu (void) const
 Retrieves the induced inflow ratio.
double GetPhiDW (void) const
 Downwash angle - positive values point leftward (given a horizontal spinning rotor)
double GetPowerRequired (void) const
 Returns the power required by the rotor.
double GetRPM (void) const
 Retrieves the RPMs of the rotor.
double GetThetaDW (void) const
 Downwash angle - positive values point forward (given a horizontal spinning rotor)
double GetThrust (void) const
 Retrieves the thrust of the rotor.
string GetThrusterLabels (int id, const string &delimeter)
string GetThrusterValues (int id, const string &delimeter)
double GetTorque (void) const
 Retrieves the torque.
double GetVi (void) const
 Retrieves the induced velocity.
void SetCollectiveCtrl (double c)
 Sets the collective control input in radians.
void SetEngineRPM (double rpm)
void SetGroundEffectScaleNorm (double g)
 Sets the ground effect scaling factor.
void SetLateralCtrl (double c)
 Sets the lateral control input in radians.
void SetLongitudinalCtrl (double c)
 Sets the longitudinal control input in radians.
void SetRPM (double rpm)

Detailed Description

Configuration File Format

<rotor name="{string}">
  <diameter unit="{LENGTH}"> {number} </diameter>
  <numblades> {number} </numblades>
  <gearratio> {number} </gearratio>
  <nominalrpm> {number} </nominalrpm>
  <minrpm> {number} </minrpm>
  <maxrpm> {number} </maxrpm>
  <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>
  <gearloss unit="{POWER}"> {number} </gearloss>
  <gearmoment unit="{MOMENT}"> {number} </gearmoment>

  <controlmap> {MAIN|TAIL|TANDEM} </controlmap>
  <ExternalRPM> {number} </ExternalRPM>

  <groundeffectexp> {number} </groundeffectexp>
  <groundeffectshift unit="{LENGTH}"> {number} </groundeffectshift>

</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.

Configuration Parameters:

Brief description and the symbol frequently found in the literature.

    <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.
    <minrpm>             - Lowest RPM used in the model, optional and defaults to 1.
    <maxrpm>             - Largest RPM used in the model, optional and defaults to 2 x nominalrpm.
    <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.
    <gearloss>           - Friction in gear, 0.2% to 3% of the engine power, optional (see notes).
    <gearmoment>         - Approximation for the moment of inertia of the gear (and engine),
                              defaults to 0.1 * polarmoment, optional.
    <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
                            (This lessens the influence of the ground effect).

Notes:

- Controls -

The behavior of the rotor is controlled/influenced by following inputs.

  • The power provided by the engine. This is handled by the regular engine controls.
  • The collective control input. This is read from the fdm property propulsion/engine[x]/collective-ctrl-rad. See below for tail rotor
  • The lateral cyclic input. Read from propulsion/engine[x]/lateral-ctrl-rad.
  • The longitudinal cyclic input. Read from propulsion/engine[x]/longitudinal-ctrl-rad.
  • The tail rotor collective (aka antitorque, aka pedal) control input. Read from propulsion/engine[x]/antitorque-ctrl-rad or propulsion/engine[x]/tail-collective-ctrl-rad.

- Tail/tandem rotor -

Providing <ExternalRPM> 0 </ExternalRPM> the tail rotor's RPM is linked to to the main (=first, =0) rotor, and specifing <controlmap> TAIL </controlmap> tells this rotor to read the collective input from propulsion/engine[1]/antitorque-ctrl-rad (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.

- Sense -

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).

- Engine issues -

In order to keep the rotor/engine speed constant, use of a RPM-Governor system is encouraged (see examples).

In case the model requires the manual use of a clutch the <gearloss> property might need attention.

  • Electrical: here the gear-loss should be rather large to keep the engine controllable when the clutch is open (although full throttle might still make it spin away).
  • Piston: this engine model already has some internal friction loss and also looses power if it spins too high. Here the gear-loss could be set to 0.25% of the engine power (which is also the approximated default).
  • Turboprop: Here the default value might be a bit too small. Also it's advisable to adjust the power table for rpm values that are far beyond the nominal value.

- Scaling the ground effect -

The property propulsion/engine[x]/groundeffect-scale-norm allows fdm based scaling of the ground effect influence. For instance the effect vanishes at speeds above approx. 50kts, or one likes to land on a 'perforated' helipad.

- Development hints -

Setting <ExternalRPM> -1 </ExternalRPM> the rotor's RPM is controlled by the propulsion/engine[x]/x-rpm-dict property. This feature can be useful when developing a FDM.

References:

/SH79/
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.
/BA41/
Bailey,F.J.,Jr., "A Simplified Theoretical Method of Determining the Characteristics of a Lifting Rotor in Forward Flight", NACA Rep.716, 1941.
/AM50/
Amer, Kenneth B.,"Theory of Helicopter Damping in Pitch or Roll and a Comparison With Flight Measurements", NACA TN-2136, 1950.
/TA77/
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.
/GE49/
Gessow, Alfred, Amer, Kenneth B. "An Introduction to the Physical Aspects of Helicopter Stability", NACA TN-1982, 1949.
Author:
Thomas Kreitler
Version:
Id:
FGRotor.h,v 1.15 2013/01/26 17:06:50 bcoconni Exp

Definition at line 242 of file FGRotor.h.


Constructor & Destructor Documentation

FGRotor ( FGFDMExec exec,
Element rotor_element,
int  num 
)
Parameters:
execa pointer to the main executive object
rotor_elementa pointer to the thruster config file XML element
numthe number of this rotor

Definition at line 74 of file FGRotor.cpp.

References FGJSBBase::Constrain(), Element::FindElement(), Element::FindElementTripletConvertTo(), Element::FindElementValue(), Element::FindElementValueAsNumber(), Element::GetDataAsNumber(), FGFDMExec::GetDeltaT(), FGPropulsion::GetEngine(), Element::GetParent(), FGFDMExec::GetPropertyManager(), FGFDMExec::GetPropulsion(), FGMatrix33::InitMatrix(), and FGMatrix33::Transposed().

  : FGThruster(exec, rotor_element, num),
    rho(0.002356),                                  // environment
    Radius(0.0), BladeNum(0),                       // configuration parameters
    Sense(1.0), NominalRPM(0.0), MinimalRPM(0.0), MaximalRPM(0.0), 
    ExternalRPM(0), RPMdefinition(0), ExtRPMsource(NULL), SourceGearRatio(1.0),
    BladeChord(0.0), LiftCurveSlope(0.0), BladeTwist(0.0), HingeOffset(0.0),
    BladeFlappingMoment(0.0), BladeMassMoment(0.0), PolarMoment(0.0),
    InflowLag(0.0), TipLossB(0.0),
    GroundEffectExp(0.0), GroundEffectShift(0.0), GroundEffectScaleNorm(1.0),
    LockNumberByRho(0.0), Solidity(0.0),            // derived parameters
    RPM(0.0), Omega(0.0),                           // dynamic values
    beta_orient(0.0),
    a0(0.0), a_1(0.0), b_1(0.0), a_dw(0.0),
    a1s(0.0), b1s(0.0),
    H_drag(0.0), J_side(0.0), Torque(0.0), C_T(0.0),
    lambda(-0.001), mu(0.0), nu(0.001), v_induced(0.0),
    theta_downwash(0.0), phi_downwash(0.0),
    ControlMap(eMainCtrl),                          // control
    CollectiveCtrl(0.0), LateralCtrl(0.0), LongitudinalCtrl(0.0),
    Transmission(NULL),                             // interaction with engine
    EngineRPM(0.0), MaxBrakePower(0.0), GearLoss(0.0), GearMoment(0.0)
{
  FGColumnVector3 location(0.0, 0.0, 0.0), orientation(0.0, 0.0, 0.0);
  Element *thruster_element;
  double engine_power_est = 0.0;

  // initialise/set remaining variables
  SetTransformType(FGForce::tCustom);
  PropertyManager = exec->GetPropertyManager();
  Type = ttRotor;
  GearRatio = 1.0;

  dt = exec->GetDeltaT();
  for (int i=0; i<5; i++) R[i] = 0.0;
  for (int i=0; i<5; i++) B[i] = 0.0;

  // get positions 
  thruster_element = rotor_element->GetParent()->FindElement("sense");
  if (thruster_element) {
    double s = thruster_element->GetDataAsNumber();
    if (s < -0.1) {
      Sense = -1.0; // 'CW' as seen from above
    } else if (s < 0.1) {
      Sense = 0.0;  // 'coaxial'
    } else {
      Sense = 1.0; // 'CCW' as seen from above
    }
  }

  thruster_element = rotor_element->GetParent()->FindElement("location");
  if (thruster_element) {
    location = thruster_element->FindElementTripletConvertTo("IN");
  } else {
    cerr << "No thruster location found." << endl;
  }

  thruster_element = rotor_element->GetParent()->FindElement("orient");
  if (thruster_element) {
    orientation = thruster_element->FindElementTripletConvertTo("RAD");
  } else {
    cerr << "No thruster orientation found." << endl;
  }

  SetLocation(location);
  SetAnglesToBody(orientation);
  InvTransform = Transform().Transposed(); // body to custom/native

  // wire controls
  ControlMap = eMainCtrl;
  if (rotor_element->FindElement("controlmap")) {
    string cm = rotor_element->FindElementValue("controlmap");
    cm = to_upper(cm);
    if (cm == "TAIL") {
      ControlMap = eTailCtrl;
    } else if (cm == "TANDEM") {
      ControlMap = eTandemCtrl;
    } else {
      cerr << "# found unknown controlmap: '" << cm << "' using main rotor config."  << endl;
    }
  }

  // ExternalRPM -- is the RPM dictated ?
  if (rotor_element->FindElement("ExternalRPM")) {
    ExternalRPM = 1;
    SourceGearRatio = 1.0;
    RPMdefinition = (int) rotor_element->FindElementValueAsNumber("ExternalRPM");
    int rdef = RPMdefinition;
    if (RPMdefinition>=0) {
      // avoid ourself and (still) unknown engines.
      if (!exec->GetPropulsion()->GetEngine(RPMdefinition) || RPMdefinition==num) {
        RPMdefinition = -1;
      } else {
        FGThruster *tr = exec->GetPropulsion()->GetEngine(RPMdefinition)->GetThruster();
        SourceGearRatio = tr->GetGearRatio();
        // cout << "# got sources' GearRatio: " << SourceGearRatio << endl;
      }
    }
    if (RPMdefinition != rdef) {
      cerr << "# discarded given RPM source (" << rdef << ") and switched to external control (-1)." << endl;
    }
  }

  // process rotor parameters
  engine_power_est = Configure(rotor_element);

  // setup transmission if needed
  if (!ExternalRPM) {

    Transmission = new FGTransmission(exec, num, dt);

    Transmission->SetThrusterMoment(PolarMoment);

    // The MOI sensed behind the gear ( MOI_engine*sqr(GearRatio) ).
    GearMoment = ConfigValueConv(rotor_element, "gearmoment", 0.1*PolarMoment, "SLUG*FT2");
    GearMoment = Constrain(1e-6, GearMoment, 1e9);
    Transmission->SetEngineMoment(GearMoment);

    Transmission->SetMaxBrakePower(MaxBrakePower);

    GearLoss = ConfigValueConv(rotor_element, "gearloss", 0.0025 * engine_power_est, "HP");
    GearLoss = Constrain(0.0, GearLoss, 1e9);
    GearLoss *= hptoftlbssec;
    Transmission->SetEngineFriction(GearLoss);

  }

  // shaft representation - a rather simple transform,
  // but using a matrix is safer.
  TboToHsr.InitMatrix(   0.0, 0.0, 1.0,
                         0.0, 1.0, 0.0,
                        -1.0, 0.0, 0.0  );
  HsrToTbo  =  TboToHsr.Transposed();

  // smooth out jumps in hagl reported, otherwise the ground effect
  // calculation would cause jumps too. 1Hz seems sufficient.
  damp_hagl = Filter(1.0, dt);

  // enable import-export
  BindModel();

  Debug(0);

}  // Constructor

Here is the call graph for this function:


The documentation for this class was generated from the following files: