Solver
A solver process allows the user to define a mathematical expression that will be computed in real time at a configured rate. The expression produces an output signal from 0 to 16 input signals or 0 to 32 constant values.
The solver is most useful for running custom controllers and models on the actual devices.
JCS Network Configuration
structure.yaml Configuration
type | proc_solver |
Signals - From Process
Signal name | Type | Required | Description |
---|---|---|---|
user defined | float32 | required | Computed expression output Signal name shall be defined by the user |
Signals - To Process
Signal name | Type | Required | Description |
---|---|---|---|
user defined | float32 | optional | Expression input Signal name shall be defined by the user |
Configuration Parameters
No parameters.
Operation
An expression is defined in the process configuration file. At system startup JCS host converts the expression to a byte code, which is transferred to the device. Once all required signals become available, a byte code interpreter on the device evaluates the expression at each rate tick.
The solver is configured by defining any constants, any input variables and any expressions.
Constants and intermediate values
storage
is used to store any constants or any intermediate values.
The solver does not interpret any numerical values in the expression. Any constants must be pre-allocated, given a name and value, then referenced by the name in the expression.
Intermediate values should have an initial value defined.
Example of intermediate value storage:
(In this example th_offset
is used as storage to pre-compute an angle offset, which is then used multiple times in a complex expression)
storage:
# Constant angle offset
- name: angle_offset
val: 1.443
# Variable storage to pre-compute theta offset
- name: th_offset
val: 0.0
signals:
- name: theta
expressions:
- name: th_offset
expr: theta - angle_offset
- name: tau
expr: sin(th_offset) / 2*cos(th_offset)
A maximum of 32 constant values is supported.
Signals
signals
defines any input signals into the solver from the outside world.
Once defined, a signal may be referenced as an input signal into the solver within the 'structure.yaml' configuration file.
A maximum of 16 input signals is supported.
Expressions
expressions
defines any actual expressions used by the solver.
The expression is given a name and an equation. The expression name becomes the output signal name and can be referenced within the 'structure.yaml' configuration file.
A maximum of 16 expressions is supported.
Available Operators
Name | Function | Example | Description |
---|---|---|---|
+ | \(x + y\) | x+y |
Computes the addition of \(x\) and \(y\). |
- | \(x - y\) | x-y |
Computes the subtraction of \(y\) from \(x\). |
- | \(-y\) | -y |
Computes the unary minus of \(y\). |
* | \(x \times y\) | x*y |
Computes the multiplication of \(x\) and \(y\). |
/ | \(x \over y\) | x/y |
Computes the division of \(x\) and \(y\). Will return an error and possibly estop if \(y\) is equal to \(0\). |
^ | \(x^y\) | x^y |
Computes \(x\) raised to the power of \(y\). Approximated. |
Available Functions
Exponential functions
Name | Function | Example | Description |
---|---|---|---|
log2 | \(y = \log_2{x}\) | log2(x) |
Computes the approximated base-2 logarithm of \(x\). |
ln | \(y = \ln{x}\) | ln(x) |
Computes the approximated natural (base-\(e\)) logarithm of \(x\). |
log10 | \(y = log_{10}(x)\) | log10(x) |
Computes the approximated base-10 logarithm of \(x\). |
exp | \(y = e^{x}\) | exp(x) |
Computes approximated \(e\) raised to the power \(x\). |
exp2 | \(y = 2^{x}\) | exp2(x) |
Computes approximated \(2\) raised to the power \(x\). |
Power functions
Name | Function | Example | Description |
---|---|---|---|
sqrt | \(y = \sqrt{x}\) | sqrt(x) |
Returns the square root of \(x\). Will return an error and possibly cause an estop if \(x\) is negative. |
hypot | \(z = \sqrt{x^2 + y^2}\) | hypot(x,y) |
Computes the square root of the sum of square of the two arguments. |
Trigonometric functions
Name | Function | Example | Description |
---|---|---|---|
sin | \(y = sin{x}\) | sin(x) |
Approximated sine function. Computed with lookup table and cubic interpolation. Valid input range \([0, 2\pi]\). |
cos | \(y = cos{x}\) | cos(x) |
Approximated cosine function. Computed with lookup table and cubic interpolation. Valid input range \([0, 2\pi]\). |
tan | \(y = tan{x}\) | tan(x) |
Approximated tangent function. Computed as \(tanx = {sinx \over cosx}\). Valid input range \([0, 2\pi]\). |
atan2 | \(y = arctan({{y}\over{x}})\) | atan2(y, x) |
Approximated arc tangent of \(y \over x\) using the signs of the arguments to determine the correct quadrant. |
Hyperbolic functions
Name | Function | Example | Description |
---|---|---|---|
sinh | \(y = sinh{x}\) | sinh(x) |
Approximated hyperbolic sine function. |
cosh | \(y = cosh{x}\) | cosh(x) |
Approximated hyperbolic cosine function. |
tanh | \(y = tanh{x}\) | tanh(x) |
Approximated hyperbolic tangent function. |
Functions
Name | Function | Example | Description |
---|---|---|---|
abs | \(y = \lvert x \rvert\) | abs(x) |
Computes the absolute value of the argument. |
sgn | \(y = \begin{cases} -1, & \text{if } x\lt 0, \\ 0 , & \text{if } x = 0,\\ 1 , & \text{if } x\gt 0\\ \end{cases}\) | sgn(x) |
Returns the sign of the argument \(x\). |
max | \(y =\begin{cases} a, & \text{if } a\gt b, \\ b, & \text{if } b\gt a.\\ \end{cases}\) | max(a,b) |
Returns the maximum of a or b. |
min | \(y =\begin{cases} a, & \text{if } a\lt b, \\ b, & \text{if } b\lt a.\\ \end{cases}\) | min(a,b) |
Returns the minimum of a or b. |
clamp | \(y =\begin{cases} a, & \text{if } x\geq a,\\ x, & b \lt x \lt a,\\ b, & \text{if } y\leq b\\ \end{cases}\) | clamp(x,a,b) |
Clamps the value \(x\) to be between the maximum value \(a\) and the minimum value \(b\). |
normpi | \(y = \lvert x \rvert\) | normpi(x) |
Normalise an angle to the range \([-\pi, \pi]\). |
norm2pi | \(y = \lvert x \rvert\) | norm2pi(x) |
Normalise an angle to the range \([0, 2\pi]\). |
Special sources
Note: \(dt\) is defined by the rate at which the solver process is ticked at.
time
Monotonically increasing time (seconds) in increments of \(dt\).
Notes:
time
will get large.time
will wrap to \(0\) at \(uint32\) max.- Approximated functions, such as sin / cos can fail at very large values of time (Fast angle normalisation has been used for speed).
time_p
Periodic time (seconds).
Counts from \(0\) to \(2\pi\) in increments of \(dt\).
dt
Timestep \(dt\) (seconds) at which the solver is called at.
Practical Notes:
Functions must have parentheses
sin x
is not valid.
sin(x)
is valid.
Implicit multiplication not supported
twox
is not valid (this will be interpreted as a constant called twox).
two*x
is valid.
Unicode characters not supported
Only */-+><=
are supported.
Divide by 0
Divide by zero will return an error from the solver and may result in an E-stop.
All trigonometric functions are in radians
Most trigonometric functions are approximations
and are optimised for the range \([0, 2\pi]\).
Boolean conditions return 1.0f or 0.0f (float)
Conditional statements (if, etc) compare floats.
Only CamelCase or snake_case variable or constant names are allowed
Expressions take a finite amount of time to be evaluated.
If the expression is too complex, it may not be evaluated in time before the next tick comes around.
In this case the solver will overrun and the system may shut down.
The time taken by the solver can be found by calling JCS host function process_timing_print
.
The solver does not yet do any optimisation of the expression.
It is recommended to pre-compute any constants. For example:
expr: A * sin(two * pi * f * time_p)
expr: A * sin(two_pi_f * time_p)
two * pi * f
is precomputed and stored as two_pi_f
.