Generated reference › Discrete Varying Observer Form — Control Systems/Linear Parameter Varying
kind: generated#block#control-systems-linear-parameter-varying

Discrete Varying Observer Form — Control Systems/Linear Parameter Varying

x

Control_Systems/Linear_Parameter_Varying/Discrete_Varying_Observer_Form · 7 input / 3 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.

Discrete Varying Observer Form

Control Systems / Linear Parameter Varying

A discrete observer with state feedback, in which every matrix is a signal rather than a setting. Each sample, in this order:

u[k] = −K[k]·x[k]
ε[k] = y[k] − C[k]·x[k] − D[k]·u[k]
x[k+1] = A[k]·x[k] + B[k]·u[k] + L[k]·ε[k]

The block estimates a plant's state from its measured output y and drives it with the feedback it computes, so a scheduling signal can move the plant model, the observer gain and the feedback gain together while it runs.

Ports

  • y – the measured plant output, [p,1].
  • A – the state matrix, [n,n]. Its size defines n.
  • B – the input matrix, [n,m].
  • C – the output matrix, [p,n].
  • D – the feedthrough matrix, [p,m].
  • K – the state-feedback gain, [m,n]. Note the minus sign is in the block: u = −K·x, so a stabilizing K is the one you would compute for that convention, not its negation.
  • L – the observer gain, [n,p], multiplying the innovation.
  • u – the computed plant input, [m,1].
  • x – the current state estimate x[k], [n,1].
  • x+ – the next state estimate x[k+1], [n,1].

The seven sizes must agree exactly, and a disagreement names both offending shapes once the model's port sizes have settled. Nothing is scalar-expanded: these are matrices with a meaning, and expanding one silently would hide a mis-wired schedule.

Parameters

  • Initial State Vector – the estimate x[0]. A scalar is used for every state, which is how Simulink's own x0 behaves and the only form that can be written before n is known; an [n,1] vector sets each state separately. Defaults to 0.
  • 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.

Only the dimensions n, m and p are fixed at export time, so every loop is statically sized while all seven matrices are read from their signals each step. There is consequently no tunable parameter on the exported core: retuning is what the gain ports are for, and they stay live on the deployed core. Only the initial estimate is emitted as a constant.

Every target emits the three lines in the order above – feedback, then innovation, then update – so the exported core cannot disagree with the simulation about which u the innovation saw.

The three HDL targets carry the arithmetic in Q16.16 fixed point and are fully synthesizable. A gain arriving on a port is already quantized to one Q16.16 quantum (1.5×10-5) before the block sees it, which is worth knowing for an observer gain L: the innovation it multiplies is a difference of two nearby quantities, so it is the term in this block most sensitive to that quantization.

Simulink bridge

Import and export, mapped to cstblocks/Linear Parameter Varying/Discrete Varying Observer Form, with "Initial State Vector" going to x0 as a pass-through value.

The rate crosses under a different name. This Simulink block calls its rate parameter Ts, not SampleTime, so the catalog entry names it explicitly. Emitting the usual name would be a hard set_param error that aborts the entire generated script rather than a warning that degrades.

OutputX and OutputDX are always implied on: both move ports in Simulink, and the ICore block's port list is fixed at 7 in / 3 out.

Notes

  • Discrete only, and stateful: the state is the [n,1] estimate x.
  • No algebraic loop, despite D multiplying a signal the block itself produces. u depends on the state alone, so the innovation's D·u term is already known by the time it is needed – which is exactly why the three lines have to run in the order given.
  • No state space, deliberately, for the same reason as Discrete Varying State Space: linear at every instant, time-varying overall, so model reduction is right to refuse it rather than merge a snapshot of whatever the gain ports happened to carry.

Code facts#

FactValue
registered typeControl_Systems/Linear_Parameter_Varying/Discrete_Varying_Observer_Form
familyControl_Systems/Linear_Parameter_Varying
solver environment classICoreBlock_0_Control_Systems_1_Linear_Parameter_Varying_2_Discrete_Varying_Observer_Form
sourcesrc/ICoreSDK/ICoreBlockLibrary/Blocks/Control_Systems/Linear_Parameter_Varying/Discrete_Varying_Observer_Form/ICoreBlock_0_Control_Systems_1_Linear_Parameter_Varying_2_Discrete_Varying_Observer_Form.cpp
headersrc/ICoreSDK/ICoreBlockLibrary/Blocks/Control_Systems/Linear_Parameter_Varying/Discrete_Varying_Observer_Form/ICoreBlock_0_Control_Systems_1_Linear_Parameter_Varying_2_Discrete_Varying_Observer_Form.h
default size on canvas160 × 150 px
ports at insert7 in, 3 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDoubley
2inICoreDoubleA
3inICoreDoubleB
4inICoreDoubleC
5inICoreDoubleD
6inICoreDoubleK
7inICoreDoubleL
8outICoreDoubleu
9outICoreDoublex
10outICoreDoublex+

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
Initial State Vector0x0

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::Both
Simulink pathcstblocks/Linear Parameter Varying/Discrete Varying Observer Form
port-count rulePortsParam::None
SampleTime parameteryes
rate parameter nameTs
always setOutputX = on, OutputDX = on
ICore configSimulink parameterValue translation
Initial State Vectorx0passes through

Caveat (shown to the user): all seven matrices are signals on both sides, so none of them is a parameter to carry across

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

Description vs code#

The checker has a blind spot here — it could not resolve something (a grouped port bullet, a computed config name), which is reported and never counted as a pass. A reader has to settle it:

  • B0 1 port label(s) this tool cannot resolve

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).

Discrete Varying Observer Form block -- observer + state feedback, all matrices varying u[k] = -K[k] x[k] (state feedback, from the state alone) eps[k] = y[k] - C[k] x[k] - D[k] u[k] (innovation, using THAT u) x[k+1] = A[k] x[k] + B[k] u[k] + L[k] eps[k] (observer update)

Seven inputs (y, A, B, C, D, K, L), three outputs (u, x[k], x[k+1]), matching cstblocks/Linear Parameter Varying/Discrete Varying Observer Form port for port.

THE ORDER OF THE THREE LINES IS THE CONTRACT. u is computed first from the current state alone, and eps uses that same u -- which is what stops the D term closing an algebraic loop even though D multiplies a signal this block produces itself. All ten generators emit the three in this order for that reason; getting it wrong shows up as a one-sample lag rather than as an obviously broken output, so it is not the kind of mistake a smoke test finds.

Like its sibling Discrete Varying State Space: no ICoreStateSpace (linear at every instant, time-varying overall), discrete by nature, and every generated loop statically sized while the coefficients themselves are read fresh each step.

Sample results#

Discrete Varying Observer Form — Step: 0 -> 1 at t = 1 sDiscrete Varying Observer Form — Step: 0 -> 1 at t = 1 s-1-0.500.51012345t (s)in ICoreDouble-Out-0in ICoreDouble-Out-0in ICoreDouble-Out-0out ICoreDouble-Out-0out ICoreDouble-Out-1out ICoreDouble-Out-2

The same rig also ran:

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

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/Control_Systems__Linear_Parameter_Varying__Discrete_Varying_Observer_Form.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).