Gain Scheduled Lead Lag — Control Systems/Gain Scheduling
Control_Systems/Gain_Scheduling/Gain_Scheduled_Lead_Lag · 3 input / 1 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.
Gain Scheduled Lead-Lag
Control Systems / Gain Scheduling
A lead-lag compensator whose two time constants arrive on ports, so a scheduler can move them while the model runs. Held still, it is the transfer function
U(s)/E(s) = (a·s + 1) / (b·s + 1)
and it is realized, as the Simulink block realizes it, by one state per entry:
u = (a·e + x) / b, dx/dt = e − u
When a and b move, two realizations of the same transfer function are different systems, and this is the one the Simulink block integrates.
Ports
- e – the signal to compensate; any size, filtered entry by entry.
- a – the lead time constant, a scalar signal, applied to every entry.
- b – the lag time constant, a scalar signal, applied to every entry. It divides, so it must stay away from zero, and it must be positive for the compensator to be stable.
- u – the compensated signal, the same size as e.
Parameters
- Initial State – x at the start of the run: a scalar, applied to every entry, or a matrix the size of e. Default 0. Note that the output at the first instant is already (a·e + x)/b, not x.
- 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 target integrates with forward Euler at the block's period: the coefficients are signals, so there is no fixed system to discretize exactly. The initial state is baked in; a and b are read from their ports every step.
The three HDL targets are simulation-only: they compute in
real arithmetic and quantize only at the ports, because the output divides by a
signal and the Q16.16 datapath a block body is given has no division.
Simulink bridge
Import and export, mapped to Aerospace Blockset's aerolibschedule/Gain
Scheduled Lead-Lag (the library path carries a newline after "Scheduled"). Initial
State ↔ x_initial, passed through unchanged – the block's only
parameter. It has no SampleTime, so Sampling Time (s) stays on the ICore
side.
Notes
- Stateful, one state per entry of e, and with direct feedthrough: the output depends on e at the same instant through a/b.
- Only e may be a vector or matrix here; the Simulink block would also take a and b entry by entry, which this block reports rather than guessing at.
- Linear at any instant but not time-invariant, so it carries no state space and model reduction reports it as unmergeable.
Code facts#
| Fact | Value |
|---|---|
| registered type | Control_Systems/Gain_Scheduling/Gain_Scheduled_Lead_Lag |
| family | Control_Systems/Gain_Scheduling |
| solver environment class | ICoreBlock_0_Control_Systems_1_Gain_Scheduling_2_Gain_Scheduled_Lead_Lag |
| source | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Gain_Scheduling/Gain_Scheduled_Lead_Lag/ICoreBlock_0_Control_Systems_1_Gain_Scheduling_2_Gain_Scheduled_Lead_Lag.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Gain_Scheduling/Gain_Scheduled_Lead_Lag/ICoreBlock_0_Control_Systems_1_Gain_Scheduling_2_Gain_Scheduled_Lead_Lag.h |
| default size on canvas | 130 × 100 px |
| ports at insert | 3 in, 1 out |
| code generators implemented | Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text |
Ports#
| # | Direction | Signal type | Description label |
|---|---|---|---|
| 1 | in | ICoreDouble | e |
| 2 | in | ICoreDouble | a |
| 3 | in | ICoreDouble | b |
| 4 | out | ICoreDouble | u |
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 variable | Default | Simulink parameter |
|---|---|---|
Initial State | 0 | x_initial |
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.
Simulink bridge#
| support | Support::Both |
| Simulink path | aerolibschedule/Gain Scheduled\nLead-Lag |
| port-count rule | PortsParam::None |
SampleTime parameter | no — the counterpart defines none; the rate stays on the ICore side |
| ICore config | Simulink parameter | Value translation |
|---|---|---|
Initial State | x_initial | passes through |
Caveat (shown to the user): the two time constants travel on ports on both sides, so x_initial is the whole mapping. The library path carries an embedded newline after 'Scheduled'. No SampleTime: the rate stays on the ICore side
Catalog contract: src/ICoreBlocks/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:
B0every stimulus in the sample errored — cross-checks skipped
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).
Gain Scheduled Lead-Lag -- (a s + 1)/(b s + 1) with a and b on ports u = (a*e + x) / b dx/dt = e - u x(0) = Initial State
MEASURED AGAINST R2026a. The masked subsystem is one Integrator (IC = x_initial, no limits, no reset), a Sum forming e - u into it, a Product a*e, a Sum a*e + x and a Product dividing that by b -- nothing else. Driven with e = 2*randn and BOTH coefficients moving every sample (a in [-0.55, 1.45], b in [0.7, 2.7]) under ode1 at 0.01 s, the real block and a forward-Euler reference of exactly the recursion below agree to EXACTLY 0 over 500 samples.
With a and b held still this is (a s + 1)/(b s + 1); with them moving, the realization is observable, and this one is the block's. The Varying Transfer Function carries a different first-order realization of the same transfer function and would not reproduce it.
Stepped runs and every export take the forward Euler step at the block's period, because a continuous system whose coefficients are signals cannot be pre-discretized; the parity testbench pins Simulink to ode1 so both sides run that one method.
No SampleTime: set_param refuses it on this mask (measured). x_initial is its only parameter.
Sample results#
No stimulus produced a sampled output in this rig — Joint integration produced a non-finite state at t = 0.100000 s. Reduce the step, or switch the stepping type to an implicit method.. That is a fact about the single-block rig, not a verdict on the block: an offline batch fit, a block whose output only appears at onSolverFinish, or one that needs a driven environment cannot be exercised alone.
Category unsampled · 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
Sample data: docs/generated/samples/Control_Systems__Gain_Scheduling__Gain_Scheduled_Lead_Lag.json