Skip to main content

Utility Functions

System Functions

FunctionDescription
time()Returns the evaluation time of the module in UTC seconds

Properties of a Channel or Value

FunctionDescription
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
1:x<0-1: x < 0
+1:x>0+1: x > 0
0:otherwise\enspace0:otherwise
sgn(x,eps)Sign of the value x with tolerance ϵ\epsilon (eps)
1:x<ϵ-1: x < -\epsilon
+1:x>ϵ+1: x > \epsilon
0:otherwise\enspace0:otherwise
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');
important

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');
important

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 15s15 s.

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.

note

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');
important

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 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');
important

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';
note

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:

ValueData Type
0void
1<bool>
2<uint>
3<int>
4<dbl>
5<cxFlt>
6<str>
> 0x80000000(Reserved)
0x8000B10BBLOB - Binary object, e.g., of a transition()
0x8000EBADERROR - 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'
tip

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.

caution

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);
tip

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

FunctionDescription
abs(x1, ..., xN)L2 norm of the individual values (x1, ..., xN),
=i=1Nxi2= \sqrt{\sum_{i=1}^N x_i^2}
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)
=1Ni=1Nxi= \frac{1}{N} \sum_{i=1}^N x_i
rms(x1, ..., xN)Square root of the arithmetic mean of the squared individual values (x1, ..., xN)
=1Ni=1Nxi2= \sqrt{\frac{1}{N}\sum_{i=1}^N x_i^2}

Limiting and Rounding

FunctionDescription
range(x, ...)Limits the input value to a specific range. See the description below.
ceil(x)Smallest integer value i>=xi >= x (preserves data type)
ceil2i(x)Smallest integer value i>=xi >= x (return type int)
floor(x)Largest integer value i<=xi <= x (preserves data type)
floor2i(x)largest integer value ixi \leq x (return type int)
trunc(x)if x0x \geq 0 then largest integer value ixi \leq x, otherwise smallest integer value ixi \geq x
round(x)integer value ii such that x0.5<ix+0.5x - 0.5 < i \leq x + 0.5 (preserves data type)
round2i(x)integer value ii such that x0.5<ix+0.5x - 0.5 < i \leq x + 0.5 (return type int)
nonZero(x, ...)Returns x if xxcritϵ\|x-x_{crit}\| \ge \epsilon, otherwise
if xxcritx \ge x_{crit}, xcrit+ϵx_{crit}+\epsilon is set; otherwise, xcritϵx_{crit}-\epsilon
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 [min,max][min, max] and offers a variety of options via optional configuration.

Value Range Limitation

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>
});
PropertyValueDescription
minoff/<val>Disables or sets a fixed lower (scalar) limit. If the function parameter min is used, this property has no effect.
maxoff/<val>Disables or sets a fixed upper (scalar) limit. If the function parameter max is used, this property has no effect.
loweroff/<val>/eraseIf enabled, the replacement value is output when the lower limit is exceeded (x < min), or the sample is removed
upperoff/<val>/eraseIf 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 [min,max][min, max]
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 ϵ\epsilon (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);
nonZero(x)={x:xxcritεxcrit+ε:x[xcrit,xcrit+ε[xcritε:x]xcritε,xcrit[.\rm{nonZero}(x) = \left\{ {\begin{array}{ll} {x:}&{\left| {x - {x_{crit}}} \right| \ge \varepsilon }\\ {{x_{crit}} + \varepsilon :}&{x \in [{x_{crit}},{x_{crit}} + \varepsilon [}\\ {{x_{crit}} - \varepsilon :}&{x \in ]{x_{crit}} - \varepsilon ,{x_{crit}}[} \end{array}} \right..

An example is the reliable conversion of fuel flow rate in l/hl/h and speed in km/hkm/h to fuel consumption in l/100kml/100km:

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.

Threshold with Hysteresis

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>
});
PropertyValueMeaning
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
startupinf|<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.

Threshold with Hysteresis

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:

HysteresisTrigger (true)Reset (false)
hysteresis<0hysteresis < 0x>thresholdx > thresholdx<threshold+hysteresisx < threshold + hysteresis
hysteresis>0hysteresis > 0x<thresholdx < thresholdx>threshold+hysteresisx > threshold + hysteresis

In the above and below operating modes, threshold and hysteresis define two boundaries of a hysteresis zone:

glow=min(threshold,threshold+hysteresis)g_{low} = min(threshold, threshold + hysteresis) ghigh=max(threshold,threshold+hysteresis)g_{high} = max(threshold, threshold + hysteresis) zone=[glow,ghigh]zone = [g_{low}, g_{high}]
Operating modeTrigger (true)Reset (false)
abovex>ghighx > g_{high}x<glowx < g_{low}
belowx<glowx < g_{low}x>ghighx > g_{high}

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);
PropertyValueMeaning
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., maxGrad0.0maxGrad \ge 0.0. A gradient of 0.0 switches the function to bypass in the corresponding direction: the input signal is output directly.

Footnotes

  1. Available starting with catalog version 10. 2 3 4 5

  2. Available starting with catalog version 11. 2 3

  3. Available starting with catalog version 12.