Generated reference › ECEF To NED Rotation Matrix — Robotics/Axes Transformations
kind: generated#block#robotics-axes-transformations

ECEF To NED Rotation Matrix — Robotics/Axes Transformations

Robotics/Axes_Transformations/ECEF_To_NED_Rotation_Matrix · 1 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.

ECEF To NED Rotation Matrix

Robotics / Axes Transformations

Builds the [3,3] direction cosine matrix that carries a vector from the Earth-centred Earth-fixed frame into the local north-east-down frame at a given geodetic latitude and longitude. Writing c and s for cosine and sine of the two angles in radians:

  • DCM00 = −cλ·sφ, DCM01 = −sλ·sφ, DCM02 = cφ
  • DCM10 = −sλ, DCM11 = cλ, DCM12 = 0
  • DCM20 = −cλ·cφ, DCM21 = −sλ·cφ, DCM22 = −sφ

with φ the latitude and λ the longitude. The rows are the north, east and down axes in turn.

Ports

  • latlon – the geodetic latitude and longitude in DEGREES, as a [2,1] column. Row 0 is the latitude, row 1 the longitude. Degrees rather than radians because that is what the Simulink block takes; the block converts internally. No range is enforced – a latitude past ±90 or a longitude past ±180 simply wraps, exactly as the Simulink block does.
  • DCM – the direction cosine matrix, [3,3]. Its size is fixed and does not follow the input's.

Parameters

  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.

There are no others: both angles arrive on the port, and the Earth model does not enter – the matrix depends on the two angles alone, not on the flattening or the radius.

Code export

All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text.

The degrees-to-radians factor is inlined into every export at 17 significant digits – it is not a tunable parameter, being part of the port contract rather than something to retune. The three hardware targets are simulation-only: the matrix needs four sines and cosines, and no fixed-point sine is available to a block body, so those exports convert at the port boundary and compute in floating point.

Simulink bridge

Import and export, mapped to Aerospace Blockset's aerolibtransform2/Direction Cosine Matrix ECEF to NED. That block has no dialog parameters at all – measured in R2026a – so nothing is mapped, and it defines no SampleTime either: the rate stays on the ICore side and a block given an explicit positive period reports that it did not cross.

Notes

  • Algebraic and stateless: the matrix depends on this sample alone.
  • Not linear, so the block carries no state space and model reduction correctly reports it as unmergeable.
  • Six of the nine entries carry a leading minus, and that is the price of a down third axis. The same matrix with a north-east-up sign pattern is orthogonal and plausible – and wrong.
  • Verified against R2026a: over 200 random in-range pairs, this block and the Simulink one agree in all 1800 entries to the last bit.

Code facts#

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

Ports#

#DirectionSignal typeDescription label
1inICoreDoublelatlon
2outICoreDoubleDCM

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#

No config variable beyond the Sampling Time (s) every block carries.

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/Direction Cosine Matrix\nECEF to NED
port-count rulePortsParam::None
SampleTime parameterno — the counterpart defines none; the rate stays on the ICore side

Caveat (shown to the user): the Aerospace Blockset block is a masked subsystem with no dialog parameters at all: latitude and longitude arrive on one port in DEGREES and the matrix leaves on one, so nothing but the signal crosses. It defines no SampleTime either, so an ICore rate set explicitly stays on this side and is reported

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 every 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).

ECEF To NED Rotation Matrix -- geodetic latitude and longitude to the [3,3] matrix that carries an Earth-centred Earth-fixed vector into the local north-east-down frame DCM = | -clo*sla -slo*sla cla | cla = cos(lat), sla = sin(lat) | -slo clo 0 | clo = cos(lon), slo = sin(lon) | -clo*cla -slo*cla -sla |

⚠ THE PORT CARRIES DEGREES, NOT RADIANS -- that is what the Simulink block takes, so it is what this one takes. Each row is multiplied by pi/180 on its way into the sine. The literal is printed at 17 significant digits and is bit-for-bit the slope MATLAB's convang uses, which is what lets the two agree exactly rather than approximately.

MEASURED: over 200 random in-range pairs the R2026a block answers this matrix in all 1800 entries to the LAST BIT. It carries no dialog parameters and no SampleTime.

⚠ THE MIDDLE ROW IS THE EAST AXIS AND ITS THIRD ENTRY IS AN EXACT ZERO -- east is horizontal by construction, whatever the latitude. Six of the nine entries carry a leading minus, which is the price of a DOWN third axis; the same matrix with a north-east-UP sign pattern is orthogonal, plausible and wrong.

⚠ IT COMPUTES RATHER THAN JUDGES. MATLAB's dcmecef2ned FUNCTION rejects a latitude past +/-90 or a longitude past +/-180; the BLOCK does not, and neither does this one -- measured at lat 95, lon 200, where the Simulink block answers an ordinary matrix. A caller who wants those bounds enforced should say so upstream.

Sample results#

No stimulus produced a sampled output in this rig — Invalid input size at ECEF To NED Rotation Matrix block: ICore Blocks/Home/ECEF To NED Rotation Matrix. 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 d60dae4fbffb95396a5d3d2dc3582537a193a262 · produced by docsSample --out <folder> --blocks Body_To_Wind_Rotation_Matrix Wind_Angles_To_Rotation_Matrix ECEF_To_NED_Rotation_Matrix --steps 60

Sample data: docs/generated/samples/Robotics__Axes_Transformations__ECEF_To_NED_Rotation_Matrix.json