Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Feedforward Angle and RC Smoothing - mashup of 12578 and 12594 #12605

Conversation

ctzsnooze
Copy link
Member

@ctzsnooze ctzsnooze commented Apr 2, 2023

This PR combines #12578 and #12594, which are now closed. Both shared a lot of common changes in pid.c and rc.c, and would be difficult to merge sequentially. It includes the current updated Angle and Horizon code.

Note: Users who want the old Angle mode behaviour should set expo to zero in their Rates, and:

set angle_feedforward = 0     // default is 50
set angle_earth_ref = 0       // default is 100
// restore angle strength (now angle_p_gain) and angle_limit to your previous value/s

Note: Horizon users should adjust the following parameters to suit their preference:

horizon_level_strength   // how aggressively the quad self-levels when flat
horizon_limit_sticks     // the percentage stick deviation at which there is no levelling
horizon_ignore_sticks    // when on, stick travel will not attenuate the levelling
horizon_limit_degrees    // the angle of the quad at which there is no levelling
horizon_delay_ms         // the time constant affecting the onset of the levelling

There are two functional changes that are added by this PR, on top of the changes in #12578 and #12594:

  1. Delayed onset of levelling in Horizon when returning sticks to the centre. As suggested by @justainchoe, this adds a delay whenever the levelling strength increases in Horizon mode. Decreases in levelling strength are unaffected and happen immediately. The delay is achieved by applying a first order lowpass filter, with a time constant of 500ms by default to the horizon strength factor, where a horizon_delay of 50 means 500ms. The code then uses the lowest of the un-smoothed and smoothed value, where a low value means no smoothing. This results in a delay only when the horizon strength value increases. The pilot can do a flip and bring their sticks hard back to centre, and the levelling will come on relatively slowly, avoiding the previously unwelcome 'snap' due to the combination of self-levelling and the pilot bringing the sticks to a halt. It there's too much 'snap', or if you want the levelling to come in only after a longer time, increase the time constant (up to 250 or 2.5s). For more immediate levelling, as perhaps preferred by a person learning Acro via Horizon, the delay can be reduced. If set to zero, there is no delay.

  2. Small modification to feedforward_max_rate_limit. Now this value affects the slope of the limiting line, with zero feedforward always by the time setpoint reaches maximum, rather than moving the line left and right, while the users PID "P" value modifies the slow. Racers may prefer feedforward_max_rate_limit at values around 100-120 to maintain full feedforward until quite late in a full stick move. Cinematic users or those with heavier quads may want a smoother, less aggressive feedforward, in which case feedforward_max_rate_limit could be around 50, and the RC smoothing on feedforward increased a bit (lower cutoff than default).

Please refer to #12576 and #12594 for detailed notes on the other changes..

There is a lot of efficiency related refactoring, resulting in significant CPU and flash space savings.

Summary of changes:

  • bug fix for an issue that caused feedforward RC smoothing to get a different value from setpoint in auto-rc-smoothing mode
  • fixes issues that caused the RC link speed to be calculated incorrectly or inaccurately, especially at high telemetry rates. - rc_smoothing calculations now use lowpass filtering with much simpler code to detect link speed changes - many thanks to @KarateBrot for advice on how to best do this. RC smoothing is now updated every 3 valid samples.
  • fixes an issue where the user's PID P value altered the feedforward max_rate_limit_factor attenuation slope. This was by design, but a bit annoying, and it was confusing that high P caused feedforward to be stronger at the start of flips, and vice versa. Now the feedforward_max_rate_limit value controls the slope of the attenuation line, so that when it is set low, feedforward will, at the start of a flip, ease back earlier, and when set high, stay strong for later. Default of 90 remains the same and suits high authority quads. Quads that overshoot at the start of a flip should consider a lower than default feedforward_max_rate_limit.
  • fixes and issue where Horizon mode would get RC stepping in the levelling element with slow link speeds
  • user-adjustment of Angle Mode Earth Referencing strength is now possible via OSD
  • refactoring and simplification of the feedforward code to improve efficiency (many changes)
  • minor fix to stop overflow of debug values in rc_smoothing_rate debug
  • quite a few debug changes since some parameters don't exist anymore
  • editorial changes to rename variables named 'rate' when the value was a time interval
  • about 1k less flash space required
  • On F411, 3% less CPU in acro, 4-4.5% less in angle/horizon.

There should be no change in feedforward or RC smoothing functionality. All quads should fly the same, just a bit more smoothly. CPU load / instability should be a bit less of a problem on marginal setups.

RC smoothing values and reported link speeds should be accurate in all circumstances. Previously when the RC smoothing calculations were in error, RC link stepping could get through to the motors via feedforward or setpoint. This shouldn't happen any more, including in Angle and Horizon mode.

The code should be able to deal with radios that change links dynamically, even in small steps. Previously there was an issue detecting change from 333 to 250hz. Now it should respond to any change greater than 1hz, and do so within a few packets.

Please also test feedforward by flying and noting normal feedforward behaviour, and log feedforward.

If you find any issues with unexpected link intervals or rc smoothing issues, please either raise an issue here on GitHub or a pre-issue on Discord.

Feedforward, when a new RC packet arrives, requires 125 cycles without averaging, jitter or transition. This increases to 170 cycles with averaging, 196 cycles when also adding jitter reduction, and 209 cycles with "the lot".

RC Smoothing requires 18 cycles while idle, about 160 cycles when a new RC packet arrives in that is not much different from the previous interval, and about 250 cycles when the interval is sufficiently different that new cutoffs are required.

Recoding for efficiency mostly involved:

  • not using "#DEFINE" values, instead using constants in the code, or setting the value when declaring the variable that needed it, with a comment
  • avoiding unnecessary int to float and float to int conversions, especially 'hidden' or inside loops
  • generally using floats if at any point they would be multiplied by a float or divided by a float
  • using const variables whenever possible, especially for values that were repeatedly calculated inside loops
  • pre-calculating values required for divisions in the pidRuntime init, so we only need to do multiplications.

@github-actions

This comment has been minimized.

@blckmn

This comment was marked as outdated.

@nerdCopter

This comment was marked as resolved.

@ctzsnooze ctzsnooze force-pushed the Angle-Horizon-Feedforward-RCSmoothing-4_5 branch 3 times, most recently from cf53c55 to 626f727 Compare April 3, 2023 01:41
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@nerdCopter

This comment was marked as outdated.

@TheIsotopes

This comment was marked as resolved.

@github-actions

This comment has been minimized.

@nerdCopter

This comment was marked as outdated.

@haslinghuis haslinghuis added this to the 4.5 milestone Apr 5, 2023
@TheIsotopes
Copy link
Contributor

TheIsotopes commented Apr 6, 2023

@ctzsnooze everything works as expected again.
smoothness is slightly worse than with the current master and the same settings.

I don't notice any difference when flying, but the logs look a bit different than usual.

BTFL_BLACKBOX_LOG_Egodrift_20230406.txt

haslinghuis
haslinghuis previously approved these changes Apr 6, 2023
Copy link
Member

@haslinghuis haslinghuis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only needs to update unit tests and remove comments.

@ctzsnooze ctzsnooze force-pushed the Angle-Horizon-Feedforward-RCSmoothing-4_5 branch from 0ddf592 to 3bdac20 Compare April 7, 2023 02:50
@github-actions

This comment has been minimized.

@TheIsotopes
Copy link
Contributor

tested again with rebased PR on ghost and frsky sbus.
everything flies as expected, to me all looks fine. 👍

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

Copy link
Member

@haslinghuis haslinghuis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to fix unit tests before merging

@ctzsnooze
Copy link
Member Author

Need someone to help get the 'container' for the unit tests. I'll do the tests themselves, but I can't figure how to do them now the code is in a different place. So if not one person here can help, then we should merge the PR without the unit tests.

@ctzsnooze
Copy link
Member Author

ctzsnooze commented Apr 21, 2023

@borisbstyle @haslinghuis - in this PR:

  • getFeedforward(axis) returns the feedforward value for the axis from rc.c, where it is calculated from incoming rc data.
  • in pid.c, pidSetpointDelta is set to getFeedforward(axis), or zero in Angle mode.
  • then, simply:
        if (feedforwardGain > 0) {
            float feedForward = feedforwardGain * pidSetpointDelta;
            pidData[axis].F = feedForward;
        } else {
            pidData[axis].F = 0;
        }

In the previous 'master' code the functions applyFeedforwardLimit, feedforwardInit, feedforwardApply, and shouldApplyFeedforwardLimits were included in the unit test.

However, the feedforwardApply calculated setpointDelta from simulated setpoint values locally. The function itself, which resided within feedforward.c, was not called; instead, a value for setpointDelta was calculated within the test itself from simulated setpoint values. This did not test the function of the feedforwardApply function within feedforward.c at all. Also, the transition factor was calculated inside the test, and did not use the transition code in pid.c.

In short, the old tests didn't test the code in master anyway - it 'cheated'. The 'test' only tested the code in the test, not the code we flew. At least that's how I see it.

After this PR, these old functions don't exist anymore.

To do the unit test entirely within the pid_unitest, we would need to get rc.c to calculate pidSetpointDelta using getFeedforward(axis) from RC values that we send to rc.c. That seems very difficult.

I think that to test the feedforward code itself, we would need need a test in rc.c that checks what would return for getFeedforward(axis), given certain stick position changes.

Then only test required in pid.c is to multiply a simulated feedforward value by the feedforward gain value, and check it is zero in angle mode.

I have updated the pid_unittest.

It now returns sensible values for feedforward for a given simulated setpointDelta value.

I don't think I have the capability to write a unit test for rc.c.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@ctzsnooze ctzsnooze force-pushed the Angle-Horizon-Feedforward-RCSmoothing-4_5 branch from 5bd86dc to b01a6d2 Compare April 23, 2023 01:11
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

Copy link
Member

@haslinghuis haslinghuis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@borisbstyle this should be good for now as we can improve the tests later.
@ctzsnooze thanks for reverting clang version - as I overlooked that.

@github-actions
Copy link

Do you want to test this code? Here you have an automated build:
Assets
WARNING: It may be unstable. Use only for testing! See: https://www.youtube.com/watch?v=I1uN9CN30gw for instructions for unified targets!

@TheIsotopes
Copy link
Contributor

@ctzsnooze here another testflight ... hope now that's the last before merge

#12605_testflight.zip

@nerdCopter
Copy link
Member

b17cd84cf LOS Horizon Mode.
set debug_mode = RC_SMOOTHING_RATE
ELRS; TX 500hz, 1:4 telem
BTFL_BLACKBOX_LOG_APEX-6inch_20230423_123855_LOS_HORIZ_PR12605.BBL.zip

# 

# version
# Betaflight / STM32F7X2 (S7X2) 4.5.0 Apr 23 2023 / 15:14:14 (b17cd84cf) MSP API: 1.46
# board: manufacturer_id: APEX, board_name: APEXF7

# rc_smoothing_info
# RC Smoothing Type: FILTER
# Detected Rx frequency: 503Hz
# Active setpoint cutoff: 25hz (manual)
# Active FF cutoff: 25hz (manual)
# Active throttle cutoff: 188hz (auto)

# status
MCU F722 Clock=216MHz, Vref=3.28V, Core temp=53degC
Stack size: 2048, Stack address: 0x20010000
Configuration: CONFIGURED, size: 3361, max available: 16384
Devices detected: SPI:1, I2C:1
Gyros detected: gyro 1 locked dma
GYRO=MPU6000, ACC=MPU6000, BARO=BMP280
OSD: MAX7456 (30 x 13)
BUILD KEY: 7e43be5093e31b54bc8383ab9a0594d0 (4.5.0-zulu)
System Uptime: 35 seconds, Current Time: 2023-04-23T17:41:19.109+00:00
CPU:34%, cycle time: 124, GYRO rate: 8064, RX rate: 500, System rate: 10
Voltage: 295 * 0.01V (0S battery - NOT PRESENT)
I2C Errors: 0
FLASH: JEDEC ID=0x00ef4018 16M
Arming disable flags: NOPREARM CLI MSP

# tasks
Task list             rate/hz  max/us  avg/us maxload avgload  total/ms   late    run reqd/us
00 - (         SYSTEM)     10       7       0    0.0%    0.0%         0      1    429       6
01 - (         SYSTEM)    995      13       0    1.2%    0.0%        23     72  42290       2
02 - (           GYRO)   8006      15       1   12.0%    1.4%       578      0 342169       0
03 - (         FILTER)   8006      29       9   23.2%    7.2%      3135      0 342169       0
04 - (            PID)   8006      64      28   51.2%   22.7%      9807      0 342169       0
05 - (            ACC)    992      18       2    1.7%    0.2%       131     45  42254       9
06 - (       ATTITUDE)    100      27      11    0.2%    0.1%        46      7   4694      22
07 - (             RX)    388      32      16    1.2%    0.6%       773     65  47997      18
08 - (         SERIAL)    100  296907       1 2969.0%    0.0%       559      0   4171      24
09 - (       DISPATCH)    993      14       0    1.3%    0.0%        27     61  42295       6
10 - (BATTERY_VOLTAGE)     50      15       3    0.0%    0.0%         4      3   2131      10
11 - (BATTERY_CURRENT)     50       7       0    0.0%    0.0%         1      6   2131       4
12 - ( BATTERY_ALERTS)      5       9       2    0.0%    0.0%         0      1    215       8
13 - (         BEEPER)    100      13       0    0.1%    0.0%         5      9   4170       9
14 - (           BARO)     40      41      23    0.1%    0.0%       119     10   5083      38
15 - (       ALTITUDE)    100      15       2    0.1%    0.0%        12      7   4170      11
16 - (      TELEMETRY)    499      19       0    0.9%    0.0%        36     21  20937       6
17 - (            OSD)     12      55      17    0.0%    0.0%       179     57  13227      32
19 - (            CMS)     20       9       2    0.0%    0.0%         1      3    852       8
20 - (        VTXCTRL)      5      35       1    0.0%    0.0%         3      4    215      34
21 - (        CAMCTRL)      5       6       0    0.0%    0.0%         0      0    215       5
23 - (    ADCINTERNAL)      1      11       3    0.0%    0.0%         0      2     43      10
24 - (       PINIOBOX)     20      15       2    0.0%    0.0%         2      2    852      11
25 - (SPEED_NEGOTIATION)    100      11       1    0.1%    0.0%         5      2   4170       5
RX Check Function                  14       0                        66
Total (excluding SERIAL)                                32.2%

# 

@haslinghuis haslinghuis merged commit 34057bf into betaflight:master Apr 23, 2023
19 checks passed
@KarateBrot
Copy link
Member

KarateBrot commented Apr 24, 2023

@haslinghuis Dismissing my review is not okay. We were still in the review process. Please never do this again!

@haslinghuis
Copy link
Member

@KarateBrot Just trying to keep the project going here. Assumed your request was fixed.

We always can fix upon (any) work if it doesn't turn out. As this PR was hanging and multiple requests for merging were pending and tested were positive I deemed it ready for merge.

@ctzsnooze
Copy link
Member Author

ctzsnooze commented Apr 24, 2023

Sorry @KarateBrot I thought that I had addressed your comments. And I remain very grateful for the time you took to make those reviews.

My error was to mark those which I thought had been addressed, as 'resolved', which I did for housekeeping purposes, so I could track which had been dealt with. I thought that this could always be reversed if we wanted to go back and check on how they were 'resolved'.

Unfortunately, I now see that, on merging, all review discussions marked as 'resolved' have vanished. I didn't expect this.

It would be much better that all review discussions, including those marked as 'resolved', are retained on merging.
I don't know if this is a GitHub option. In future I will leave all reviews 'open' even if they are 'resolved' because the discussions in those reviews can be useful in future.

The remaining review questions that I didn't resolve are still open, eg the query about the CLI print line function.

@blckmn I wonder if those review discussions can be restored somehow? Or if we can change our GitHub settings to not delete 'resolved' review discussions? Could it be that the 'squash' associated with the merge causes our review discussion to be lost?

@nerdCopter
Copy link
Member

nerdCopter commented Apr 24, 2023

recommend author(s) set long-standing PR(s) as draft until truly "ready".

@nerdCopter
Copy link
Member

nerdCopter commented Apr 24, 2023

we can still see some comments/unresolved via the "files changed" tab.
e.g. https://github.com/betaflight/betaflight/pull/12605/files#r1172738403 & https://github.com/betaflight/betaflight/pull/12605/files#r1172778392

maybe the conversations drop-down as well
image

AkankshaJjw pushed a commit to AkankshaJjw/betaflight that referenced this pull request May 29, 2023
…94 (betaflight#12605)

* Refactor Feedforward Angle and RC Smoothing

* update rc_smoothing at regular intervals

* add Earth Ref to OSD, update pid and rate PG

* Initialise filters correctly

* refactoring to improve performance

* Save 24 cycles in Horizon calculations, other optimisations

At a cost of 40 bytes

* save 25 cycles and 330 bytes in rc_smoothing

* feedforward max rate improvements

* typo fix

* Karatebrot's review suggestions  part one

* Karatebrot's excellent suggestions part 2

* more efficient if we calculate inverse at init time

Co-Authored-By: Jan Post <post@stud.tu-darmstadt.de>

* Horizon delay, to ease it in when returning sticks to centre

* fix unit tests after horizon changes

Co-Authored-By: 4712 <4712@users.noreply.github.com>

* horizon_delay_ms, default 500

* fix unit test for feedforward from setpointDelta

* Final optimisations - thanks @KarateBrot for your advice

* increase horizon level strength default to 75 now we have the delay

* restore Makefile value which allowed local make test on mac

---------

Co-authored-by: Jan Post <post@stud.tu-darmstadt.de>
Co-authored-by: 4712 <4712@users.noreply.github.com>
davidbitton pushed a commit to davidbitton/betaflight that referenced this pull request Feb 5, 2024
…94 (betaflight#12605)

* Refactor Feedforward Angle and RC Smoothing

* update rc_smoothing at regular intervals

* add Earth Ref to OSD, update pid and rate PG

* Initialise filters correctly

* refactoring to improve performance

* Save 24 cycles in Horizon calculations, other optimisations

At a cost of 40 bytes

* save 25 cycles and 330 bytes in rc_smoothing

* feedforward max rate improvements

* typo fix

* Karatebrot's review suggestions  part one

* Karatebrot's excellent suggestions part 2

* more efficient if we calculate inverse at init time

Co-Authored-By: Jan Post <post@stud.tu-darmstadt.de>

* Horizon delay, to ease it in when returning sticks to centre

* fix unit tests after horizon changes

Co-Authored-By: 4712 <4712@users.noreply.github.com>

* horizon_delay_ms, default 500

* fix unit test for feedforward from setpointDelta

* Final optimisations - thanks @KarateBrot for your advice

* increase horizon level strength default to 75 now we have the delay

* restore Makefile value which allowed local make test on mac

---------

Co-authored-by: Jan Post <post@stud.tu-darmstadt.de>
Co-authored-by: 4712 <4712@users.noreply.github.com>
@ctzsnooze ctzsnooze deleted the Angle-Horizon-Feedforward-RCSmoothing-4_5 branch April 3, 2024 05:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: COMPLETED
Development

Successfully merging this pull request may close these issues.

None yet

7 participants