Wind Turbulence Model — Robotics/Wind
Robotics/Wind/Wind_Turbulence_Model · 3 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.
Wind Turbulence Model
Robotics / Wind
Atmospheric turbulence as band-limited white noise shaped by the Dryden or von Kármán spectra, giving the three gust velocities [ug; vg; wg] and the three gust angular rates [pg; qg; rg] in body axes. Two regimes run at once and the block blends them by altitude h (in feet internally):
- h ≤ 1000 ft – the intensities come from the wind speed at 20 ft (σw = 0.1·W20, σu = σv = σw/(0.177 + 0.000823h)0.4) and the scale lengths from the altitude (Lw = h, Lu = Lv = h/(0.177 + 0.000823h)1.2); the gusts are in the mean-wind frame and are rotated into body axes by the wind direction and the DCM on the port.
- h ≥ 2000 ft – the intensity comes from the probability-of-exceedance table against altitude, the scale length is the dialog's, and the turbulence is isotropic, so it is already in body axes.
- between – linear in altitude between the two.
Ports
- Altitude – h, a scalar [1,1], in m or ft per Units.
- Airspeed – V, a scalar [1,1], in m/s, ft/s or knots per Units; it must be positive, since every filter's break frequency is V/L.
- DCM – the earth-to-body direction cosine matrix [3,3], used only in the low-altitude regime.
- Vw – the gust velocities [ug; vg; wg], [3,1], in the unit the airspeed is given in.
- Omega – the gust angular rates [pg; qg; rg], [3,1], in rad/s in every unit system.
Parameters
- Units – Metric (MKS) (altitude m, airspeed m/s), English (Velocity in ft/s) or English (Velocity in kts) (altitude ft). The model itself is in feet and ft/s; the gust velocities come back in the airspeed's unit.
- Specification – MIL-F-8785C, MIL-HDBK-1797 or MIL-HDBK-1797B. It selects the discrete pg filter and nothing else.
- Model Type – the nine presets, spelled as the Aerospace dialog spells them: Continuous Von Karman (+q −r), (+q +r), (−q +r), Continuous Dryden (+q −r), (+q +r), (−q +r), Discrete Dryden (+q −r), (+q +r), (−q +r). Continuous or discrete decides the filter forms; the signs are the q and r conventions.
- Wind Speed At 6 m Altitude – W20, the mean wind at 20 ft (6 m), in the airspeed's unit. It sets the low-altitude intensity.
- Wind Direction At 6 m Altitude (deg) – the mean wind's direction, degrees clockwise from north; it rotates the low-altitude gusts.
- Probability Of Exceedance Of High-Altitude Intensity – one of 2x10^-1, 10^-1, 10^-2 - Light, 10^-3 - Moderate, 10^-4, 10^-5 - Severe, 10^-6; the row of the intensity table.
- Scale Length At Medium/High Altitudes – L above 2000 ft, in m or ft per Units. 533.4 m (1750 ft) is the Dryden default, 762 m (2500 ft) the von Kármán one.
- Wingspan – b, in m or ft; it sets the angular-rate filters' break frequencies.
- Band-Limited Noise Sample Time (s) – the period the four white-noise streams are drawn at. It must be a whole multiple of the block's own sample time.
- Noise Seeds [ug vg wg pg] – four non-negative whole numbers, one per stream, seeding Simulink's generator exactly.
- Turbulence On – on or off; off publishes zeros on both ports, as disabling the filters does in Simulink.
- Integration Substeps Per Sample – how many classical Runge–Kutta substeps a CONTINUOUS preset takes per sample, a whole number ≥ 1. The default 100 is Simulink's own fixed-step ode4 at Ts/100. A discrete preset ignores it: its recursions take one step per noise period.
- 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 core carries the same generator – the Park–Miller recursion is integer arithmetic that each target can hold exactly – so an exported core reproduces the same gust sequence as the simulation, sample for sample. The unit factors, the intensity table, the seeds and the filter constants are folded into the body at export time; a continuous preset's core runs its configured number of Runge–Kutta substeps per sample.
The three HDL targets are simulation-only real
arithmetic, quantized only at the ports: a logarithm, a cube root and a noise whose
scale spans decades have no Q16.16 form. The cores simulate correctly and are not
offered as synthesizable.
Simulink bridge
Import and export, mapped to Aerospace Blockset's
aerolibwind2/Dryden Wind Turbulence Model (Continuous (+q +r)):
Units → units, Specification → spec,
Model Type → model, Wind Speed At 6 m Altitude →
W20, Wind Direction At 6 m Altitude (deg) → Wdeg,
Probability Of Exceedance Of High-Altitude Intensity → TurbProb,
Scale Length At Medium/High Altitudes → L_high, Wingspan
→ Wingspan, Band-Limited Noise Sample Time (s) →
ts, Noise Seeds [ug vg wg pg] → Seed and
Turbulence On → T_on – the whole dialog, every enum 1:1
and lossless. The other eight library entries (the five other Dryden variants and the
three von Kármán ones) are the same masked block at a different
model, and import through the bridge's alias table with that preset
applied. "Sampling Time (s)" does not cross: the Simulink block defines no
SampleTime parameter, measured on R2026a. Integration Substeps Per
Sample does not cross either: it is an ICore-side integration choice, and the
Simulink block has no counterpart for it.
Notes
- Discrete-only and stateful: the filter states of both altitude regimes, the four noise streams' generator states, the held noise and a sample counter. A continuous preset advances its states with 100 RK4 substeps per sample, which is what Simulink's ode4 at Ts/100 does.
- The output depends on the altitude, airspeed and DCM of the same instant (the intensities, the break frequencies and the rotation), so the block feeds through.
- Drawing a random number is a side effect, so the block is evaluated once per step.
- A gust sequence is reproducible: the same seeds, noise period and sample time give the same sequence in the app and in every exported core.
Code facts#
| Fact | Value |
|---|---|
| registered type | Robotics/Wind/Wind_Turbulence_Model |
| family | Robotics/Wind |
| solver environment class | ICoreBlock_0_Robotics_1_Wind_2_Wind_Turbulence_Model |
| source | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Wind/Wind_Turbulence_Model/ICoreBlock_0_Robotics_1_Wind_2_Wind_Turbulence_Model.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Wind/Wind_Turbulence_Model/ICoreBlock_0_Robotics_1_Wind_2_Wind_Turbulence_Model.h |
| default size on canvas | 150 × 110 px |
| ports at insert | 3 in, 2 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 | Altitude |
| 2 | in | ICoreDouble | Airspeed |
| 3 | in | ICoreDouble | DCM |
| 4 | out | ICoreDouble | Vw |
| 5 | out | ICoreDouble | Omega |
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 |
|---|---|---|
Units | std::string(UNIT_NAMES[0])%~%UNIT_NAMES[1]%~%UNIT_NAMES[2… | units |
Specification | std::string(SPEC_NAMES[0])%~%SPEC_NAMES[1]%~%SPEC_NAMES[2… | spec |
Model Type | opts~~MODEL_NAMES[4] | model |
Wind Speed At 6 m Altitude | 15 | W20 |
Wind Direction At 6 m Altitude (deg) | 0 | Wdeg |
Probability Of Exceedance Of High-Altitude Intensity | opts~~PROB_NAMES[2] | TurbProb |
Scale Length At Medium/High Altitudes | 533.4 | L_high |
Wingspan | 10 | Wingspan |
Band-Limited Noise Sample Time (s) | 0.1 | ts |
Noise Seeds [ug vg wg pg] | [23341 23342 23343 23344] | Seed |
Turbulence On | on%~%off~~on | T_on |
Integration Substeps Per Sample | 100 | not 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.
Simulink bridge#
| support | Support::Both |
| Simulink path | aerolibwind2/Dryden Wind Turbulence Model \n(Continuous (+q +r)) |
| port-count rule | PortsParam::None |
SampleTime parameter | no — the counterpart defines none; the rate stays on the ICore side |
| deliberately not crossed | Integration Substeps Per Sample |
| ICore config | Simulink parameter | Value translation |
|---|---|---|
Units | units | UNIT_NAMES[0] → UNIT_NAMES[0], UNIT_NAMES[1] → UNIT_NAMES[1], UNIT_NAMES[2] → UNIT_NAMES[2] |
Specification | spec | SPEC_NAMES[0] → SPEC_NAMES[0], SPEC_NAMES[1] → SPEC_NAMES[1], SPEC_NAMES[2] → SPEC_NAMES[2] |
Model Type | model | MODEL_NAMES[0] → MODEL_NAMES[0], MODEL_NAMES[1] → MODEL_NAMES[1], MODEL_NAMES[2] → MODEL_NAMES[2], MODEL_NAMES[3] → MODEL_NAMES[3], MODEL_NAMES[4] → MODEL_NAMES[4], MODEL_NAMES[5] → MODEL_NAMES[5], MODEL_NAMES[6] → MODEL_NAMES[6], MODEL_NAMES[7] → MODEL_NAMES[7], MODEL_NAMES[8] → MODEL_NAMES[8] |
Wind Speed At 6 m Altitude | W20 | passes through |
Wind Direction At 6 m Altitude (deg) | Wdeg | passes through |
Probability Of Exceedance Of High-Altitude Intensity | TurbProb | PROB_NAMES[0] → PROB_NAMES[0], PROB_NAMES[1] → PROB_NAMES[1], PROB_NAMES[2] → PROB_NAMES[2], PROB_NAMES[3] → PROB_NAMES[3], PROB_NAMES[4] → PROB_NAMES[4], PROB_NAMES[5] → PROB_NAMES[5], PROB_NAMES[6] → PROB_NAMES[6] |
Scale Length At Medium/High Altitudes | L_high | passes through |
Wingspan | Wingspan | passes through |
Band-Limited Noise Sample Time (s) | ts | passes through |
Noise Seeds [ug vg wg pg] | Seed | passes through |
Turbulence On | T_on | on → on, off → off |
Caveat (shown to the user): The nine aerolibwind2 library entries are ONE masked block (MaskType "Wind Turbulence Model", measured on all nine): "Model Type" carries the same nine strings, and the eight non-canonical paths import through the bridge's alias table. The block has NO SampleTime parameter (verified against the R2026a dialog), so "Sampling Time (s)" does not cross
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).
Wind Turbulence Model -- the Dryden and von Karman gust filters, all nine Aerospace presets Band-limited white noise through shaping filters, in two altitude regimes at once:
low (h <= 1000 ft) sigma_w = 0.1 W20, sigma_u = sigma_v = sigma_w/(0.177 + 0.000823 h)^0.4, L_w = h, L_u = L_v = h/(0.177 + 0.000823 h)^1.2 (h held in [10, 1000] ft for the lengths and [0, 1000] ft for the intensities), the gusts in the mean-wind frame and rotated into body axes by the wind direction and DCM high (h >= 2000 ft) sigma from the MIL-HDBK-1797 probability-of-exceedance table over the twelve altitude breakpoints, L = the dialog's medium/high scale length, the gusts already body axes between linear in altitude: low_body + (high - low_body)(h - 1000)/1000
⚠ EVERY NUMBER HERE WAS MEASURED AGAINST R2026a BEFORE IT WAS WRITTEN, by reading the masked subsystem (find_system LookUnderMasks) block by block and then running the block:
- The noise is Simulink's Random Number block: a Park-Miller LCG (Schrage's decomposition)
into Marsaglia's polar method, the dialog seed scrambled into the initial state. Eleven seeds x 100 draws reproduced at EXACTLY zero, which is what makes this block comparable to Simulink sample by sample rather than only in distribution.
- Its amplitude is NOT the same in the two families: the continuous presets carry the noise
power pi (so the noise is sqrt(pi/ts) z) and the discrete presets carry ts (so it is exactly z). Reading the continuous gain into the discrete filters is a factor of 17.7.
- The unit delays of the discrete presets run at the NOISE rate while everything around them
runs at the block's rate, so a delay's output moves one noise period after its input: the recursion carries the delay's OUTPUT and its PENDING LATCH as two states. Measured at a noise rate three times the block's: one state is exact at the noise hits and ~15 % out between them, two states are exact everywhere.
- The 'spec' only reaches the DISCRETE p filter (three variants) -- measured across all 27
model x spec combinations, nothing else in the diagram moves with it.
- The block has NO SampleTime parameter ("Wind Turbulence Model block (mask) does not have a
parameter named 'SampleTime'").
DISCRETE-ONLY. The continuous presets are advanced by the classical RK4 with 100 substeps per sample, which is Simulink's fixed-step ode4 at Ts/100 -- measured at exactly 0 over 200 samples on Dryden, von Karman and a three-sample noise period, with the altitude, airspeed and DCM held across each sample as the solver holds them.
The whole computation -- the pre-pass, the outputs, the derivative and the recursions -- is built ONCE as a little expression IR and then either evaluated (the live run) or printed (the ten targets), so the eleven implementations cannot drift apart.
Sample results#
No stimulus produced a sampled output in this rig — Invalid input size at Wind Turbulence Model block: ICore Blocks/Home/Wind Turbulence Model. 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 83b4036dc8d5efdf28a47c36be1e27203065c75b · produced by docsSample --out <folder> --blocks Symbolic_Expression Symbolic_Derivative Gradient Jacobian Hessian Divergence_And_Curl Laplacian Taylor_Approximation Linear_Program LTI_System Wind_Turbulence_Model --steps 60
Sample data: docs/generated/samples/Robotics__Wind__Wind_Turbulence_Model.json