You are on page 1of 11

Chapter 10 Flight Control System

Flight Control System: Introduction


An aircraft flight control system (FCS) can range from the simple, unaugmented direct-link systems of general aviation aircraft to the very complex, multi-mode fly-by-wire systems of current and next-generation fighters. Because the FCS varies so greatly between different aircraft, it is necessary for the user to provide some additional C++ code to integrate it into the full D-Six aircraft flight simulation. Fortunately, because of the modular nature of D-Six, much of the difficulty of coding the FCS in C++ (variable declaration, header files, etc.) is performed automatically. Only a rudimentary knowledge of computer programming (i.e. BASIC, FORTRAN, etc.) is necessary. A simple example will be presented from beginning to end in this section to illustrate the process of building the flight control system in the model dependent code in the MDEPDLL.CPP file and to provide most of the basic C++ syntax that is needed to implement an automatic FCS.

FCS Block Diagram


Because many modern flight control systems can be quite complex, it is usually convenient to represent them graphically with a block diagram. Typically, there are several block diagrams; one for each of the three aircraft axes and for different FCS systems used during various flight modes. For this F-30 example, located in the sample models directory in D-Six, two block diagrams will be presented. The first is a relatively simple longitudinal control system. The second is the lateral-directional control system, which is essentially two distinct block diagrams linked together by a simple aileron-differential tail interconnect or ARI. The configuration used for this has conventional wing controls, but uses a V-tail for both longitudinal and directional control. This aircraft achieves pitch control using symmetric tail deflection, lateral control using differential aileron, and directional control using differential tail deflection. Before the specifics of coding the FCS are presented, it may be useful to briefly describe the example FCS. Although this system tries to incorporate realistic FCS parameters and characteristics, it is by no means intended to be complete or fully robust. It is used solely for demonstration purposes.

Longitudinal Block Diagram

The longitudinal flight control system, shown above , receives longitudinal stick, dsx, as its primary input. This input is multiplied by a stick scale factor, Ksx, to convert the stick input to the desired angle of attack in degrees, referred to as commanded a or ac. The actual a is subtracted from this signal to make the error in angle of attack, or ae. This signal is processed through a first-order lag (FOL) filter. That filtered alpha error signal is then multiplied by a gain, Ka, and added to the alpha-rate signal processed through a similar gain, KaD. This total signal represents

Chapter 10 Flight Control System the symmetric tail command and is processed through a simple FOL actuator model to get the symmetric tail position which is used in the D-Six aero model. The functionality describing the effect of symmetric tail deflection is determined by the InfoFile. Note that the actuator rate limit and control surface hard limits are not represented in the block diagram. They are, however, represented in the model and will be described later in this section. Obviously, in modeling of a real flight control system, additional filters and lag functions may be involved to model the characteristics of other components like the angle of attack sensors, etc.

Lateral-Directional Block Diagram

The lateral-directional block diagram is made up of two simple, essentially independent block diagrams. The lateral portion, shown in the top half of the above diagram, receives lateral stick, dsy, as its primary input. This input is multiplied by a stick scale factor, Ksy, to convert the stick input to the desired aileron deflection in degrees. That signal is added to roll rate, p, processed through a FOL filter and multiplied by a gain, Kp. This combined signal is referred to as comma ded aileron or dac. That signal is passed through a simple FOL actuator transfer function whose output represents the aileron surface eflection. The dac signal is also passed to the directional control system for roll coordination. Unlike the lateral portion, the directional portion of the lateral-directional block diagram, shown in the bottom half of the above diagram, has no direct control input. Instead, it is used to min mize sideslip, b, which includes auto-coordination of wind-axis maneuvers. This is done by summing the dac signal (multiplied by the gai KARI) and the b (passed through an OL filter) and b-rate signals, multiplie by th gains Kb and KbD, re pecti ely. The b and b-rate signals (filtered and augmented) represent what is called the directio al command, or drc. The total differentia tail command (drc + dac * KARI) is processed through a simple FOL actuator model, the output of which is differential tail surface deflection.

Chapter 10 Flight Control System Like the longitudinal portion of the FCS, the functionality describing the effect of aileron and differential tail surface deflections is determined in the InfoFile. Note: The actuator rate limits and control surface hard limits are not represented in the block diagram, but are represented in the model and will be described in a later section.

FCS Variables
The block diagrams representing the FCS presented in the Longitudinal Block Diagram and the Lateral-Directional Block Diagram can be described by a relatively short segment of C++ code. The more challenging task is to determine the total number of variables and their relative sources. There are four basic types of variables used by the FCS. They are: 1. A stick input from D-Six Longitudinal Stick Lateral Stick Rudder (not used in the example) Throttle 2. D-Six simulation output Aircraft States (, , p, q, r, Mach, etc.- internally defined in D-Six) Output from data tables (i.e. control system gains & other constants which are functions of , Mach, etc. - defined in the InfoFile.) 3. A new variable that was created solely for the FCS Output from summation nodes Error Signals Actuator rate and position limits Transfer function constants 4. An intermediate variable created for transfer function integration

Identification of Required FCS Variables


The simplest way to identify each variable required for the FCS is to assign a variable name to each signal path in the block diagram (represented by a line ending with an arrowhead). Both figures below show the block diagrams with the C++ variable names assigned to each path. There are some considerations that should be taken when naming variables: - variable names cannot start with a number - variable names cannot include any special characters (except underscore _ ) - variable names cannot have spaces in them - variables cannot have the same name as C++ keywords or functions - variables are CASE SENSITIVE Descriptive character names are allowed and encouraged to aid in describing the particular function of each variable. There is no limit on variable name length. All of the variable names used in Longitudinal FCS Diagram are summarized in Table A and variable names used in Lateral-Directional FCS Diagram are summarized in Table B.

Chapter 10 Flight Control System Longitudinal FCS Variable Diagram

Lateral-Directional FCS Variable Diagram

Chapter 10 Flight Control System Table A C++ variables used in example longitudinal FCS. C++ Variable Variable Location Defined Description Name Type Stk_x 1 Variable List Longitudinal stick input (keyboard, joystick, or file) ksx 2 InfoFile Gain in longitudinal stick alpha_com Alphad alpha_error aa alpha_error_flt ka Alpha_dot kad Dh_com Dh 3 2 3 3 3 2 2 2 3 2 Variable List D-Six Variable List InfoFile Afcs(); Local InfoFile D-Six InfoFile Variable List Variable List Commanded angle of attack (deg) True angle of attack (deg) Error between commanded and true angle of attack (deg) Constant for alpha error filter (sec) Filtered angle of attack error (deg) Gain on filtered alpha Rate of change of angle of attack (deg/sec) Gain on alpha dot Symmetric tail deflection command sent to actuator (deg) Actual symmetric tail deflection

Note: "Variable Type" is defined in FCS Variables. Table B C++ variables used in example lateral-directional FCS. C++ Variable Variable Location Description Name Type Defined Stk_y 1 Variable List Lateral stick input (keyboard, joystick or file) ksy 2 InfoFile Gain on lateral stick ail_com 3 Variable List Commanded aileron deflection (deg) Pbodyd 2 D-Six Body-axis roll rate (deg/sec) ap 3 Variable List Constant for roll rate filter (sec) p_flt 3 Afcs(); Local Filtered body-axis roll rate (deg/sec) kp 2 InfoFile Gain on body-axis roll rate Dar_com 3 Variable List Aileron deflection command sent to actuator (deg) Da 3 Variable List Actual aileron position (deg) Dr_com 3 Variable List Differential tail command Betad 2 D-Six Sideslip angle (deg) ab 3 Variable List Constant for sideslip filter (sec) beta_flt kb Beta_dot kbd kari Ddh 3 2 2 2 2 2 Afcs(); local InfoFile D-Six InfoFile InfoFile Variable List Filtered sideslip angle (deg) Gain on filtered sideslip Rate of sideslip (deg/sec) Gain on rate of sideslip Gain for aileron-rudder interconnect Actual differential tail position (deg)

Chapter 10 Flight Control System Note: "Variable Type" is defined in FCS Variables. All type 1 variables in Tables A and B are pilot input variables. Some type 2 variables are also internally defined by D-Six (e.g. Betad, Alphad, Pbodyd, etc.) and do not have to be defined by the user. The other type 2 variables that are defined by the user in the InfoFile are the result of a table lookup. For the example FCS, all of these are FCS gain tables, scheduled with angle of attack (angle of attack and Mach for body axis roll rate). Finally, the type 3 variables are either constants, such as filter constants, or variables that were created as a result of an operation, such as summation or multiplication (Dh_com, beta_flt, etc.). Notice that there are no type 4 variables. This is because no transfer function, other than a simple FOL, is used in the example. One simple first order differential equation can be used to describe the relationship between the input and the output, and therefore, no intermediate state variables are required for the integration. The next section will describe the conversion of simple transfer functions from the s-domain (Laplace transform) to the time domain (differential equation) which can be implemented into D-Six.

Conversion of Transfer Functions to Time Domain and Implementation


The transfer functions used in the example are used to describe two things: a FOL filter and a simple actuator model. Using the actuator model as an example, the transfer function can be equated to the ratio of its output to input as follows:

Taking the inverse Laplace transform yields the differential equation:

or

All of the transfer functions in this example can be converted to a single first-order differential equation in this manner. However, if more complex transfer functions are used, they must be implemented as a set of first order differential equations. The easiest way to do this is to use a matrix manipulation program (e.g. MATLAB or Matrix X) which converts transfer functions to state space equations of the form:

Where u is the vector of inputs (usually of length 1), y is the vector of outputs (usually of length 1), x is the vector of intermediate state variables (length equal to the order of the transfer function) and A, B, C and D which are vectors output from the matrix manipulation software.

Chapter 10 Flight Control System

Conversion Of Transfer Function

The code can then be implemented into C++ as several first order differential equations, and one (typically) assignment statement (typically, the matrix D is zero). The following is an example of the conversion of a second order transfer function to two differential equations and an assignment statement:

Using matrix manipulation software (e.g. the tf2ss function in MATLAB which stands for transfer function to state space), the differential equations which relate the input of this transfer function to its output are described by the following equations:

or, in C++ code: x1dot = -400.0f * x1 - 30000.0f * x2 + Dr_com; x2dot = x1; Dr = 30000.0f * x2; This set of equations can be rearranged into two differential equations, but for simplicity, can be implemented into D-Six in the three equations shown above. In addition, the new variables, x1 and x2, created by the matrix manipulation software are of type four as described in FCS Variables. Of course, a transfer function of any order may be used in the same fashion, with complexity increasing with order. This completes the description of how to identify FCS variables, define them, and determine the differential equations which relate the output from a transfer function to the input. The following section will present the example FCS and describe several steps which must be taken to implement the C++ code into the model dependent code located in MDEPDLL.CPP.

Chapter 10 Flight Control System

Incorporating FCS Into D-Six

Incorporating FCS into D-Six


The most direct way to describe the coding of the FCS in C++ is to present the F-30s Afcs function as it appears in the MDEPDLL.CPP file and explain it one section at a time. No line of C++ for this function will be omitted or considered out of order as it has been implemented into D-Six for the example FCS.

Initialize Ncs Model Dependent Global Variable


Before a discussion of the Afcs function is started, the global variable Ncs at the beginning of the MDEPDLL.CPP file must be initialized. This variable represents the number of FCS variables that need to be integrated by D-Six after Afcs is called. This is typically equal to the sum of the individual orders of all of the transfer functions. Therefore, for the F-30 example FCS Ncs is set equal to 6 because it has a total of six had 4 first order actuators, 2 second order and 5 first order filters, then Ncs would be initialized to 13.

Afcs Function in MDEPDLL.CPP file


This first section of Afcs does not need to be modified unless local variables need to be defined as in this example. If any local variables need to be declared or defined, that should be done immediately following the left brace, {, after void Afcs() as shown below. // Flight control system routine. void Afcs() { // Define F-30 flight control local variables static float alpha_error_flt; static float beta_flt; static float p_flt; Typically, global and intermediate variables used in a flight control system should be initialized prior to the start of a simulation run to avoid numerical problems, such as division-by-zero. Code to mechanize the initialization process should be placed in Init_gains() function in the MDEPDLL.CPP. At time-zero, the code in Init_gains()is called and executed from the afcs() as shown below. However, for the F-30 FCS example, no initialization is required and no code is implemented in Init_gains(). // Provide initialization support at the start of a run. if ((pGetFlightModes)()->Time==0) Init_gains(); The section below begins the code for the FCS. All characters on a line following a // are comments. The comments, along with previous discussions should provide adequate information to follow the C++ code, with one exception. That is the handling of the six differential equations created by the individual transfer functions. This is simply done by using the D-Six array pCsdot. Instead of assigning the FCS time derivatives to new variables (such as Dh_dot for the time derivative of symmetric tail deflection) D-Six keeps all FCS derivatives in one array named pCsdot. This is done so D-Six can integrate all of the FCS derivatives, store their integrated states in pCs and return them to the Afcs function for the next time step. The global variable Ncs, initialized above, is used to initialize the dimension of the pCsdot and pCs arrays.

Chapter 10 Flight Control System

Incorporating FCS Into D-Six

Each differential equation uses the pCsdot array to store an individual time derivative value. For the example the pCs array is assigned to FCS variables as follows : pCs[0][0] assigned to alpha_error_flt pCs[0][1] assigned to Dh pCs[0][2] assigned to Ddh pCs[0][3] assigned to beta_flt pCs[0][4] assigned to Da pCs[0][5] assigned to p_flt Note that the C++ array index starts with zero. // Longitudinal Channel // calculate the derivatives for the longitudinal (AOA) control system: alpha_com = ksx * Stk_x; // limit alpha based on D-six user's input if (alpha_com > alpha_lim) alpha_com=alpha_lim; if (g_limit_switch != 0.0f){ if (alpha_com > g_limit_lookup) alpha_com=g_limit_lookup; } // raw alpha_error signal alpha_error = alpha_com - Alphad; // FOL filter for alpha_error_flt (or pCs[0][0]) if (aa) pCsdot[0][0] = 1.0f / aa * (alpha_error - alpha_error_flt); else { pCsdot[0][0] = 0.0f; pCs[0][0] = alpha_error; } // raw Dh_com signal Dh_com = Dh_com + ka * alpha_error_flt + kad * Alpha_dot; // limit Dh_com if (Dh_com > 30.0f) Dh_com = 30.0f; if (Dh_com < -30.0f) Dh_com = -30.0f; // define Dh-dot; also limited by actuator rate pCsdot[0][1] = 20.0f * (Dh_com - pCs[0][1]); In the longitudinal channel, there is algorithm to model the rate limit on the symmetric tail actuator. Since the pCs[0][1] variable is assigned to Dh or the actuator output, limiting the pCsdot[0][1] variable is equivalent to imposing the actuator-rate limit. This actuator, like the other two, is limited to 60 degrees per second. if (pCsdot[0][1] > 60.0f) pCsdot[0][1] = 60.0f; if (pCsdot[0][1] < -60.0f) pCsdot[0][1] = -60.0f;

Chapter 10 Flight Control System

Incorporating FCS Into D-Six

Below is the lateral portion of the flight control system. The lateral channel is calculated before the directional portion because the aileron command, Dar_com, is required for the command to the differential tail actuator. // Lateral/Directional Channels: // calculate the derivatives for the lateral control system: ail_com = -Stk_y; // FOL filter for roll rate if (ap) pCsdot[0][3] = 1.0f / ap * (Pbodyd - p_flt); else { pCsdot[0][3] = 0.0f; pCs[0][3] = Pbodyd; } // raw Dar_com signal Dar_com = ail_com + kp * Pbodyd; // define Dar_com-dot; also limited by actuator rate pCsdot[0][4] = 20.0f * (Dar_com - pCs[0][4]); The following is the aileron actuator rate limit: if (pCsdot[0][4] > 60.0f) pCsdot[0][4] = 60.0f; if (pCsdot[0][4] < -60.0f) pCsdot[0][4] = -60.0f; For the directional channel: // Directional Channel // FOL filter for Betad feedback if (ab) pCsdot[0][5] = 1.0f / ab * (Betad - beta_flt); else { pCsdot[0][5] = 0.0f; pCs[0][5] = Betad; } // raw Dr_com signal Dr_com = kb * beta_flt + kbd * Beta_dot; // define Dr-dot; also limited by actuator rate pCsdot[0][2] = 20.0f * (Dr_com + kari * ail_com - pCs[0][2]); The differential tail actuator rate limit follows. if (pCsdot[0][2] > 60.0f) pCsdot[0][2] = 60.0f; if (pCsdot[0][2] < -60.0f) pCsdot[0][2] = -60.0f;

Chapter 10 Flight Control System

Incorporating FCS Into D-Six

The following C++ statements are used to assign the values from the integrated pCs array to the appropriate global project or local variables. This function is necessary so that these FCS variables can be returned to D-Six correctly to be used for table look-up, plotting, etc. // assign integrated values to control surface variables Dh = pCs[0][1]; Da = pCs[0][4]; Ddh = pCs[0][2]; Dlef = Dlef_schedule;

// assign integrated values to local FCS variables alpha_error_flt = pCs[0][0]; beta_flt = pCs[0][3]; p_flt = pCs[0][5]; The final section of C++ code sets the surface hard limits. For the aileron this is quite straightforward. However, for the symmetric and differential tail this is slightly more complicated because they use the same surfaces. Although the specific logic used will not be discussed here, this section of code does introduce two new variables, _Dhr and _Dhl, which represent right and left tails, respectively. These variables could have been declared locally at the top of the Afcs function, but that would not allow them to be plotted in D-Six. Instead, for this example, they were defined as global D-Six project variables using the Variable List from D-Six. // set limit Dh if(Dh > 30.0f) Dh = 30.0f; if(Dh < -30.0f) Dh = -30.0f;

// set aileron limits if (Da > 30.0f) Da = 30.0f; if (Da < -30.0f) Da = -30.0f;

// set tail limits: _Dhr = Dh + Ddh / 2.0f; _Dhl = Dh - Ddh / 2.0f; if (_Dhr > 45.0f) _Dhr = 45.0f; if (_Dhr < -45.0f) _Dhr = -45.0f; if (_Dhl > 45.0f) _Dhl = 45.0f; if (_Dhl < -45.0f) _Dhl = -45.0f; Dh = (_Dhr + _Dhl) / 2.0f; Ddh = (_Dhr - _Dhl); } // end of afcs{}

You might also like