Generated reference › Frequency Point Estimator — System Identification/Frequency Domain
kind: generated#block#system-identification-frequency-domain

Frequency Point Estimator — System Identification/Frequency Domain

System_Identification/Frequency_Domain/Frequency_Point_Estimator · 2 input / 2 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Description#

The block's own DESCRIPTION_HTML, rendered verbatim — the same text the config dialog's info panel and the library navigator show. Fix a wrong sentence in the block's .cpp (R-D9), never here.

Frequency Point Estimator

System Identification / Frequency Domain

Measures one point of the u→y frequency response, live, by the correlation (lock-in) method. It multiplies both signals by a reference cos(ωt) and sin(ωt) at the configured frequency, keeps exponentially-forgotten averages of the four products, and divides the resulting phasors: G = Y ÷ U. Noise at every other frequency averages towards zero by construction, so this is a cheap and very robust commissioning measurement.

Ports

  • u – the excitation signal, scalar.
  • y – the measured response, scalar.
  • Re G – the real part of the response at the configured frequency, scalar.
  • Im G – the imaginary part, scalar.

Parameters

  • Frequency (Hz) – the single frequency the estimate is made at. The excitation must actually contain it: a signal that does not stir this frequency leaves the denominator at its floor and the answer means nothing.
  • Forgetting Factor – λ, how fast old products are discounted, in (0,1]. Just below 1 (0.9–0.99) tracks a response that drifts; 1 makes the four correlations plain growing sums, which never settle, so it is offered but not recommended.
  • Epsilon – the FLOOR under the divisor, not an added term: the denominator is max(Uc² + Us², Epsilon), so an excitation with no content at this frequency cannot divide by zero. It floors rather than regularizes, so on any signal that does excite the frequency the value changes nothing at all.
  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period. It also sets the reference's per-sample rotation, so it must be small enough to resolve the frequency – below half a period, by Nyquist.

Notes

  • Re/Im, not magnitude/phase, deliberately. Recovering phase needs atan2, which the ten export targets do not carry evenly – IEC 61131-3 has ATAN but no ATAN2, and the HDL targets have neither. Feed these two into Robotics / Coordinate Transforms / Cartesian to Polar, which already exists, if magnitude and phase are what you want.
  • The reference is generated by rotation, not by calling sin/cos. The block carries the reference phasor as state and turns it by one sample's angle each step, from two constants fixed when the model is built. That is why it needs no trigonometry at all in any exported language.
  • Stateful and discrete only. The state is the reference phasor and the four correlations, all seeded at the start of the run. The estimate is meaningless until several periods have been averaged, which is a property of the statistic rather than a state the block guards.
  • No state space, deliberately: the output divides two quantities that both move, so no A/B/C/D is true of it. Model reduction reports the block as unmergeable, which is the honest answer.
  • The natural partner of a Multisine Generator or PRBS Generator excitation – put one of those in, and read the response off here.

Code export

All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text. λ, Epsilon and the reference's two rotation constants are baked into the body at export time, so no target computes a trigonometric function or reads a clock.

The three HDL targets are simulation-only: the recursion is carried in double arithmetic and quantized only on the way out. That is because G = Y ÷ U is a data-dependent divide – not because of the reference, which is plain multiply-add and would have been synthesizable on its own.

Simulink bridge

Neither direction. The System Identification Toolbox is not installed on this machine, so a bridge could not be verified against the real block even if it were written; the bridge reports this block with that reason rather than silently dropping it.

Code facts#

FactValue
registered typeSystem_Identification/Frequency_Domain/Frequency_Point_Estimator
familySystem_Identification/Frequency_Domain
solver environment classICoreBlock_0_System_Identification_1_Frequency_Domain_2_Frequency_Point_Estimator
sourcesrc/ICoreSDK/ICoreBlockLibrary/Blocks/System_Identification/Frequency_Domain/Frequency_Point_Estimator/ICoreBlock_0_System_Identification_1_Frequency_Domain_2_Frequency_Point_Estimator.cpp
headersrc/ICoreSDK/ICoreBlockLibrary/Blocks/System_Identification/Frequency_Domain/Frequency_Point_Estimator/ICoreBlock_0_System_Identification_1_Frequency_Domain_2_Frequency_Point_Estimator.h
default size on canvas110 × 70 px
ports at insert2 in, 2 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDouble
2inICoreDouble
3outICoreDouble
4outICoreDouble

Ports the constructor creates. A block whose port list changes with its configuration adds or removes ports at load time; the count above is the one a freshly inserted block has.

Configuration variables#

Config variableDefaultSimulink parameter
Frequency (Hz)1
Forgetting Factor0.98
Epsilon1e-12

Every block also carries Sampling Time (s) from ICoreBlockSolverEnvironment: zero or less inherits the solver's rate, a positive value runs the block at that period.

supportSupport::None
Simulink path
port-count rulePortsParam::None
SampleTime parameteryes

Caveat (shown to the user): the System Identification Toolbox is not installed on this machine, so a bridge could not be verified against the real block even if it were written

Catalog contract: src/ICoreSDK/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h

Description vs code#

The lists agree. check_block_descriptions.py finds no disagreement between the description's Ports, Parameters, Code export and Simulink bridge lists and the code's.

The verdict above is tools/docs/check_block_descriptions.py (P7.1), which compares LISTS. It cannot read a sentence: "stateless" on a block with a state, an initial-value semantic the recursion does not implement, a "not synthesizable" caveat the HDL banner contradicts. That is the agent audit (P7.3) on BLOCK_DESCRIPTION_AUDIT.md, and this tool's green is not a substitute for one.

Sample results#

Frequency Point Estimator — Step: 0 -> 1 at t = 1 sFrequency Point Estimator — Step: 0 -> 1 at t = 1 s00.51012345t (s)in ICoreDouble-Out-0in ICoreDouble-Out-0out ICoreDouble-Out-0out ICoreDouble-Out-1

The same rig also ran:

StimulusWhat it isOutput range
impulseImpulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair)0 … 1
rampRamp: slope 1 from t = 00 … 1
sineSine Wave: amplitude 1, 2 rad/s, no phase, no bias0 … 1
tableRepeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample1 … 1

Plotted: step — Step: 0 -> 1 at t = 1 s

Category dynamic · sample time 0.1 · 60 steps · commit ccf005c8 · produced by docsSample --out <folder> --steps 60 · data docs/generated/samples/System_Identification__Frequency_Domain__Frequency_Point_Estimator.json · the SVG is generated from those numbers by tools/docs/plot_svg.py, so it is a run and not a drawing (R-D10).