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

ECI To ECEF Rotation Matrix — Robotics/Axes Transformations

i e

Robotics/Axes_Transformations/ECI_To_ECEF_Rotation_Matrix · 5 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.

ECI To ECEF Rotation Matrix

Robotics / Axes Transformations

The direction cosine matrix that takes a vector from the Earth-centred inertial frame to the Earth-centred, Earth-fixed one at a given moment, by the IAU-2000/2006 (CIO based) reduction:

  • DCM = W·R·Q
  • W – polar motion, from the TIO locator s′ = −47µas·t and the two crust angles xp, yp
  • R – Earth rotation, the Earth rotation angle θ = 2π(f + 0.77905727 + 0.0027378119·d) in UT1 days d with fractional part f
  • Q – the celestial motion of the Celestial Intermediate Pole: the P03 precession polynomials for X, Y and s, plus the full 2941-term series of the IERS Conventions (2010) – 1600 terms for X, 1275 for Y and 66 for s, each a sine and a cosine of a small integer combination of fourteen fundamental arguments

The date is a parameter and only a time increment arrives on a port, in the unit Time Increment names, so a run sweeps time from the configured instant.

Ports

  • dUT1 – UT1 − UTC in seconds, a scalar [1,1]. It moves the Earth rotation angle and nothing else.
  • dAT – TAI − UTC in seconds, a scalar [1,1]. It moves terrestrial time, and so the precession and the series, and not the rotation.
  • xp_yp – polar motion along x and y in radians, one [2,1].
  • dX_dY – the measured offsets of the Celestial Intermediate Pole, ΔX and ΔY, in radians, one [2,1]. They are added to the series' X and Y.
  • dt – the time increment added to the configured date, a scalar [1,1] in the unit Time Increment names. It may be fractional.
  • DCM – the rotation, one [3,3].

Parameters

  • Reduction – which reduction to run:
    • IAU-2000/2006 (the default) – the CIO based reduction, the one this block computes.
    • IAU-76/FK5 – refused, with the reason: that reduction reads its nutation angles from the JPL DE405 ephemeris, a data file that ships in a separate data package rather than in the toolbox, so it cannot be reproduced from anything in this tree. Selecting it stops the run.
  • Year – a whole number of 1 or more; a fractional year is truncated. Defaults to 2013, as the Simulink block's does.
  • Month – January to December. Defaults to January.
  • Day – the day of the month, a whole number from 1 to 31. Defaults to 1.
  • Hour – 0 to 24; a fractional hour is truncated. Defaults to 0.
  • Minutes – 0 to 60; a fractional minute is truncated. Defaults to 0.
  • Seconds – 0 to 60, fractions kept. Defaults to 0.
  • Time Increment – the unit of the dt port, and so the field it is added to: Day (the default), Hour, Min or Sec.
  • 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 target carries the whole series: 18768 integers, which is the 2941 terms stored as an amplitude pair in hundredths of a microarcsecond plus one integer per nonzero multiplier. That is what makes the ten cores agree with each other to a part in 1016 and with the reference implementation exactly, and it is also why a generated program for this block is a few hundred kilobytes and evaluates 2941 sines and cosines per sample. Nothing about the series is tunable: it is the table, and it is inlined rather than exposed as a parameter.

The three hardware targets are simulation-only real arithmetic. The matrix itself fits a Q16.16 port comfortably – every entry is within ±1 – but the arithmetic behind it spans from 2×109 microarcseconds down to 10−2, which a fixed-point datapath cannot hold, so the body runs in floating point and quantizes only at the port. One consequence is worth stating: a Q16.16 port quantum is 1.5×10−5, which on the dX_dY and xp_yp ports is larger than the real measured offsets they carry – a hardware export of this block is exact about the rotation and blind to the sub-milliarcsecond corrections.

Simulink bridge

Import and export, mapped to Aerospace Blockset's aerolibtransform2/Direction Cosine Matrix ECI to ECEF (a library path drawn on two lines, so it carries an embedded newline). Reduction → red, Year → year, Month → month, Day → day, Hour → hour, Minutes → min, Seconds → sec and Time Increment → deltaT, every combo 1:1.

Three Simulink parameters are always implied and carry no configuration here. extraparamflag is always on: that is what gives the Simulink block the four correction ports this block always has, and with it off it has one port and reads every correction as zero – which is what feeding zeros here does. errorflag is always None: this block never stops a run over the increment's range. Simulink's fifth increment value, None, is not offered – it removes that block's input port, and a port list here is fixed. The Simulink block defines no SampleTime parameter, so the rate stays on the ICore side.

Notes

  • Algebraic and stateless: the output depends only on this sample's inputs and the configured date.
  • Not linear, so the block carries no state space and model reduction correctly reports it as unmergeable.
  • The two reductions do not agree with each other, and neither is an approximation of the other: they differ by about 10−8 radians in the modern era. Reporting a refusal rather than substituting the one that is available is the point.
  • The Gregorian rule is applied to every year, before 1582 included, exactly as the Simulink block does.

Code facts#

FactValue
registered typeRobotics/Axes_Transformations/ECI_To_ECEF_Rotation_Matrix
familyRobotics/Axes_Transformations
solver environment classICoreBlock_0_Robotics_1_Axes_Transformations_2_ECI_To_ECEF_Rotation_Matrix
sourcesrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Axes_Transformations/ECI_To_ECEF_Rotation_Matrix/ICoreBlock_0_Robotics_1_Axes_Transformations_2_ECI_To_ECEF_Rotation_Matrix.cpp
headersrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Axes_Transformations/ECI_To_ECEF_Rotation_Matrix/ICoreBlock_0_Robotics_1_Axes_Transformations_2_ECI_To_ECEF_Rotation_Matrix.h
default size on canvas170 × 120 px
ports at insert5 in, 1 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDoubledUT1
2inICoreDoubledAT
3inICoreDoublexp_yp
4inICoreDoubledX_dY
5inICoreDoubledt
6outICoreDoubleDCM

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
Reductionstd::string(RED_FK5)%~%RED_2000~~RED_2000—
Year2013—
MonthmonthCombo()—
Day1—
Hour0—
Minutes0—
Seconds0—
Time IncrementDay%~%Hour%~%Min%~%Sec~~Day—

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\nECI to ECEF
port-count rulePortsParam::None
SampleTime parameterno — the counterpart defines none; the rate stays on the ICore side
always seterrorflag = None, extraparamflag = on
ICore configSimulink parameterValue translation
CONFIG_RED.c_str()redRED_2000 → RED_2000, RED_FK5 → RED_FK5
CONFIG_YEAR.c_str()yearpasses through
CONFIG_MONTH.c_str()monthpasses through
CONFIG_DAY.c_str()daypasses through
CONFIG_HOUR.c_str()hourpasses through
CONFIG_MIN.c_str()minpasses through
CONFIG_SEC.c_str()secpasses through
CONFIG_INC.c_str()deltaTDay → Day, Hour → Hour, Min → Min, Sec → Sec

Caveat (shown to the user): the five input ports mirror the Simulink block's, in its order: dUT1, dAT, the polar motion pair, the pole offset pair and the time increment. 'extraparamflag' is always written as on, which is what gives the Simulink block those four correction ports; with it off it has one, and reading every correction as zero is what feeding zeros here does. 'errorflag' is always None: this block never stops a run over the increment's range. Simulink's deltaT value 'None' removes the input port and is not offered. The Simulink block has no SampleTime parameter, so the rate stays on the ICore side. ⚠ 'Reduction' crosses both ways but only IAU-2000/2006 RUNS: IAU-76/FK5 reads its nutation angles from the JPL DE405 ephemeris, which ships in a separate data package rather than in the toolbox, so an imported model that selects it is carried faithfully and refused at run time with that reason

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 8 Simulink params rule(s) this tool cannot resolve
  • 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).

ECI To ECEF Rotation Matrix -- the inertial frame to the planet-fixed one, at a moment DCM = W(t) * R(t) * Q(t)

W polar motion: the TIO locator (a straight line in time) and the two crust angles R Earth rotation: the Earth rotation angle, a straight line in UT1 days modulo a turn Q the celestial motion of the Celestial Intermediate Pole: the P03 precession polynomials plus the full X, Y and S series of the IERS Conventions (2010)

The date is configured and a time INCREMENT arrives on a port, in the unit the configuration names -- the same arrangement Julian Date Conversion has, through the same masked subsystem, so the whole-day part of the calendar folds to one constant at export time.

⚠ ONE REDUCTION IS SHIPPED AND THE OTHER IS REFUSED BY NAME. IAU-2000/2006 is analytic: its 2941 series terms are numbers, they are in this tree, and they are carried whole in all ten targets. IAU-76/FK5 is not: it reads its nutation angles out of the JPL DE405 ephemeris, a data file that ships in a separate data package. Selecting it stops the run with that sentence rather than answering something that resembles a rotation.

⚠ WHAT EACH SUITE CAN AND CANNOT SEE, because the two answer different questions here. The matrix's entries are of order 1 and the series moves them by at most 3.3e-5, so the export comparison's own band (0.1 % of the peak) cannot tell a dropped series from a kept one -- what tells them apart is the residual it MEASURES, which sits at 1e-16 when the ten backends really do share the table. The Simulink parity run is the instrument for the series itself: at 1e-12 it is thirty million times finer than the smallest thing the series does.

ALGEBRAIC and STATELESS: everything happens inside one sample.

Sample results#

No stimulus produced a sampled output in this rig — Invalid input size at ECI To ECEF Rotation Matrix block: ICore Blocks/Home/ECI To ECEF 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 875fdbf564cf31a145283edf6a75dc1d64d1090a · produced by docsSample --out <folder> --blocks Wigner_Ville_Distribution Cross_Wigner_Ville_Distribution Inverse_STFT Fourier_Synchrosqueezed_Transform Time_Frequency_Ridges Frequency_Domain_Filter_Identification Fill_Gaps EOM_6DOF_ECEF_Quaternion EOM_6DOF_Custom_Variable_Mass_ECEF_Quaternion EOM_6DOF_Simple_Variable_Mass_ECEF_Quaternion ECI_To_ECEF_Rotation_Matrix ECI_Position_To_LLA LLA_To_ECI_Position ECI_Position_To_AER --steps 60

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