Repository navigation
Conversation
taskRunRealtimeCallbacks() calls afatfs_poll() from scheduler(), which is FAST_CODE, and LTO inlines the file system's state machine into it. On targets with an SD card that puts 800 to 980 bytes of afatfs code in ITCM, depending on the target, where KAKUTEF7 and KAKUTEF7HDV are at 99%. The poll does a little work at most once per scheduler loop, so it runs from flash like the rest of afatfs.
Adds a high-pass filtered copy of the throttle on top of it, so the motors follow quick throttle moves sooner: throttle_boost (0-100, the boost is the value / 10 times the high-passed throttle) and throttle_boost_cutoff (5-50 Hz, 15 by default), as in Betaflight. Off by default. Only the motors get the boost: mixerThrottleCommand, which OSD, telemetry and servos read, stays the throttle that was asked for. Multirotor only, and not while navigation controls the throttle, during a VTOL transition, with reversible motors or with the logic-condition throttle override. After the mixer skipped it for more than 100 ms (disarmed, motors stopped, navigation in control), the filter restarts from the current throttle. Both settings are appended to motorConfig_t without a version bump: the first one lands in the old record's tail padding, stored as zero, which is its default, and the cutoff starts past the end of any stored record, so it keeps its default of 15 Hz.
A propeller's thrust grows faster than linearly with the motor command, so a multirotor responds less to the same correction at low throttle. thrust_linear (0-100, off by default) raises each motor output and lowers the throttle before the mix by the inverse amount, with the formulas of Betaflight 2026.6 (#15226): a second-order expansion of ArduPilot's MOT_THST_EXPO model, so the value is about MOT_THST_EXPO * 100 and hover stays where it was (within 8 us up to 50, 80 us at 100). Betaflight allows 150, but above 100 its compensation goes negative at low throttle and from about 130 the curve stops being monotonic, so the range stops at 100. The formulas live in flight/thrust_linear.h with their own unit test. Unlike Betaflight, outputs at or below idle are left alone, so the failsafe clamp to min_command is not pushed further down, and the setting is global rather than per PID profile. As with the throttle boost, only the motors get the lowered throttle. Multirotor only. Off on VTOL setups (any mixer profile that is not a multirotor), so it never switches at a transition; also off with reversible motors and with the logic-condition throttle override. Built on the throttle boost commit, so the three settings share one layout in motorConfig_t: thrustLinear lands in the tail padding of that record, stored as zero, which is its default.
|
ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing |
PR Summary by QodoAdd multirotor throttle boost and thrust linearization
AI Description
Diagram
High-Level Assessment
Files changed (7)
|
Code Review by Qodo
1.
|
…change The low-pass restarted only after 100 ms without the mixer, so a shorter motor stop resumed against the throttle from before the stop, and a cutoff changed while mixing kept the old one. Restart from the current throttle whenever the gap is longer than any mixer period (20 ms; looptime is at most 9 ms) or the cutoff differs from the one in use.
… motor INAV multiplies the absolute throttle command by each motor's mixer weight, so the throttle compensation, worked out on the common throttle, is not the inverse of the curve for any other weight: with 0.8, a 1500 command and thrust_linear 100, a motor went from 1200 down to idle. The standard multirotor mixes all use 1; with any other weight the feature stays off.
|
RAM / Flash usage vs. base commit
See RAM/flash optimization guide for techniques to reduce usage. |
|
Test firmware build ready — commit Download firmware for PR #12121 251 targets built. Find your board's
|
The throttle boost fields follow the SRXL2 ones, which existed only where USE_MOTOR_SRXL2 is defined. A target that turned it on or off would then read its stored boost cutoff as the SRXL2 reverse channel, or the other way round, and a cutoff of 0 blocks arming as an invalid setting. With the fields always there the layout is the same everywhere; on targets without SRXL2 they stay zero and unused.
As Betaflight writes them, so a log says whether the boost was on and how strong it was.
As Betaflight writes it, so a log says whether the linearization was on and how strong it was.
# Conflicts: # src/main/io/asyncfatfs/asyncfatfs.c
Builds on #12120 (throttle boost), which builds on #12118 (afatfs_poll out of ITCM). The settings of both mixer PRs
share one layout in
motorConfig_t.Betaflight's thrust linearization, for multirotors. A propeller's thrust grows faster than linearly with the motor
command, so the same PID correction moves the quad less at low throttle than at high throttle.
thrust_linear(0-100, default 0, off) raises each motor output and lowers the throttle before the mix by the inverse amount, so the
response is more even across the throttle range while hover stays where it was.
The formulas are Betaflight 2026.6's (betaflight/betaflight#15226), a second-order expansion of ArduPilot's
MOT_THST_EXPOmodel. The value is therefore about
MOT_THST_EXPOtimes 100, and ArduPilot's per-propeller values carry over. Withe = thrust_linear / 100, on 0-1 over the throttle range (idle to max):ubecomesu * (1 + e * (1 - u) * (1 + e * (1 - 2u))), the curve on each motor before theclamps, in the same place as Betaflight;
tbecomest * (1 - e * (1 - t)), the inverse of the curve to second order. Hover moves by at most8 us up to 50, 23 us at 70 and 80 us at 100, at worst near 15 % throttle.
Differences from Betaflight:
motors at idle around a third of the stick, and from about 130 the curve is no longer monotonic.
min_command, and the curve wouldpush a below-idle output further down.
for.
motorConfig_t, so a profile switch cannot change it in flight.step the motors.
weight, so with any other weight the compensation is not the curve's inverse. The standard multirotor mixes all
use 1.
The formulas are in
flight/thrust_linear.h, as two pure inline functions with their own unit test:The throttle compensation runs in the throttle boost's out-of-line call before the motor loop. The curve is one
out-of-line call per motor, to keep
mixTable()small in ITCM.Settings storage
thrust_linearis appended after the throttle boost settings without a version bump, at offset 15 of 16 on everytarget (checked in the debug info of F7, F405 and H7 builds). That is the tail padding of a record saved with #12120,
stored as zero, or past the end of an older one, and its default is 0.
Bench
Flywoo F722 Pro V2 (FLYWOOF722PRO image), no battery, so the motors could not spin. I armed it over MSP RC with a
QUADX mixer,
throttle_boost0, and held the throttle at three levels. The mean motor output matches the formulas:thrust_linearAt 1182, about 11 % throttle, the compensation lowers a little more than the curve raises: that is the worst corner
of the second-order inverse, as in Betaflight. With 0 the motors get exactly the throttle, as before.
Size, over the throttle boost PR
Flash +312 to +352 B (MATEKF722SE +336 B, 98.66 %). ITCM +32 B on F722 targets, +40 B on KAKUTEH7MINI, 0 on
KAKUTEF7/KAKUTEF7HDV (15 360 / 15 480 B). RAM: 4 B of FASTRAM.
Testing
The unit tests pass, the new ones included. Not flown. Flight tests would be welcome: a quad flown with 0 and then with its propellers'
MOT_THST_EXPOx 100,looking at how it holds attitude at low throttle and on throttle chops.
Log header
The header also carries
thrust_linear, under Betaflight's name (b2fd306). The same log on MAMBAF722_2022B with itat 30:
H thrust_linear:30. +32 B of flash on MATEKF722SE over #12120 (98.68 %). All 237 targets build with both changes, and the unit tests pass (620 of 620 on #12120, 625 of 625 here).