Generators
Pick the generator that matches how a member behaves: a source signal, a transform of another value, or a lifecycle-dependent response.
Give a member a generator when its value should change at runtime instead of staying fixed.
Technical details
Generator families
- Source generators produce a value on their own:
sine,noise,random-walk,step,ramp,mean-reverting-noise,timetable,state-machine,waveform,chirp,impulse. - Transformers build on another member, a previous-tick value, a parameter, or an input port:
first-order-lag,integrator,transport-delay,slew-rate-limiter,second-order,hysteresis-relay,weighted-sum,expression,gate. - Context-aware generators derive from another signal or switch by lifecycle stage.
correlatedcouples a member directly to another.health-dependentgives each lifecycle stage its own source generator.
Where a generator reads its input
generator:
type: first-order-lag
tau: 30
input: { member: "speed_feedback" }Write an expression
Use expression when the value is a formula over other values and weighted-sum would need nested terms. Miravo parses the expression once at load and evaluates it every tick. It never calls eval. The language supports numbers, + - * /, unary minus, parentheses, min(a, b, ...), max(a, b, ...), and clamp(x, lo, hi).
generator:
type: expression
expression: "max(0, $param.design_load_kw * (18 - outdoor_temperature) / (18 - $param.design_outdoor_temp_c))"
min: 0
max: 6000| Reference | Reads |
|---|---|
name | A member's value from the current tick. Declare that member earlier, as with input.member. |
$prev.name | A member's value from the previous tick, like previous_member. |
$param.name | A numeric parameter. |
$port.name | A declared input port. |
Names use letters, digits, and underscores, so a-b is a subtraction. Booleans read as 0 and 1. A result that is not finite, such as a division by zero, raises an error. Guard denominators with max(..., 0.001). The min and max fields clamp the result and accept numbers or $param expressions. Load-time validation checks syntax, that members, parameters, and ports exist, and member order.
Build a chain
speed_setpoint:
kind: variable
data_type: Double
access: readwrite
unit: rpm
generator:
type: timetable
repeat: true
interpolation: step
points:
- { time: 0, value: 0 }
- { time: 21600, value: 1200 }
- { time: 64800, value: 900 }
speed_feedback:
kind: variable
data_type: Double
access: read
unit: rpm
generator:
type: slew-rate-limiter
input: { member: "speed_setpoint" }
rate_up: 220
rate_down: 320
min: 0
max: 1850Keep dependencies easy to follow. Long chains are fine; hidden coupling is not. Member order is part of the runtime contract.
Rates and durations
state-machinetransitions take an optionalrate_per_hour. Without it, the transition is unconditional. A transition withon: faultfires only while the asset has an active fault.impulsetakes eitherrate_per_hourorinterval(simulated seconds), plusduration_sand adecayfactor per simulated second.- Rates use
p = 1 - exp(-rate_per_hour * dt / 3600)per step. random-walkincrements scale bysqrt(dt), so variance follows simulated time.noisedraws an independent sample on every evaluation. It is not an event rate. For time-correlated variation, usemean-reverting-noise.- With substeps,
previous_memberinputs read the previous substep.
Start at a parameter value
The initial_value of first-order-lag, second-order, integrator, and slew-rate-limiter accepts a number or a $param expression, resolved on the first tick. A lag with initial_value: "$param.supply_temp_setpoint_c" starts at its setpoint instead of climbing to it, so a plant that is already running starts in steady state.
Reference
| Role | Generator types |
|---|---|
| Source | sine, noise, random-walk, step, ramp, mean-reverting-noise, timetable, state-machine, waveform, chirp, impulse |
| Transformer | first-order-lag, integrator, transport-delay, slew-rate-limiter, second-order, hysteresis-relay, weighted-sum, expression, gate |
| Context-aware | correlated, health-dependent |
Parameters by generator
Key parameters, one generator per row. Transformers and gate also take an input.
| Generator | Key parameters | Produces |
|---|---|---|
sine | center, amplitude, period | Smooth oscillation |
noise | center, stddev | Independent Gaussian samples each tick |
random-walk | min, max, step | A bounded, drifting value |
step | values[], interval | Cycles through fixed values |
ramp | start_value, rate, duration, start_time, min, max | Linear change over time, then a hold |
mean-reverting-noise | mean, tau, sigma, initial_value, min, max | Correlated wander around a mean |
timetable | points[{time, value}], repeat, interpolation (linear or step) | A scheduled profile |
state-machine | states[], initial, transitions[{from, to, rate_per_hour, on}] | Discrete state labels |
waveform | shape (sawtooth, triangle, square, pulse), center, amplitude, period, duty_cycle | A periodic non-sine signal |
chirp | center, amplitude, start_freq_hz, end_freq_hz, sweep_duration, sweep (linear or exponential), repeat | A frequency sweep |
impulse | baseline, amplitude, rate_per_hour or interval, duration_s, decay | Random or periodic spikes |
first-order-lag | tau, initial_value, gain, bias, min, max | A smoothed input with thermal or mechanical inertia |
integrator | gain, bias_rate, initial_value, min, max, wrap, wrap_at | A running total of a rate |
transport-delay | delay, initial_value, interpolation (linear or zoh) | The input shifted in time |
slew-rate-limiter | rate_up, rate_down (defaults to rate_up), initial_value, min, max | An input with a limited rate of change |
second-order | natural_freq_hz, damping_ratio, initial_velocity, initial_value, gain, bias, min, max | An oscillating response with overshoot |
hysteresis-relay | on_threshold, off_threshold, output_on, output_off, initial_state (on or off), mode (rising or falling) | On and off with a dead zone |
weighted-sum | terms[{weight, input}], bias, min, max | A blend of several inputs |
expression | expression, min, max | A formula over members, $prev, $param, and $port |
gate | enabled_member, input, disabled_value | The input while a Boolean member is true, otherwise a fallback |
correlated | source, factor, offset, power | factor * source^power + offset, with power a positive integer |
health-dependent | stages{stage: generator} | A different source generator per lifecycle stage |
$param coefficients
These fields accept a $param expression instead of a number: center (sine, noise, waveform, chirp), mean (mean-reverting-noise), factor and offset (correlated), initial_value, gain, and bias (first-order-lag and second-order), initial_value and gain (integrator), initial_value (slew-rate-limiter), delay (transport-delay), the thresholds of hysteresis-relay, the bias, weights, min, and max of weighted-sum, and the min and max of expression.
A $param field is an expression over numbers and $param.X only. It supports + - * /, parentheses, min, max, and clamp. Examples: factor: "$param.rated_voltage_v / $param.rated_frequency_hz" or max: "($param.rated_frequency_hz + 2) * 1.01". Miravo evaluates it once per asset, so it rejects member, $prev, and $port references at load. Use an expression generator for those.
Observation effects
Generators and faults define the process truth. Observation effects then distort what a sensor reports, the way a real instrument would. Declare them in observation_effects on a numeric read variable. Relative parameters use the member's eu_range span as the scale, or an explicit scale on the effect.
| Effect | Parameters | Quality | Purpose |
|---|---|---|---|
white_noise | strength (0 to 1, of scale) | good | Measurement noise floor |
drift | tau (seconds), sigma (0 to 1, of scale) | good | Slow sensor drift |
outlier | probability, magnitude (multiple of scale) | uncertain | Occasional spikes |
gap | probability, duration (ticks, default 10) | bad | Sensor dropout. Value and timestamp freeze. |
noise_burst | probability, duration (ticks, default 5), strength | uncertain | Intermittent interference |
quantize | resolution, or bits (8 to 24, needs eu_range) | good | ADC or display resolution |
deadband | absolute, or percent of the eu_range span | good | Report by exception: unchanged values are not republished |
stuck | probability, duration_s (number or [min, max]), quality | good or uncertain | A frozen transmitter. The timestamp keeps moving. |
Declare white_noise, drift, outlier, and noise_burst first, in any order. Then quantize, then deadband and stuck. The schema rejects other orders. miravo lint warns when a quantize step exceeds 1% of the eu_range span or a deadband exceeds 5%. See Asset models for a full member example.
Related pages
Asset models
Where generators sit in an .asset.yaml file.
Lifecycle and faults
Wear and failure effects.
Model catalog
Built-in generator chains.
CLI ⭢ models inspect
Inspect one model definition from the shell.
Was this page useful?
Last updated on
Miravo