Skip to content

Commit ca6e4b2

Browse files
authored
Merge pull request #11571 from breadoven/abo_pt1filter_cleanup
PT1 low pass filter clean up + fixes
2 parents 3eede56 + 3b4090d commit ca6e4b2

19 files changed

Lines changed: 200 additions & 193 deletions

docs/Settings.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5946,6 +5946,7 @@ Selection of pitot hardware. VIRTUAL only works if a GPS is enabled.
59465946
| FAKE | |
59475947
| MSP | |
59485948
| DLVR-L10D | |
5949+
| MS5525 | |
59495950

59505951
---
59515952

src/main/common/filter.c

Lines changed: 20 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -34,72 +34,54 @@ float nullFilterApply(void *filter, float input)
3434
return input;
3535
}
3636

37-
float nullFilterApply4(void *filter, float input, float f_cut, float dt)
37+
float nullFilterApply3(void *filter, float input, float dt)
3838
{
3939
UNUSED(filter);
40-
UNUSED(f_cut);
4140
UNUSED(dt);
4241
return input;
4342
}
4443

45-
// PT1 Low Pass filter
44+
/* PT1 Low Pass filter
45+
* f_cut = cutoff frequency. Use pt1FilterSetTimeConstant to directly set RC time constant tau if required.
46+
*/
4647

47-
static float FAST_CODE pt1ComputeRC(const float f_cut)
48+
static float pt1ComputeRC(const float f_cut)
4849
{
4950
return 1.0f / (2.0f * M_PIf * f_cut);
5051
}
5152

52-
// f_cut = cutoff frequency
53-
void pt1FilterInitRC(pt1Filter_t *filter, float tau, float dT)
53+
void pt1FilterInit(pt1Filter_t *filter, float f_cut, float dT)
5454
{
55-
filter->state = 0.0f;
56-
filter->RC = tau;
55+
filter->RC = pt1ComputeRC(f_cut);
5756
filter->dT = dT;
5857
filter->alpha = filter->dT / (filter->RC + filter->dT);
58+
filter->state = 0.0f;
5959
}
6060

61-
void pt1FilterInit(pt1Filter_t *filter, float f_cut, float dT)
61+
float FAST_CODE NOINLINE pt1FilterApply(pt1Filter_t *filter, float input) // use with pt1FilterInit if dT and f_cut are constants
6262
{
63-
pt1FilterInitRC(filter, pt1ComputeRC(f_cut), dT);
64-
}
65-
66-
void pt1FilterSetTimeConstant(pt1Filter_t *filter, float tau) {
67-
filter->RC = tau;
68-
}
69-
70-
float pt1FilterGetLastOutput(pt1Filter_t *filter) {
71-
return filter->state;
63+
return filter->state = filter->state + filter->alpha * (input - filter->state);
7264
}
7365

74-
void pt1FilterUpdateCutoff(pt1Filter_t *filter, float f_cut)
66+
float FAST_CODE NOINLINE pt1FilterApply3(pt1Filter_t *filter, float input, float dT)
7567
{
76-
filter->RC = pt1ComputeRC(f_cut);
68+
filter->dT = dT; // cache latest dT for possible use in pt1FilterApply
7769
filter->alpha = filter->dT / (filter->RC + filter->dT);
78-
}
7970

80-
float FAST_CODE NOINLINE pt1FilterApply(pt1Filter_t *filter, float input)
81-
{
82-
filter->state = filter->state + filter->alpha * (input - filter->state);
83-
return filter->state;
71+
return filter->state = filter->state + filter->alpha * (input - filter->state);
8472
}
8573

86-
float pt1FilterApply3(pt1Filter_t *filter, float input, float dT)
87-
{
88-
filter->dT = dT;
89-
filter->state = filter->state + dT / (filter->RC + dT) * (input - filter->state);
90-
return filter->state;
74+
void pt1FilterSetTimeConstant(pt1Filter_t *filter, float tau) {
75+
filter->RC = tau;
9176
}
9277

93-
float FAST_CODE NOINLINE pt1FilterApply4(pt1Filter_t *filter, float input, float f_cut, float dT)
78+
void pt1FilterSetCutoff(pt1Filter_t *filter, float f_cut)
9479
{
95-
// Pre calculate and store RC
96-
if (!filter->RC) {
97-
filter->RC = pt1ComputeRC(f_cut);
98-
}
99-
100-
filter->dT = dT; // cache latest dT for possible use in pt1FilterApply
80+
filter->RC = pt1ComputeRC(f_cut);
10181
filter->alpha = filter->dT / (filter->RC + filter->dT);
102-
filter->state = filter->state + filter->alpha * (input - filter->state);
82+
}
83+
84+
float pt1FilterGetLastOutput(pt1Filter_t *filter) {
10385
return filter->state;
10486
}
10587

src/main/common/filter.h

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ typedef struct biquadFilter_s {
4747
float x1, x2, y1, y2;
4848
} biquadFilter_t;
4949

50-
typedef union {
51-
biquadFilter_t biquad;
50+
typedef union {
51+
biquadFilter_t biquad;
5252
pt1Filter_t pt1;
5353
pt2Filter_t pt2;
5454
pt3Filter_t pt3;
@@ -88,22 +88,19 @@ typedef struct alphaBetaGammaFilter_s {
8888
} alphaBetaGammaFilter_t;
8989

9090
typedef float (*filterApplyFnPtr)(void *filter, float input);
91-
typedef float (*filterApply4FnPtr)(void *filter, float input, float f_cut, float dt);
91+
typedef float (*filterApply3FnPtr)(void *filter, float input, float dt);
9292

9393
#define BIQUAD_BANDWIDTH 1.9f /* bandwidth in octaves */
9494
#define BIQUAD_Q 1.0f / sqrtf(2.0f) /* quality factor - butterworth*/
9595

9696
float nullFilterApply(void *filter, float input);
97-
float nullFilterApply4(void *filter, float input, float f_cut, float dt);
98-
97+
float nullFilterApply3(void *filter, float input, float dt);
9998
void pt1FilterInit(pt1Filter_t *filter, float f_cut, float dT);
100-
void pt1FilterInitRC(pt1Filter_t *filter, float tau, float dT);
101-
void pt1FilterSetTimeConstant(pt1Filter_t *filter, float tau);
102-
void pt1FilterUpdateCutoff(pt1Filter_t *filter, float f_cut);
103-
float pt1FilterGetLastOutput(pt1Filter_t *filter);
10499
float pt1FilterApply(pt1Filter_t *filter, float input);
105100
float pt1FilterApply3(pt1Filter_t *filter, float input, float dT);
106-
float pt1FilterApply4(pt1Filter_t *filter, float input, float f_cut, float dt);
101+
void pt1FilterSetTimeConstant(pt1Filter_t *filter, float tau);
102+
void pt1FilterSetCutoff(pt1Filter_t *filter, float f_cut);
103+
float pt1FilterGetLastOutput(pt1Filter_t *filter);
107104
void pt1FilterReset(pt1Filter_t *filter, float input);
108105

109106
/*

src/main/common/fp_pid.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ float navPidApply3(
4646
) {
4747
float newProportional, newDerivative, newFeedForward;
4848
float error = 0.0f;
49-
49+
5050
if (pid->errorLpfHz > 0.0f) {
51-
error = pt1FilterApply4(&pid->error_filter_state, setpoint - measurement, pid->errorLpfHz, dt);
51+
error = pt1FilterApply3(&pid->error_filter_state, setpoint - measurement, dt);
5252
} else {
5353
error = setpoint - measurement;
5454
}
@@ -73,7 +73,7 @@ float navPidApply3(
7373
}
7474

7575
if (pid->dTermLpfHz > 0.0f) {
76-
newDerivative = pid->param.kD * pt1FilterApply4(&pid->dterm_filter_state, newDerivative, pid->dTermLpfHz, dt);
76+
newDerivative = pid->param.kD * pt1FilterApply3(&pid->dterm_filter_state, newDerivative, dt);
7777
} else {
7878
newDerivative = pid->param.kD * newDerivative;
7979
}
@@ -105,10 +105,7 @@ float navPidApply3(
105105
pid->output_constrained = outValConstrained;
106106

107107
/* Update I-term */
108-
if (
109-
!(pidFlags & PID_ZERO_INTEGRATOR) &&
110-
!(pidFlags & PID_FREEZE_INTEGRATOR)
111-
) {
108+
if (!(pidFlags & PID_ZERO_INTEGRATOR) && !(pidFlags & PID_FREEZE_INTEGRATOR)) {
112109
const float newIntegrator = pid->integrator + (error * pid->param.kI * gainScaler * dt) + (backCalc * pid->param.kT * dt);
113110

114111
if (pidFlags & PID_SHRINK_INTEGRATOR) {
@@ -121,10 +118,10 @@ float navPidApply3(
121118
pid->integrator = newIntegrator;
122119
}
123120
}
124-
121+
125122
if (pidFlags & PID_LIMIT_INTEGRATOR) {
126123
pid->integrator = constrainf(pid->integrator, outMin, outMax);
127-
}
124+
}
128125

129126
return outValConstrained;
130127
}
@@ -143,8 +140,9 @@ void navPidReset(pidController_t *pid)
143140
pid->integrator = 0.0f;
144141
pid->last_input = 0.0f;
145142
pid->feedForward = 0.0f;
146-
pt1FilterReset(&pid->dterm_filter_state, 0.0f);
147143
pid->output_constrained = 0.0f;
144+
145+
pt1FilterReset(&pid->dterm_filter_state, 0.0f);
148146
}
149147

150148
void navPidInit(pidController_t *pid, float _kP, float _kI, float _kD, float _kFF, float _dTermLpfHz, float _errorLpfHz)
@@ -169,5 +167,9 @@ void navPidInit(pidController_t *pid, float _kP, float _kI, float _kD, float _kF
169167
}
170168
pid->dTermLpfHz = _dTermLpfHz;
171169
pid->errorLpfHz = _errorLpfHz;
170+
171+
pt1FilterSetCutoff(&pid->dterm_filter_state, pid->dTermLpfHz);
172+
pt1FilterSetCutoff(&pid->error_filter_state, pid->errorLpfHz);
173+
172174
navPidReset(pid);
173175
}

src/main/flight/imu.c

Lines changed: 23 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -99,21 +99,16 @@ FASTRAM float rMat[3][3];
9999

100100
STATIC_FASTRAM imuRuntimeConfig_t imuRuntimeConfig;
101101

102-
STATIC_FASTRAM pt1Filter_t rotRateFilterX;
103-
STATIC_FASTRAM pt1Filter_t rotRateFilterY;
104-
STATIC_FASTRAM pt1Filter_t rotRateFilterZ;
102+
STATIC_FASTRAM pt1Filter_t rotRateFilter[XYZ_AXIS_COUNT];
105103
FASTRAM fpVector3_t imuMeasuredRotationBFFiltered = {.v = {0.0f, 0.0f, 0.0f}};
106104

107-
STATIC_FASTRAM pt1Filter_t accelFilterX;
108-
STATIC_FASTRAM pt1Filter_t accelFilterY;
109-
STATIC_FASTRAM pt1Filter_t accelFilterZ;
105+
STATIC_FASTRAM pt1Filter_t accelFilter[XYZ_AXIS_COUNT];
110106
FASTRAM fpVector3_t imuMeasuredAccelBFFiltered = {.v = {0.0f, 0.0f, 0.0f}};
111107

112-
STATIC_FASTRAM pt1Filter_t HeadVecEFFilterX;
113-
STATIC_FASTRAM pt1Filter_t HeadVecEFFilterY;
114-
STATIC_FASTRAM pt1Filter_t HeadVecEFFilterZ;
108+
STATIC_FASTRAM pt1Filter_t HeadVecEFFilter[XYZ_AXIS_COUNT];
115109
FASTRAM fpVector3_t HeadVecEFFiltered = {.v = {0.0f, 0.0f, 0.0f}};
116110

111+
static pt1Filter_t GPS3DspeedFilter;
117112

118113
FASTRAM bool gpsHeadingInitialized;
119114

@@ -202,18 +197,19 @@ void imuInit(void)
202197
quaternionInitUnit(&orientation);
203198
imuComputeRotationMatrix();
204199

205-
// Initialize rotation rate filter
206-
pt1FilterReset(&rotRateFilterX, 0);
207-
pt1FilterReset(&rotRateFilterY, 0);
208-
pt1FilterReset(&rotRateFilterZ, 0);
209-
// Initialize accel filter
210-
pt1FilterReset(&accelFilterX, 0);
211-
pt1FilterReset(&accelFilterY, 0);
212-
pt1FilterReset(&accelFilterZ, 0);
213-
// Initialize Heading vector filter
214-
pt1FilterReset(&HeadVecEFFilterX, 0);
215-
pt1FilterReset(&HeadVecEFFilterY, 0);
216-
pt1FilterReset(&HeadVecEFFilterZ, 0);
200+
// Initialize rotation rate, accel and Heading vector filters
201+
for (uint8_t axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
202+
pt1FilterSetCutoff(&rotRateFilter[axis], IMU_ROTATION_LPF);
203+
pt1FilterReset(&rotRateFilter[axis], 0.0f);
204+
205+
pt1FilterSetCutoff(&accelFilter[axis], IMU_ROTATION_LPF);
206+
pt1FilterReset(&accelFilter[axis], 0.0f);
207+
208+
pt1FilterSetCutoff(&HeadVecEFFilter[axis], IMU_ROTATION_LPF);
209+
pt1FilterReset(&HeadVecEFFilter[axis], 0.0f);
210+
}
211+
212+
pt1FilterSetCutoff(&GPS3DspeedFilter, IMU_ROTATION_LPF);
217213
}
218214

219215
void imuSetMagneticDeclination(float declinationDeg)
@@ -684,19 +680,11 @@ static float imuCalculateAccelerometerWeightRateIgnore(const float acc_ignore_sl
684680

685681
static void imuCalculateFilters(float dT)
686682
{
687-
//flitering
688-
imuMeasuredRotationBFFiltered.x = pt1FilterApply4(&rotRateFilterX, imuMeasuredRotationBF.x, IMU_ROTATION_LPF, dT);
689-
imuMeasuredRotationBFFiltered.y = pt1FilterApply4(&rotRateFilterY, imuMeasuredRotationBF.y, IMU_ROTATION_LPF, dT);
690-
imuMeasuredRotationBFFiltered.z = pt1FilterApply4(&rotRateFilterZ, imuMeasuredRotationBF.z, IMU_ROTATION_LPF, dT);
691-
692-
imuMeasuredAccelBFFiltered.x = pt1FilterApply4(&accelFilterX, imuMeasuredAccelBF.x, IMU_ROTATION_LPF, dT);
693-
imuMeasuredAccelBFFiltered.y = pt1FilterApply4(&accelFilterY, imuMeasuredAccelBF.y, IMU_ROTATION_LPF, dT);
694-
imuMeasuredAccelBFFiltered.z = pt1FilterApply4(&accelFilterZ, imuMeasuredAccelBF.z, IMU_ROTATION_LPF, dT);
695-
696-
HeadVecEFFiltered.x = pt1FilterApply4(&HeadVecEFFilterX, rMat[0][0], IMU_ROTATION_LPF, dT);
697-
HeadVecEFFiltered.y = pt1FilterApply4(&HeadVecEFFilterY, rMat[1][0], IMU_ROTATION_LPF, dT);
698-
HeadVecEFFiltered.z = pt1FilterApply4(&HeadVecEFFilterZ, rMat[2][0], IMU_ROTATION_LPF, dT);
699-
683+
for (uint8_t axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
684+
imuMeasuredRotationBFFiltered.v[axis] = pt1FilterApply3(&rotRateFilter[axis], imuMeasuredRotationBF.v[axis], dT);
685+
imuMeasuredAccelBFFiltered.v[axis] = pt1FilterApply3(&accelFilter[axis], imuMeasuredAccelBF.v[axis], dT);
686+
HeadVecEFFiltered.v[axis] = pt1FilterApply3(&HeadVecEFFilter[axis], rMat[axis][0], dT);
687+
}
700688
}
701689

702690
static void imuCalculateGPSacceleration(fpVector3_t *vEstAccelEF,fpVector3_t *vEstcentrifugalAccelBF, float *acc_ignore_slope_multipiler)
@@ -732,12 +720,11 @@ static void imuCalculateTurnRateacceleration(fpVector3_t *vEstcentrifugalAccelBF
732720
if (isGPSTrustworthy()) {
733721
//first speed choice is gps
734722
static bool lastGPSHeartbeat;
735-
static pt1Filter_t GPS3DspeedFilter;
736723
static float GPS3DspeedFiltered = 0.0f;
737724
if (gpsSol.flags.gpsHeartbeat != lastGPSHeartbeat) {
738725
lastGPSHeartbeat = gpsSol.flags.gpsHeartbeat;
739726
float GPS3Dspeed = calc_length_pythagorean_3D(gpsSol.velNED[X], gpsSol.velNED[Y], gpsSol.velNED[Z]);
740-
GPS3DspeedFiltered = pt1FilterApply4(&GPS3DspeedFilter, GPS3Dspeed, IMU_ROTATION_LPF, dT);
727+
GPS3DspeedFiltered = pt1FilterApply3(&GPS3DspeedFilter, GPS3Dspeed, dT);
741728
}
742729
currentspeed = GPS3DspeedFiltered;
743730
*acc_ignore_slope_multipiler = 4.0f;

0 commit comments

Comments
 (0)