Generated reference › Geodetic To Geocentric Latitude — Robotics/Axes Transformations
kind: generated#block#robotics-axes-transformations

Geodetic To Geocentric Latitude — Robotics/Axes Transformations

φ λ

Robotics/Axes_Transformations/Geodetic_To_Geocentric_Latitude · 2 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.

Geodetic To Geocentric Latitude

Robotics / Axes Transformations

Converts the geodetic latitude a map uses – the angle between the equatorial plane and the ellipsoid's surface normal – into the geocentric latitude, the angle at the planet's centre. With e² = f(2−f):

  • N = R / √(1 − e²·sin²φ), the prime vertical radius of curvature
  • ρ = (N + h)·cosφ, the distance from the spin axis
  • z = (N(1−e²) + h)·sinφ, the height above the equatorial plane
  • λ = atan2(z, ρ)

The two definitions differ because an ellipsoid's surface normal does not point at its centre. On Earth the gap peaks near 45° at about 0.19°, and it is exactly zero at the equator and at the poles. Its inverse is Geocentric To Geodetic Latitude.

Ports

  • gd – the geodetic latitude, in DEGREES. Any size [m,n]; the block works entry by entry.
  • h – the altitude above the ellipsoid, in R's length unit. The same size as gd – there is no scalar expansion here, because a latitude and an altitude are a position rather than a signal, and a broadcast would more often be a mistake than a convenience.
  • gc – the geocentric latitude, in DEGREES. Same size as the inputs.

Parameters

  • Flattening – the ellipsoid's flattening f, a dimensionless scalar. Defaults to 0.0033528106647474805, which is WGS84's 1/298.257223563. Zero gives a sphere, on which the two latitudes are equal at every point. A value of exactly 1 is refused: it is a degenerate ellipsoid with no polar extent.
  • Equatorial Radius – the ellipsoid's equatorial radius R, a scalar. Defaults to WGS84's 6378137 metres, and its unit is the unit h is read in.
  • 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.

R and e² are baked into the arithmetic at export time rather than exposed as tunables: they say which planet this is, which is structure and not a knob. Both are printed at 17 significant digits, so every backend computes the same double.

The three hardware targets are simulation-only: a sine, a square root, a division and an arctangent have no Q16.16 form, so values convert at the port boundary and the arithmetic runs in floating point. And a fixed-point port cannot carry an Earth-sized radius or altitude at all – Q16.16 saturates past about 32767 – so a hardware export of this block is for a small custom body, or for lengths expressed in a larger unit. PLC Structured Text has no ATAN2 in IEC 61131-3, so it is rebuilt from ATAN with the quadrant tests written out.

Simulink bridge

Import and export, mapped to Aerospace Blockset's aerolibtransform2/Geodetic to Geocentric Latitude. Flattening → F and Equatorial Radius → R, values passing straight through.

Three Simulink parameters are always implied and carry no configuration here: ptype is always Custom, units always Metric (MKS), and outputRadius always off. Custom is not cosmetic – a block left on its Earth (WGS84) setting accepts and discards a written F or R, so the pair only takes effect alongside it, and Custom carrying the WGS84 numbers is bit-identical to the Earth setting. outputRadius would add a second output port carrying the radius to the point; this block has one output, so it is pinned off. The Simulink block defines no SampleTime, so the rate stays on the ICore side.

Notes

  • Algebraic and stateless: the output depends on this sample alone.
  • Not linear, so the block carries no state space and model reduction correctly reports it as unmergeable.
  • Nothing checks that h and R share a unit. Feed metres against an R in feet and the answer is still a latitude, wrong by an amount no diagnostic can see.
  • Verified against R2026a: over 200 random latitude/altitude pairs the arrangement above reproduces the Simulink block in all 200 samples to the last bit. Driven end to end through the parity rig – where the exported MATLAB core meets Simulink's own Gain shapers rather than a transcription of the formula – the two agree to 7.1×10−15 degrees.

Code facts#

FactValue
registered typeRobotics/Axes_Transformations/Geodetic_To_Geocentric_Latitude
familyRobotics/Axes_Transformations
solver environment classICoreBlock_0_Robotics_1_Axes_Transformations_2_Geodetic_To_Geocentric_Latitude
sourcesrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Axes_Transformations/Geodetic_To_Geocentric_Latitude/ICoreBlock_0_Robotics_1_Axes_Transformations_2_Geodetic_To_Geocentric_Latitude.cpp
headersrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Axes_Transformations/Geodetic_To_Geocentric_Latitude/ICoreBlock_0_Robotics_1_Axes_Transformations_2_Geodetic_To_Geocentric_Latitude.h
default size on canvas150 × 78 px
ports at insert2 in, 1 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDoublegd
2inICoreDoubleh
3outICoreDoublegc

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
FlatteninggFmt(WGS84_F)—
Equatorial RadiusgFmt(WGS84_R)—

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 pathaerolibtransform2/Geodetic to \nGeocentric Latitude
port-count rulePortsParam::None
SampleTime parameterno — the counterpart defines none; the rate stays on the ICore side
always setptype = Custom, units = Metric (MKS), outputRadius = off
ICore configSimulink parameterValue translation
CONFIG_F.c_str()Fpasses through
CONFIG_R.c_str()Rpasses through

Caveat (shown to the user): both latitudes are in DEGREES and the altitude carries R's length unit. 'ptype' is always written as Custom, because a block left on Earth (WGS84) accepts a written F or R and discards it -- Custom carrying the WGS84 numbers is bit-identical to the Earth setting, so nothing is lost. 'outputRadius' is always off: switching it on adds a SECOND output port carrying the radius to the point, and this block has one output. 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 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 2 Simulink params rule(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).

Geodetic To Geocentric Latitude -- the map latitude to the angle at the planet's centre e2 = f * (2 - f) N = R / sqrt(1 - e2 * sin(gd)^2) rho = (N + h) * cos(gd) z = (N * (1 - e2) + h) * sin(gd) gc = atan2(z, rho)

Both latitudes in DEGREES, as the Aerospace Blockset block takes them; the altitude carries R's length unit. The two definitions differ because the surface normal of an ellipsoid does not point at its centre -- on Earth the gap peaks near 45 degrees at about 0.19 degrees, and it vanishes at the equator and at the poles.

⚠ THE ARRANGEMENT ABOVE WAS MEASURED, NOT DERIVED. Over 200 random (latitude, altitude) pairs it reproduces R2026a's block in all 200 samples TO THE LAST BIT. An algebraically identical spelling does not: gd * 0.017453292519943295 in place of gd * pi / 180 moves 74 of the 200 by one unit in the last place, and the same on the way out. Every backend therefore writes both conversions the same way round, and this is why the two blocks of this family differ on the point -- ECEF To NED's Simulink counterpart really does multiply by a pre-divided slope, and this one really does not.

⚠ THE TWO CONSTANTS ARE STRUCTURE, NOT TUNING. R and f say which planet this is, so they are baked into every export rather than exposed as tunable parameters.

ALGEBRAIC and STATELESS, and nonlinear in its input, so no state space.

Sample results#

Geodetic To Geocentric Latitude — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sampleGeodetic To Geocentric Latitude — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample-202012345t (s)in ICoreDouble-Out-0in ICoreDouble-Out-0out ICoreDouble-Out-0
tin ICoreDouble-Out-0in ICoreDouble-Out-0out ICoreDouble-Out-0
0-2-2-1.987
0.40.50.50.4967
0.8-2-2-1.987
1.20.50.50.4967
1.6-2-2-1.987
20.50.50.4967
2.4-2-2-1.987
2.80.50.50.4967
3.2-2-2-1.987
3.60.50.50.4967
4-2-2-1.987
4.40.50.50.4967
4.8-2-2-1.987
5.20.50.50.4967

Every 4th of 60 samples, from the table stimulus.

The same rig also ran:

StimulusWhat it isOutput range
impulseImpulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair)0 … 0.9933
rampRamp: slope 1 from t = 00 … 5.761
sineSine Wave: amplitude 1, 2 rad/s, no phase, no bias-0.9933 … 0.9929
stepStep: 0 -> 1 at t = 1 s0 … 0.9933

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 d541288cd5ad49da343fa0a3f9debc142164f671 · produced by docsSample --out <folder> --blocks Geodetic_To_Geocentric_Latitude Geocentric_To_Geodetic_Latitude --steps 60 · data docs/generated/samples/Robotics__Axes_Transformations__Geodetic_To_Geocentric_Latitude.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).