Multirotor With Flap Effects — Robotics/Rotorcraft
Robotics/Rotorcraft/Multirotor_With_Flap_Effects · 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.
Multirotor With Flap Effects
Robotics / Rotorcraft
A four-rotor machine as one block, with each rotor's disc allowed to tilt: every rotor sees its own hub velocity, flaps its own way, and contributes its tilted thrust and its torque to one force and one moment about the vehicle's centre.
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
With flap effects the rotor disc tilts, and the thrust tilts with it:
- F = T·[sin(a1s)·(−cos(b1s)); sin(b1s); cos(b1s)·(−cos(a1s))]
- M = [0; 0; Mz] + arm × F
a1s and b1s are the steady-state longitudinal and lateral flapping angles, solved from the hub's own velocity Vr = Vb + ωb × arm: the advance ratio μ = |Vr,xy|/(|Ω|·R), the inflow ratio λc = |Vr,z|/(|Ω|·R), the sideslip angle ψ = atan2(Vr,y, Vr,x) that rotates the pair back into body axes, the blade pitch, the Lock number and the hinge offset.
The sums are F = ΣFi and M = Σ([0; 0; Mz,i] + armi × Fi), and the arm is what makes each rotor's hub velocity different: Vr,i = Vb + ωb × armi.
Ports
- Omega – the four rotational speeds in rad/s, a [4,1] column in the arm order below; each sign is that rotor's sense of rotation.
- rho – ρ, the air density, [1,1], in kg/m³ or slug/ft³.
- Vb – the body velocity of the vehicle's centre, a [3,1] column in m/s, ft/s or knots, as the Units say.
- wb – the body angular velocity ωb, a [3,1] column in rad/s. It moves every hub at a different velocity, so a rolling or pitching machine flaps its four discs differently.
- Fxyz – the summed force in body axes, a [3,1] column in N or lbf.
- Mxyz – the summed moment about the centre, 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.
- Configuration – where the four arms point, with l the arm length and h the
rotor height:
- Quadcopter X – the diagonals: [l/√2, −l/√2, h], [l/√2, l/√2, h], [−l/√2, l/√2, h], [−l/√2, −l/√2, h]
- Quadcopter + – the axes: [l, 0, h], [0, l, h], [−l, 0, h], [0, −l, h]
- Arm Length – l, the distance from the centre to a rotor hub, in the length unit.
- Rotor Height – h, the rotors' common z in body axes (negative is above the centre), in the length unit.
- 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: one number for all four rotors, or a four-element vector, one per rotor. It also reaches each rotor's flapping, through the coning term.
- Torque Coefficient – CQ, the same two shapes.
- Number Of Blades – Nb, used by the momentum solver (through the solidity σ = Nb·c/(π·R) and Prandtl's tip loss).
- 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.
- 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.
- Lock Number – γ, the ratio of the blade's aerodynamic to inertial flapping moments. It reaches the flapping only, and it is in every one of its hinge-offset terms.
- 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: an arctangent, a square root, two divisions and the trigonometry of the flapping angles 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.
The four rotors are written out one after another rather than looped, so every arm and every coefficient is a constant in the emitted core.
Simulink bridge
Export only, onto Aerospace Blockset's aerolibrotordyn/Multirotor with
modelMode fixed at With flap effects. The Multirotor block owns
the import of that library block, because two entries claiming one path can only differ by a
parameter the importer cannot see. Units → units, Configuration →
config, Arm Length → armLength, Rotor Height →
rotorHeight, 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, Lock Number → gamma, Twist
Distribution → twistType, Blade Root Angle → thetaRoot,
Blade Twist Angle → thetaTwist and Blade Tip Angle →
thetaTip. controlInput = off and CTout =
off are written fixed, because each adds a port; Simulink's Ports
coefficient source 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.
- The inflow ratio uses the MAGNITUDE of the hub's vertical velocity, so a climb and a descent of the same speed flap identically. Measured on the Simulink block.
- A rotor at Ω = 0 contributes zero, not a NaN: its flapping is undefined (every term divides by |Ω|) and its thrust is zero anyway. The Simulink block answers zero too.
- Four rotors, always. Both Simulink configurations are quadcopters; the rotor count is not a parameter on either side.
- A negative density is not refused here. The Simulink block stops the run on one.
Code facts#
| Fact | Value |
|---|---|
| registered type | Robotics/Rotorcraft/Multirotor_With_Flap_Effects |
| family | Robotics/Rotorcraft |
| solver environment class | ICoreBlock_0_Robotics_1_Rotorcraft_2_Multirotor_With_Flap_Effects |
| source | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Rotorcraft/Multirotor_With_Flap_Effects/ICoreBlock_0_Robotics_1_Rotorcraft_2_Multirotor_With_Flap_Effects.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Rotorcraft/Multirotor_With_Flap_Effects/ICoreBlock_0_Robotics_1_Rotorcraft_2_Multirotor_With_Flap_Effects.h |
| default size on canvas | 170 × 150 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 | in | ICoreDouble | Vb |
| 4 | in | ICoreDouble | wb |
| 5 | out | ICoreDouble | Fxyz |
| 6 | 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 |
Configuration | RA::comboValue(RA::quadOptions(), "Quadcopter X") | config |
Arm Length | 0.0624 | armLength |
Rotor Height | -0.0159 | rotorHeight |
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 |
Lock Number | 0.6051 | gamma |
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::ExportOnly |
| Simulink path | aerolibrotordyn/Multirotor |
| port-count rule | PortsParam::None |
SampleTime parameter | no — the counterpart defines none; the rate stays on the ICore side |
| always set | modelMode = With 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) |
Configuration | config | Quadcopter X → Quadcopter X, Quadcopter + → Quadcopter + |
Arm Length | armLength | passes through |
Rotor Height | rotorHeight | passes through |
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 |
Lock Number | gamma | 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): Export only: the Rotor block owns the import of this library path, and this entry is the same block with modelMode fixed at With flap effects. controlInput and CTout are written fixed because each adds a port, and Simulink's Ports coefficient source 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 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).
Multirotor With Flap Effects -- four flapping rotors as one block The Multirotor block, with every rotor's disc allowed to tilt. Each hub moves at its own velocity, Vr_i = Vb + wb x arm_i, so a rolling or pitching machine flaps its four discs differently, and each tilted thrust enters the sum with its own arm.
MEASURED against R2026a's aerolibrotordyn/Multirotor at modelMode = With flap effects; the arithmetic is in ICoreRotorAeroSupport.h.
ALGEBRAIC and STATELESS; nonlinear, so no state space. The three HDL targets are simulation-only real arithmetic, quantized only at the ports.
Sample results#
No stimulus produced a sampled output in this rig — Invalid input size at Multirotor With Flap Effects block: ICore Blocks/Home/Multirotor With Flap Effects. 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 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
Sample data: docs/generated/samples/Robotics__Rotorcraft__Multirotor_With_Flap_Effects.json