block
Vehicles.Rdd2.RateControlAllocator
Sampled body-rate control and motor allocation task
This block owns the fast RTOS task boundary. It samples the outer-loop body-rate and thrust command, computes body moment in the shared FLU convention, and allocates the result to the four motors.
The model intentionally retains vector and matrix equations. Rumoca lowers those equations to bounded scalar Production Code; the source model remains compact and auditable.
Public declarations
Explicit source declarations; dimensions, modifications and defaults are shown as written, without evaluation.
| Role | Name | Type | Dimensions / attributes / default | Description |
|---|---|---|---|---|
| parameter | samplePeriod | Real | (unit = "s") = 0.000625 | |
| parameter | inertia | Real | [3] = {
0.02166666666666667,
0.02166666666666667,
0.04000000000000001} | |
| parameter | rateGain | Real | [3] = {20.0, 20.0, 10.0} | |
| parameter | maximumBodyMoment_Nm | Real | [3] = {2.6, 2.6, 0.30} | Conservative requested-moment bounds before allocation |
| parameter | thrustCoefficient | Real | = 8.54858e-6 | Rotor thrust coefficient [N/(rad/s)^2] |
| parameter | maxMotorSpeed | Real | (unit = "rad/s") = 1100.0 | |
| parameter | rotorGeometry | Vehicles.Rdd2.RotorGeometry | =
Vehicles.Rdd2.RotorGeometry() | Airframe geometry, fixed at code generation; geometry changes recompile through calibration rather than tuning the allocation at runtime |
| parameter | wrenchToRotorThrust | Real | [4, 4] =
Control.Multirotor.Allocation.quadrotorWrenchToThrust(
rotorGeometry.positionBodyFlu_m,
rotorGeometry.yawMomentPerThrust_m) |
Modelica declarations and implementation
Show parameters, interfaces and source
Parameters, inputs, outputs, defaults and equations from the source file.
block RateControlAllocator
"Sampled body-rate control and motor allocation task"
import Interfaces = Vehicles.Rdd2.ControllerInterfaces;
parameter Real samplePeriod(unit = "s") = 0.000625;
parameter Real inertia[3] = {
0.02166666666666667,
0.02166666666666667,
0.04000000000000001};
parameter Real rateGain[3] = {20.0, 20.0, 10.0};
parameter Real maximumBodyMoment_Nm[3] = {2.6, 2.6, 0.30}
"Conservative requested-moment bounds before allocation";
parameter Real thrustCoefficient = 8.54858e-6
"Rotor thrust coefficient [N/(rad/s)^2]";
parameter Real maxMotorSpeed(unit = "rad/s") = 1100.0;
parameter Vehicles.Rdd2.RotorGeometry rotorGeometry =
Vehicles.Rdd2.RotorGeometry()
"Airframe geometry, fixed at code generation; geometry changes recompile
through calibration rather than tuning the allocation at runtime"
annotation(Evaluate = true);
parameter Real wrenchToRotorThrust[4, 4] =
Control.Multirotor.Allocation.quadrotorWrenchToThrust(
rotorGeometry.positionBodyFlu_m,
rotorGeometry.yawMomentPerThrust_m);
Interfaces.RateControlInput inputSignal;
Interfaces.MotorCommands commands;
protected
discrete Real unboundedMomentBodyFlu_Nm[3](each start = 0.0);
discrete Real momentBodyFlu_Nm[3](each start = 0.0);
discrete Real allocatedMotorCommand[4](each start = 0.0, each fixed = true);
equation
commands.motor = if inputSignal.armed then
allocatedMotorCommand
else
zeros(4);
initial algorithm
assert(inertia[1] > 0.0 and inertia[2] > 0.0 and inertia[3] > 0.0,
"Every body inertia must be positive");
assert(rateGain[1] >= 0.0 and rateGain[2] >= 0.0 and rateGain[3] >= 0.0,
"Every body-rate gain must be nonnegative");
assert(thrustCoefficient > 0.0,
"Every rotor thrust coefficient must be positive");
assert(maxMotorSpeed > 0.0,
"Every maximum rotor speed must be positive");
algorithm
when sample(0.0, samplePeriod) then
unboundedMomentBodyFlu_Nm := Control.Multirotor.RateLoop.bodyMoment(
inputSignal.angularVelocityCommandFlu_rad_s,
inputSignal.angularVelocityMeasuredFlu_rad_s,
inertia,
rateGain);
momentBodyFlu_Nm := {
MathUtilities.clip(unboundedMomentBodyFlu_Nm[1],
-maximumBodyMoment_Nm[1], maximumBodyMoment_Nm[1]),
MathUtilities.clip(unboundedMomentBodyFlu_Nm[2],
-maximumBodyMoment_Nm[2], maximumBodyMoment_Nm[2]),
MathUtilities.clip(unboundedMomentBodyFlu_Nm[3],
-maximumBodyMoment_Nm[3], maximumBodyMoment_Nm[3])};
allocatedMotorCommand := Control.Multirotor.Allocation.rotorCommands(
4,
inputSignal.thrust_N,
momentBodyFlu_Nm,
wrenchToRotorThrust,
fill(thrustCoefficient, 4),
fill(maxMotorSpeed, 4));
end when;
annotation(Documentation(info = "<html>
<p>This block owns the fast RTOS task boundary. It samples the outer-loop
body-rate and thrust command, computes body moment in the shared FLU
convention, and allocates the result to the four motors.</p>
<p>The model intentionally retains vector and matrix equations. Rumoca
lowers those equations to bounded scalar Production Code; the source model
remains compact and auditable.</p>
</html>"));
end RateControlAllocator;