EOM 3DOF Custom Variable Mass Body Axes — Robotics/Equations Of Motion
Robotics/Equations_Of_Motion/EOM_3DOF_Custom_Variable_Mass_Body_Axes · 6 input / 4 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.
EOM 3DOF Custom Variable Mass Body Axes
Robotics / Equations Of Motion
The longitudinal equations of motion of a rigid body whose mass and inertia are supplied on wires, carried in body axes. The mass m, the pitch inertia Iyy and its rate dIyy/dt arrive as inputs every sample; the block does not check that the inertia and its rate agree.
- u' = Fx/m − q·w − g·sin θ, w' = Fz/m + q·u + g·cos θ
- q' = (M − dIyy/dt·q)/Iyy, θ' = q
- xe' = u·cos θ + w·sin θ, ze' = −u·sin θ + w·cos θ
Ports
- Fx – the force along the body x axis, a scalar [1,1].
- Fz – the force along the body z axis (positive down), a scalar [1,1].
- M – the pitching moment about the centre of gravity, a scalar [1,1].
- m – the mass, a nonzero scalar [1,1].
- Iyy_dot – the rate of change of the pitch inertia, a scalar [1,1].
- Iyy – the pitch inertia, a nonzero scalar [1,1].
- theta – the pitch attitude θ in radians, [1,1].
- q – the pitch rate in rad/s, [1,1].
- Xe – the position [xe; ze] in the flat-earth frame, [2,1].
- Vb – the body velocity [u; w], [2,1].
Parameters
- Units – Metric (MKS) (the default) or English (velocity in ft/s). The two are the same arithmetic – the gravity is a parameter – so the choice only says which units the numbers are in.
- Initial Airspeed – V0, a scalar. Defaults to 100.
- Initial Pitch Attitude – θ0 in radians. Defaults to 0.
- Initial Body Rotation Rate – q0 in rad/s. Defaults to 0.
- Initial Incidence – α0 in radians: the initial body velocity is V0·[cos α0; sin α0]. Defaults to 0.
- Initial Position [x z] – the initial [xe ze], two values. Defaults to [0 0].
- Gravity – g, a scalar. Defaults to 9.81.
- Integration Substeps – M, how many fourth-order Runge-Kutta steps a sample is integrated with on the discrete solver and in exported code, a whole number of 1 or more. Defaults to 100. No Simulink counterpart.
- 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. A core holds the six states, publishes the outputs from them, and integrates one sample with the inputs held and M Runge-Kutta substeps – with M = 100, the same computation as Simulink's fixed-step ode4 at one hundredth of the sample time.
The three HDL targets are simulation-only real arithmetic, quantized at the port: a sine of a state has no Q16.16 form. The cores simulate correctly and are not offered as synthesizable.
Simulink bridge
Import and export, mapped to Aerospace Blockset's aerolib3dof2/Custom Variable Mass 3dof (Body Axes): Units → units (the two offered values 1:1), Initial Airspeed → v_ini, Initial Pitch Attitude → theta_ini, Initial Body Rotation Rate → q_ini, Initial Incidence → alpha_ini, Initial Position [x z] → pos_ini, Gravity → g. Always emitted with axes = Body, mtype = Custom Variable, g_in = Internal and vre_flag and mass_flag off: each of those moves that block's port list, and this block has one; mdot_flag moves none and is emitted at its default, on. The knots unit system is not offered – it converts velocities inside the integration – and an imported one is reported. "Sampling Time (s)" does not cross: the Simulink block is continuous and defines no SampleTime.
Notes
- Stateful, continuous and nonlinear: six continuous states. The outputs are states, so the block has no direct feedthrough and a loop through it is not an algebraic loop.
- The mass and the inertia divide, so neither wire may carry zero.
Code facts#
| Fact | Value |
|---|---|
| registered type | Robotics/Equations_Of_Motion/EOM_3DOF_Custom_Variable_Mass_Body_Axes |
| family | Robotics/Equations_Of_Motion |
| solver environment class | ICoreBlock_0_Robotics_1_Equations_Of_Motion_2_EOM_3DOF_Custom_Variable_Mass_Body_Axes |
| source | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Equations_Of_Motion/EOM_3DOF_Custom_Variable_Mass_Body_Axes/ICoreBlock_0_Robotics_1_Equations_Of_Motion_2_EOM_3DOF_Custom_Variable_Mass_Body_Axes.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Equations_Of_Motion/EOM_3DOF_Custom_Variable_Mass_Body_Axes/ICoreBlock_0_Robotics_1_Equations_Of_Motion_2_EOM_3DOF_Custom_Variable_Mass_Body_Axes.h |
| default size on canvas | 150 × 130 px |
| ports at insert | 6 in, 4 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 | Fx |
| 2 | in | ICoreDouble | Fz |
| 3 | in | ICoreDouble | M |
| 4 | in | ICoreDouble | m |
| 5 | in | ICoreDouble | Iyy_dot |
| 6 | in | ICoreDouble | Iyy |
| 7 | out | ICoreDouble | theta |
| 8 | out | ICoreDouble | q |
| 9 | out | ICoreDouble | Xe |
| 10 | out | ICoreDouble | Vb |
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 (velocity in ft/s)~~Metric (MKS) | units |
Initial Airspeed | 100 | v_ini |
Initial Pitch Attitude | 0 | theta_ini |
Initial Body Rotation Rate | 0 | q_ini |
Initial Incidence | 0 | alpha_ini |
Initial Position [x z] | [0 0] | pos_ini |
Gravity | 9.81 | g |
Integration Substeps | 100 | not crossed |
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 | aerolib3dof2/Custom Variable Mass 3dof (Body Axes) |
| port-count rule | PortsParam::None |
SampleTime parameter | no — the counterpart defines none; the rate stays on the ICore side |
| deliberately not crossed | Integration Substeps |
| always set | axes = Body, mtype = Custom Variable, g_in = Internal, vre_flag = off, mdot_flag = on, mass_flag = off |
| ICore config | Simulink parameter | Value translation |
|---|---|---|
Units | units | Metric (MKS) → Metric (MKS), English (velocity in ft/s) → English (velocity in ft/s) |
Initial Airspeed | v_ini | passes through |
Initial Pitch Attitude | theta_ini | passes through |
Initial Body Rotation Rate | q_ini | passes through |
Initial Incidence | alpha_ini | passes through |
Initial Position [x z] | pos_ini | passes through |
Gravity | g | passes through |
Caveat (shown to the user): aerolib3dof2/Custom Variable Mass 3dof (Body Axes) is continuous and has NO SampleTime parameter (verified against the R2026a block dialog). axes, mtype, g_in, vre_flag and mass_flag are pinned because each moves that block's port list (measured); mdot_flag moves none and is pinned at its measured default; the kts unit system is not offered because it converts velocities inside the integration; "Integration Substeps" is how this block integrates a sample and has no counterpart
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:
B0every 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).
Custom Variable Mass 3dof (Body Axes) -- longitudinal rigid-body equations of motion, custom variable mass State [u w q theta xe ze]. Inputs Fx, Fz, M and -- on WIRES -- the mass m, the inertia rate dIyy/dt and the inertia Iyy:
u' = (Fx/m - q*w) - g*sin(theta) w' = (Fz/m + q*u) + g*cos(theta) q' = (M - dIyy/dt*q)/Iyy theta' = q, and the two position rates
⚠ MEASURED AGAINST R2026a (a compiled EOM3DOFNoAccel block, so measured, not read): ode4 at 1e-4 for 0.5 s from a non-trivial state under constant, distinct inputs reproduces every output to the last printed digit. What the measurement settled:
- SIX inputs in the order Fx, Fz, M, m, dIyy/dt, Iyy. There is NO dm/dt input and no mass-flow
term in the force equations while vre_flag is off: the translational rates are the fixed-mass block's with m read off the wire, to the bit.
- The inertia rate enters only q': a constant inertia with a nonzero rate is accepted and
integrated as given -- the block does not check that the two wires agree.
- "Metric" and "English (velocity in ft/s)" are the same arithmetic; kts is not offered (it
converts velocities inside the integration). axes, mtype, g_in, vre_flag and mass_flag move the Simulink block's port list and are pinned; mdot_flag moves none and is pinned at its measured default.
A continuous block with a real derivative, like the fixed-mass pair; the discrete path and every exported core run ICoreEomRk4's map -- M RK4 substeps in ode4's association. At M = 100 that is Simulink's fixed-step ode4 at Ts/100, step for step.
Sample results#
No stimulus produced a sampled output in this rig — Joint integration produced a non-finite state at t = 0.100000 s. Reduce the step, or switch the stepping type to an implicit method.. 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 9a488f18c · produced by docsSample --out <folder> --blocks EOM_3DOF_Custom_Variable_Mass_Body_Axes EOM_3DOF_Custom_Variable_Mass_Wind_Axes EOM_3DOF_Simple_Variable_Mass_Body_Axes EOM_3DOF_Simple_Variable_Mass_Wind_Axes --steps 60
Sample data: docs/generated/samples/Robotics__Equations_Of_Motion__EOM_3DOF_Custom_Variable_Mass_Body_Axes.json