Three Axis Gyroscope — Robotics/Navigation Sensors
Robotics/Navigation_Sensors/Three_Axis_Gyroscope · 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.
Three-axis Gyroscope
Robotics / Navigation Sensors
What a three-axis rate gyroscope reads: the body angular rates, passed through a scale-factor and cross-coupling matrix, a bias, a g-sensitive bias driven by the acceleration the sensor feels, an optional second-order sensor response and output limits.
ωmeas = sat( H( SFCC · ω + bias + gs · G ) ), the g-sensitive term taken entry by entry, with H(s) = ωn² / (s² + 2ζωns + ωn²) on each axis
Ports
- w – ω, the body angular rates p, q, r in rad/s, a [3,1] column.
- G – the acceleration the sensor feels, in g, a [3,1] column; it reaches the output only through the G-sensitive Bias.
- w_meas – ωmeas, the measured rates, always a [3,1] column.
The port order is the Simulink block's own. Both inputs must be [3,1] columns.
Parameters
- Second-order Dynamics – whether the sensor has a response:
- on – each axis passes through H(s) above (default).
- off – the sensor is instantaneous: ωmeas = sat(SFCC · ω + bias + gs · G).
- Natural Frequency (rad/s) – ωn, a scalar greater than zero. Default 190.
- Damping Ratio – ζ, a scalar of zero or more. Default 0.707.
- Scale Factors and Cross-coupling – the [3,3] matrix SFCC. The identity (default) is a perfect sensor; the diagonal holds the scale factors and the off-diagonal entries the cross-axis sensitivities.
- Measurement Bias – three numbers added after the matrix and before the dynamics. Default [0 0 0].
- G-sensitive Bias – gs, three numbers in rate per g, each multiplying its own entry of G and added before the dynamics. Default [0 0 0], which makes the G port inert.
- Update Rate (s) – how the dynamics are realized, and the Simulink block's
own "Update rate":
- 0 (default) – continuous. Under a continuous solver the response is integrated as it stands; when the block is stepped – the discrete solver, and every code export – it is the exact zero-order-hold discretization at the block's period, which is what the continuous sensor computes from inputs that hold across each sample.
- greater than 0 – a discrete sensor updating every that many seconds, with the Tustin (bilinear, unwarped) discretization of H(s) – exactly what the Simulink block builds for a positive rate. The block then runs at its own period, which must be this same value: set Sampling Time (s) to it, or leave that at zero with the model's sampling time equal to it. A mismatch is reported and stops the run.
- Lower and Upper Output Limits – six numbers, the three lower limits then
the three upper ones, applied last.
-infandinf(default on all six) mean no limit. Each lower limit must not exceed its upper one. - 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 parameter is baked in at export time, and so is the discretization: the section coefficients are computed for the block's period (or its update rate) and printed at full precision. All ten are rendered from the one description of the arithmetic the block's own simulation runs, so they perform the same operations in the same order.
The three HDL targets are simulation-only: they carry the whole model in
real arithmetic and quantize only at the ports. At a period short against the
sensor's response the section's poles sit close to z = 1, where Q16.16 coefficients lose
the filter's DC gain, and the default limits are infinite, which fixed point cannot hold.
VHDL keeps the arithmetic in a function of its own, called once per value it returns.
Simulink bridge
Import and export, mapped to Aerospace Blockset's
aerolibnav/Three-axis Gyroscope. Second-order Dynamics ↔
dtype_g (on/off, 1:1), Natural Frequency (rad/s) ↔ w_g,
Damping Ratio ↔ z_g, Scale Factors and Cross-coupling ↔
g_sf_cc, Measurement Bias ↔ g_bias, G-sensitive Bias ↔
g_sen, Update Rate (s) ↔ g_Ts, Lower and Upper Output Limits
↔ g_sat, all passing their values through unchanged.
g_rand ("Noise on") is always off (see Notes); a model
importing it on is reported rather than silently changed. The block has no
SampleTime, so Sampling Time (s) stays on the ICore side and the rate crosses as
g_Ts instead – which is not the same thing: a rate of −1 in
g_Ts makes the Simulink block's filter diverge.
Notes
- Stateful with the dynamics on: two states per axis, starting at zero. With Update Rate (s) at 0 the output has no direct feedthrough (it reads the response state); with a positive rate, or with the dynamics off, it does.
- No sensor noise. The Simulink block can add white noise from its own random number generator; no generated code can reproduce that sequence, so no test could confirm a noisy export, and the option is not offered. To model noise, add a Band-Limited White Noise per axis after this block – it lands after the output limits rather than before them.
- Linear in its inputs until the limits clamp, but the limits make it nonlinear, so the block carries no state space and model reduction reports it as unmergeable.
- The Three-axis Inertial Measurement Unit is this block and the Three-axis Accelerometer in one, with G taken from the body acceleration.
Code facts#
| Fact | Value |
|---|---|
| registered type | Robotics/Navigation_Sensors/Three_Axis_Gyroscope |
| family | Robotics/Navigation_Sensors |
| solver environment class | ICoreBlock_0_Robotics_1_Navigation_Sensors_2_Three_Axis_Gyroscope |
| source | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Navigation_Sensors/Three_Axis_Gyroscope/ICoreBlock_0_Robotics_1_Navigation_Sensors_2_Three_Axis_Gyroscope.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Navigation_Sensors/Three_Axis_Gyroscope/ICoreBlock_0_Robotics_1_Navigation_Sensors_2_Three_Axis_Gyroscope.h |
| default size on canvas | 150 × 90 px |
| ports at insert | 2 in, 1 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 | w |
| 2 | in | ICoreDouble | G |
| 3 | out | ICoreDouble | w_meas |
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 |
|---|---|---|
Second-order Dynamics | on%~%off~~on | dtype_g |
Natural Frequency (rad/s) | 190 | w_g |
Damping Ratio | 0.707 | z_g |
Scale Factors and Cross-coupling | [1 0 0; 0 1 0; 0 0 1] | g_sf_cc |
Measurement Bias | [0 0 0] | g_bias |
G-sensitive Bias | [0 0 0] | g_sen |
Update Rate (s) | 0 | g_Ts |
Lower and Upper Output Limits | [-inf -inf -inf inf inf inf] | g_sat |
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 | aerolibnav/Three-axis Gyroscope |
| port-count rule | PortsParam::None |
SampleTime parameter | no — the counterpart defines none; the rate stays on the ICore side |
| always set | g_rand = off |
| ICore config | Simulink parameter | Value translation |
|---|---|---|
Second-order Dynamics | dtype_g | on → on, off → off |
Natural Frequency (rad/s) | w_g | passes through |
Damping Ratio | z_g | passes through |
Scale Factors and Cross-coupling | g_sf_cc | passes through |
Measurement Bias | g_bias | passes through |
G-sensitive Bias | g_sen | passes through |
Update Rate (s) | g_Ts | passes through |
Lower and Upper Output Limits | g_sat | passes through |
Caveat (shown to the user): the noise is not modelled, so 'Noise on' (g_rand) is pinned off and its seeds and powers do not cross. The block has no SampleTime: its rate crosses as g_Ts, where 0 is continuous and a positive value is a Tustin update rate
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).
Three-axis Gyroscope -- body rates through the inertial sensors' error model w_meas = saturate( H( (SFCC * w + bias) + G .* gsens ) )
MEASURED AGAINST R2026a exactly as the accelerometer was: the masked subsystem's wiring read with find_system, then a reference built from that reading simulated against the real block -- 2.2e-15 with the dynamics on, EXACTLY 0 with them off, and the same reference with the g-sensitive bias negated is out by 0.50, so that term is being exercised.
What the wiring says:
- The mask's Sum4 is (SFCC * w + bias) + G .* gsens, the product taking G first, and all
of it goes through the second-order response; the limits come after.
- G is whatever acceleration the model feeds it, in g. The IMU feeds it the body
acceleration Ab converted to g; a stand-alone gyroscope takes it from its second port.
- "Update rate" behaves exactly as the accelerometer's: 0 is a continuous Second-Order
Integrator (9.5e-12 from its exact ZOH under ode45, measured), a positive rate is a Tustin Discrete Transfer Fcn, and -1 DIVERGES (3.3e16 in 500 samples).
- There is no "units" and no location: a rate is the same everywhere on a rigid body.
The noise is not modelled: see the description.
Sample results#
Plotted: vector — Sine Wave, [3,1]: amplitudes 1/2/3 at 2 rad/s (tried only because every scalar stimulus was refused)
Category dynamic · sample time 0.1 · 60 steps · commit 6280f52f3 · produced by docsSample --out <folder> --blocks Rational_Resample,Three_Axis_Accelerometer,Three_Axis_Gyroscope,Three_Axis_Inertial_Measurement_Unit,Eclipse_Shadow_Model,To_String,String_To_ASCII,ASCII_To_String,Substring,String_Constant,String_Concatenate,String_Compare,String_Length --steps 60 · data docs/generated/samples/Robotics__Navigation_Sensors__Three_Axis_Gyroscope.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).