Three Axis Inertial Measurement Unit — Robotics/Navigation Sensors
Robotics/Navigation_Sensors/Three_Axis_Inertial_Measurement_Unit · 5 input / 2 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 Inertial Measurement Unit
Robotics / Navigation Sensors
A Three-axis Accelerometer and a Three-axis Gyroscope in one block, sharing one location, one update rate and one set of inputs. The accelerometer reads the specific force at the IMU location; the gyroscope reads the body rates, its g-sensitive bias driven by the body acceleration in g.
d = [1 −1 1] · (CG − location)
A = (Ab − g) + ω × (ω × d) + ω̇
× d
Ameas = sata( Ha( SFCCa · A +
biasa ) )
ωmeas = satg( Hg( SFCCg ·
ω + biasg + gs · Ab / g0 ) ),
with each H(s) = ωn² / (s² + 2ζωns +
ωn²) on each axis and g0 the standard gravity in the
chosen units.
Ports
- Ab – Ab, the acceleration of the CG in body axes, a [3,1] column. It also drives the gyroscope's g-sensitive bias.
- w – ω, the body angular rates p, q, r in rad/s, a [3,1] column.
- dw/dt – ω̇, the body angular accelerations in rad/s², a [3,1] column.
- CG – the centre of gravity, a [3,1] column in the axes and units of the IMU Location: station (positive aft), buttline (positive right), waterline (positive up).
- g – the gravity vector in body axes, a [3,1] column, subtracted by the accelerometer.
- A_meas – the measured acceleration, always a [3,1] column.
- w_meas – the measured body rates, always a [3,1] column.
The port order is the Simulink block's own. Every input must be a [3,1] column.
Parameters
- Units – the unit system of the accelerations, and here it moves one number:
the standard gravity g0 the gyroscope's g-sensitive term divides by.
- Metric (MKS) – m/s², g0 = 9.80665 (default).
- English – ft/s², g0 = 9.80665 / 0.3048.
- IMU Location – where the IMU sits, three numbers in the station/buttline/waterline axes the CG port uses. Default [0 0 0].
- Update Rate (s) – how both sensors' dynamics are realized, and the
Simulink block's own "Update rate":
- 0 (default) – continuous. Under a continuous solver the responses are integrated as they stand; when the block is stepped – the discrete solver, and every code export – each 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 – discrete sensors updating every that many seconds, with the Tustin (bilinear, unwarped) discretization – 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.
- Accelerometer Second-order Dynamics – on (default) passes each accelerometer axis through Ha; off makes it instantaneous.
- Accelerometer Natural Frequency (rad/s) – ωn of Ha, greater than zero. Default 190.
- Accelerometer Damping Ratio – ζ of Ha, zero or more. Default 0.707.
- Accelerometer Scale Factors and Cross-coupling – the [3,3] matrix SFCCa; the identity (default) is a perfect sensor.
- Accelerometer Measurement Bias – three numbers added before the dynamics. Default [0 0 0].
- Accelerometer Lower and Upper Output Limits – six numbers, three lower then
three upper, applied last;
-inf/inf(default) mean no limit. - Gyro Second-order Dynamics – on (default) passes each gyroscope axis through Hg; off makes it instantaneous.
- Gyro Natural Frequency (rad/s) – ωn of Hg, greater than zero. Default 190.
- Gyro Damping Ratio – ζ of Hg, zero or more. Default 0.707.
- Gyro Scale Factors and Cross-coupling – the [3,3] matrix SFCCg. Default the identity.
- Gyro Measurement Bias – three numbers added before the dynamics. Default [0 0 0].
- G-sensitive Bias – gs, three numbers in rate per g, each multiplying its own axis of Ab / g0. Default [0 0 0].
- Gyro Lower and Upper Output Limits – six numbers, three lower then three
upper, applied last;
-inf/inf(default) mean no limit. - Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.
Each lower limit must not exceed its upper one.
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
sensors' response the sections' poles sit close to z = 1, where Q16.16 coefficients lose
the filters' 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
Inertial Measurement Unit (the library path carries a newline after "Inertial").
Units ↔ units (Metric (MKS)/English, 1:1), IMU Location ↔
imu, Update Rate (s) ↔ i_Ts, Accelerometer Second-order
Dynamics ↔ dtype_a (on/off, 1:1), Accelerometer Natural Frequency (rad/s)
↔ w_a, Accelerometer Damping Ratio ↔ z_a, Accelerometer
Scale Factors and Cross-coupling ↔ a_sf_cc, Accelerometer Measurement Bias
↔ a_bias, Accelerometer Lower and Upper Output Limits ↔
a_sat, Gyro Second-order Dynamics ↔ dtype_g (on/off, 1:1),
Gyro Natural Frequency (rad/s) ↔ w_g, Gyro Damping Ratio ↔
z_g, Gyro Scale Factors and Cross-coupling ↔ g_sf_cc, Gyro
Measurement Bias ↔ g_bias, G-sensitive Bias ↔ g_sens,
Gyro Lower and Upper Output Limits ↔ g_sat, the numbers passing through
unchanged.
i_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
i_Ts instead – which is not the same thing: a rate of −1 in
i_Ts makes both of the Simulink block's filters diverge.
Notes
- Stateful with either sensor's dynamics on: two states per axis per sensor, starting at zero. With Update Rate (s) at 0 a sensor with dynamics has no direct feedthrough; with a positive rate, or with its dynamics off, it does.
- The gyroscope's g-sensitive bias sees Ab, not the specific force: no gravity and no lever arm reach it, exactly as in the Simulink block.
- 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.
- Nonlinear – the lever-arm terms are products of the rates, and the limits clamp – so the block carries no state space and model reduction reports it as unmergeable.
Code facts#
| Fact | Value |
|---|---|
| registered type | Robotics/Navigation_Sensors/Three_Axis_Inertial_Measurement_Unit |
| family | Robotics/Navigation_Sensors |
| solver environment class | ICoreBlock_0_Robotics_1_Navigation_Sensors_2_Three_Axis_Inertial_Measurement_Unit |
| source | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Navigation_Sensors/Three_Axis_Inertial_Measurement_Unit/ICoreBlock_0_Robotics_1_Navigation_Sensors_2_Three_Axis_Inertial_Measurement_Unit.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Navigation_Sensors/Three_Axis_Inertial_Measurement_Unit/ICoreBlock_0_Robotics_1_Navigation_Sensors_2_Three_Axis_Inertial_Measurement_Unit.h |
| default size on canvas | 150 × 150 px |
| ports at insert | 5 in, 2 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 | Ab |
| 2 | in | ICoreDouble | w |
| 3 | in | ICoreDouble | dw/dt |
| 4 | in | ICoreDouble | CG |
| 5 | in | ICoreDouble | g |
| 6 | out | ICoreDouble | A_meas |
| 7 | 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 |
|---|---|---|
Units | Metric (MKS)%~%English~~Metric (MKS) | units |
IMU Location | [0 0 0] | imu |
Update Rate (s) | 0 | i_Ts |
Accelerometer Second-order Dynamics | on%~%off~~on | dtype_a |
Accelerometer Natural Frequency (rad/s) | 190 | w_a |
Accelerometer Damping Ratio | 0.707 | z_a |
Accelerometer Scale Factors and Cross-coupling | [1 0 0; 0 1 0; 0 0 1] | a_sf_cc |
Accelerometer Measurement Bias | [0 0 0] | a_bias |
Accelerometer Lower and Upper Output Limits | [-inf -inf -inf inf inf inf] | a_sat |
Gyro Second-order Dynamics | on%~%off~~on | dtype_g |
Gyro Natural Frequency (rad/s) | 190 | w_g |
Gyro Damping Ratio | 0.707 | z_g |
Gyro Scale Factors and Cross-coupling | [1 0 0; 0 1 0; 0 0 1] | g_sf_cc |
Gyro Measurement Bias | [0 0 0] | g_bias |
G-sensitive Bias | [0 0 0] | g_sens |
Gyro 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 Inertial\nMeasurement Unit |
| port-count rule | PortsParam::None |
SampleTime parameter | no — the counterpart defines none; the rate stays on the ICore side |
| always set | i_rand = off |
| ICore config | Simulink parameter | Value translation |
|---|---|---|
Units | units | Metric (MKS) → Metric (MKS), English → English |
IMU Location | imu | passes through |
Update Rate (s) | i_Ts | passes through |
Accelerometer Second-order Dynamics | dtype_a | on → on, off → off |
Accelerometer Natural Frequency (rad/s) | w_a | passes through |
Accelerometer Damping Ratio | z_a | passes through |
Accelerometer Scale Factors and Cross-coupling | a_sf_cc | passes through |
Accelerometer Measurement Bias | a_bias | passes through |
Accelerometer Lower and Upper Output Limits | a_sat | passes through |
Gyro Second-order Dynamics | dtype_g | on → on, off → off |
Gyro Natural Frequency (rad/s) | w_g | passes through |
Gyro Damping Ratio | z_g | passes through |
Gyro Scale Factors and Cross-coupling | g_sf_cc | passes through |
Gyro Measurement Bias | g_bias | passes through |
G-sensitive Bias | g_sens | passes through |
Gyro Lower and Upper Output Limits | g_sat | passes through |
Caveat (shown to the user): the noise is not modelled, so 'Noise on' (i_rand) is pinned off and its seeds and powers do not cross. 'units' is live on this block only through the g0 the gyroscope's g-sensitive term divides by. The block has no SampleTime: its rate crosses as i_Ts, where 0 is continuous and a positive value is a Tustin update rate. The library path carries an embedded newline after 'Inertial'
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 Inertial Measurement Unit -- the accelerometer and the gyroscope in one block A_meas = saturate( H_a( SFCC_a * A + bias_a ) ), A = ((Ab - g) + w x (w x d)) + dw/dt x d w_meas = saturate( H_g( (SFCC_g * w + bias_g) + (Ab / g0) .* gsens ) )
MEASURED AGAINST R2026a: the IMU's masked subsystem holds a Three-axis Accelerometer, a Three-axis Gyroscope and an "Acceleration Conversion" Unit Conversion, with the IMU's own parameters passed down (location -> acc, i_Ts -> both rates, i_seeds/i_pow split 3 + 3). Simulated against references built from that wiring: 2.0e-14 on A_meas, 2.2e-15 on w_meas.
What the wiring says, each measured:
- The gyroscope's G port is fed the BODY acceleration Ab through the Unit Conversion --
not the specific force the accelerometer senses, and no lever arm. Its divisor is g0 = 9.80665 in metric (2.2e-15) and 9.80665/0.3048 = 32.174048556... in English (2.3e-15; the rounded 32.174049 is out by 8e-11, the metric g0 by 1.3e-2).
- "Units" changes NOTHING ELSE: the accelerometer output is identical in both.
- i_Ts = -1 diverges exactly as the two sensors' rates do (3.5e25 on A_meas, 6.4e18 on
w_meas in 500 samples), so the rate crosses as "Update Rate (s)", never as SampleTime -- which this mask does not define (set_param refuses it, measured).
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_Inertial_Measurement_Unit.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).