mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-17 05:15:25 +03:00
Rework Acc filtering
This commit is contained in:
parent
974274b748
commit
57a3e59a38
8 changed files with 48 additions and 46 deletions
|
@ -492,8 +492,7 @@ static void resetConf(void)
|
||||||
resetRollAndPitchTrims(&masterConfig.accelerometerTrims);
|
resetRollAndPitchTrims(&masterConfig.accelerometerTrims);
|
||||||
|
|
||||||
masterConfig.mag_declination = 0;
|
masterConfig.mag_declination = 0;
|
||||||
masterConfig.acc_lpf_hz = 20;
|
masterConfig.acc_lpf_hz = 10.0f;
|
||||||
masterConfig.accz_lpf_cutoff = 5.0f;
|
|
||||||
masterConfig.accDeadband.xy = 40;
|
masterConfig.accDeadband.xy = 40;
|
||||||
masterConfig.accDeadband.z = 40;
|
masterConfig.accDeadband.z = 40;
|
||||||
masterConfig.acc_unarmedcal = 1;
|
masterConfig.acc_unarmedcal = 1;
|
||||||
|
@ -730,6 +729,7 @@ void activateConfig(void)
|
||||||
|
|
||||||
useFailsafeConfig(&masterConfig.failsafeConfig);
|
useFailsafeConfig(&masterConfig.failsafeConfig);
|
||||||
setAccelerationTrims(&masterConfig.accZero);
|
setAccelerationTrims(&masterConfig.accZero);
|
||||||
|
setAccelerationFilter(masterConfig.acc_lpf_hz);
|
||||||
|
|
||||||
mixerUseConfigs(
|
mixerUseConfigs(
|
||||||
#ifdef USE_SERVOS
|
#ifdef USE_SERVOS
|
||||||
|
@ -745,7 +745,6 @@ void activateConfig(void)
|
||||||
|
|
||||||
imuRuntimeConfig.dcm_kp = masterConfig.dcm_kp / 10000.0f;
|
imuRuntimeConfig.dcm_kp = masterConfig.dcm_kp / 10000.0f;
|
||||||
imuRuntimeConfig.dcm_ki = masterConfig.dcm_ki / 10000.0f;
|
imuRuntimeConfig.dcm_ki = masterConfig.dcm_ki / 10000.0f;
|
||||||
imuRuntimeConfig.acc_cut_hz = masterConfig.acc_lpf_hz;
|
|
||||||
imuRuntimeConfig.acc_unarmedcal = masterConfig.acc_unarmedcal;
|
imuRuntimeConfig.acc_unarmedcal = masterConfig.acc_unarmedcal;
|
||||||
imuRuntimeConfig.small_angle = masterConfig.small_angle;
|
imuRuntimeConfig.small_angle = masterConfig.small_angle;
|
||||||
|
|
||||||
|
@ -753,7 +752,6 @@ void activateConfig(void)
|
||||||
&imuRuntimeConfig,
|
&imuRuntimeConfig,
|
||||||
¤tProfile->pidProfile,
|
¤tProfile->pidProfile,
|
||||||
&masterConfig.accDeadband,
|
&masterConfig.accDeadband,
|
||||||
masterConfig.accz_lpf_cutoff,
|
|
||||||
masterConfig.throttle_correction_angle
|
masterConfig.throttle_correction_angle
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -72,8 +72,7 @@ typedef struct master_t {
|
||||||
|
|
||||||
rollAndPitchTrims_t accelerometerTrims; // accelerometer trim
|
rollAndPitchTrims_t accelerometerTrims; // accelerometer trim
|
||||||
|
|
||||||
uint8_t acc_lpf_hz; // Set the Low Pass Filter factor for ACC. Reducing this value would reduce ACC noise (visible in GUI), but would increase ACC lag time. Zero = no filter
|
float acc_lpf_hz; // cutoff frequency for the low pass filter used on the acc z-axis for althold in Hz
|
||||||
float accz_lpf_cutoff; // cutoff frequency for the low pass filter used on the acc z-axis for althold in Hz
|
|
||||||
accDeadband_t accDeadband;
|
accDeadband_t accDeadband;
|
||||||
barometerConfig_t barometerConfig;
|
barometerConfig_t barometerConfig;
|
||||||
uint8_t acc_unarmedcal; // turn automatic acc compensation on/off
|
uint8_t acc_unarmedcal; // turn automatic acc compensation on/off
|
||||||
|
|
|
@ -56,7 +56,6 @@
|
||||||
// http://gentlenav.googlecode.com/files/fastRotations.pdf
|
// http://gentlenav.googlecode.com/files/fastRotations.pdf
|
||||||
#define SPIN_RATE_LIMIT 20
|
#define SPIN_RATE_LIMIT 20
|
||||||
|
|
||||||
int16_t accSmooth[XYZ_AXIS_COUNT];
|
|
||||||
int32_t accSum[XYZ_AXIS_COUNT];
|
int32_t accSum[XYZ_AXIS_COUNT];
|
||||||
|
|
||||||
uint32_t accTimeSum = 0; // keep track for integration of acc
|
uint32_t accTimeSum = 0; // keep track for integration of acc
|
||||||
|
@ -111,14 +110,13 @@ void imuConfigure(
|
||||||
imuRuntimeConfig_t *initialImuRuntimeConfig,
|
imuRuntimeConfig_t *initialImuRuntimeConfig,
|
||||||
pidProfile_t *initialPidProfile,
|
pidProfile_t *initialPidProfile,
|
||||||
accDeadband_t *initialAccDeadband,
|
accDeadband_t *initialAccDeadband,
|
||||||
float accz_lpf_cutoff,
|
|
||||||
uint16_t throttle_correction_angle
|
uint16_t throttle_correction_angle
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
imuRuntimeConfig = initialImuRuntimeConfig;
|
imuRuntimeConfig = initialImuRuntimeConfig;
|
||||||
pidProfile = initialPidProfile;
|
pidProfile = initialPidProfile;
|
||||||
accDeadband = initialAccDeadband;
|
accDeadband = initialAccDeadband;
|
||||||
fc_acc = calculateAccZLowPassFilterRCTimeConstant(accz_lpf_cutoff);
|
fc_acc = calculateAccZLowPassFilterRCTimeConstant(5.0f); // Set to fix value
|
||||||
throttleAngleScale = calculateThrottleAngleScale(throttle_correction_angle);
|
throttleAngleScale = calculateThrottleAngleScale(throttle_correction_angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,11 +375,8 @@ static bool isMagnetometerHealthy(void)
|
||||||
|
|
||||||
static void imuCalculateEstimatedAttitude(void)
|
static void imuCalculateEstimatedAttitude(void)
|
||||||
{
|
{
|
||||||
static biquad_t accLPFState[3];
|
|
||||||
static bool accStateIsSet;
|
|
||||||
static uint32_t previousIMUUpdateTime;
|
static uint32_t previousIMUUpdateTime;
|
||||||
float rawYawError = 0;
|
float rawYawError = 0;
|
||||||
int32_t axis;
|
|
||||||
bool useAcc = false;
|
bool useAcc = false;
|
||||||
bool useMag = false;
|
bool useMag = false;
|
||||||
bool useYaw = false;
|
bool useYaw = false;
|
||||||
|
@ -390,20 +385,6 @@ static void imuCalculateEstimatedAttitude(void)
|
||||||
uint32_t deltaT = currentTime - previousIMUUpdateTime;
|
uint32_t deltaT = currentTime - previousIMUUpdateTime;
|
||||||
previousIMUUpdateTime = currentTime;
|
previousIMUUpdateTime = currentTime;
|
||||||
|
|
||||||
// Smooth and use only valid accelerometer readings
|
|
||||||
for (axis = 0; axis < 3; axis++) {
|
|
||||||
if (imuRuntimeConfig->acc_cut_hz) {
|
|
||||||
if (accStateIsSet) {
|
|
||||||
accSmooth[axis] = lrintf(applyBiQuadFilter((float) accADC[axis], &accLPFState[axis]));
|
|
||||||
} else {
|
|
||||||
for (axis = 0; axis < 3; axis++) BiQuadNewLpf(imuRuntimeConfig->acc_cut_hz, &accLPFState[axis], 1000);
|
|
||||||
accStateIsSet = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
accSmooth[axis] = accADC[axis];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (imuIsAccelerometerHealthy()) {
|
if (imuIsAccelerometerHealthy()) {
|
||||||
useAcc = true;
|
useAcc = true;
|
||||||
}
|
}
|
||||||
|
@ -445,9 +426,9 @@ void imuUpdateGyroAndAttitude(void)
|
||||||
if (sensors(SENSOR_ACC) && isAccelUpdatedAtLeastOnce) {
|
if (sensors(SENSOR_ACC) && isAccelUpdatedAtLeastOnce) {
|
||||||
imuCalculateEstimatedAttitude();
|
imuCalculateEstimatedAttitude();
|
||||||
} else {
|
} else {
|
||||||
accADC[X] = 0;
|
accSmooth[X] = 0;
|
||||||
accADC[Y] = 0;
|
accSmooth[Y] = 0;
|
||||||
accADC[Z] = 0;
|
accSmooth[Z] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ extern int16_t throttleAngleCorrection;
|
||||||
extern uint32_t accTimeSum;
|
extern uint32_t accTimeSum;
|
||||||
extern int accSumCount;
|
extern int accSumCount;
|
||||||
extern float accVelScale;
|
extern float accVelScale;
|
||||||
extern int16_t accSmooth[XYZ_AXIS_COUNT];
|
|
||||||
extern int32_t accSum[XYZ_AXIS_COUNT];
|
extern int32_t accSum[XYZ_AXIS_COUNT];
|
||||||
|
|
||||||
#define DEGREES_TO_DECIDEGREES(angle) (angle * 10)
|
#define DEGREES_TO_DECIDEGREES(angle) (angle * 10)
|
||||||
|
@ -74,7 +73,6 @@ void imuConfigure(
|
||||||
imuRuntimeConfig_t *initialImuRuntimeConfig,
|
imuRuntimeConfig_t *initialImuRuntimeConfig,
|
||||||
pidProfile_t *initialPidProfile,
|
pidProfile_t *initialPidProfile,
|
||||||
accDeadband_t *initialAccDeadband,
|
accDeadband_t *initialAccDeadband,
|
||||||
float accz_lpf_cutoff,
|
|
||||||
uint16_t throttle_correction_angle
|
uint16_t throttle_correction_angle
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -84,7 +82,7 @@ void imuUpdateAccelerometer(rollAndPitchTrims_t *accelerometerTrims);
|
||||||
void imuUpdateGyroAndAttitude(void);
|
void imuUpdateGyroAndAttitude(void);
|
||||||
float calculateThrottleAngleScale(uint16_t throttle_correction_angle);
|
float calculateThrottleAngleScale(uint16_t throttle_correction_angle);
|
||||||
int16_t calculateThrottleAngleCorrection(uint8_t throttle_correction_value);
|
int16_t calculateThrottleAngleCorrection(uint8_t throttle_correction_value);
|
||||||
float calculateAccZLowPassFilterRCTimeConstant(float accz_lpf_cutoff);
|
float calculateAccZLowPassFilterRCTimeConstant(float accz_lpf_hz);
|
||||||
|
|
||||||
int16_t imuCalculateHeading(t_fp_vector *vec);
|
int16_t imuCalculateHeading(t_fp_vector *vec);
|
||||||
|
|
||||||
|
|
|
@ -658,10 +658,9 @@ const clivalue_t valueTable[] = {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{ "acc_hardware", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, &masterConfig.acc_hardware, .config.lookup = { TABLE_ACC_HARDWARE } },
|
{ "acc_hardware", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, &masterConfig.acc_hardware, .config.lookup = { TABLE_ACC_HARDWARE } },
|
||||||
{ "acc_lpf_hz", VAR_UINT8 | MASTER_VALUE, &masterConfig.acc_lpf_hz, .config.minmax = { 0, 200 } },
|
{ "acc_lpf_hz", VAR_FLOAT | MASTER_VALUE, &masterConfig.acc_lpf_hz, .config.minmax = { 0, 400 } },
|
||||||
{ "accxy_deadband", VAR_UINT8 | MASTER_VALUE, &masterConfig.accDeadband.xy, .config.minmax = { 0, 100 } },
|
{ "accxy_deadband", VAR_UINT8 | MASTER_VALUE, &masterConfig.accDeadband.xy, .config.minmax = { 0, 100 } },
|
||||||
{ "accz_deadband", VAR_UINT8 | MASTER_VALUE, &masterConfig.accDeadband.z, .config.minmax = { 0, 100 } },
|
{ "accz_deadband", VAR_UINT8 | MASTER_VALUE, &masterConfig.accDeadband.z, .config.minmax = { 0, 100 } },
|
||||||
{ "accz_lpf_cutoff", VAR_FLOAT | MASTER_VALUE, &masterConfig.accz_lpf_cutoff, .config.minmax = { 1, 20 } },
|
|
||||||
{ "acc_unarmedcal", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, &masterConfig.acc_unarmedcal, .config.lookup = { TABLE_OFF_ON } },
|
{ "acc_unarmedcal", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, &masterConfig.acc_unarmedcal, .config.lookup = { TABLE_OFF_ON } },
|
||||||
{ "acc_trim_pitch", VAR_INT16 | MASTER_VALUE, &masterConfig.accelerometerTrims.values.pitch, .config.minmax = { -300, 300 } },
|
{ "acc_trim_pitch", VAR_INT16 | MASTER_VALUE, &masterConfig.accelerometerTrims.values.pitch, .config.minmax = { -300, 300 } },
|
||||||
{ "acc_trim_roll", VAR_INT16 | MASTER_VALUE, &masterConfig.accelerometerTrims.values.roll, .config.minmax = { -300, 300 } },
|
{ "acc_trim_roll", VAR_INT16 | MASTER_VALUE, &masterConfig.accelerometerTrims.values.roll, .config.minmax = { -300, 300 } },
|
||||||
|
|
|
@ -651,7 +651,6 @@ int main(void) {
|
||||||
|
|
||||||
setTaskEnabled(TASK_GYROPID, true);
|
setTaskEnabled(TASK_GYROPID, true);
|
||||||
if(sensors(SENSOR_ACC)) {
|
if(sensors(SENSOR_ACC)) {
|
||||||
uint32_t accTargetLooptime = 0;
|
|
||||||
setTaskEnabled(TASK_ACCEL, true);
|
setTaskEnabled(TASK_ACCEL, true);
|
||||||
switch(targetLooptime) {
|
switch(targetLooptime) {
|
||||||
case(500):
|
case(500):
|
||||||
|
|
|
@ -17,14 +17,17 @@
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
#include "common/axis.h"
|
#include "common/axis.h"
|
||||||
|
#include "common/filter.h"
|
||||||
|
|
||||||
#include "drivers/sensor.h"
|
#include "drivers/sensor.h"
|
||||||
#include "drivers/accgyro.h"
|
#include "drivers/accgyro.h"
|
||||||
#include "drivers/system.h"
|
#include "drivers/system.h"
|
||||||
|
#include "drivers/gyro_sync.h"
|
||||||
|
|
||||||
#include "sensors/battery.h"
|
#include "sensors/battery.h"
|
||||||
#include "sensors/sensors.h"
|
#include "sensors/sensors.h"
|
||||||
|
@ -35,11 +38,12 @@
|
||||||
|
|
||||||
#include "sensors/acceleration.h"
|
#include "sensors/acceleration.h"
|
||||||
|
|
||||||
int32_t accADC[XYZ_AXIS_COUNT];
|
int32_t accSmooth[XYZ_AXIS_COUNT];
|
||||||
|
|
||||||
acc_t acc; // acc access functions
|
acc_t acc; // acc access functions
|
||||||
sensor_align_e accAlign = 0;
|
sensor_align_e accAlign = 0;
|
||||||
uint16_t acc_1G = 256; // this is the 1G measured acceleration.
|
uint16_t acc_1G = 256; // this is the 1G measured acceleration.
|
||||||
|
uint32_t accTargetLooptime;
|
||||||
|
|
||||||
uint16_t calibratingA = 0; // the calibration is done is the main loop. Calibrating decreases at each cycle down to 0, then we enter in a normal mode.
|
uint16_t calibratingA = 0; // the calibration is done is the main loop. Calibrating decreases at each cycle down to 0, then we enter in a normal mode.
|
||||||
|
|
||||||
|
@ -51,6 +55,10 @@ extern bool AccInflightCalibrationActive;
|
||||||
|
|
||||||
static flightDynamicsTrims_t *accelerationTrims;
|
static flightDynamicsTrims_t *accelerationTrims;
|
||||||
|
|
||||||
|
static float accLpfCutHz = 0;
|
||||||
|
static biquad_t accFilterState[XYZ_AXIS_COUNT];
|
||||||
|
static bool accFilterInitialised = false;
|
||||||
|
|
||||||
void accSetCalibrationCycles(uint16_t calibrationCyclesRequired)
|
void accSetCalibrationCycles(uint16_t calibrationCyclesRequired)
|
||||||
{
|
{
|
||||||
calibratingA = calibrationCyclesRequired;
|
calibratingA = calibrationCyclesRequired;
|
||||||
|
@ -89,10 +97,10 @@ void performAcclerationCalibration(rollAndPitchTrims_t *rollAndPitchTrims)
|
||||||
a[axis] = 0;
|
a[axis] = 0;
|
||||||
|
|
||||||
// Sum up CALIBRATING_ACC_CYCLES readings
|
// Sum up CALIBRATING_ACC_CYCLES readings
|
||||||
a[axis] += accADC[axis];
|
a[axis] += accSmooth[axis];
|
||||||
|
|
||||||
// Reset global variables to prevent other code from using un-calibrated data
|
// Reset global variables to prevent other code from using un-calibrated data
|
||||||
accADC[axis] = 0;
|
accSmooth[axis] = 0;
|
||||||
accelerationTrims->raw[axis] = 0;
|
accelerationTrims->raw[axis] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,9 +139,9 @@ void performInflightAccelerationCalibration(rollAndPitchTrims_t *rollAndPitchTri
|
||||||
if (InflightcalibratingA == 50)
|
if (InflightcalibratingA == 50)
|
||||||
b[axis] = 0;
|
b[axis] = 0;
|
||||||
// Sum up 50 readings
|
// Sum up 50 readings
|
||||||
b[axis] += accADC[axis];
|
b[axis] += accSmooth[axis];
|
||||||
// Clear global variables for next reading
|
// Clear global variables for next reading
|
||||||
accADC[axis] = 0;
|
accSmooth[axis] = 0;
|
||||||
accelerationTrims->raw[axis] = 0;
|
accelerationTrims->raw[axis] = 0;
|
||||||
}
|
}
|
||||||
// all values are measured
|
// all values are measured
|
||||||
|
@ -165,9 +173,9 @@ void performInflightAccelerationCalibration(rollAndPitchTrims_t *rollAndPitchTri
|
||||||
|
|
||||||
void applyAccelerationTrims(flightDynamicsTrims_t *accelerationTrims)
|
void applyAccelerationTrims(flightDynamicsTrims_t *accelerationTrims)
|
||||||
{
|
{
|
||||||
accADC[X] -= accelerationTrims->raw[X];
|
accSmooth[X] -= accelerationTrims->raw[X];
|
||||||
accADC[Y] -= accelerationTrims->raw[Y];
|
accSmooth[Y] -= accelerationTrims->raw[Y];
|
||||||
accADC[Z] -= accelerationTrims->raw[Z];
|
accSmooth[Z] -= accelerationTrims->raw[Z];
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateAccelerationReadings(rollAndPitchTrims_t *rollAndPitchTrims)
|
void updateAccelerationReadings(rollAndPitchTrims_t *rollAndPitchTrims)
|
||||||
|
@ -179,9 +187,22 @@ void updateAccelerationReadings(rollAndPitchTrims_t *rollAndPitchTrims)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (axis = 0; axis < XYZ_AXIS_COUNT; axis++) accADC[axis] = accADCRaw[axis];
|
for (axis = 0; axis < XYZ_AXIS_COUNT; axis++) accSmooth[axis] = accADCRaw[axis];
|
||||||
|
|
||||||
alignSensors(accADC, accADC, accAlign);
|
if (accLpfCutHz) {
|
||||||
|
if (!accFilterInitialised) {
|
||||||
|
if (accTargetLooptime) { /* Initialisation needs to happen once sample rate is known */
|
||||||
|
for (axis = 0; axis < 3; axis++) BiQuadNewLpf(accLpfCutHz, &accFilterState[axis], accTargetLooptime);
|
||||||
|
accFilterInitialised = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accFilterInitialised) {
|
||||||
|
for (axis = 0; axis < XYZ_AXIS_COUNT; axis++) accSmooth[axis] = lrintf(applyBiQuadFilter((float) accSmooth[axis], &accFilterState[axis]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
alignSensors(accSmooth, accSmooth, accAlign);
|
||||||
|
|
||||||
if (!isAccelerationCalibrationComplete()) {
|
if (!isAccelerationCalibrationComplete()) {
|
||||||
performAcclerationCalibration(rollAndPitchTrims);
|
performAcclerationCalibration(rollAndPitchTrims);
|
||||||
|
@ -198,3 +219,8 @@ void setAccelerationTrims(flightDynamicsTrims_t *accelerationTrimsToUse)
|
||||||
{
|
{
|
||||||
accelerationTrims = accelerationTrimsToUse;
|
accelerationTrims = accelerationTrimsToUse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setAccelerationFilter(float initialAccLpfCutHz)
|
||||||
|
{
|
||||||
|
accLpfCutHz = initialAccLpfCutHz;
|
||||||
|
}
|
||||||
|
|
|
@ -36,8 +36,9 @@ typedef enum {
|
||||||
extern sensor_align_e accAlign;
|
extern sensor_align_e accAlign;
|
||||||
extern acc_t acc;
|
extern acc_t acc;
|
||||||
extern uint16_t acc_1G;
|
extern uint16_t acc_1G;
|
||||||
|
extern uint32_t accTargetLooptime;
|
||||||
|
|
||||||
extern int32_t accADC[XYZ_AXIS_COUNT];
|
extern int32_t accSmooth[XYZ_AXIS_COUNT];
|
||||||
|
|
||||||
typedef struct rollAndPitchTrims_s {
|
typedef struct rollAndPitchTrims_s {
|
||||||
int16_t roll;
|
int16_t roll;
|
||||||
|
@ -54,3 +55,4 @@ void accSetCalibrationCycles(uint16_t calibrationCyclesRequired);
|
||||||
void resetRollAndPitchTrims(rollAndPitchTrims_t *rollAndPitchTrims);
|
void resetRollAndPitchTrims(rollAndPitchTrims_t *rollAndPitchTrims);
|
||||||
void updateAccelerationReadings(rollAndPitchTrims_t *rollAndPitchTrims);
|
void updateAccelerationReadings(rollAndPitchTrims_t *rollAndPitchTrims);
|
||||||
void setAccelerationTrims(flightDynamicsTrims_t *accelerationTrimsToUse);
|
void setAccelerationTrims(flightDynamicsTrims_t *accelerationTrimsToUse);
|
||||||
|
void setAccelerationFilter(float initialAccLpfCutHz);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue