CIRA 86 Atmosphere — Robotics/Atmosphere
Robotics/Atmosphere/CIRA_86_Atmosphere · 2 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.
CIRA-86 Atmosphere
Robotics / Atmosphere
The COSPAR International Reference Atmosphere 1986: a monthly mean climatology of temperature, zonal wind and geopotential height or pressure, from 80° south to 80° north and from the ground to 120 km. A geodetic latitude and a coordinate go in, and the month's tables are read by bilinear interpolation:
- the coordinate becomes a table axis – c = h·0.001 in kilometres, or c = −ln(P/101300), the log-pressure the tables are built on
- each axis is clipped: outside the table the nearest breakpoint is used and the interpolation fraction is zero, so the answer is held rather than extrapolated
- the value is linear in the coordinate first and in the latitude second, y = (y₁ − y₀)f + y₀
It is a lookup and not a formula: what it reproduces is the table and the interpolation rule, both taken from the reference implementation.
Ports
- lat – the geodetic latitude in degrees, north positive. Any size [m,n]; the block works entry by entry. Outside ±80° the edge of the table is held.
- coord – the coordinate chosen by Coordinate Type: a geopotential altitude in metres (0 to 120000 outside of which the table is held), or a static pressure in pascals (101300 down to 0.0025). Same size as lat.
- T – the mean temperature, in kelvin. Same size as the inputs.
- alt – the pressure in pascals when the coordinate is a geopotential height, and the geopotential height in metres when the coordinate is a pressure. Same size as the inputs.
- ZW – the mean zonal wind, in m/s, eastward positive. Same size as the inputs.
Parameters
- Coordinate Type – which coordinate the second input carries,
and therefore which quantity the second output is.
- Geopotential Height – metres in, pressure out. The temperature and wind tables run from 0 to 120 km; the pressure table starts at 20 km, so below that the pressure is the 20 km value.
- Pressure – pascals in, geopotential height out, on a log-pressure axis from 0 to 17.5 (101300 Pa down to 0.0025 Pa).
- Month – which of the twelve monthly means is read, January to December. Nothing is interpolated between months.
- 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.
An export carries the selected month's three tables and nothing else – 1207 numbers on the geopotential-height coordinate, 7029 on the pressure one – beside one interpolation routine used three times. The numbers are printed at 17 significant digits, so every backend interpolates the same doubles as the block's own simulation.
The three hardware targets are simulation-only: an interpolation fraction, a logarithm and an exponential have no Q16.16 form, so values convert at the port boundary and the arithmetic runs in floating point. A fixed-point port also cannot carry a sea-level pressure or a 120 km altitude (Q16.16 saturates past about 32767), so a hardware export is for the part of the atmosphere whose numbers fit.
A hole in the data cannot cross to hardware: VHDL's real
has no NaN, so the four hardware targets write 0.0 where the other six
write NaN.
Simulink bridge
Import and export, mapped to Aerospace Blockset's
aerolibatmos2/CIRA-86 Atmosphere Model. Two configuration values
cross: Coordinate Type → ctype (Geopotential
Height is that block's GPHeight) and Month →
month, one for one.
Three Simulink parameters are always implied: units is always
Metric (MKS), this block being metric throughout; action is
always None, that parameter only choosing whether Simulink warns for an
out-of-range input or a hole; and mtype is always Monthly
– see Notes. The Simulink block defines no SampleTime
parameter, measured, so the rate stays on the ICore side.
Notes
- Algebraic and stateless: the outputs depend on this sample alone.
- Not linear, so the block carries no state space and model reduction correctly reports it as unmergeable.
- Both ends are HELD, not extrapolated – a latitude past ±80°, an altitude past 120 km or a pressure above 101300 Pa all read the edge of the table, because the interpolation fraction is zero there.
- A non-positive pressure reads the TOP of the table, which is what the
reference answers (measured at 0 and at −500 Pa); the block spells it as
an explicit branch, because VHDL's
LOGasserts on a non-positive argument rather than answering. - The data has holes, and they come out as NaN: CIRA omits the levels inside the Antarctic land mass – 80° south at sea level, and the three southernmost latitudes at the two highest pressures – and the interpolation carries the NaN through, as the reference does.
- Mean value type is pinned to Monthly. Simulink's Annual setting makes each output a seven-element vector – a mean plus the amplitude and phase of the annual, semi-annual and ter-annual harmonics – which is a different quantity on the same port rather than a different atmosphere. It is not offered here. (That setting is also refused by the Simulink block itself on the geopotential-height coordinate, measured: it resets to Monthly.)
- Verified against R2026a over 185814 answers – every breakpoint, both clip regions and the holes – where every temperature, every zonal wind and every geopotential height agrees bit for bit, and the pressure output sits within one unit in the last place.
Code facts#
| Fact | Value |
|---|---|
| registered type | Robotics/Atmosphere/CIRA_86_Atmosphere |
| family | Robotics/Atmosphere |
| solver environment class | ICoreBlock_0_Robotics_1_Atmosphere_2_CIRA_86_Atmosphere |
| source | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Atmosphere/CIRA_86_Atmosphere/ICoreBlock_0_Robotics_1_Atmosphere_2_CIRA_86_Atmosphere.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Atmosphere/CIRA_86_Atmosphere/ICoreBlock_0_Robotics_1_Atmosphere_2_CIRA_86_Atmosphere.h |
| default size on canvas | 170 × 110 px |
| ports at insert | 2 in, 3 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 | lat |
| 2 | in | ICoreDouble | coord |
| 3 | out | ICoreDouble | T |
| 4 | out | ICoreDouble | alt |
| 5 | out | ICoreDouble | ZW |
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 |
|---|---|---|
Coordinate Type | Geopotential Height%~%Pressure~~Geopotential Height | ctype |
Month | January%~%February%~%March%~%April%~%May%~%June%~%July%~%… | month |
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 | aerolibatmos2/CIRA-86 Atmosphere Model |
| port-count rule | PortsParam::None |
SampleTime parameter | no — the counterpart defines none; the rate stays on the ICore side |
| always set | units = Metric (MKS), mtype = Monthly, action = None |
| ICore config | Simulink parameter | Value translation |
|---|---|---|
Coordinate Type | ctype | Geopotential Height → GPHeight, Pressure → Pressure |
Month | month | passes through |
Caveat (shown to the user): two inputs -- a geodetic latitude in degrees and either a geopotential altitude in metres or a static pressure in pascals -- and three outputs: temperature in kelvin, then pressure in pascals (Geopotential Height) or geopotential height in metres (Pressure), then the zonal wind in m/s. Both ends of both axes are HELD rather than extrapolated, and the data's Antarctic holes come out as NaN. 'units' is always Metric (MKS), 'action' always None (it only chooses whether Simulink warns), and 'mtype' is always Monthly: Simulink's Annual setting makes each output a seven-element harmonic vector rather than an atmosphere, and is not offered here. The Simulink block has no SampleTime, so the rate stays on the ICore side
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).
CIRA-86 Atmosphere -- the COSPAR International Reference Atmosphere 1986, read as a table c = h * 0.001 (Geopotential Height: metres to kilometres) c = -ln(P * (1/101300)) (Pressure: a gain by the reciprocal, then a log) y = bilinear interpolation of the month's table in (c, latitude), CLIPPED at both ends alt = ZH (Pressure) or 101300*exp(-ZH) (Geopotential Height)
The tables are the block's own data files, and the lookup is Simulink's Prelookup / Interpolation n-D semantics rather than a formula -- both in ICoreCira86Support, with the measurements that pinned them.
⚠ MEASURED BIT FOR BIT AGAINST R2026a over 185814 answers (three months of the geopotential-height coordinate, two of the pressure coordinate, one annual set; every breakpoint, both clip regions and the data's NaN holes). The single exception is the pressure OUTPUT of the geopotential-height coordinate, one unit in the last place on about 8% of samples, which is this platform's
expagainst the MathWorks one -- MATLAB's own reproduces the block exactly, and the MATLAB body is what Simulink parity compares.⚠ THE HOLES IN THE DATA ARE PART OF THE ANSWER: NaN at 80 degrees south at sea level, and at the three southernmost latitudes at the two highest pressures. The four hardware targets cannot carry a NaN and write 0.0 there; every rig stays far from them.
ALGEBRAIC and STATELESS, and nonlinear in its inputs, so no state space.
Sample results#
| t | in ICoreDouble-Out-0 | in ICoreDouble-Out-0 | out ICoreDouble-Out-0 | out ICoreDouble-Out-1 | out ICoreDouble-Out-2 |
|---|---|---|---|---|---|
| 0 | -2 | -2 | 300.6 | 5597 | -1.96 |
| 0.4 | 0.5 | 0.5 | 300.6 | 5593 | -2.155 |
| 0.8 | -2 | -2 | 300.6 | 5597 | -1.96 |
| 1.2 | 0.5 | 0.5 | 300.6 | 5593 | -2.155 |
| 1.6 | -2 | -2 | 300.6 | 5597 | -1.96 |
| 2 | 0.5 | 0.5 | 300.6 | 5593 | -2.155 |
| 2.4 | -2 | -2 | 300.6 | 5597 | -1.96 |
| 2.8 | 0.5 | 0.5 | 300.6 | 5593 | -2.155 |
| 3.2 | -2 | -2 | 300.6 | 5597 | -1.96 |
| 3.6 | 0.5 | 0.5 | 300.6 | 5593 | -2.155 |
| 4 | -2 | -2 | 300.6 | 5597 | -1.96 |
| 4.4 | 0.5 | 0.5 | 300.6 | 5593 | -2.155 |
| 4.8 | -2 | -2 | 300.6 | 5597 | -1.96 |
| 5.2 | 0.5 | 0.5 | 300.6 | 5593 | -2.155 |
Every 4th of 60 samples, from the table stimulus.
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) | 300.5 … 300.6 |
ramp | Ramp: slope 1 from t = 0 | 300.2 … 300.6 |
sine | Sine Wave: amplitude 1, 2 rad/s, no phase, no bias | 300.5 … 300.6 |
step | Step: 0 -> 1 at t = 1 s | 300.5 … 300.6 |
Plotted: table — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample
Category static · sample time 0.1 · 60 steps · commit 815ea40263e300a4a7d9b94098e5eb36a9702a08 · produced by docsSample --out <folder> --blocks CIRA_86_Atmosphere --steps 60 · data docs/generated/samples/Robotics__Atmosphere__CIRA_86_Atmosphere.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).