Rotor — Robotics/Rotorcraft
Robotics/Rotorcraft/Rotor · 0 input / 0 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.
Rotor
Robotics / Rotorcraft
The thrust and torque a propeller or rotor of a given size produces at a given rotational speed and air density, as a force and a moment in body axes.
One rotor's thrust and torque, with kT = CT·R²·π·R² and kQ = −CQ·R³·π·R²:
- T = (kT·Ω²)·ρ, so thrust does not care which way the rotor turns
- Mz = ρ·(kQ·Ω·|Ω|), which does – a rotor spun backwards reverses its torque, and that is how a quadcopter's counter-rotating pairs cancel
Without flap effects the disc does not tilt, so F = [0; 0; −T] and M = [0; 0; Mz].
Ports
- Omega – Ω, the rotor's rotational speed in rad/s, [1,1]. Its sign is the sense of rotation and reaches the torque only.
- rho – ρ, the air density, [1,1], in kg/m³ or slug/ft³.
- Fxyz – the force in body axes, a [3,1] column in N or lbf.
- Mxyz – the moment in body axes, a [3,1] column in N·m or lbf·ft.
Parameters
- Units – Metric (MKS), English (velocity in ft/s) or English (velocity in kts). The arithmetic is unit-consistent in both systems, so the first two run the same numbers; kts is the only one that converts anything – the body velocity, by 1852/3600/0.3048 ≈ 1.68781 ft/s per knot.
- Coefficient Source – where the two coefficients come from:
- Dialog – the two values below, used as given
- Compute using BEMT – blade element momentum theory over the blade geometry below, solved once when the configuration is loaded, so the export carries the resulting pair as constants
- Thrust Coefficient – CT, used when the source is Dialog.
- Torque Coefficient – CQ, used when the source is Dialog.
- Number Of Blades – Nb, used by the momentum solver (through the solidity σ = Nb·c/(π·R) and Prandtl's tip loss) and by nothing else when the source is Dialog.
- Blade Radius – R, in the length unit; it sets the whole scale of the block, thrust going as R⁴ and torque as R⁵.
- Blade Chord – c, in the length unit.
- Hinge Offset – e, the flapping hinge's distance from the shaft, in the length unit; at least zero and less than the radius, and read only by the momentum solver here.
- Lift Curve Slope – the blade section's lift slope per radian.
- Mean Drag Coefficient – cd0, the profile drag the momentum solver adds to the torque coefficient as σ·cd0/8. It reaches nothing else.
- Twist Distribution – Linear or Ideal, which decides the one blade pitch the block uses: (2/3)·θroot + (1/2)·θtwist on a Linear blade, θtip on an Ideal one.
- Blade Root Angle – θroot, in radians (Linear twist).
- Blade Twist Angle – θtwist, in radians (Linear twist).
- Blade Tip Angle – θtip, in radians (Ideal twist).
- 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 into the arithmetic at export, the two coefficients included – so a core exported with Compute using BEMT carries the pair the solver found and does not re-solve anything at run time.
The three HDL targets are simulation-only: a division and a signed square does not belong in a Q16.16
datapath, so they compute in real and quantize only at the ports – which also
bounds what can cross one, ±32768. PLC Structured Text has no ATAN2 in
IEC 61131-3, so where one is needed it is rebuilt from ATAN(y/x) with the
quadrant reconstruction.
Simulink bridge
Import and export, mapped to Aerospace Blockset's aerolibrotordyn/Rotor. Units
→ units, Coefficient Source → CTCQMode, Thrust Coefficient
→ CT, Torque Coefficient → CQ, Number Of Blades →
Nb, Blade Radius → radius, Blade Chord → chord,
Hinge Offset → hingeOffset, Lift Curve Slope → clalpha, Mean
Drag Coefficient → cd0, Twist Distribution → twistType,
Blade Root Angle → thetaRoot, Blade Twist Angle →
thetaTwist and Blade Tip Angle → thetaTip; every combo is
Simulink's own list, so the mapping is lossless. Three Simulink parameters are always written
fixed, because each of them MOVES A PORT and a fixed port list cannot follow one:
modelMode = Without flap effects (with them the block gains a body
velocity and a body angular rate input – that is the Rotor With Flap Effects block),
controlInput = off (it adds a collective pitch input) and
CTout = off (it adds two coefficient outputs). Simulink's third CT and
CQ source, Ports, is not offered for the same reason. The Simulink block has
no SampleTime (measured), so the rate stays on the ICore side.
Notes
- Algebraic and stateless; nonlinear, so no state space.
- Measured, not derived. Every rule above was read off Aerospace Blockset R2026a's own block, which is a built-in block type whose source does not ship, and the transcription agrees with it to 1e-16 on about 1600 random states.
- A negative density is not refused here. The Simulink block stops the run on one ("Density must be greater than or equal to 0"); this block computes with what it is given, which at ρ < 0 is a thrust pointing the other way.
- The momentum solver runs once per configuration load, not per sample: 100 blade elements, Newton from λ = 0.001 to a step under 1e-6, at most 100 iterations.
Code facts#
| Fact | Value |
|---|---|
| registered type | Robotics/Rotorcraft/Rotor |
| family | Robotics/Rotorcraft |
| solver environment class | ICoreBlock_0_Robotics_1_Rotorcraft_2_Rotor |
| source | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Rotorcraft/Rotor/ICoreBlock_0_Robotics_1_Rotorcraft_2_Rotor.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Rotorcraft/Rotor/ICoreBlock_0_Robotics_1_Rotorcraft_2_Rotor.h |
| default size on canvas | 170 × 120 px |
| ports at insert | ? in, ? 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 | Omega |
| 2 | in | ICoreDouble | rho |
| 3 | out | ICoreDouble | Fxyz |
| 4 | out | ICoreDouble | Mxyz |
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 | RA::comboValue(RA::unitOptions(), "Metric (MKS)") | units |
Coefficient Source | RA::comboValue(RA::sourceOptions(), "Dialog") | CTCQMode |
Thrust Coefficient | 0.0107 | CT |
Torque Coefficient | 7.8263e-4 | CQ |
Number Of Blades | 2 | Nb |
Blade Radius | 0.0330 | radius |
Blade Chord | 0.0080 | chord |
Hinge Offset | 0 | hingeOffset |
Lift Curve Slope | 5.5 | clalpha |
Mean Drag Coefficient | 0 | cd0 |
Twist Distribution | RA::comboValue(RA::twistOptions(), "Linear") | twistType |
Blade Root Angle | 0.2548 | thetaRoot |
Blade Twist Angle | -0.1361 | thetaTwist |
Blade Tip Angle | 0.1018 | thetaTip |
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 | aerolibrotordyn/Rotor |
| port-count rule | PortsParam::None |
SampleTime parameter | no — the counterpart defines none; the rate stays on the ICore side |
| always set | modelMode = Without flap effects, controlInput = off, CTout = off |
| ICore config | Simulink parameter | Value translation |
|---|---|---|
Units | units | Metric (MKS) → Metric (MKS), English (velocity in ft/s) → English (velocity in ft/s), English (velocity in kts) → English (velocity in kts) |
Coefficient Source | CTCQMode | Dialog → Dialog, Compute using BEMT → Compute using BEMT |
Thrust Coefficient | CT | passes through |
Torque Coefficient | CQ | passes through |
Number Of Blades | Nb | passes through |
Blade Radius | radius | passes through |
Blade Chord | chord | passes through |
Hinge Offset | hingeOffset | passes through |
Lift Curve Slope | clalpha | passes through |
Mean Drag Coefficient | cd0 | passes through |
Twist Distribution | twistType | Linear → Linear, Ideal → Ideal |
Blade Root Angle | thetaRoot | passes through |
Blade Twist Angle | thetaTwist | passes through |
Blade Tip Angle | thetaTip | passes through |
Caveat (shown to the user): modelMode, controlInput and CTout are always written fixed: each of the three MOVES A PORT on the Simulink block (flap effects add a body velocity and a body angular rate input, pitch angle inputs add a collective, and the computed-coefficient outputs add two), and a fixed port list cannot follow a parameter that does. The third CT and CQ source, Ports, is not offered for the same reason. The block has no SampleTime, so the rate stays on the ICore side
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).
Rotor -- thrust and torque of one propeller or rotor T = (CT*R*R*pi*R*R * Omega^2) * rho, Mz = rho * (-CQ*R*R*R*pi*R*R * Omega*|Omega|) F = [0; 0; -T], M = [0; 0; Mz]
The two coefficients are either dialled in or found by blade element momentum theory over the blade geometry, once per configuration load.
MEASURED against R2026a's aerolibrotordyn/Rotor, a built-in block type whose source does not ship; the rules and the differences from its obsolete masked-subsystem form are in ICoreRotorAeroSupport.h.
The three parameters that move a port on the Simulink block are written fixed, so this block is its "Without flap effects" arrangement -- the flapping one is Rotor With Flap Effects.
ALGEBRAIC and STATELESS; nonlinear, so no state space. The three HDL targets are simulation-only real arithmetic, quantized only at the ports.
Sample results#
| t | in ICoreDouble-Out-0 | in ICoreDouble-Out-0 | out ICoreDouble-Out-0 [3x1] entry 0 | out ICoreDouble-Out-1 [3x1] entry 0 |
|---|---|---|---|---|
| 0 | -2 | -2 | [0, 0, 3.189e-7] | [0, 0, -7.698e-10] |
| 0.4 | 0.5 | 0.5 | [0, 0, -4.983e-9] | [0, 0, -1.203e-11] |
| 0.8 | -2 | -2 | [0, 0, 3.189e-7] | [0, 0, -7.698e-10] |
| 1.2 | 0.5 | 0.5 | [0, 0, -4.983e-9] | [0, 0, -1.203e-11] |
| 1.6 | -2 | -2 | [0, 0, 3.189e-7] | [0, 0, -7.698e-10] |
| 2 | 0.5 | 0.5 | [0, 0, -4.983e-9] | [0, 0, -1.203e-11] |
| 2.4 | -2 | -2 | [0, 0, 3.189e-7] | [0, 0, -7.698e-10] |
| 2.8 | 0.5 | 0.5 | [0, 0, -4.983e-9] | [0, 0, -1.203e-11] |
| 3.2 | -2 | -2 | [0, 0, 3.189e-7] | [0, 0, -7.698e-10] |
| 3.6 | 0.5 | 0.5 | [0, 0, -4.983e-9] | [0, 0, -1.203e-11] |
| 4 | -2 | -2 | [0, 0, 3.189e-7] | [0, 0, -7.698e-10] |
| 4.4 | 0.5 | 0.5 | [0, 0, -4.983e-9] | [0, 0, -1.203e-11] |
| 4.8 | -2 | -2 | [0, 0, 3.189e-7] | [0, 0, -7.698e-10] |
| 5.2 | 0.5 | 0.5 | [0, 0, -4.983e-9] | [0, 0, -1.203e-11] |
Every 4th of 60 samples, from the table stimulus.
The same rig also ran:
| Stimulus | What it is | Output range |
|---|---|---|
impulse | Impulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair) | 0 … 0 |
ramp | Ramp: slope 1 from t = 0 | 0 … 0 |
sine | Sine Wave: amplitude 1, 2 rad/s, no phase, no bias | 0 … 0 |
step | Step: 0 -> 1 at t = 1 s | 0 … 0 |
Plotted: table — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample
Category static · sample time 0.1 · 60 steps · commit 23d8841c6561ca4bb64cd9b5b64da9638de12629 · produced by docsSample --out <folder> --blocks Fixed_Wing_Point_Mass Kernel_Classifier_Predictor Kernel_Regression_Predictor Rotor Rotor_With_Flap_Effects Multirotor Multirotor_With_Flap_Effects Dynamic_Inflow_3_State Kurtogram Empirical_Mode_Decomposition Modal_FRF Order_Spectrum --steps 60 · data docs/generated/samples/Robotics__Rotorcraft__Rotor.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).