Utility Functions
System Functions
| Function | Description |
|---|---|
| time() | Returns the evaluation time of the module in UTC seconds |
Properties of a Channel or Value
| Function | Description |
|---|---|
| deltaT(x) | Returns the time interval between the last two evaluation times of term x in seconds |
| deltaY(x) | Returns the difference in values between the last two samples of term x; is positive for a rising signal curve |
| time(x) | Returns the time of the last modified data sample of the term x |
| sgn(x) | Sign of the value x |
| sgn(x,eps) | Sign of the value x with tolerance (eps) |
| abs(x) | Absolute value of the scalar x, For the length of a vector, see Length(V) |
| isConnected(x) | Check SmartCORE connection |
| isEmpty(x) | Check data source status |
| isTimeout(x) | Check for data gap |
| isDefault(x) | Query channel for default value |
| isError(x) | Query error status of a result |
| typeOf(x) | Query data type |
| value(x, ...) | Query channel values without time stamp |
| shiftT(x,dT) | Time shift of channel data |
Query SmartCORE connection "isConnected" 1
The function returns true if the channel has been successfully connected as an input to a smartCORE channel.
If no smartCORE channel can be found when the smartCORE and Math modules start up, this is not only logged in the log file but also signaled via this status (false).
In this case, the default value is written to the variable as a constant so that calculations can be performed. This is initially false, but can be set to any constant value and type using the #property macro via default=<variant>. See also isDefault().
The query returns the status for the current batch interval.
s1 = isConnected(x);
s2 = isConnected($'other.y');
The function’s argument must be an input variable.
Query the status of the data source "isEmpty" 1
The function returns true if no data has yet been produced in the smartCORE input channel when the smartCORE and Math Module start. This can happen if other data sources can only produce data after an initialization phase or a prolonged establishment of a data connection.
If the channel remains empty and the timeout condition related to the Math module’s start time is met, and an explicit default value has been set via the #property macro with the option default=<val>, this value is temporarily used as a substitute until the first data sample arrives. See also isDefault().
The query returns the status for the current batch interval and is independent of the channel’s data content and timestamps.
s1 = isEmpty(x);
s2 = isEmpty($'other.y');
The function’s argument must be an immediate input variable.
Query data gap "isTimeout" 1
The function returns true if the most recent sample in the smartCORE input signal is older than a configurable timeout interval and thus likely no new data has been produced on the smartCORE input signal. This can have various causes, such as the absence of a CAN bus message, a missing GPS signal, or a missing internet connection for querying control information. As soon as new data arrives, the status reverts to false.
For each input channel, an individual timeout value can be assigned using the #property macro with the option timeout=<val>. This overrides the global setting for the channel via inputTimeoutS, which is preset to .
If the timeout condition occurs relative to the start time of the Math module while the channel remains empty, and an explicit default value is set via the #property macro with the option default=<val>, this value is temporarily used as a substitute until the first data sample arrives. See also isDefault().
If data samples are already present in the channel, the timeout status extends the validity of the variable’s most recent value. It then lags behind the current execution time of the Math module by the set timeout interval. Dependent calculations can then continue until this point.
This time offset is only visible where data is visualized or used without timestamps, e.g., in the MQTT live data, but not in the OSF files.
The query returns the status for the current batch interval and is independent of the channel’s data content and timestamps.
s1 = isTimeout(x);
s2 = isTimeout($'other.y');
The function’s argument must be an input variable.
Query channel for default value "isDefault" 2
The function returns true if the channel is permanently or temporarily set to a default replacement value.
For each input channel, an individual, constant default value can be assigned using the #property macro with the option default=<val>. If this is not set, false (<bool> => 0, 0.0, "false") is used.
The default value is used as a constant substitute if the channel could not be connected to a smartCORE channel.
The default value is used as a temporary substitute if
- the channel has been connected
isConnected() - and the channel is still empty
isEmpty() - and the channel has timed out
isTimeout() - and
- the default value was explicitly set via the
#propertymacro - or the channel was marked as
#timeless.
- the default value was explicitly set via the
The query returns the status for the current batch interval and is independent of the channel’s data content and timestamps.
s1 = isDefault(x);
s2 = isDefault($'other.y');
The function’s argument must be an immediate input variable.
Query the error status of a result "isError" 1
The function returns true if the evaluation of a term has generated a runtime error. When the variable is output to the smartCORE, the error message is also stored in the log file or can be reused as a string in the Math module.
res = ...; // some expression
use = isError(res) ? 12.34 : res; // use alternate value on error
errCode = isError(res) ? int(res) : 0;
errMsg = isError(res) ? str(res) : 'ok';
Using a (local) variable to reuse the result is recommended.
Query data type "typeOf" 1
The typeOf function returns the data type of the passed value as an ENUM value:
t = typeOf(x);
The values have the following correspondences:
| Value | Data Type |
|---|---|
| 0 | void |
| 1 | <bool> |
| 2 | <uint> |
| 3 | <int> |
| 4 | <dbl> |
| 5 | <cxFlt> |
| 6 | <str> |
| > 0x80000000 | (Reserved) |
| 0x8000B10B | BLOB - Binary object, e.g., of a transition() |
| 0x8000EBAD | ERROR - Runtime error of a term |
Querying channel values timelessly "value" 2
This function allows you to resolve the time dependency of a computation path at a specific point in the computation, similar to #timeless.
To do this, the last value available before the batch interval (evaluationTimeMs) is used as the starting value for the interval, then all samples with timestamps within the batch interval are copied, and finally the last value is extended to the end of the interval. If an empty channel is used as an argument, a replacement value can be explicitly specified.
The query returns values for the current batch interval and is independent of the channel’s data content and timestamps.
v1 = value(x);
v2 = value(x, def); // use def, if isEmpty(x)
Typically, a circular reference in the Math Module results in a switch to a discrete sampling interval (discreteSampleTimeMs) for the affected channel, which must then also be provided with an explicit start value (@0 syntax):
zv@0 = 0; // start value for discrete calculation
zv = a * zv + (1 - a) * x; // example of circular use of 'zv'
In the context of logic controllers, state machines, limit value monitoring, etc., it can be useful to execute calculations in real time while still utilizing the feedback of a calculation result back to the beginning of the calculation. The value() function represents exactly the point at which the feedback is broken locally in the sense of #timeless.
Resolving time dependencies leads to behavior at the corresponding point that is no longer 100% predictable or defined. Short-term signal changes on the input term may be overlooked, or changes may only become visible in a later batch interval. The effects of the function must be carefully tested before productive use!
Temporal shift of channel data "shiftT" 2
To shift the data of a channel by a specific time interval dT, the shiftT() function can be used. Since shifting the data and subsequently synchronizing it with other data always results in buffering, the shift should be limited to a few seconds.
The time interval dT in seconds is added to all timestamps of the x-term data. A shift with dT > 0.0 shifts the data into the future, dT < 0.0 into the past.
xs = shiftT(x, dT);
This function can be used to compensate for known time delays caused by data transmission from the actual acquisition system (AD converter, microcontroller) of an analog signal to the reception and timestamping of the data in smartCORE. This can be useful for compensating for phase shifts, particularly with signals sampled at very high frequencies.
Properties of Multiple Values
| Function | Description |
|---|---|
| abs(x1, ..., xN) | L2 norm of the individual values (x1, ..., xN), |
| min(x1, ..., xN) | Minimum of the individual values (x1, ..., xN) |
| max(x1, ..., xN) | Maximum of the individual values (x1, ..., xN) |
| mean(x1, ..., xN) | Arithmetic mean of the individual values (x1, ..., xN) |
| rms(x1, ..., xN) | Square root of the arithmetic mean of the squared individual values (x1, ..., xN) |
Limiting and Rounding
| Function | Description |
|---|---|
| range(x, ...) | Limits the input value to a specific range. See the description below. |
| ceil(x) | Smallest integer value (preserves data type) |
| ceil2i(x) | Smallest integer value (return type int) |
| floor(x) | Largest integer value (preserves data type) |
| floor2i(x) | largest integer value (return type int) |
| trunc(x) | if then largest integer value , otherwise smallest integer value |
| round(x) | integer value such that (preserves data type) |
| round2i(x) | integer value such that (return type int) |
| nonZero(x, ...) | Returns x if , otherwise if , is set; otherwise, See the description below. |
Value range "range"
The function restricts the value range for a given input signal x (scalar or vector) to the range and offers a variety of options via optional configuration.
r1 = range(x);
r2 = range(x, [min, max]); // better readability
r3 = range(x, min, max); // no longer used
// Optional configuration for all variants
rx = range(..., { min: off|<val>
, max: off|<val>
, lower: off|<val>|erase
, upper: off|<val>|erase
, mode: <enum>
, defXY: [<dbl>, <dbl>]
, limVar: <str>
});
| Property | Value | Description |
|---|---|---|
| min | off/<val> | Disables or sets a fixed lower (scalar) limit. If the function parameter min is used, this property has no effect. |
| max | off/<val> | Disables or sets a fixed upper (scalar) limit. If the function parameter max is used, this property has no effect. |
| lower | off/<val>/erase | If enabled, the replacement value is output when the lower limit is exceeded (x < min), or the sample is removed |
| upper | off/<val>/erase | If enabled, the replacement value is output when the upper limit is exceeded (x > max), or the sample is removed |
| mode | <enum> | If x is a vector, the following applies depending on mode - box: all coordinates individually… - length: the length of the vector ( >= 0.0 )... - azimuth: the angle of the vector in the XY plane... - elevation: the angle of the vector from the XY plane to the Z-axis… ...limited to the set range |
| defXY | [<dbl>, <dbl>] | In elevation mode, defXY is the default direction when the vector must be rotated back from the vertical (default: [1, 0, 0]). |
| limVar | <str> | limVar optionally defines the name of a local <bool> variable to signal the active limitation |
Non-zero "nonZero"
The function ensures that a critical value (def.: 0.0) is never returned. Instead, the value range is excluded by a margin of (def.: 1e-6) around the critical value. The function is optimized, for example, for divisions where division by zero is possible and must be prevented.
xnz1 = nonZero(x); // eps := 1e-6, x_crit := 0.0
xnz2 = nonZero(x, eps); // x_crit := 0.0
xnz3 = nonZero(x, eps, x_crit);
An example is the reliable conversion of fuel flow rate in and speed in to fuel consumption in :
consumption = volFlow / nonZero(speed, 0.1) * 100;
Switching threshold with hysteresis "threshold"
This function generates a switching signal by comparing a signal against a fixed threshold value threshold. Using hysteresis hysteresis and delay times delayOn, delayOff, disturbances in the signal waveform can be suppressed.
The function can be used in various ways:
trig1 = threshold(x);
trig2 = threshold(x, t);
trig3 = threshold(x, t, h);
// Optional configuration for all variants
trigX = threshold(..., { threshold: <dbl>
, hysteresis: <dbl>
, delayOn: <dbl>
, delayOff: <dbl>
, logic: <enum>
, startup: inf|<bool>
});
| Property | Value | Meaning |
|---|---|---|
| threshold | <dbl> | Trigger threshold, def.: 0.55 Overridden by the t argument |
| hysteresis | <dbl> | Width of the hysteresis zone, added to the threshold for the second limit value, def.: -0.10 Overridden by the h argument |
| delayOn | <dbl> | Optional filter time in seconds for the switch-on process |
| delayOff | <dbl> | Optional filter time in seconds for the switch-off process |
| logic | <enum> | - auto: Function is determined by the sign of the hysteresis - above: Triggering above the hysteresis zone - below: Triggering below the hysteresis zone |
| startup | inf|<bool> | Startup behavior: inf: The position of the first sample determines the initial value relative to the threshold (default). <bool>: It is assumed that this initial value was output before the first sample. |
- The function returns true at the point where the signal x crosses the defined trigger threshold and false at the point where the signal x falls back below it.
If the delay times are set, the signal x must remain continuously in the trigger or reset state for the specified interval before the switch is implemented. The switch is thus delayed relative to the crossing of the respective threshold value.
In auto mode (default), triggering depends on the sign of the hysteresis:
| Hysteresis | Trigger (true) | Reset (false) |
|---|---|---|
In the above and below operating modes, threshold and hysteresis define two boundaries of a hysteresis zone:
| Operating mode | Trigger (true) | Reset (false) |
|---|---|---|
| above | ||
| below |
Slope Limitation "rampLimit" 3
This function ensures that changes in the input signal x are passed on with a limited ramp slope. Optionally, one or two additional parameters can be used to define either a direction-independent maximum gradient or different gradients for rising and falling function curves.
y1 = rampLimit(x, maxGrad);
y2 = rampLimit(x, maxPosGrad, maxNegGrad);
| Property | Value | Meaning |
|---|---|---|
| x | <dbl> | Input signal |
| maxGrad | <dbl> | Common maximum gradient for rising and falling signal curves |
| maxPosGrad | <dbl> | Maximum gradient for rising signal curves |
| maxNegGrad | <dbl> | Maximum gradient for falling signal curves |
The unit of the maximum gradients is [unit of x] / s. The value is unsigned, i.e., . A gradient of 0.0 switches the function to bypass in the corresponding direction: the input signal is output directly.