Please, correct error in anti-aliasing filter for gyro
Current Behavior
The 250 Hz pt1 filter used as anti-aliasing filter for gyro. It have attenuation about 1/5 at 1kHz, that is very insufficient.
Steps to Reproduce
model pt1 filter 250Hz, sampling rate 4kHz and measure attenuation at 1kHz.
Expected behavior
attenuation, at fS/2 should more than the signal-to-noise ratio (SNR) of the sampling system.
https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ApplicationNotes/ApplicationNotes/00699b.pdf https://electronics.stackexchange.com/questions/274696/anti-aliasing-filter-design
For 16bit representation this is about 90dB.
Suggested solution(s)
Use much effective filters.
Additional context
All versions of Inav have this problem.
Part of the issue is that for flight control case, we are interested not only in attenuation but also introduced group delay. I've run some numbers and current PT1 used indroduces 0.5ms of group delay. Doubling attenuation would double group delay as well (BiQuad). Increasing filter order would increase delay even more
Yes, but ignoring Dr. Nyquist will result in high frequency noise being pushed into the low frequency region. And filtering out low frequency noise will result in more delay. There is usually a lot of high frequency noise in a gyroscope.
Maybe not ignoring Dr. Nyquist. Rather compromising. Anyway, I quickly added https://github.com/iNavFlight/inav/pull/10710 but not really tested it yet
You are fast. I make two avereging. tested on bench. Next week will try to fly.
const bool ack = busReadBuf(gyro->busDev, ICM45600_RA_ACCEL_DATA_X1, data, 12);
if (!ack) {
return;
}
//(rand()%10000-5000);
GYRO_A[0]-= (int32_t) GYRO_V[0][IMU_ptr];
GYRO_V[0][IMU_ptr] = (int16_t)(rand()%10000-5000);//int16_val_little_endian(data, 3);
GYRO_A[0]+= (int32_t) GYRO_V[0][IMU_ptr];
GYRO_A1[0]-= GYRO_V1[0][IMU_ptr1];
GYRO_V1[0][IMU_ptr1] = GYRO_A[0];
GYRO_A1[0]+= GYRO_V1[0][IMU_ptr1];
GYRO_A[1]-= (int32_t) GYRO_V[1][IMU_ptr];
GYRO_V[1][IMU_ptr] = int16_val_little_endian(data, 4);
GYRO_A[1]+= (int32_t) GYRO_V[1][IMU_ptr];
GYRO_A1[1]-= GYRO_V1[1][IMU_ptr1];
GYRO_V1[1][IMU_ptr1] = GYRO_A[1];
GYRO_A1[1]+= GYRO_V1[1][IMU_ptr1];
GYRO_A[2]-= (int32_t) GYRO_V[2][IMU_ptr];
GYRO_V[2][IMU_ptr] = int16_val_little_endian(data, 5);
GYRO_A[2]+= (int32_t) GYRO_V[2][IMU_ptr];
GYRO_A1[2]-= GYRO_V1[2][IMU_ptr1];
GYRO_V1[2][IMU_ptr1] = GYRO_A[2];
GYRO_A1[2]+= GYRO_V1[2][IMU_ptr1];
ACC_A[0]-= (int32_t) ACC_V[0][IMU_ptr];
ACC_V[0][IMU_ptr] = int16_val_little_endian(data, 0);
ACC_A[0]+= (int32_t) ACC_V[0][IMU_ptr];
ACC_A1[0]-= ACC_V1[0][IMU_ptr1];
ACC_V1[0][IMU_ptr1] = ACC_A[0];
ACC_A1[0]+= ACC_V1[0][IMU_ptr1];
ACC_A[1]-= (int32_t) ACC_V[1][IMU_ptr];
ACC_V[1][IMU_ptr] = int16_val_little_endian(data, 1);
ACC_A[1]+= (int32_t) ACC_V[1][IMU_ptr];
ACC_A1[1]-= ACC_V1[1][IMU_ptr1];
ACC_V1[1][IMU_ptr1] = ACC_A[1];
ACC_A1[1]+= ACC_V1[1][IMU_ptr1];
ACC_A[2]-= (int32_t) ACC_V[2][IMU_ptr];
ACC_V[2][IMU_ptr] = int16_val_little_endian(data, 2);
ACC_A[2]+= (int32_t) ACC_V[2][IMU_ptr];
ACC_A1[2]-= ACC_V1[2][IMU_ptr1];
ACC_V1[2][IMU_ptr1] = ACC_A[2];
ACC_A1[2]+= ACC_V1[2][IMU_ptr1];
IMU_ptr++;
if(IMU_ptr>=n)
{
IMU_ptr=0;
}
IMU_ptr1++;
if(IMU_ptr1>=n1)
{
IMU_ptr1=0;
}
Spectrum and step response 1 and 2 averaging 20 and 14 points in comparison to pt1 250Hz.
Tested Flies no worse than with standard filters. There is a little less noise.
- Standard filters. All by default.
- All standard filters off, except Kalman
It is interesting that despite the delay of about 6 ms, there is practically no prop wash. I even lowered the idle to 5 percent. https://youtu.be/yxB54G2ou74