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

Smith Compensator on PID measurement #6900

Merged
merged 6 commits into from
Apr 30, 2021
Merged

Conversation

DzikuVx
Copy link
Member

@DzikuVx DzikuVx commented Apr 27, 2021

Based on work in emuflight/EmuFlight

CC @Quick-Flash

@@ -349,6 +352,30 @@ bool pidInitFilters(void)
}
}

#ifdef USE_SMITH_PREDICTOR
smithPredictorInit(

Choose a reason for hiding this comment

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

any reason you don't use a for loop here to get all three axis?

Copy link
Member Author

Choose a reason for hiding this comment

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

At the end it's almost the same. Loop or 3 calls.

Choose a reason for hiding this comment

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

do 3 calls use more memory than a loop? Thats what i've always thought and for init code we don't need to worry about performance. Maybe i'm wrong and the compiler will optimize for that anyway.


// filter the delayedGyro to help reduce the overall noise this prediction adds
float delayed = pt1FilterApply(&predictor->smithPredictorFilter, predictor->data[predictor->idx]);
float delayCompensatedSample = predictor->smithPredictorStrength * (sample - delayed);

Choose a reason for hiding this comment

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

Small note here, in EmuFlight I recently changed this code. I moved the pt1Filter to be on the delayCompensatedSample instead of the delayed data. Seems to fly a bit better that way.

Choose a reason for hiding this comment

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

You've made other changes, but i'd still suggest this change.
float delayed = predictor->data[predictor->idx];
float delayCompensatedSample = pt1FilterApply(&predictor->smithPredictorFilter, predictor->smithPredictorStrength * (sample - delayed));

@Quick-Flash
Copy link

Quick-Flash commented Apr 27, 2021

I do like the idea of a separate file for the smith predictor. The original idea for the smith predictor came from dRonin actually. They used the smith predictor on the motor outputs, but doing it on the gyro is a lot simpler and I would guess give better results. Heres the dRonin code if you are interested. d-ronin/dRonin#2044

@DzikuVx
Copy link
Member Author

DzikuVx commented Apr 30, 2021

image

Red - not compensated gyro
Teal - 4ms compensated gyro

tests show that it indeed works and the compensated signal is indeed around 4ms in front of the not-compensated one.

Subjective flight results:

  • no change in smooths flight
  • seems to reduce propwash quite noticeably
  • fast turns to feel more controllable and locked-in (I know it's a abused phrase). Quad felt more on the rails

Cons: when working with a noisy gyro, can amplify noise. In those tests, both gyro LPF was off, only Matrix and Unicorn Filter were enabled

@DzikuVx DzikuVx added this to the 3.0 milestone Apr 30, 2021
@DzikuVx DzikuVx merged commit 5a4aaed into master Apr 30, 2021
@DzikuVx DzikuVx deleted the dzikuvx-smith-predictor branch April 30, 2021 16:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants