JSBSim Flight Dynamics Model  1.0 (02 March 2017)
An Open Source Flight Dynamics and Control Software Library in C++
FGFunction Class Reference

Represents a mathematical function. More...

#include <FGFunction.h>

+ Inheritance diagram for FGFunction:
+ Collaboration diagram for FGFunction:

Public Member Functions

 FGFunction (FGPropertyManager *PropertyManager, Element *element, const std::string &prefix="")
 Constructor. More...
 
virtual ~FGFunction ()
 Destructor.
 
void cacheValue (bool shouldCache)
 Specifies whether to cache the value of the function, so it is calculated only once per frame. More...
 
std::string GetName (void) const
 Retrieves the name of the function.
 
double GetValue (void) const
 Retrieves the value of the function object. More...
 
std::string GetValueAsString (void) const
 The value that the function evaluates to, as a string. More...
 
- Public Member Functions inherited from FGParameter
double getDoubleValue (void) const
 
- Public Member Functions inherited from FGJSBBase
 FGJSBBase ()
 Constructor for FGJSBBase.
 
virtual ~FGJSBBase ()
 Destructor for FGJSBBase.
 
void disableHighLighting (void)
 Disables highlighting in the console output.
 
std::string GetVersion (void)
 Returns the version number of JSBSim. More...
 
void PutMessage (const Message &msg)
 Places a Message structure on the Message queue. More...
 
void PutMessage (const std::string &text)
 Creates a message with the given text and places it on the queue. More...
 
void PutMessage (const std::string &text, bool bVal)
 Creates a message with the given text and boolean value and places it on the queue. More...
 
void PutMessage (const std::string &text, int iVal)
 Creates a message with the given text and integer value and places it on the queue. More...
 
void PutMessage (const std::string &text, double dVal)
 Creates a message with the given text and double value and places it on the queue. More...
 
int SomeMessages (void)
 Reads the message on the queue (but does not delete it). More...
 
void ProcessMessage (void)
 Reads the message on the queue and removes it from the queue. More...
 
MessageProcessNextMessage (void)
 Reads the next message on the queue and removes it from the queue. More...
 

Additional Inherited Members

- Public Types inherited from FGJSBBase
enum  { eL = 1, eM, eN }
 Moments L, M, N.
 
enum  { eP = 1, eQ, eR }
 Rates P, Q, R.
 
enum  { eU = 1, eV, eW }
 Velocities U, V, W.
 
enum  { eX = 1, eY, eZ }
 Positions X, Y, Z.
 
enum  { ePhi = 1, eTht, ePsi }
 Euler angles Phi, Theta, Psi.
 
enum  { eDrag = 1, eSide, eLift }
 Stability axis forces, Drag, Side force, Lift.
 
enum  { eRoll = 1, ePitch, eYaw }
 Local frame orientation Roll, Pitch, Yaw.
 
enum  { eNorth = 1, eEast, eDown }
 Local frame position North, East, Down.
 
enum  { eLat = 1, eLong, eRad }
 Locations Radius, Latitude, Longitude.
 
enum  {
  inNone = 0, inDegrees, inRadians, inMeters,
  inFeet
}
 Conversion specifiers.
 
- Static Public Member Functions inherited from FGJSBBase
static double CelsiusToFahrenheit (double celsius)
 Converts from degrees Celsius to degrees Fahrenheit. More...
 
static double CelsiusToKelvin (double celsius)
 Converts from degrees Celsius to degrees Kelvin. More...
 
static double CelsiusToRankine (double celsius)
 Converts from degrees Celsius to degrees Rankine. More...
 
static double Constrain (double min, double value, double max)
 Constrain a value between a minimum and a maximum value.
 
static bool EqualToRoundoff (double a, double b)
 Finite precision comparison. More...
 
static bool EqualToRoundoff (float a, float b)
 Finite precision comparison. More...
 
static bool EqualToRoundoff (float a, double b)
 Finite precision comparison. More...
 
static bool EqualToRoundoff (double a, float b)
 Finite precision comparison. More...
 
static double FahrenheitToCelsius (double fahrenheit)
 Converts from degrees Fahrenheit to degrees Celsius. More...
 
static double FeetToMeters (double measure)
 Converts from feet to meters. More...
 
static double GaussianRandomNumber (void)
 
static double KelvinToCelsius (double kelvin)
 Converts from degrees Kelvin to degrees Celsius. More...
 
static double KelvinToFahrenheit (double kelvin)
 Converts from degrees Kelvin to degrees Fahrenheit. More...
 
static double KelvinToRankine (double kelvin)
 Converts from degrees Kelvin to degrees Rankine. More...
 
static double MachFromVcalibrated (double vcas, double p, double psl, double rhosl)
 Calculate the Mach number from the calibrated airspeed. More...
 
static double PitotTotalPressure (double mach, double p)
 Compute the total pressure in front of the Pitot tube. More...
 
static double RankineToCelsius (double rankine)
 Converts from degrees Rankine to degrees Celsius. More...
 
static double RankineToKelvin (double rankine)
 Converts from degrees Rankine to degrees Kelvin. More...
 
static double sign (double num)
 
static double VcalibratedFromMach (double mach, double p, double psl, double rhosl)
 Calculate the calibrated airspeed from the Mach number. More...
 
- Static Public Attributes inherited from FGJSBBase
static short debug_lvl = 1
 
static char highint [5] = {27, '[', '1', 'm', '\0' }
 highlights text
 
static char halfint [5] = {27, '[', '2', 'm', '\0' }
 low intensity text
 
static char normint [6] = {27, '[', '2', '2', 'm', '\0' }
 normal intensity text
 
static char reset [5] = {27, '[', '0', 'm', '\0' }
 resets text properties
 
static char underon [5] = {27, '[', '4', 'm', '\0' }
 underlines text
 
static char underoff [6] = {27, '[', '2', '4', 'm', '\0' }
 underline off
 
static char fgblue [6] = {27, '[', '3', '4', 'm', '\0' }
 blue text
 
static char fgcyan [6] = {27, '[', '3', '6', 'm', '\0' }
 cyan text
 
static char fgred [6] = {27, '[', '3', '1', 'm', '\0' }
 red text
 
static char fggreen [6] = {27, '[', '3', '2', 'm', '\0' }
 green text
 
static char fgdef [6] = {27, '[', '3', '9', 'm', '\0' }
 default text
 
- Protected Member Functions inherited from FGJSBBase
void Debug (int)
 
- Static Protected Member Functions inherited from FGJSBBase
static std::string CreateIndexedPropertyName (const std::string &Property, int index)
 
- Static Protected Attributes inherited from FGJSBBase
static const double degtorad = 0.017453292519943295769236907684886
 
static const double fpstokts = 1.0/ktstofps
 
static const double fttom = 0.3048
 
static int gaussian_random_number_phase = 0
 
static const double hptoftlbssec = 550.0
 
static const double in3tom3 = 1.638706E-5
 
static const double inchtoft = 0.08333333
 
static const double inhgtopa = 3386.38
 
static const std::string JSBSim_version = "1.0 " __DATE__ " " __TIME__
 
static const double kgtolb = 2.20462
 
static const double kgtoslug = 0.06852168
 
static const double ktstofps = 1.68781
 
static const double lbtoslug = 1.0/slugtolb
 
static Message localMsg
 
static const double m3toft3 = 1.0/(fttom*fttom*fttom)
 
static double Mair = 28.9645
 
static unsigned int messageId = 0
 
static std::queue< MessageMessages
 
static const std::string needed_cfg_version = "2.0"
 
static const double psftoinhg = 0.014138
 
static const double psftopa = 47.88
 
static const double radtodeg = 57.295779513082320876798154814105
 
static double Reng = 1716.56
 
static double Rstar = 1545.348
 
static const double SHRatio = 1.40
 
static const double slugtolb = 32.174049
 

Detailed Description

Represents a mathematical function.

The FGFunction class is a powerful and versatile resource that allows algebraic functions to be defined in a JSBSim configuration file. It is similar in concept to MathML (Mathematical Markup Language, www.w3.org/Math/), but simpler and more terse. A function definition consists of an operation, a value, a table, or a property (which evaluates to a value). The currently supported operations are:

  • sum (takes n args)
  • difference (takes n args)
  • product (takes n args)
  • quotient (takes 2 args)
  • pow (takes 2 args)
  • sqrt (takes one argument)
  • toradians (takes one argument)
  • todegrees (takes one argument)
  • exp (takes 2 args)
  • log2 (takes 1 arg)
  • ln (takes 1 arg)
  • log10 (takes 1 arg)
  • abs (takes 1 arg)
  • sin (takes 1 arg)
  • cos (takes 1 arg)
  • tan (takes 1 arg)
  • asin (takes 1 arg)
  • acos (takes 1 arg)
  • atan (takes 1 arg)
  • atan2 (takes 2 args)
  • min (takes n args)
  • max (takes n args)
  • avg (takes n args)
  • fraction
  • mod
  • lt (less than, takes 2 args)
  • le (less equal, takes 2 args)
  • gt (greater than, takes 2 args)
  • ge (greater than, takes 2 args)
  • eq (equal, takes 2 args)
  • nq (not equal, takes 2 args)
  • and (takes n args)
  • or (takes n args)
  • not (takes 1 args)
  • if-then (takes 2-3 args)
  • switch (takes 2 or more args)
  • random (Gaussian distribution random number)
  • urandom (Uniform random number between -1 and +1)
  • pi
  • integer
  • interpolate 1-dimensional (takes a minimum of five arguments, odd number)

An operation is defined in the configuration file as in the following example:

<sum>
<value> 3.14159 </value>
<property> velocities/qbar </property>
<product>
<value> 0.125 </value>
<property> metrics/wingarea </property>
</product>
</sum>

A full function definition, such as is used in the aerodynamics section of a configuration file includes the function element, and other elements. It should be noted that there can be only one non-optional (non-documentation) element - that is, one operation element - in the top-level function definition. Multiple value and/or property elements cannot be immediate child members of the function element. Almost always, the first operation within the function element will be a product or sum. For example:

<function name="aero/moment/Clr">
<description>Roll moment due to yaw rate</description>
<product>
<property>aero/qbar-area</property>
<property>metrics/bw-ft</property>
<property>aero/bi2vel</property>
<property>velocities/r-aero-rad_sec</property>
<table>
<independentVar>aero/alpha-rad</independentVar>
<tableData>
0.000 0.08
0.094 0.19
</tableData>
</table>
</product>
</function>

The "lowest level" in a function is always a value or a property, which cannot itself contain another element. As shown, operations can contain values, properties, tables, or other operations. In the first above example, the sum element contains all three. What is evaluated is written algebraically as:

3.14159 + qbar + (0.125 * wingarea)

Some operations can take only a single argument. That argument, however, can be an operation (such as sum) which can contain other items. The point to keep in mind is that it evaluates to a single value - which is just what the trigonometric functions require (except atan2, which takes two arguments).

Specific Function Definitions

Note: In the definitions below, a "property" refers to a single property specified within either the <property></property> tag or the shortcut tag, <p></p>. The keyword "value" refers to a single numeric value specified either within the <value></value> tag or the shortcut <v></v> tag. The keyword "table" refers to a single table specified either within the <table></table> tag or the shortcut <t></t> tag. The plural form of any of the three words refers to one or more instances of a property, value, or table.

  • sum, sums the values of all immediate child elements:
    <sum>
    {properties, values, tables, or other function elements}
    </sum>
    Example: Mach + 0.01
    <sum>
    <p> velocities/mach </p>
    <v> 0.01 </v>
    </sum>
  • difference, subtracts the values of all immediate child elements from the value of the first child element:
    <difference>
    {properties, values, tables, or other function elements}
    </difference>
    Example: Mach - 0.01
    <difference>
    <p> velocities/mach </p>
    <v> 0.01 </v>
    </difference>
  • product multiplies together the values of all immediate child elements:
    <product>
    {properties, values, tables, or other function elements}
    </product>
    Example: qbar*S*beta*CY_beta
    <product>
    <property> aero/qbar-psf </property>
    <property> metrics/Sw-sqft </property>
    <property> aero/beta-rad </property>
    <property> aero/coefficient/CY_beta </property>
    </product>
  • quotient, divides the value of the first immediate child element by the second immediate child element:
    <quotient>
    {property, value, table, or other function element}
    {property, value, table, or other function element}
    </quotient>
    Example: (2*GM)/R
    <quotient>
    <product>
    <v> 2.0 </v>
    <p> guidance/executive/gm </p>
    </product>
    <p> position/radius-to-vehicle-ft </p>
    </quotient>
  • pow, raises the value of the first immediate child element to the power of the value of the second immediate child element:
    <pow>
    {property, value, table, or other function element}
    {property, value, table, or other function element}
    </pow>
    Example: Mach^2
    <pow>
    <p> velocities/mach </p>
    <v> 2.0 </v>
    </pow>
  • sqrt, takes the square root of the value of the immediate child element:
    <sqrt>
    {property, value, table, or other function element}
    </sqrt>
    Example: square root of 25
    <sqrt> <v> 25.0 </v> </sqrt>
  • toradians, converts a presumed argument in degrees to radians by multiplying the value of the immediate child element by pi/180:
    <toradians>
    {property, value, table, or other function element}
    </toradians>
    Example: convert 45 degrees to radians
    <toradians> <v> 45 </v> </toradians>
  • todegrees, converts a presumed argument in radians to degrees by multiplying the value of the immediate child element by 180/pi:
    <todegrees>
    {property, value, table, or other function element}
    </todegrees>
    Example: convert 0.5*pi radians to degrees
    <todegrees>
    <product> <v> 0.5 </v> <pi/> </product>
    </todegrees>
  • exp, raises "e" to the power of the immediate child element:
    <exp>
    {property, value, table, or other function element}
    </exp>
    Example: raise "e" to the 1.5 power, e^1.5
    <exp> <v> 1.5 </v> </exp>
  • log2, calculates the log base 2 value of the immediate child element:
    <log2>
    {property, value, table, or other function element}
    </log2>
    Example:
    <log2> <v> 128 </v> </log2>
  • ln, calculates the natural logarithm of the value of the immediate child element:
    <ln>
    {property, value, table, or other function element}
    </ln>
    Example: ln(128)
    <ln> <v> 200 </v> </ln>
  • log10 calculates the base 10 logarithm of the value of the immediate child element
    <log10>
    {property, value, table, or other function element}
    </log10>
    Example log(Mach)
    <log10> <p> velocities/mach </p> </log10>
  • abs calculates the absolute value of the immediate child element
    <abs>
    {property, value, table, or other function element}
    </abs>
    Example:
    <abs> <p> flight-path/gamma-rad </p> </abs>
  • sin calculates the sine of the value of the immediate child element (the argument is expected to be in radians)
    <sin>
    {property, value, table, or other function element}
    </sin>
    Example:
    <sin> <toradians> <p> fcs/heading-true-degrees </p> </toradians> </sin>
  • cos calculates the cosine of the value of the immediate child element (the argument is expected to be in radians)
    <cos>
    {property, value, table, or other function element}
    </cos>
    Example:
    <cos> <toradians> <p> fcs/heading-true-degrees </p> </toradians> </cos>
  • tan calculates the tangent of the value of the immediate child element (the argument is expected to be in radians)
    <tan>
    {property, value, table, or other function element}
    </tan>
    Example:
    <tan> <toradians> <p> fcs/heading-true-degrees </p> </toradians> </tan>
  • asin calculates the arcsine (inverse sine) of the value of the immediate child element. The value provided should be in the range from -1 to +1. The value returned will be expressed in radians, and will be in the range from -pi/2 to +pi/2.
    <asin>
    {property, value, table, or other function element}
    </asin>
    Example:
    <asin> <v> 0.5 </v> </asin>
  • acos calculates the arccosine (inverse cosine) of the value of the immediate child element. The value provided should be in the range from -1 to +1. The value returned will be expressed in radians, and will be in the range from 0 to pi.
    <acos>
    {property, value, table, or other function element}
    </acos>
    Example:
    <acos> <v> 0.5 </v> </acos>
  • atan calculates the inverse tangent of the value of the immediate child element. The value returned will be expressed in radians, and will be in the range from -pi/2 to +pi/2.
    <atan>
    {property, value, table, or other function element}
    </atan>
    Example:
    <atan> <v> 0.5 </v> </atan>
  • atan2 calculates the inverse tangent of the value of the immediate child elements, Y/X (in that order). It even works for X values near zero. The value returned will be expressed in radians, and in the range -pi to +pi.
    <atan2>
    {property, value, table, or other function element} {property, value, table, or other function element}
    </atan2>
    Example: inverse tangent of 0.5/0.25, evaluates to: 1.107 radians
    <atan2> <v> 0.5 </<v> <v> 0.25 </v> </atan2>
  • min returns the smallest value from all the immediate child elements
    <min>
    {properties, values, tables, or other function elements}
    </min>
    Example: returns the lesser of velocity and 2500
    <min>
    <p> velocities/eci-velocity-mag-fps </p>
    <v> 2500.0 </v>
    </min>
  • max returns the largest value from all the immediate child elements
    <max>
    {properties, values, tables, or other function elements}
    </max>
    Example: returns the greater of velocity and 15000
    <max>
    <p> velocities/eci-velocity-mag-fps </p>
    <v> 15000.0 </v>
    </max>
  • avg returns the average value of all the immediate child elements
    <avg>
    {properties, values, tables, or other function elements}
    </avg>
    Example: returns the average of the four numbers below, evaluates to 0.50.
    <avg>
    <v> 0.25 </v>
    <v> 0.50 </v>
    <v> 0.75 </v>
    <v> 0.50 </v>
    </avg>
  • fraction returns the fractional part of the value of the immediate child element
    <fraction>
    {property, value, table, or other function element}
    </fraction>
    Example: returns the fractional part of pi - or, roughly, 0.1415926...
    <fraction> <pi/> </fraction>
  • integer returns the integer portion of the value of the immediate child element
    <integer>
    {property, value, table, or other function element}
    </integer>
  • mod returns the remainder from the integer division of the value of the first immediate child element by the second immediate child element, X/Y (X modulo Y). The value returned is the value X-I*Y, for the largest integer I such that if Y is nonzero, the result has the same sign as X and magnitude less than the magnitude of Y. For instance, the expression "5 mod 2" would evaluate to 1 because 5 divided by 2 leaves a quotient of 2 and a remainder of 1, while "9 mod 3" would evaluate to 0 because the division of 9 by 3 has a quotient of 3 and leaves a remainder of 0.
    <mod>
    {property, value, table, or other function element} {property, value, table, or other function element}
    </mod>
    Example: 5 mod 2, evaluates to 1
    <mod> <v> 5 </v> <v> 2 </v> </mod>
  • lt returns a 1 if the value of the first immediate child element is less than the value of the second immediate child element, returns 0 otherwise
    <lt>
    {property, value, table, or other function element}
    {property, value, table, or other function element}
    </lt>
    Example: returns 1 if thrust is less than 10,000, returns 0 otherwise
    <lt>
    <p> propulsion/engine[2]/thrust-lbs </p>
    <v> 10000.0 </v>
    </lt>
  • le returns a 1 if the value of the first immediate child element is less than or equal to the value of the second immediate child element, returns 0 otherwise
    <le>
    {property, value, table, or other function element}
    {property, value, table, or other function element}
    </le>
    Example: returns 1 if thrust is less than or equal to 10,000, returns 0 otherwise
    <le>
    <p> propulsion/engine[2]/thrust-lbs </p>
    <v> 10000.0 </v>
    </le>
  • gt returns a 1 if the value of the first immediate child element is greater than the value of the second immediate child element, returns 0 otherwise
    <gt>
    {property, value, table, or other function element}
    {property, value, table, or other function element}
    </gt>
    Example: returns 1 if thrust is greater than 10,000, returns 0 otherwise
    <gt>
    <p> propulsion/engine[2]/thrust-lbs </p>
    <v> 10000.0 </v>
    </gt>
  • ge returns a 1 if the value of the first immediate child element is greater than or equal to the value of the second immediate child element, returns 0 otherwise
    <ge>
    {property, value, table, or other function element}
    {property, value, table, or other function element}
    </ge>
    Example: returns 1 if thrust is greater than or equal to 10,000, returns 0 otherwise
    <ge>
    <p> propulsion/engine[2]/thrust-lbs </p>
    <v> 10000.0 </v>
    </ge>
  • eq returns a 1 if the value of the first immediate child element is equal to the second immediate child element, returns 0 otherwise
    <eq>
    {property, value, table, or other function element}
    {property, value, table, or other function element}
    </eq>
    Example: returns 1 if thrust is equal to 10,000, returns 0 otherwise
    <eq>
    <p> propulsion/engine[2]/thrust-lbs </p>
    <v> 10000.0 </v>
    </eq>
  • nq returns a 1 if the value of the first immediate child element is not equal to the value of the second immediate child element, returns 0 otherwise
    <nq>
    {property, value, table, or other function element}
    {property, value, table, or other function element}
    </nq>
    Example: returns 1 if thrust is not 0, returns 0 otherwise
    <nq>
    <p> propulsion/engine[2]/thrust-lbs </p>
    <v> 0.0 </v>
    </nq>
  • and returns a 1 if the values of the immediate child elements are all 1, returns 0 otherwise. Values provided are expected to be either 1 or 0 within machine precision.
    <and>
    {properties, values, tables, or other function elements}
    </and>
    Example: returns 1 if the specified flags are all 1
    <and>
    <p> guidance/first-stage-flight-flag </p>
    <p> control/engines-running-flag </p>
    </and>
  • or returns a 1 if the values of any of the immediate child elements 1, returns 0 otherwise. Values provided are expected to be either 1 or 0 within machine precision.
    <or>
    {properties, values, tables, or other function elements}
    </or>
    Example: returns 1 if any of the specified flags are 1
    <or>
    <p> guidance/first-stage-flight-flag </p>
    <p> control/engines-running-flag </p>
    </or>
  • not returns the inverse of the value of the supplied immediate child element (e.g., returns 1 if supplied a 0)
    <not>
    {property, value, table, or other function element}
    </not>
    Example: returns 0 if the value of the supplied flag is 1
    <not> <p> guidance/first-stage-flight-flag </p> </not>
  • ifthen if the value of the first immediate child element is 1, then the value of the second immediate child element is returned, otherwise the value of the third child element is returned
    <ifthen>
    {property, value, table, or other function element}
    {property, value, table, or other function element}
    {property, value, table, or other function element}
    </ifthen>
    Example: if flight-mode is greater than 2, then a value of 0.00 is returned,
    otherwise the value of the property control/pitch-lag is returned.
    <ifthen>
    <gt> <p> executive/flight-mode </p> <v> 2 </v> </gt>
    <v> 0.00 </v>
    <p> control/pitch-lag </p>
    </ifthen>
  • switch uses the integer value of the first immediate child element as an index to select one of the subsequent immediate child elements to return the value of
    <switch>
    {property, value, table, or other function element}
    {property, value, table, or other function element}
    {property, value, table, or other function element}
    ...
    </switch>
    Example: if flight-mode is 2, the switch function returns 0.50
    <switch>
    <p> executive/flight-mode </p>
    <v> 0.25 </v>
    <v> 0.50 </v>
    <v> 0.75 </v>
    <v> 1.00 </v>
    </switch>
  • random Takes no arguments and returns a Gaussian distributed random number
    <random/>
  • urandom Takes no arguments and returns a uniformly distributed random number between -1 and +1
    <urandom/>
  • pi Takes no argument and returns the value of Pi
    <pi/>
  • interpolate1d returns the result from a 1-dimensional interpolation of the supplied values, with the value of the first immediate child element representing the lookup value into the table, and the following pairs of values representing the independent and dependent values. The first provided child element is expected to be a property. The interpolation does not extrapolate, but holds the highest value if the provided lookup value goes outside of the provided range.
    <interpolate1d>
    {property, value, table, or other function element}
    {property, value, table, or other function element} {property, value, table, or other function element}
    ...
    </interpolate1d>
    Example: If mach is 0.4, the interpolation will return 0.375. If mach is 1.5, the interpolation
    will return 0.60.
    <interpolate1d>
    <p> velocities/mach </p>
    <v> 0.00 </v> <v> 0.25 </v>
    <v> 0.80 </v> <v> 0.50 </v>
    <v> 0.90 </v> <v> 0.60 </v>
    </interpolate1d>
    Author
    Jon Berndt

Definition at line 699 of file FGFunction.h.

Constructor & Destructor Documentation

◆ FGFunction()

FGFunction ( FGPropertyManager PropertyManager,
Element element,
const std::string &  prefix = "" 
)

Constructor.

When this constructor is called, the XML element pointed to in memory by the element argument is traversed. If other FGParameter-derived objects (values, functions, properties, or tables) are encountered, this instance of the FGFunction object will store a pointer to the found object and pass the relevant Element pointer to the constructor for the new object. In other words, each FGFunction object maintains a list of "child" FGParameter-derived objects which in turn may each contain its own list, and so on. At runtime, each object evaluates its child parameters, which each may have its own child parameters to evaluate.

Parameters
PropertyManagera pointer to the property manager instance.
elementa pointer to the Element object containing the function definition.
prefixan optional prefix to prepend to the name given to the property that represents this function (if given).

Definition at line 111 of file FGFunction.cpp.

112  : PropertyManager(propMan), Prefix(prefix)
113 {
114  Element* element;
115  string operation, property_name;
116  cached = false;
117  cachedValue = -HUGE_VAL;
118  invlog2val = 1.0/log10(2.0);
119  pCopyTo = 0L;
120 
121  Name = el->GetAttributeValue("name");
122  operation = el->GetName();
123 
124  if (operation == function_string) {
125  sCopyTo = el->GetAttributeValue("copyto");
126  if (!sCopyTo.empty()) {
127 
128  if (sCopyTo.find("#") != string::npos) {
129  if (is_number(Prefix)) sCopyTo = replace(sCopyTo,"#",Prefix);
130  }
131 
132  pCopyTo = PropertyManager->GetNode(sCopyTo);
133  if (pCopyTo == 0L) cerr << "Property \"" << sCopyTo << "\" must be previously defined in function "
134  << Name << endl;
135  }
136  Type = eTopLevel;
137  } else if (operation == product_string) {
138  Type = eProduct;
139  } else if (operation == difference_string) {
140  Type = eDifference;
141  } else if (operation == sum_string) {
142  Type = eSum;
143  } else if (operation == quotient_string) {
144  Type = eQuotient;
145  } else if (operation == pow_string) {
146  Type = ePow;
147  } else if (operation == sqrt_string) {
148  Type = eSqrt;
149  } else if (operation == toradians_string) {
150  Type = eToRadians;
151  } else if (operation == todegrees_string) {
152  Type = eToDegrees;
153  } else if (operation == log2_string) {
154  Type = eLog2;
155  } else if (operation == ln_string) {
156  Type = eLn;
157  } else if (operation == log10_string) {
158  Type = eLog10;
159  } else if (operation == abs_string) {
160  Type = eAbs;
161  } else if (operation == sign_string) {
162  Type = eSign;
163  } else if (operation == sin_string) {
164  Type = eSin;
165  } else if (operation == exp_string) {
166  Type = eExp;
167  } else if (operation == cos_string) {
168  Type = eCos;
169  } else if (operation == tan_string) {
170  Type = eTan;
171  } else if (operation == asin_string) {
172  Type = eASin;
173  } else if (operation == acos_string) {
174  Type = eACos;
175  } else if (operation == atan_string) {
176  Type = eATan;
177  } else if (operation == atan2_string) {
178  Type = eATan2;
179  } else if (operation == min_string) {
180  Type = eMin;
181  } else if (operation == max_string) {
182  Type = eMax;
183  } else if (operation == avg_string) {
184  Type = eAvg;
185  } else if (operation == fraction_string) {
186  Type = eFrac;
187  } else if (operation == integer_string) {
188  Type = eInteger;
189  } else if (operation == mod_string) {
190  Type = eMod;
191  } else if (operation == random_string) {
192  Type = eRandom;
193  } else if (operation == urandom_string) {
194  Type = eUrandom;
195  } else if (operation == pi_string) {
196  Type = ePi;
197  } else if (operation == rotation_alpha_local_string) {
198  Type = eRotation_alpha_local;
199  } else if (operation == rotation_beta_local_string) {
200  Type = eRotation_beta_local;
201  } else if (operation == rotation_gamma_local_string) {
202  Type = eRotation_gamma_local;
203  } else if (operation == rotation_bf_to_wf_string) {
204  Type = eRotation_bf_to_wf;
205  } else if (operation == rotation_wf_to_bf_string) {
206  Type = eRotation_wf_to_bf;
207  } else if (operation == lessthan_string) {
208  Type = eLT;
209  } else if (operation == lessequal_string) {
210  Type = eLE;
211  } else if (operation == greatthan_string) {
212  Type = eGT;
213  } else if (operation == greatequal_string) {
214  Type = eGE;
215  } else if (operation == equal_string) {
216  Type = eEQ;
217  } else if (operation == notequal_string) {
218  Type = eNE;
219  } else if (operation == and_string) {
220  Type = eAND;
221  } else if (operation == or_string) {
222  Type = eOR;
223  } else if (operation == not_string) {
224  Type = eNOT;
225  } else if (operation == ifthen_string) {
226  Type = eIfThen;
227  } else if (operation == switch_string) {
228  Type = eSwitch;
229  } else if (operation == interpolate1d_string) {
230  Type = eInterpolate1D;
231  } else if (operation != description_string) {
232  cerr << "Bad operation " << operation << " detected in configuration file" << endl;
233  }
234 
235  element = el->GetElement();
236  if (!element && Type != eRandom && Type != eUrandom && Type != ePi) {
237  cerr << fgred << highint << endl;
238  cerr << " No element was specified as an argument to the \"" << operation << "\" operation" << endl;
239  cerr << " This can happen when, for instance, a cos operation is specified and a " << endl;
240  cerr << " property name is given explicitly, but is not placed within a" << endl;
241  cerr << " <property></property> element tag pair." << endl;
242  cerr << reset;
243  exit(-2);
244  }
245 
246  while (element) {
247  operation = element->GetName();
248 
249  // data types
250  if (operation == property_string || operation == p_string) {
251  property_name = element->GetDataLine();
252  if (property_name.find("#") != string::npos) {
253  if (is_number(Prefix)) {
254  property_name = replace(property_name,"#",Prefix);
255  }
256  }
257  if (PropertyManager->HasNode(property_name)) {
258  FGPropertyNode* newNode = PropertyManager->GetNode(property_name);
259  Parameters.push_back(new FGPropertyValue( newNode ));
260  } else {
261  // cerr << fgcyan << "Warning: The property " + property_name + " is initially undefined."
262  // << reset << endl;
263  Parameters.push_back(new FGPropertyValue( property_name,
264  PropertyManager ));
265  }
266  } else if (operation == value_string || operation == v_string) {
267  Parameters.push_back(new FGRealValue(element->GetDataAsNumber()));
268  } else if (operation == table_string || operation == t_string) {
269  Parameters.push_back(new FGTable(PropertyManager, element));
270  // operations
271  } else if (operation == product_string ||
272  operation == difference_string ||
273  operation == sum_string ||
274  operation == quotient_string ||
275  operation == pow_string ||
276  operation == sqrt_string ||
277  operation == toradians_string ||
278  operation == todegrees_string ||
279  operation == exp_string ||
280  operation == log2_string ||
281  operation == ln_string ||
282  operation == log10_string ||
283  operation == abs_string ||
284  operation == sign_string ||
285  operation == sin_string ||
286  operation == cos_string ||
287  operation == tan_string ||
288  operation == asin_string ||
289  operation == acos_string ||
290  operation == atan_string ||
291  operation == atan2_string ||
292  operation == min_string ||
293  operation == max_string ||
294  operation == fraction_string ||
295  operation == integer_string ||
296  operation == mod_string ||
297  operation == random_string ||
298  operation == urandom_string ||
299  operation == pi_string ||
300  operation == avg_string ||
301  operation == rotation_alpha_local_string||
302  operation == rotation_beta_local_string||
303  operation == rotation_gamma_local_string||
304  operation == rotation_bf_to_wf_string||
305  operation == rotation_wf_to_bf_string ||
306  operation == lessthan_string ||
307  operation == lessequal_string ||
308  operation == greatthan_string ||
309  operation == greatequal_string ||
310  operation == equal_string ||
311  operation == notequal_string ||
312  operation == and_string ||
313  operation == or_string ||
314  operation == not_string ||
315  operation == ifthen_string ||
316  operation == switch_string ||
317  operation == interpolate1d_string)
318  {
319  Parameters.push_back(new FGFunction(PropertyManager, element, Prefix));
320  } else if (operation != description_string) {
321  cerr << "Bad operation " << operation << " detected in configuration file" << endl;
322  }
323  element = el->GetNextElement();
324  }
325 
326  bind(); // Allow any function to save its value
327 
328  Debug(0);
329 }
static char reset[5]
resets text properties
Definition: FGJSBBase.h:131
static char fgred[6]
red text
Definition: FGJSBBase.h:141
static char highint[5]
highlights text
Definition: FGJSBBase.h:125
FGFunction(FGPropertyManager *PropertyManager, Element *element, const std::string &prefix="")
Constructor.
Definition: FGFunction.cpp:111
+ Here is the call graph for this function:

Member Function Documentation

◆ cacheValue()

void cacheValue ( bool  shouldCache)

Specifies whether to cache the value of the function, so it is calculated only once per frame.

If shouldCache is true, then the value of the function is calculated, and a flag is set so further calculations done this frame will use the cached value. In order to turn off caching, cacheValue must be called with a false argument.

Parameters
shouldCachespecifies whether the function should cache the computed value.

Definition at line 340 of file FGFunction.cpp.

341 {
342  cached = false; // Must set cached to false prior to calling GetValue(), else
343  // it will _never_ calculate the value;
344  if (cache) {
345  cachedValue = GetValue();
346  cached = true;
347  }
348 }
double GetValue(void) const
Retrieves the value of the function object.
Definition: FGFunction.cpp:364
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ GetValue()

double GetValue ( void  ) const
virtual

Retrieves the value of the function object.

Returns
the total value of the function.

Implements FGParameter.

Definition at line 364 of file FGFunction.cpp.

365 {
366  unsigned int i;
367  double scratch;
368  double temp=0;
369 
370  if (cached) return cachedValue;
371 
372  if ( Type != eRandom
373  && Type != eUrandom
374  && Type != ePi ) temp = Parameters[0]->GetValue();
375 
376  switch (Type) {
377  case eTopLevel:
378  if (pCopyTo) pCopyTo->setDoubleValue(temp);
379  break;
380  case eProduct:
381  for (i=1;i<Parameters.size();i++) {
382  temp *= Parameters[i]->GetValue();
383  }
384  break;
385  case eDifference:
386  for (i=1;i<Parameters.size();i++) {
387  temp -= Parameters[i]->GetValue();
388  }
389  break;
390  case eSum:
391  for (i=1;i<Parameters.size();i++) {
392  temp += Parameters[i]->GetValue();
393  }
394  break;
395  case eQuotient:
396  if (Parameters[1]->GetValue() != 0.0)
397  temp /= Parameters[1]->GetValue();
398  else
399  temp = HUGE_VAL;
400  break;
401  case ePow:
402  temp = pow(temp,Parameters[1]->GetValue());
403  break;
404  case eSqrt:
405  temp = sqrt(temp);
406  break;
407  case eToRadians:
408  temp *= M_PI/180.0;
409  break;
410  case eToDegrees:
411  temp *= 180.0/M_PI;
412  break;
413  case eExp:
414  temp = exp(temp);
415  break;
416  case eLog2:
417  if (temp > 0.00) temp = log10(temp)*invlog2val;
418  else temp = -HUGE_VAL;
419  break;
420  case eLn:
421  if (temp > 0.00) temp = log(temp);
422  else temp = -HUGE_VAL;
423  break;
424  case eLog10:
425  if (temp > 0.00) temp = log10(temp);
426  else temp = -HUGE_VAL;
427  break;
428  case eAbs:
429  temp = fabs(temp);
430  break;
431  case eSign:
432  temp = temp < 0 ? -1:1; // 0.0 counts as positive.
433  break;
434  case eSin:
435  temp = sin(temp);
436  break;
437  case eCos:
438  temp = cos(temp);
439  break;
440  case eTan:
441  temp = tan(temp);
442  break;
443  case eACos:
444  temp = acos(temp);
445  break;
446  case eASin:
447  temp = asin(temp);
448  break;
449  case eATan:
450  temp = atan(temp);
451  break;
452  case eATan2:
453  temp = atan2(temp, Parameters[1]->GetValue());
454  break;
455  case eMod:
456  temp = ((int)temp) % ((int) Parameters[1]->GetValue());
457  break;
458  case eMin:
459  for (i=1;i<Parameters.size();i++) {
460  if (Parameters[i]->GetValue() < temp) temp = Parameters[i]->GetValue();
461  }
462  break;
463  case eMax:
464  for (i=1;i<Parameters.size();i++) {
465  if (Parameters[i]->GetValue() > temp) temp = Parameters[i]->GetValue();
466  }
467  break;
468  case eAvg:
469  for (i=1;i<Parameters.size();i++) {
470  temp += Parameters[i]->GetValue();
471  }
472  temp /= Parameters.size();
473  break;
474  case eFrac:
475  temp = modf(temp, &scratch);
476  break;
477  case eInteger:
478  modf(temp, &scratch);
479  temp = scratch;
480  break;
481  case eRandom:
482  temp = GaussianRandomNumber();
483  break;
484  case eUrandom:
485  temp = -1.0 + (((double)rand()/double(RAND_MAX))*2.0);
486  break;
487  case ePi:
488  temp = M_PI;
489  break;
490  case eLT:
491  temp = (temp < Parameters[1]->GetValue())?1:0;
492  break;
493  case eLE:
494  temp = (temp <= Parameters[1]->GetValue())?1:0;
495  break;
496  case eGT:
497  temp = (temp > Parameters[1]->GetValue())?1:0;
498  break;
499  case eGE:
500  temp = (temp >= Parameters[1]->GetValue())?1:0;
501  break;
502  case eEQ:
503  temp = (temp == Parameters[1]->GetValue())?1:0;
504  break;
505  case eNE:
506  temp = (temp != Parameters[1]->GetValue())?1:0;
507  break;
508  case eAND:
509  {
510  bool flag = (GetBinary(temp) != 0u);
511  for (i=1; i<Parameters.size() && flag; i++) {
512  flag = (GetBinary(Parameters[i]->GetValue()) != 0);
513  }
514  temp = flag ? 1 : 0;
515  }
516  break;
517  case eOR:
518  {
519  bool flag = (GetBinary(temp) != 0);
520  for (i=1; i<Parameters.size() && !flag; i++) {
521  flag = (GetBinary(Parameters[i]->GetValue()) != 0);
522  }
523  temp = flag ? 1 : 0;
524  }
525  break;
526  case eNOT:
527  temp = (GetBinary(temp) != 0) ? 0 : 1;
528  break;
529  case eIfThen:
530  {
531  i = Parameters.size();
532  if (i == 3) {
533  if (GetBinary(temp) == 1) {
534  temp = Parameters[1]->GetValue();
535  } else {
536  temp = Parameters[2]->GetValue();
537  }
538  } else {
539  throw("Malformed if/then function statement");
540  }
541  }
542  break;
543  case eSwitch:
544  {
545  size_t n = Parameters.size()-1;
546  i = int(temp+0.5);
547  if (i < n) {
548  temp = Parameters[i+1]->GetValue();
549  } else {
550  throw(string("The switch function index selected a value above the range of supplied values"
551  " - not enough values were supplied."));
552  }
553  }
554  break;
555  case eInterpolate1D:
556  {
557  size_t sz = Parameters.size();
558  if (temp <= Parameters[1]->GetValue()) {
559  temp = Parameters[2]->GetValue();
560  } else if (temp >= Parameters[sz-2]->GetValue()) {
561  temp = Parameters[sz-1]->GetValue();
562  } else {
563  for (unsigned int i=1; i<=sz-4; i+=2) {
564  if (temp < Parameters[i+2]->GetValue()) {
565  double factor = (temp - Parameters[i]->GetValue()) /
566  (Parameters[i+2]->GetValue() - Parameters[i]->GetValue());
567  double span = Parameters[i+3]->GetValue() - Parameters[i+1]->GetValue();
568  double val = factor*span;
569  temp = Parameters[i+1]->GetValue() + val;
570  break;
571  }
572  }
573  }
574  }
575  break;
576  case eRotation_alpha_local:
577  if (Parameters.size()==6) // calculates local angle of attack for skydiver body component
578  //Euler angles from the intermediate body frame to the local body frame must be from a z-y-x axis rotation order
579  {
580  double alpha = Parameters[0]->GetValue()*degtorad;
581  double beta = Parameters[1]->GetValue()*degtorad;
582  double gamma = Parameters[2]->GetValue()*degtorad;
583  double phi = Parameters[3]->GetValue()*degtorad;
584  double theta = Parameters[4]->GetValue()*degtorad;
585  double psi = Parameters[5]->GetValue()*degtorad;
586  double cphi2 = cos(-phi/2), ctht2 = cos(-theta/2), cpsi2 = cos(-psi/2);
587  double sphi2 = sin(-phi/2), stht2 = sin(-theta/2), spsi2 = sin(-psi/2);
588  double calpha2 = cos(-alpha/2), salpha2 = sin(-alpha/2);
589  double cbeta2 = cos(beta/2), sbeta2 = sin(beta/2);
590  double cgamma2 = cos(-gamma/2), sgamma2 = sin(-gamma/2);
591  //calculate local body frame to the intermediate body frame rotation quaternion
592  double At = cphi2*ctht2*cpsi2 - sphi2*stht2*spsi2;
593  double Ax = cphi2*stht2*spsi2 + sphi2*ctht2*cpsi2;
594  double Ay = cphi2*stht2*cpsi2 - sphi2*ctht2*spsi2;
595  double Az = cphi2*ctht2*spsi2 + sphi2*stht2*cpsi2;
596  //calculate the intermediate body frame to global wind frame rotation quaternion
597  double Bt = calpha2*cbeta2*cgamma2 - salpha2*sbeta2*sgamma2;
598  double Bx = calpha2*cbeta2*sgamma2 + salpha2*sbeta2*cgamma2;
599  double By = calpha2*sbeta2*sgamma2 + salpha2*cbeta2*cgamma2;
600  double Bz = calpha2*sbeta2*cgamma2 - salpha2*cbeta2*sgamma2;
601  //multiply quaternions
602  double Ct = At*Bt - Ax*Bx - Ay*By - Az*Bz;
603  double Cx = At*Bx + Ax*Bt + Ay*Bz - Az*By;
604  double Cy = At*By - Ax*Bz + Ay*Bt + Az*Bx;
605  double Cz = At*Bz + Ax*By - Ay*Bx + Az*Bt;
606  //calculate alpha_local
607  temp = -atan2(2*(Cy*Ct-Cx*Cz),(Ct*Ct+Cx*Cx-Cy*Cy-Cz*Cz));
608  temp *= radtodeg;
609  } else {
610  temp = 1;
611  }
612  break;
613  case eRotation_beta_local:
614  if (Parameters.size()==6) // calculates local angle of sideslip for skydiver body component
615  //Euler angles from the intermediate body frame to the local body frame must be from a z-y-x axis rotation order
616  {
617  double alpha = Parameters[0]->GetValue()*degtorad; //angle of attack of intermediate body frame
618  double beta = Parameters[1]->GetValue()*degtorad; //sideslip angle of intermediate body frame
619  double gamma = Parameters[2]->GetValue()*degtorad; //roll angle of intermediate body frame
620  double phi = Parameters[3]->GetValue()*degtorad; //x-axis Euler angle from the intermediate body frame to the local body frame
621  double theta = Parameters[4]->GetValue()*degtorad; //y-axis Euler angle from the intermediate body frame to the local body frame
622  double psi = Parameters[5]->GetValue()*degtorad; //z-axis Euler angle from the intermediate body frame to the local body frame
623  double cphi2 = cos(-phi/2), ctht2 = cos(-theta/2), cpsi2 = cos(-psi/2);
624  double sphi2 = sin(-phi/2), stht2 = sin(-theta/2), spsi2 = sin(-psi/2);
625  double calpha2 = cos(-alpha/2), salpha2 = sin(-alpha/2);
626  double cbeta2 = cos(beta/2), sbeta2 = sin(beta/2);
627  double cgamma2 = cos(-gamma/2), sgamma2 = sin(-gamma/2);
628  //calculate local body frame to the intermediate body frame rotation quaternion
629  double At = cphi2*ctht2*cpsi2 - sphi2*stht2*spsi2;
630  double Ax = cphi2*stht2*spsi2 + sphi2*ctht2*cpsi2;
631  double Ay = cphi2*stht2*cpsi2 - sphi2*ctht2*spsi2;
632  double Az = cphi2*ctht2*spsi2 + sphi2*stht2*cpsi2;
633  //calculate the intermediate body frame to global wind frame rotation quaternion
634  double Bt = calpha2*cbeta2*cgamma2 - salpha2*sbeta2*sgamma2;
635  double Bx = calpha2*cbeta2*sgamma2 + salpha2*sbeta2*cgamma2;
636  double By = calpha2*sbeta2*sgamma2 + salpha2*cbeta2*cgamma2;
637  double Bz = calpha2*sbeta2*cgamma2 - salpha2*cbeta2*sgamma2;
638  //multiply quaternions
639  double Ct = At*Bt - Ax*Bx - Ay*By - Az*Bz;
640  double Cx = At*Bx + Ax*Bt + Ay*Bz - Az*By;
641  double Cy = At*By - Ax*Bz + Ay*Bt + Az*Bx;
642  double Cz = At*Bz + Ax*By - Ay*Bx + Az*Bt;
643  //calculate beta_local
644  temp = asin(2*(Cx*Cy+Cz*Ct));
645  temp *= radtodeg;
646  }
647  else //
648  {temp = 1;}
649  break;
650  case eRotation_gamma_local:
651  if (Parameters.size()==6) // calculates local angle of attack for skydiver body component
652  //Euler angles from the intermediate body frame to the local body frame must be from a z-y-x axis rotation order
653  {
654  double alpha = Parameters[0]->GetValue()*degtorad; //angle of attack of intermediate body frame
655  double beta = Parameters[1]->GetValue()*degtorad; //sideslip angle of intermediate body frame
656  double gamma = Parameters[2]->GetValue()*degtorad; //roll angle of intermediate body frame
657  double phi = Parameters[3]->GetValue()*degtorad; //x-axis Euler angle from the intermediate body frame to the local body frame
658  double theta = Parameters[4]->GetValue()*degtorad; //y-axis Euler angle from the intermediate body frame to the local body frame
659  double psi = Parameters[5]->GetValue()*degtorad; //z-axis Euler angle from the intermediate body frame to the local body frame
660  double cphi2 = cos(-phi/2), ctht2 = cos(-theta/2), cpsi2 = cos(-psi/2);
661  double sphi2 = sin(-phi/2), stht2 = sin(-theta/2), spsi2 = sin(-psi/2);
662  double calpha2 = cos(-alpha/2), salpha2 = sin(-alpha/2);
663  double cbeta2 = cos(beta/2), sbeta2 = sin(beta/2);
664  double cgamma2 = cos(-gamma/2), sgamma2 = sin(-gamma/2);
665  //calculate local body frame to the intermediate body frame rotation quaternion
666  double At = cphi2*ctht2*cpsi2 - sphi2*stht2*spsi2;
667  double Ax = cphi2*stht2*spsi2 + sphi2*ctht2*cpsi2;
668  double Ay = cphi2*stht2*cpsi2 - sphi2*ctht2*spsi2;
669  double Az = cphi2*ctht2*spsi2 + sphi2*stht2*cpsi2;
670  //calculate the intermediate body frame to global wind frame rotation quaternion
671  double Bt = calpha2*cbeta2*cgamma2 - salpha2*sbeta2*sgamma2;
672  double Bx = calpha2*cbeta2*sgamma2 + salpha2*sbeta2*cgamma2;
673  double By = calpha2*sbeta2*sgamma2 + salpha2*cbeta2*cgamma2;
674  double Bz = calpha2*sbeta2*cgamma2 - salpha2*cbeta2*sgamma2;
675  //multiply quaternions
676  double Ct = At*Bt - Ax*Bx - Ay*By - Az*Bz;
677  double Cx = At*Bx + Ax*Bt + Ay*Bz - Az*By;
678  double Cy = At*By - Ax*Bz + Ay*Bt + Az*Bx;
679  double Cz = At*Bz + Ax*By - Ay*Bx + Az*Bt;
680  //calculate local roll anlge
681  temp = -atan2(2*(Cx*Ct-Cz*Cy),(Ct*Ct-Cx*Cx+Cy*Cy-Cz*Cz));
682  temp *= radtodeg;
683  }
684  else //
685  {temp = 1;}
686  break;
687  case eRotation_bf_to_wf:
688  if (Parameters.size()==7) // transforms the input vector from a body frame to a wind frame. The origin of the vector remains the same.
689  {
690  double rx = Parameters[0]->GetValue(); //x component of input vector
691  double ry = Parameters[1]->GetValue(); //y component of input vector
692  double rz = Parameters[2]->GetValue(); //z component of input vector
693  double alpha = Parameters[3]->GetValue()*degtorad; //angle of attack of the body frame
694  double beta = Parameters[4]->GetValue()*degtorad; //sideslip angle of the body frame
695  double gamma = Parameters[5]->GetValue()*degtorad; //roll angle of the body frame
696  double index = Parameters[6]->GetValue();
697  double calpha2 = cos(-alpha/2), salpha2 = sin(-alpha/2);
698  double cbeta2 = cos(beta/2), sbeta2 = sin(beta/2);
699  double cgamma2 = cos(-gamma/2), sgamma2 = sin(-gamma/2);
700  //calculate the body frame to wind frame quaternion
701  double qt = calpha2*cbeta2*cgamma2 - salpha2*sbeta2*sgamma2;
702  double qx = calpha2*cbeta2*sgamma2 + salpha2*sbeta2*cgamma2;
703  double qy = calpha2*sbeta2*sgamma2 + salpha2*cbeta2*cgamma2;
704  double qz = calpha2*sbeta2*cgamma2 - salpha2*cbeta2*sgamma2;
705  //calculate the quaternion conjugate
706  double qstart = qt;
707  double qstarx = -qx;
708  double qstary = -qy;
709  double qstarz = -qz;
710  //multiply quaternions v*q
711  double vqt = -rx*qx - ry*qy - rz*qz;
712  double vqx = rx*qt + ry*qz - rz*qy;
713  double vqy = -rx*qz + ry*qt + rz*qx;
714  double vqz = rx*qy - ry*qx + rz*qt;
715  //multiply quaternions qstar*vq
716  double Cx = qstart*vqx + qstarx*vqt + qstary*vqz - qstarz*vqy;
717  double Cy = qstart*vqy - qstarx*vqz + qstary*vqt + qstarz*vqx;
718  double Cz = qstart*vqz + qstarx*vqy - qstary*vqx + qstarz*vqt;
719 
720  if (index == 1) temp = Cx;
721  else if (index ==2) temp = Cy;
722  else temp = Cz;
723  }
724  else //
725  {temp = 1;}
726  break;
727  case eRotation_wf_to_bf:
728  if (Parameters.size()==7) // transforms the input vector from q wind frame to a body frame. The origin of the vector remains the same.
729  {
730  double rx = Parameters[0]->GetValue(); //x component of input vector
731  double ry = Parameters[1]->GetValue(); //y component of input vector
732  double rz = Parameters[2]->GetValue(); //z component of input vector
733  double alpha = Parameters[3]->GetValue()*degtorad; //angle of attack of the body frame
734  double beta = Parameters[4]->GetValue()*degtorad; //sideslip angle of the body frame
735  double gamma = Parameters[5]->GetValue()*degtorad; //roll angle of the body frame
736  double index = Parameters[6]->GetValue();
737  double calpha2 = cos(alpha/2), salpha2 = sin(alpha/2);
738  double cbeta2 = cos(-beta/2), sbeta2 = sin(-beta/2);
739  double cgamma2 = cos(gamma/2), sgamma2 = sin(gamma/2);
740  //calculate the wind frame to body frame quaternion
741  double qt = cgamma2*cbeta2*calpha2 + sgamma2*sbeta2*salpha2;
742  double qx = -cgamma2*sbeta2*salpha2 + sgamma2*cbeta2*calpha2;
743  double qy = cgamma2*cbeta2*salpha2 - sgamma2*sbeta2*calpha2;
744  double qz = cgamma2*sbeta2*calpha2 + sgamma2*cbeta2*salpha2;
745  //calculate the quaternion conjugate
746  double qstart = qt;
747  double qstarx = -qx;
748  double qstary = -qy;
749  double qstarz = -qz;
750  //multiply quaternions v*q
751  double vqt = -rx*qx - ry*qy - rz*qz;
752  double vqx = rx*qt + ry*qz - rz*qy;
753  double vqy = -rx*qz + ry*qt + rz*qx;
754  double vqz = rx*qy - ry*qx + rz*qt;
755  //multiply quaternions qstar*vq
756  double Cx = qstart*vqx + qstarx*vqt + qstary*vqz - qstarz*vqy;
757  double Cy = qstart*vqy - qstarx*vqz + qstary*vqt + qstarz*vqx;
758  double Cz = qstart*vqz + qstarx*vqy - qstary*vqx + qstarz*vqt;
759 
760  if (index == 1) temp = Cx;
761  else if (index ==2) temp = Cy;
762  else temp = Cz;
763  }
764  else //
765  {temp = 1;}
766  break;
767  default:
768  cerr << "Unknown function operation type" << endl;
769  break;
770  }
771 
772  return temp;
773 }
double GetValue(void) const
Retrieves the value of the function object.
Definition: FGFunction.cpp:364
+ Here is the caller graph for this function:

◆ GetValueAsString()

string GetValueAsString ( void  ) const

The value that the function evaluates to, as a string.

Returns
the value of the function as a string.

Definition at line 777 of file FGFunction.cpp.

778 {
779  ostringstream buffer;
780 
781  buffer << setw(9) << setprecision(6) << GetValue();
782  return buffer.str();
783 }
double GetValue(void) const
Retrieves the value of the function object.
Definition: FGFunction.cpp:364
+ Here is the call graph for this function:

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