RPN Scripting


Contents
Related Links

Overview

In addition to the newer LUA Scripting, Prepar3D supports Reverse Polish Notation (RPN) scripting. The evaluation of RPN scripts is done using a stack and reverse polish notation. For example, if you want a gauge to show altitude in thousands of feet, divide the value of INDICATED ALTITUDE by 1000. In RPN this would be:

(A:INDICATD ALTITUDE, feet) 1000 /

To execute an arithmetic operation, put both operands first in the script and then include the symbol of operation (the divide symbol in this case). This is how some programmable calculators performed arithmetic operations in the past.

This convention works the following way: When the script parser comes across a value, it pushes it onto the top of the stack. When the script parser comes across an operator, it pops from the stack the number of operands that the operator works on (usually one or two values).

Whatever value is left on top of the stack at the end of the execution is the result of the calculated expression. The Examples section provides a list of simple and more complex script examples.

The Variable Overview article describes all of the systems that support variable access.


Operators

The operators that are available in RPN are as follows:

Operator Operation Arguments Example Result
Common Operator
+ addition 2 3 5 + 8
- subtraction. If the stack contains A B -, then the calculation is A - B. 2 (L:Value) 90 - The local value minus 90.
/ division. If the stack contains A B /, then the calculation is A / B. 2 5 2 / 2.5
* multiplication 2 pi 2 * 2 pi
% taking modulo 1 5.3 % 5
++ increment 1 4 ++ 5
-- decrement 1 4 -- 3
/-/
neg
negates a number 1 4 /-/ -4
Comparison Operators
== true if equal 2 (L:Value) 0 == if{ A } Operation A is carried out if Value is 0.
!= true if not equal 2 (L:Value) 0 != if{ A } Operation A is carried out if Value is not 0.
> true if greater than 2 (L:Value1) (L:Value2) > if{ A } els{ B } If Value1 is greater than Value2, operation A is carried out, otherwise operation B is carried out.
< true if less 2 (L:Value1) (L:Value2) < if{ A } els{ B } If Value1 is less than Value2, operation A is carried out, otherwise operation B is carried out.
>= true greater than or equal 2 (L:Value1) (L:Value2) >= if{ A } els{ B } If Value1 is greater than or equal to Value2, operation A is carried out, otherwise operation B is carried out.
<= true if less than or equal 2 (L:Value1) (L:Value2) <= if{ A } els{ B } If Value1 is less than or equal to Value2, operation A is carried out, otherwise operation B is carried out.
? The third operand determines whether the first (True) or second (False) is selected. 3 A B True ? This evaluates to A.
Bit Operators
& bitwise AND 2 5 3 & 1
| bitwise OR 2 5 3 | 7
^ bitwise XOR 2 5 3 ^ 6
~ bitwise NOT 1 5 ~ -6
>> shift right operand number of bits 2 5 3 >> 0
<< shift left operand number of bits 2 5 3 << 40
Logical Operators
!, NOT NOT 1 (L:Local) ! (>L:Local) Toggles the variable Local
&&, AND AND 2 (L:Local) 0xFF00 && (>L:Local) The variable Local is ANDed with hex 0xFF00
||, OR OR 2 (L:Local) 07777 OR (>L:Local) The variable Local is ORed with octal 7777.
Numerical Operators
abs Absolute value 1 -5 abs 5
int
flr
Calculates nearest integer number which is less than the source number 1 5.98 flr 5
rng Range; returns True if the third operand lies between values one and two. 3 4 7 6 rng True
cos Cosine (input in radians) 1 pi cos -1
lg Logarithm to base 10 1 10 lg 1
min Minimum 2 5 2 min 2
sin Sine (input in radians) 1 pi sin 0
acos Arc cosine (returns radians) 1 pi acos
ctg cotangent (input in radians) 1 pi ctg
ln Natural logarithm 1 2.718282 ln 1
sqr Square 1 5 sqr 25
asin arc sine 1 pi asin
eps Floating-point relative accuracy 1 1 eps 2^(-52)
log Logarithm of operand one, to the base of operand two. 2 8 2 log 3
pi Pi = 3.14159; puts pi on the stack 0 pi 3.14159
sqrt Square root 1 25 sqrt 5
atg2 arc tangent with two inputs (input in radians) 2
exp Exponent; e to the power of the operand 1 1 exp 2.718282
max Maximum 2 5 2 max 5
pow Power of; the first value to the power of the second 2 2 5 pow 32
tg Tangent (input in radians) 1 pi tg 0
atg arc tangent with one input 1 pi atg
Special Operators
div Divides integers; its result is always an integer 2 5 3 div 1
ceil Calculates nearest integer number which is bigger than the source 1 4.3 ceil 5
near Calculates the nearest integer number, rounding .5 up. 1 4.5 near 5
dnor
d360
rdeg
Normalizes an angle expressed in degrees. The result in an value between 0 and 360. 1 -15 dnor 345
rddg Converts radians to degrees 1 pi rddg 180
dgrd Converts degrees to radians 1 180 dgrd pi
rnor Normalizes an angle expressed in radians, the result of this operation is between 0 and 2 pi 1 5 pi 1.8584
if{ .... } If statement, note there is no space between the if and the { 1 (L:Value) 0 == if{ A } Operation A is carried out if Value is 0.
els{ .... } Else statement, note there is no space between the els and the { 1 (L:Value1) (L:Value2) <= if{ A } els{ B } If Value1 is less than or equal to Value2, operation A is carried out, otherwise operation B is carried out.
quit The quit statement allows expression evaluation to stop completely, and avoid the use of nesting if{ statements. 0 pi quit (L:Value1) (L:Value2) <= if{ A } els{ B } pi. The rest of the script is ignored.
g0...gn Goto label. Execution will jump to the specified label. Labels are set by entering a colon followed by the label number. 0 g4 Execution jump to :4
case Case statement 50 40 30 20 10 5 (L:value) case The "5" indicates there are five case values, which are selected depending on the evaluation of (L:value).
If the evaluation is equal to or greater than 0, but less than 1, the result is 10. If the evaluation is equal to or greater than 1, but less than 2, the result is 20, and so on.
String Operators
lc Converts a string to lowercase 1 'ABcd10' lc 'abcd10'
uc
cap
Converts a string to uppercase 1 'ABcd10' uc 'ABCD10'
chr Converts a number to a symbol 1 65 chr 'A'
ord Converts a symbol to an integer 1 'A' ord 65
scat Concatenates strings 2 'abc' 'red' scat 'abcred'
schr Finds a symbol in a string
scmp Compares strings, case sensitive 2 (M:Event) 'LeftSingle' scmp 0 == if{ A }els{ B } Performs A if the left mouse button has been pressed, otherwise performs B
scmi Compares strings, ignoring case 2 'left' 'Left' scmi 0 == if{ 'yes' } 'yes'
sstr Finds a substring 2 'cd' 'abcde' sstr 2
ssub Extracts a substring 2 'ab' 'abcde' ssub 'cde'
symb Extracts a single character 2 'abc' 1 symb 'b'
Stack Operators
b Backup the stack 0
c Clears the stack 0 stack: 1 2 3 c stack:
d Duplicates the value that is on the top of the stack 1 stack: 5 d stack: 5 5
p Pops and discards the top value on the stack 1 stack: 1 2 3 p stack: 1 2
r Reverses the top and second values on the stack 2 stack: 1 2 3 r stack: 1 3 2
s0, s1, … s49 Stores the top value in an internal register, but does not pop it from the stack. 1 stack: 1 2 3 s0 stack: 1 2 3
s0: 3
l0, l1, … l49 Loads a value from a register to the top of the stack 1 stack: 1 2 3 s0 l0 stack: 1 2 3 3
sp0, sp1, … sp49 Stores the top value and pops it from the stack 1 stack: 1 2 3 sp0 stack: 1 2
sp0: 3


Notes


Examples

The table below gives a range of script examples that can be used for aircraft. See also the examples for the GaugeText object, and a few examples in the Gauge Color Scripts section.

Aircraft Script Examples

# Expression Gauge Description
1 (A:LIGHT NAV, bool) Navigation Lights Returns True (1) if the navigation light switch is on, False (0) otherwise.
2 (A:TRAILING EDGE FLAPS LEFT ANGLE, radians) 1.1 * Flaps Returns the left flaps angle in radians, multiplied by 1.1. Multiplications like this can help reduce rounding errors when making comparisons with integer settings.
3 (A:PARTIAL PANEL ELECTRICAL,enum) ! Electrical gauges The enum for this variable is (0 = OK, 1= fail, 2 = blank), so in this case the result is inverted by the "!" operator to give 1 = OK and 0 = fail.
4 (A:PLANE HEADING DEGREES GYRO, degrees) /-/ dgrd HSI Compass ring Returns the aircraft heading negated and converted to radians.
5 (A:NAV GSI:1,percent) 250 / HSI Glideslope deflection Returns the percentage for the GSI (Glideslope deviation indicator) for Nav1, divided by 250.
6 (P:Units of measure, enum) 2 == if{ (A:RADIO HEIGHT, meters) } els{ (RADIO HEIGHT, feet) } Radio Height (or Radar Altitude)  needle The Units of measure enum is:
0 = English
1 = Metric (with altitude in feet)
2 = Metric (with altitude in meters)
So if this enum value is 2, the If statement is evaluated, otherwise the Els statement is evaluated.
7 (A:PARTIAL PANEL ELECTRICAL,enum)! if{ 25 (A:GENERAL ENG FUEL PRESSURE:1, psi) - } els{ 25.5 } Fuel Pressure If the Partial Panel Electrical is OK (see Example 3 above) then 25 minus the fuel reading for engine 1 is returned, if not the fixed value of 25.5 is returned.
8 (A:FUEL TANK SELECTOR 1, enum) 0 ==
(A:FUEL TANK SELECTOR 1, enum) 3 == or
if { pi 2 / } els{ 0 }
Right Valve of Fuel Gauge If all the fuel tanks are selected (FUEL TANK SELECTOR enum value is 0) or the right fuel tank is selected (the enum value is 3) then the fuel valve is set at pi/2, otherwise it is set at zero.
9 (A:NAV1 OBS, degrees) d (A:PARTIAL PANEL HEADING, bool) (A:PARTIAL PANEL ELECTRICAL, bool) or 0 ==
if{ (A:PLANE HEADING DEGREES GYRO, degrees) 90 - - } dgrd
GPS element of HSI If the PARTIAL PANEL HEADING is false and the PARTIAL PANEL ELECTIRCAL is false, then this expression returns the NAV1 OBS reading  minus the (PLANE HEADING DEGREES GYRO reading minus 90), converted to radians.
10 (P:Units of measure, enum) 2 ==
if{ (A:INDICATED ALTITUDE, meters) } els{ (A:INDICATED ALTITUDE, feet) } 100000 / 360 * dgrd
Altimeter ten thousand foot needle Divides the altitude by one hundred thousand, then multiplies by 360, and converts the result from degrees to radians.
11 (L:Show Volts 1,bool)
    if{  (A:ELECTRICAL GENALT BUS VOLTAGE:1, volts) 2 *
       } els{
          (A:ELECTRICAL GENALT BUS AMPS:1, amps) }
Amps/Volts  If the local variable Show Volts 1 is true, the bus voltage for engine 1, multiplied by 2, is returned. Otherwise the bus amps for engine 1 is returned.
12 (A:ADF Radial:1,degrees) 360 +
d360 dgrd
ADF The ADF radial value in degrees is added to 360 and then normalized to a value between 0 and 360. It is then converted to radians.

Notes


The Infix2Postfix Tool

The Infix2Postfix tool makes it easier to both understand the logic of existing postfix (often called reverse Polish) notation, and enables the writing of scripts in the more normal infix notation familiar to all programmers. The Infix2Posfix tool is in the Panels and Gauges SDK folder. The following screen shots show a conversion from infix to postfix, and vice versa. You can use the Paste button to take infix notation from the clipboard, and the Copy button to copy the postfix notation to the clipboard, so that it can be pasted into a gauge script. Alternatively use the File menu to select an existing XML gauge file, and you can then step through the scripts in the file, and examine the conversion to infix. The syntax for the infix notation is similar to C# or C++, and is available in a text file through an option in the Help menu.

Note

This tool is for educational purposes only, there are some scripts that it will not convert correctly.

Converting from infix to postfix
Converting from postfix to infix