Generated reference › Transfer Function Estimate — Control Systems/Spectral Measurements
kind: generated#block#control-systems-spectral-measurements

Transfer Function Estimate — Control Systems/Spectral Measurements

H(f)

Control_Systems/Spectral_Measurements/Transfer_Function_Estimate · 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.

Transfer Function Estimate

Control Systems / Spectral Measurements

The frequency response from x to y estimated by Welch's method – MATLAB's tfestimate – over a sliding window: K windowed L-point segments of the input x and the output y, their spectra averaged and divided:

H1(m) = Pyx(m) ÷ Pxx(m) (tfestimate's default), or H2(m) = Pyy(m) ÷ Pxy(m).

That is tfestimate(x, y, window, noverlap, L) over the last W = L + (K−1)·hop samples. The answer is complex; it is published as its real and imaginary parts on two ports, because an ICore signal carries doubles. Its magnitude is the gain and its angle the phase of the system from x to y at each bin.

Ports

  • x – the system's input, a scalar stream.
  • y – the system's output, a scalar stream.
  • Re – the real part of the estimate, a column of L/2 + 1 entries, DC first and Nyquist last; entry m is at m/L cycles per sample.
  • Im – the imaginary part, the same size.

Parameters

  • Segment Length – L, the transform length, an even whole number from 4 to 32. It sets the frequency resolution and the number of output bins.
  • Segments – K, how many segments are averaged, from 1 to 8. One is allowed: a single segment is the empirical ratio Y/X, noisy but meaningful.
  • Segment Overlap – how far the segments overlap.
    • None (0%) – the hop is L.
    • Half (50%) – the hop is L/2. MATLAB's default, and this block's.
    • Three quarters (75%) – the hop is L/4; needs L divisible by four.
    The window the block holds is W = L + (K−1)·hop samples long.
  • Window – the taper applied to each segment: Hamming (MATLAB's default), Hann or Rectangular, the symmetric forms hamming and hann return.
  • Estimator – which ratio:
    • H1 – Pyx/Pxx, tfestimate's default: unbiased when the noise is on the output.
    • H2 – Pyy/Pxy: unbiased when the noise is on the input.
    tfestimate's third estimator, Hv, is not offered.
  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.

Code export

All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text. Every transform is a fixed weighted sum of window taps, computed once at export time, so no emitted core contains a sine, a cosine or a loop over data; the two windows become shift registers. All five settings are structural.

The three HDL targets are simulation-only: they carry the arithmetic in real and quantize only at the port boundary, as Magnitude-Squared Coherence's do – the answer is a ratio of run-time quantities.

Simulink bridge

No equivalent a bridge can write (Support::None), and the block that exists is named here rather than denied. DSP System Toolbox's dspspect3/Discrete Transfer Function Estimator computes the H1 estimate, but, measured on R2026a: it answers on one complex port, where this block presents Re and Im on two real ones; driven one sample per step it publishes once every hop samples, so its output runs at a lower rate than its input; and its windows are the periodic forms – its steady-state outputs equal tfestimate with hann(L,'periodic') over the W samples ending one sample before each output, while this block uses the symmetric window tfestimate uses by default. So no configuration crosses and no parity testbench is owed.

Notes

  • Stateful and inherently discrete: two shift registers of W samples, advanced once per sample (setDiscreteOnlyBlock(true)), and zero-prefilled at the start of every run.
  • A silent window answers 0, not MATLAB's NaN: the denominators are floored at 10−30, as Magnitude-Squared Coherence floors its own. The first samples of a run, while the window is still filling from zeros, are the usual place to meet it.
  • Related blocks. Magnitude-Squared Coherence reads the same averaged sums and says how far to trust this estimate bin by bin; Cross Power Spectral Density is its numerator; System Identification / Frequency Point Estimator tracks the response at ONE frequency recursively rather than at every bin of a window.

Code facts#

FactValue
registered typeControl_Systems/Spectral_Measurements/Transfer_Function_Estimate
familyControl_Systems/Spectral_Measurements
solver environment classICoreBlock_0_Control_Systems_1_Spectral_Measurements_2_Transfer_Function_Estimate
sourcesrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Spectral_Measurements/Transfer_Function_Estimate/ICoreBlock_0_Control_Systems_1_Spectral_Measurements_2_Transfer_Function_Estimate.cpp
headersrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Spectral_Measurements/Transfer_Function_Estimate/ICoreBlock_0_Control_Systems_1_Spectral_Measurements_2_Transfer_Function_Estimate.h
default size on canvas160 × 86 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
1inICoreDoublex
2inICoreDoubley
3outICoreDoubleRe
4outICoreDoubleIm

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
Segment Length8not crossed
Segments4not crossed
Segment OverlapWC::OVL_NONE%~%WC::OVL_HALF%~%WC::OVL_3Q~~WC::OVL_HALFnot crossed
WindowWC::WIN_HAMMING%~%WC::WIN_HANN%~%WC::WIN_RECT~~WC::WIN_HA…not crossed
EstimatorH1%~%H2~~H1not crossed

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
deliberately not crossedSegment Length, Segments, Segment Overlap, Window, Estimator

Caveat (shown to the user): dspspect3/Discrete Transfer Function Estimator computes the H1 estimate and is named here rather than denied, but no port-to-port mapping exists, for three reasons measured on R2026a: it answers on ONE COMPLEX port where this block presents Re and Im on two real ones; driven one sample per step it publishes once every hop samples, so its output rate is not its input's; and its windows are the PERIODIC forms (its steady-state outputs equal tfestimate with hann(L,'periodic') over the W samples ending one sample before each output, to 4.4e-16), where this block uses the symmetric window tfestimate uses by default

Catalog contract: src/ICoreBlocks/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.

File banner (developer view)#

The top comment of the block's .cpp — the maths, the realization and the export strategy, addressed to whoever changes it. It must not contradict the description above (P7.5).

Transfer Function Estimate -- MATLAB's tfestimate over a sliding window, as Re and Im H1(m) = Pyx(m) / Pxx(m) = SUM_s conj(X_s) Y_s / SUM_s |X_s|^2 tfestimate's default H2(m) = Pyy(m) / Pxy(m) = SUM_s |Y_s|^2 / SUM_s X_s conj(Y_s)

over the last W = L + (K-1)*hop samples of the input x and the output y, K windowed L-point segments. Welch's normalising constants cancel in both ratios, so with Magnitude-Squared Coherence's four averaged sums -- pr + j pi = SUM conj(X) Y, pxx, pyy -- H1 is (pr + j pi) / pxx and H2 is pyy (pr + j pi) / (pr^2 + pi^2). The sums, the table and the emitted multiply-accumulates are that block's, shared through ICoreWelchCrossSupport: this is not a second implementation of Welch.

⚠ MEASURED AGAINST R2026a BEFORE ANY C++ WAS WRITTEN, over hamming, hann and rectwin at L = 8, K = 4, 50 % overlap: H1 as (pr + j pi)/pxx agrees with tfestimate to 1.5e-16, and its conjugate disagrees by 1.7-1.9; H2 as pyy/(pr - j pi) agrees with tfestimate(...,'Estimator', 'H2') to 2.2e-16. So the conjugate sits on x in H1 and on y in the Pxy of H2, and a core that put it on the other side would publish the transfer function of the time-reversed system.

⚠ THE SIMULINK BLOCK EXISTS AND CANNOT BE THE BRIDGE, for the three reasons Cross Power Spectral Density records for its own: dspspect3/Discrete Transfer Function Estimator answers on ONE COMPLEX port; driven one sample per step it publishes once every HOP samples; and its windows are PERIODIC -- its steady-state outputs equal tfestimate with hann(8,'periodic') over the W samples ending one sample before each output, to 4.4e-16. Support::None, the block named.

A silent x window answers 0 rather than MATLAB's NaN: the denominators are floored at 1e-30, as the coherence floors its own.

The three HDL targets are SIMULATION-ONLY real arithmetic, as the coherence's are.

Sample results#

Transfer Function Estimate — Step: 0 -> 1 at t = 1 sTransfer Function Estimate — Step: 0 -> 1 at t = 1 s00.51012345t (s)in ICoreDouble-Out-0in ICoreDouble-Out-0out ICoreDouble-Out-0 [5x1] entry 0out ICoreDouble-Out-1 [5x1] entry 0

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 93133d604 · produced by docsSample --out <folder> --blocks Gain_Scheduled_Lead_Lag Controller_1D Controller_Blend_1D Controller_2D Controller_3D Observer_Form_1D Self_Conditioned_1D Line_Of_Sight_Access Orbit_Propagator_Kepler Attitude_Dynamics Attitude_Profile_Nadir_Pointing Attitude_Profile_Geographic_Pointing Multitaper_PSD Cross_Power_Spectral_Density Transfer_Function_Estimate Envelope_Spectrum Compose_String Scan_String --steps 60 · data docs/generated/samples/Control_Systems__Spectral_Measurements__Transfer_Function_Estimate.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).