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

Rotation Matrix To Alpha Beta — Robotics/Axes Transformations

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

Rotation Matrix To Alpha Beta

Robotics / Axes Transformations

Reads the two aerodynamic angles back out of the [3,3] body-to-wind direction cosine matrix they describe. It is the inverse of Body To Wind Rotation Matrix, whose forward form is

  • DCM00 = cosβ·cosα, DCM01 = sinβ, DCM02 = sinα·cosβ
  • DCM20 = −sinα, DCM21 = 0, DCM22 = cosα

so each angle comes straight back out of one entry, through an arcsine:

  • α = asin(−DCM20) – the incidence angle.
  • β = asin(DCM01) – the sideslip angle.

Two arcsines and no arctangent anywhere, which is what the Simulink block this mirrors does – measured by opening its mask, where a Reshape and a Selector of [3 4] feed two asin blocks. The arctangent form atan2(−DCM20, DCM22) that many references give is α as well on a genuine matrix, and on nothing else.

Ports

  • DCM – the body-to-wind matrix, [3,3]. The size is fixed.
  • ab – the two angles in radians, a [2,1] column [α; β], in the same order Body To Wind Rotation Matrix takes them. 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.

Code export

All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text. There is no tunable parameter, because the block has no parameter at all – the matrix arrives on a port.

On the three HDL targets the block is offered as simulation-only: a Q16.16 datapath has no inverse trigonometric function, so both arcsines go through real arithmetic and only the ports quantize.

Simulink bridge

Both directions, onto aerolibtransform2/Direction Cosine Matrix Body to Wind to Alpha and Beta in the Aerospace Blockset. Its two dialog parameters do not cross and are listed as ignored: action and tolerance select what the Simulink block does when the matrix is not orthonormal, and this block validates nothing.

The block's name is drawn on three lines, so the real library path carries two embedded newlines – after Matrix and after Wind. The flattened one-line spelling resolves to nothing, silently. And the block defines no SampleTime parameter, so the rate stays on this side and a block configured with an explicit positive rate reports that the rate did not cross.

The Simulink block returns the pair as a row; this one returns a column, as every vector port in this family does.

Notes

  • Algebraic, with no state: the output depends only on the current input.
  • Angles are radians, on this port and on both sides of the bridge. Note that its sibling ECEF To NED Rotation Matrix uses degrees – the two conventions sit side by side in this family because the Aerospace blocks they mirror do.
  • Both arcsine arguments are clamped to [−1, 1]. On an exact rotation matrix they are already inside it; the clamp is what keeps rounding at the boundary from producing NaN in six targets, a complex number in MATLAB and an aborted simulation in VHDL. The Simulink block clamps too – measured.
  • BOTH ANGLES ARE CONFINED TO [−90°, 90°], which is an arcsine's range. An incidence past a quarter turn comes back as its reflection rather than as itself. That is the reference's behaviour: an arctangent form would have returned the larger angle, and it is not what the Simulink block computes.
  • Orthonormality is not checked. The two formulas are evaluated on whatever arrives.
  • Deliberately no state space – the map is not linear.

Code facts#

FactValue
registered typeRobotics/Axes_Transformations/Rotation_Matrix_To_Alpha_Beta
familyRobotics/Axes_Transformations
solver environment classICoreBlock_0_Robotics_1_Axes_Transformations_2_Rotation_Matrix_To_Alpha_Beta
sourcesrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Axes_Transformations/Rotation_Matrix_To_Alpha_Beta/ICoreBlock_0_Robotics_1_Axes_Transformations_2_Rotation_Matrix_To_Alpha_Beta.cpp
headersrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Axes_Transformations/Rotation_Matrix_To_Alpha_Beta/ICoreBlock_0_Robotics_1_Axes_Transformations_2_Rotation_Matrix_To_Alpha_Beta.h
default size on canvas140 × 70 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
1inICoreDoubleDCM
2outICoreDoubleab

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\nBody to Wind\nto Alpha and Beta
port-count rulePortsParam::None
SampleTime parameterno — the counterpart defines none; the rate stays on the ICore side

Caveat (shown to the user): MEASURED 2026-09-10: the Simulink block's only dialog parameters are 'action' (None/Warning/Error) and 'tolerance', which decide what it does when the matrix is not orthonormal. Neither crosses: this block validates nothing. Its library path carries TWO embedded newlines, the name being drawn on three lines, and it returns the pair as a row where this block returns a column. It defines no SampleTime parameter: 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).

Rotation Matrix To Alpha Beta — the body-to-wind matrix back to its two aerodynamic angles alpha = asin(clamp(-DCM(2,0))) beta = asin(clamp( DCM(0,1)))

The inverse of Body_To_Wind_Rotation_Matrix, whose forward form is

DCM = | cb*ca sb sa*cb | | -sb*ca cb -sa*sb | | -sa 0 ca |

so -DCM(2,0) is sin(alpha) and DCM(0,1) is sin(beta), and both angles come straight back out of one entry each.

⚠⚠ TWO ARCSINES, AND NOT AN ARCTANGENT ANYWHERE - which is measured rather than chosen. The first version of this block took alpha from atan2(-DCM(2,0), DCM(2,2)), which is alpha as well on a genuine matrix and is what most references give. It failed parity at 0.503. Opening the Simulink mask settles it: a Reshape 3x3 -> 9 feeds a Selector of [3 4] - column-major, so DCM(2,0) and DCM(0,1) - into two Trigonometric Function blocks set to asin, with a Unary Minus on the first. MEASURED on the matrix [1.2 0.8 0.25; 1.5 0.5 1.3; 0.15 1.15 1.7]: the block answers -0.150568, which is asin(-0.15) exactly, where the arctangent form answers -0.088007. The two agree on every rotation matrix and on nothing else.

⚠ SO ALPHA IS CONFINED TO [-pi/2, pi/2], as beta is. An incidence past a quarter turn comes back as its reflection; the arctangent form would have returned it. That is the reference's behaviour, and the description says so.

⚠ ITS LIBRARY PATH CARRIES TWO EMBEDDED NEWLINES, not one: the block's name is drawn on three lines. The flattened spelling resolves to nothing, silently.

⚠ SIMULATION-ONLY on the three HDL targets: two arcsines.

Sample results#

No stimulus produced a sampled output in this rig — Invalid input size at Rotation Matrix To Alpha Beta block: ICore Blocks/Home/Rotation Matrix To Alpha Beta. 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 c29996956 · produced by docsSample --out <folder> --blocks Direction_Cosine_Matrix_To_Rotation_Angles Rotation_Matrix_To_Alpha_Beta Rotation_Matrix_To_Latitude_Longitude Rotation_Matrix_To_Wind_Angles --steps 60

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