Turbofan Engine System — Robotics/Propulsion
Robotics/Propulsion/Turbofan_Engine_System · 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.
Turbofan Engine System
Robotics / Propulsion
A turbofan's installed thrust and fuel flow from a throttle position u, a Mach number M and an altitude h. The engine's thrust F follows a commanded thrust through a first-order lag whose time constant depends on the thrust itself:
- from the 1976 standard atmosphere at h, the temperature and pressure ratios θ = T(1 + 0.2M²)/288.15 and δ = p(1 + 0.2M²)3.5/101325
- Fcmd = sat[0, Fmax](δ·nT(u, M)·Fmax)
- F' = (Fcmd − F) / τeff with τeff = nτ(F/(Fmaxδ))·τ·δ/√θ
- thrust = Nt·F and fuel flow = nSFC(nT, M)·SFC/3600·√θ·F
nT, nτ and nSFC are the Aerospace Blockset's own non-dimensional tables for this engine: thrust against throttle (0 to 1) and Mach (0 to 1 in steps of 0.1), the time-constant multiplier against thrust over maximum thrust (0 to 1 in steps of 0.04, from 5.18 at idle down to 1 from 64 % upward), and fuel consumption against the commanded non-dimensional thrust and Mach. All three interpolate linearly and clip at both ends.
Ports
- throttle – the throttle position u, 0 (idle) to 1 (full); values outside that range are clipped. A scalar [1,1].
- Mach – the flight Mach number M; the tables clip it to [0, 1], while the pressure and temperature ratios use it as given. A scalar [1,1].
- altitude – the geopotential altitude h, in metres (Metric) or feet (English). A scalar [1,1].
- thrust – the installed thrust Nt·F, [1,1].
- fuel flow – the fuel mass flow, [1,1]: the SFC's mass unit per second.
Parameters
- Units – Metric (MKS) (the default) or English. The choice converts only the altitude: English reads it in feet and hands the atmosphere h·0.3048. Thrust, fuel flow and every parameter are in whatever consistent system you choose (N, kg/s and kg/(N·h), or lbf, lbm/s and lbm/(lbf·h)).
- Initial Thrust – F at the start of the run, a scalar. Defaults to 0.
- Maximum Sea-Level Static Thrust – Fmax, a scalar > 0: the thrust at full throttle, Mach 0 and sea level, and the ceiling of the commanded thrust. Defaults to 45000.
- Fastest Engine Time Constant (s) – τ, a scalar > 0: the lag's time constant at sea-level static and high thrust. The lag is up to 5.18 times slower near idle. Defaults to 1.
- Sea-Level Static TSFC – SFC, the thrust-specific fuel consumption at sea-level static, in fuel mass per unit thrust per hour. Defaults to 0.35.
- Installed Thrust Ratio – Nt, installed over uninstalled thrust; it scales the thrust output only, not the fuel flow. Defaults to 0.9.
- Integration Substeps – how many fourth-order Runge-Kutta steps a sample is integrated with on the discrete solver and in exported code, a whole number of 1 or more. Defaults to 100. No Simulink counterpart.
- 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. A core holds the thrust F, publishes the two outputs, and integrates one sample with the three inputs held and the chosen number of Runge-Kutta substeps – with 100, the same computation as Simulink's fixed-step ode4 at one hundredth of the sample time. The atmosphere, the three tables and every parameter are folded into the emitted code at export time as comparison chains with their constants printed at 17 significant digits, so no target carries a table.
The three hardware targets are simulation-only: powers, exponentials, square roots and divisions have no Q16.16 form, so values convert at the port boundary and the arithmetic runs in floating point. And a Q16.16 port saturates past about 32767, so a hardware core needs thrusts and altitudes below that – a small engine, or English units at modest altitude.
Simulink bridge
Import and export, mapped to Aerospace Blockset's
aerolibpropulsion2/Turbofan Engine System: Units →
units (the two values 1:1), Initial Thrust →
IC, Maximum Sea-Level Static Thrust →
Fmax, Fastest Engine Time Constant (s) →
tau, Sea-Level Static TSFC → SFC and
Installed Thrust Ratio → Nt.
ic_source is always Internal: the External choice adds a
fourth input port for the initial thrust, which no configuration here can add,
and an imported External block is reported. "Sampling Time (s)" does not
cross: the Simulink block is continuous and defines no
SampleTime.
Notes
- Stateful, continuous and nonlinear: one continuous state, the thrust. Its time constant is a function of the thrust, so there is no state space. The thrust output depends only on the state; the fuel flow also reads this sample's inputs, so the block has direct feedthrough.
- The altitude is geopotential, and outside the standard's 0 to 84852 m the atmosphere is extrapolated, not clamped – as in Simulink. Keep the altitude below roughly 170 km, where the extrapolated temperature would reach zero and the model has no meaning.
- Verified against R2026a's own block: its prototype reproduces the Simulink block under fixed-step ode4 to about 1e-15 relative on both outputs, in both unit systems, with every table clipped at both ends during the run.
Code facts#
| Fact | Value |
|---|---|
| registered type | Robotics/Propulsion/Turbofan_Engine_System |
| family | Robotics/Propulsion |
| solver environment class | ICoreBlock_0_Robotics_1_Propulsion_2_Turbofan_Engine_System |
| source | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Propulsion/Turbofan_Engine_System/ICoreBlock_0_Robotics_1_Propulsion_2_Turbofan_Engine_System.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Propulsion/Turbofan_Engine_System/ICoreBlock_0_Robotics_1_Propulsion_2_Turbofan_Engine_System.h |
| default size on canvas | 150 × 100 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 | throttle |
| 2 | in | ICoreDouble | Mach |
| 3 | in | ICoreDouble | altitude |
| 4 | out | ICoreDouble | thrust |
| 5 | out | ICoreDouble | fuel flow |
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 | Metric (MKS)%~%English~~Metric (MKS) | units |
Initial Thrust | 0 | IC |
Maximum Sea-Level Static Thrust | 45000 | Fmax |
Fastest Engine Time Constant (s) | 1 | tau |
Sea-Level Static TSFC | 0.35 | SFC |
Installed Thrust Ratio | 0.9 | Nt |
Integration Substeps | 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 | aerolibpropulsion2/Turbofan Engine System |
| port-count rule | PortsParam::None |
SampleTime parameter | no — the counterpart defines none; the rate stays on the ICore side |
| deliberately not crossed | Integration Substeps |
| always set | ic_source = Internal |
| ICore config | Simulink parameter | Value translation |
|---|---|---|
Units | units | Metric (MKS) → Metric (MKS), English → English |
Initial Thrust | IC | passes through |
Maximum Sea-Level Static Thrust | Fmax | passes through |
Fastest Engine Time Constant (s) | tau | passes through |
Sea-Level Static TSFC | SFC | passes through |
Installed Thrust Ratio | Nt | passes through |
Caveat (shown to the user): aerolibpropulsion2/Turbofan Engine System is continuous and has NO SampleTime parameter (verified against the R2026a block dialog). 'ic_source' is always Internal: its External choice adds a fourth input port for the initial thrust, which no configuration here can add, so an imported External block is reported. "Integration Substeps" is how this block integrates a sample and has no counterpart
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).
Turbofan Engine System -- a first-order thrust lag scheduled on throttle, Mach and altitude Inputs: throttle position u, Mach number M, altitude h. State: the thrust F. Per sample:
T, p = 1976 COESA standard atmosphere at h (feet converted to metres first in English) s = 1 + ((M*M)(gamma-1))*0.5 gamma = 1.4 theta = (T*s)(1/288.15), delta = (p*s^(gamma/(gamma-1)))*(1/101325) nT = Thrust(u, M) 2-D table, throttle [0 1] x Mach 0:0.1:1 Fcmd = sat[0, Fmax]( (delta*nT)*Fmax ) tau_eff = ((Tau(((1/Fmax)*F)/delta) / sqrt(theta))*tau)*delta 1-D table on 0:0.04:1 F' = (Fcmd - F) / tau_eff thrust = Nt*F fuel = (((TSFC(nT, M)*SFC)/3600)*sqrt(theta))*F 2-D table, nT 0:0.04:1 x Mach
⚠ MEASURED AGAINST R2026a BEFORE ANY OF IT WAS WRITTEN, because the board's one-line summary ("thrust lag against throttle, altitude and Mach") says nothing about three of the four things that decide the numbers.
find_system(...,'LookUnderMasks','all')on aerolibpropulsion2/Turbofan Engine System gives the wiring above, block for block: a COESA Atmosphere Model feeding a Relative Ratio subsystem (sqrt(theta) and delta only), three Lookup_n-D blocks, one Saturation, one continuous Integrator with an external IC, and the products in the association written above. The three tables are NOT mask parameters -- the mask initialization reads them from a private callback (aeroblkturbofandata) -- so they are constants of the block, printed from it at 17 digits and carried below as the shortest literals that round-trip to the same doubles.Three things the measurement settled that the dialog does not say:
- THE TIME CONSTANT IS A TABLE OF THE THRUST, NOT A PARAMETER. The mask's "fastest time
constant" is only the floor of a 26-point table that runs from 5.18x at zero thrust down to 1x at 64 % of delta*Fmax, and it is scaled by delta/sqrt(theta). The lag is therefore nonlinear in its own state -- no state space.
- THE FUEL TABLE IS READ AT THE COMMANDED NON-DIMENSIONAL THRUST, not at the lagged one.
Only the final factor F is the engine's actual thrust.
- UNITS MOVE ONLY THE ALTITUDE. English feeds the atmosphere h*0.3048; nothing else converts,
so thrust, fuel flow and every parameter are in whatever consistent system the user meant.
All three tables are Linear point-slope with Clip: below the first breakpoint the first value, above the last one the last interval at fraction 1, and inside, along the table's first dimension first. The atmosphere is the one Robotics/Atmosphere/COESA_Atmosphere uses (ICoreCoesa1976Support), which extrapolates its outer layers rather than clamping them.
Sample results#
The same rig also ran:
| Stimulus | What it is | Output range |
|---|---|---|
impulse | Impulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair) | 0 … 431.9 |
ramp | Ramp: slope 1 from t = 0 | 0 … 6338 |
sine | Sine Wave: amplitude 1, 2 rad/s, no phase, no bias | 0 … 8951 |
table | Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample | 0 … 5198 |
Plotted: step — Step: 0 -> 1 at t = 1 s
Category dynamic · sample time 0.1 · 60 steps · commit ae1a5a4f23bf9080195613e8ad1f6128ae5da42d · produced by docsSample --out <folder> --blocks Turbofan_Engine_System EOM_6DOF_Wind_Angles EOM_6DOF_Custom_Variable_Mass_Wind_Angles EOM_6DOF_Simple_Variable_Mass_Wind_Angles Surface_Fit Smoothing_Spline Thin_Plate_Spline LPC_To_LSF_LSP --steps 60 · data docs/generated/samples/Robotics__Propulsion__Turbofan_Engine_System.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).