# How to write expression to change HW component behavior#

## Exprtk library#

In various scenarios, you may want to modify the drone components behavior. To achieve that, Parrot Sphinx offers the feature of injecting mathematical expressions using the ExprTk syntax in real time.

Most of the keywords recognized by ExprTk are listed below:

Mathematical operators:

+, -, *, /, %, ^

Functions:

min, max, avg, sum, abs, ceil, floor, round, roundn, exp, log, log10, logn, root, sqrt, clamp, inrange, swap

Trigonometry:

sin, cos, tan, acos, asin, atan, atan2, cosh, cot, csc, sec, sinh, tanh, d2r, r2d, d2g, g2d, hyp

Equalities, Inequalities:

=, ==, <>, !=, <, <=, >, >=

Assignment:

:=, +=, -=, *=, /=, %=

Boolean logic:

and, mand, mor, nand, nor, not, or, xor, xnor

Control Structures (if-then-else, ternary conditional, switch case, return-statement)

Loop Structures (while loop, for loop, repeat until loop, break, continue)

String operations (equalities, inequalities, boolean logic, concatenation and ranges)

Expression local variables, vectors and strings

User defined variables, vectors, strings, constants and function support

Component parameters that support ExprTk syntax are recognized by the “_expr” at
the end of their name. For instance, IMU’s acceleration in X can be modified by
setting the value of its `acceleroX_expr`

component parameter (see
Interact with the simulation for more information on component parameters).

## Special variables and functions#

To help the user write expressions for component parameters, Parrot Sphinx provides additional variables and functions in the expression evaluation context.

### Current value#

By default, expressions are often set to `val`

. `val`

usually refers to the
exact and actual value before any modification. For example, in the context of
the `acceleroX_expr`

component parameter, the `val`

variable refers to the
real acceleration in X. In the context of the `gyroP_expr`

component
parameter, the `val`

variable refers to the real angular velocity around the
X axis. So, setting an expression to `val`

usually means the original value
will remain unaffected.

### Noise functions#

`noise()`

#

The `noise()`

function is defined as \(~\mathcal{N}(0,1)\).

By editing the expression string, it is easy to change the standard
deviation (`std = 10`

) and the mean (`mean = 2`

) of the noise:

```
acceleroX_expr = val + noise() * 10 + 2
```

`randu()`

#

The `randu()`

function is defined as \(~\mathcal{U}\) (uniform
distribution between 0 and 1).

This function is useful in particular to select an output function with a given probability, for example:

```
acceleroX_expr = (0.001 > randu()) ? val + noise() * 0.05 : val + noise() * 0.01
```

`randwalk()`

#

The `randwalk()`

function is defined as an accumulation of noise data
following \(~\mathcal{N}(0,1)\) over time (random walk).

Example:

```
pressure_expr = 1.756*noise()+0.05*randwalk()
```

Accumulated data is reset to zero each time that a parameter held by the transformer is changed.

`markov_noise()`

#

The `markov_noise(k, std)`

function is defined as an accumulation of noise data
which depends on the previously computed value. Mathematically it corresponds to:

where acc is what was accumulated at the previous iteration (starts at 0).

It has two parameters:

k (between 0.0 and 1.0) which defines how much of the previous value is kept.

std is the standard deviation of the noise range.

Example:

```
markov_noise(0.5, 1.0) # 50% of the accumulator value is added to a gaussian of std 1.0
markov_noise(1.0, 0.0) # Same as noise()
markov_noise(1.0, 1.0) # Same as randwalk()
```

Accumulated data is reset to zero each time that a parameter held by the transformer is changed.

### Other variables#

Other variables available in the expression evaluation context are shown below:

`posX`

: X coordinate in world frame [m]`posY`

: Y coordinate in world frame [m]`posZ`

: Z coordinate in world frame [m]`speedX`

: linear body speeds [m/s]`speedY`

: linear body speeds [m/s]`speedZ`

: linear body speeds [m/s]`accX`

: linear body accelerations [m/s2]`accY`

: linear body accelerations [m/s2]`accZ`

: linear body accelerations [m/s2]`p`

: roll [rad]`q`

: pitch [rad]`r`

: yaw [rad]`phi`

: angular body speeds [rad/s]`theta`

: angular body speeds [rad/s]`psi`

: angular body speeds [rad/s]`phidot`

: X angular body accelerations [rad/s2]`thetadot`

: Y angular body accelerations [rad/s2]`psidot`

: Z angular body accelerations [rad/s2]`temperature`

: atmospheric pressure at the current location of the drone. [°C]`pressure`

: atmospheric pressure at the current location of the drone. [Pa]`atm_density_ratio`

: ratio between current atmospheric density over reference atmospheric density (atmostpheric density at altitude 0 at 15°C)`time`

: time of the simulation since the launch of Parrot Sphinx. [s]`rtime`

: time of the simulation since the last expression edition drone-wide. [s]

## Modify the output of sensors#

Most of the expressions affecting the output of sensors are set to `val`

to
return a perfect output. For some sensors, like the barometer, the firmware
considers the sensor to be defective if it receives perfect output. In such
cases, a minimal noise is added by default:

```
pressure_expr = val + noise() * 0.01
```

The list of available expressions for each sensor can be found on their respective reference page.

You can modify the expressions altering the output of sensors with the
`sphinx-cli param`

command.

**Example 1:** The following example shows how to modify the Y-axis component
of the accelerometer output by adding a sinus to it:

```
$ sphinx-cli param imu/icm40609 acceleroY_expr "val + sin(time) * 10"
```

**Example 2:** The following example shows how to modify the barometer pressure
output by adding noise and a bias error of 12 Pa to it:

```
$ sphinx-cli param barometer/lps22hb pressure_expr "val + noise() * 0.01 + 12"
```

**Example 3:** The following example shows how to modify the barometer pressure
output by adding noise and a bias error depending on the altitude to it:

```
$ sphinx-cli param barometer/lps22hb pressure_expr "val + noise() * 0.01 + posZ"
```