Skip to content

Commit 5ba4e5b

Browse files
Merge pull request #4681 from iNavFlight/de_yg_accel_weight_scaling
Ignore acceleration in estimated position when clipping or high vibration
2 parents 43630a0 + 0428b70 commit 5ba4e5b

File tree

5 files changed

+54
-8
lines changed

5 files changed

+54
-8
lines changed

src/main/flight/imu.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,7 @@ void imuCheckVibrationLevels(void)
580580
DEBUG_SET(DEBUG_VIBE, 1, accVibeLevels.y * 100);
581581
DEBUG_SET(DEBUG_VIBE, 2, accVibeLevels.z * 100);
582582
DEBUG_SET(DEBUG_VIBE, 3, accClipCount);
583+
// DEBUG_VIBE values 4-7 are used by NAV estimator
583584
}
584585

585586
void FAST_CODE NOINLINE imuUpdateAttitude(timeUs_t currentTimeUs)

src/main/navigation/navigation_pos_estimator.c

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#if defined(USE_NAV)
2626

2727
#include "build/build_config.h"
28+
#include "build/debug.h"
2829

2930
#include "common/axis.h"
3031
#include "common/log.h"
@@ -354,8 +355,37 @@ static bool gravityCalibrationComplete(void)
354355
return zeroCalibrationIsCompleteS(&posEstimator.imu.gravityCalibration);
355356
}
356357

357-
static void updateIMUTopic(void)
358+
static void updateIMUEstimationWeight(const float dt)
358359
{
360+
bool isAccClipped = accIsClipped();
361+
362+
// If accelerometer measurement is clipped - drop the acc weight to zero
363+
// and gradually restore weight back to 1.0 over time
364+
if (isAccClipped) {
365+
posEstimator.imu.accWeightFactor = 0.0f;
366+
}
367+
else {
368+
const float relAlpha = dt / (dt + INAV_ACC_CLIPPING_RC_CONSTANT);
369+
posEstimator.imu.accWeightFactor = posEstimator.imu.accWeightFactor * (1.0f - relAlpha) + 1.0f * relAlpha;
370+
}
371+
372+
// DEBUG_VIBE[0-3] are used in IMU
373+
DEBUG_SET(DEBUG_VIBE, 4, posEstimator.imu.accWeightFactor * 1000);
374+
}
375+
376+
float navGetAccelerometerWeight(void)
377+
{
378+
const float accWeightScaled = posEstimator.imu.accWeightFactor * positionEstimationConfig()->w_xyz_acc_p;
379+
DEBUG_SET(DEBUG_VIBE, 5, accWeightScaled * 1000);
380+
381+
return accWeightScaled;
382+
}
383+
384+
static void updateIMUTopic(timeUs_t currentTimeUs)
385+
{
386+
const float dt = US2S(currentTimeUs - posEstimator.imu.lastUpdateTime);
387+
posEstimator.imu.lastUpdateTime = currentTimeUs;
388+
359389
if (!isImuReady()) {
360390
posEstimator.imu.accelNEU.x = 0;
361391
posEstimator.imu.accelNEU.y = 0;
@@ -364,6 +394,9 @@ static void updateIMUTopic(void)
364394
restartGravityCalibration();
365395
}
366396
else {
397+
/* Update acceleration weight based on vibration levels and clipping */
398+
updateIMUEstimationWeight(dt);
399+
367400
fpVector3_t accelBF;
368401

369402
/* Read acceleration data in body frame */
@@ -435,12 +468,6 @@ static bool navIsHeadingUsable(void)
435468
}
436469
}
437470

438-
float navGetAccelerometerWeight(void)
439-
{
440-
// TODO(digitalentity): consider accelerometer health in weight calculation
441-
return positionEstimationConfig()->w_xyz_acc_p;
442-
}
443-
444471
static uint32_t calculateCurrentValidityFlags(timeUs_t currentTimeUs)
445472
{
446473
/* Figure out if we have valid position data from our data sources */
@@ -768,6 +795,7 @@ void initializePositionEstimator(void)
768795
posEstimator.est.eph = positionEstimationConfig()->max_eph_epv + 0.001f;
769796
posEstimator.est.epv = positionEstimationConfig()->max_eph_epv + 0.001f;
770797

798+
posEstimator.imu.lastUpdateTime = 0;
771799
posEstimator.gps.lastUpdateTime = 0;
772800
posEstimator.baro.lastUpdateTime = 0;
773801
posEstimator.surface.lastUpdateTime = 0;
@@ -778,6 +806,8 @@ void initializePositionEstimator(void)
778806
posEstimator.est.flowCoordinates[X] = 0;
779807
posEstimator.est.flowCoordinates[Y] = 0;
780808

809+
posEstimator.imu.accWeightFactor = 0;
810+
781811
restartGravityCalibration();
782812

783813
for (axis = 0; axis < 3; axis++) {
@@ -806,7 +836,7 @@ void FAST_CODE NOINLINE updatePositionEstimator(void)
806836
const timeUs_t currentTimeUs = micros();
807837

808838
/* Read updates from IMU, preprocess */
809-
updateIMUTopic();
839+
updateIMUTopic(currentTimeUs);
810840

811841
/* Update estimate */
812842
updateEstimatedTopic(currentTimeUs);

src/main/navigation/navigation_pos_estimator_private.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
#define INAV_BARO_AVERAGE_HZ 1.0f
5252
#define INAV_SURFACE_AVERAGE_HZ 1.0f
5353

54+
#define INAV_ACC_CLIPPING_RC_CONSTANT (0.010f) // Reduce acc weight for ~10ms after clipping
55+
5456
#define RANGEFINDER_RELIABILITY_RC_CONSTANT (0.47802f)
5557
#define RANGEFINDER_RELIABILITY_LIGHT_THRESHOLD (0.15f)
5658
#define RANGEFINDER_RELIABILITY_LOW_THRESHOLD (0.33f)
@@ -126,9 +128,11 @@ typedef struct {
126128
} navPositionEstimatorESTIMATE_t;
127129

128130
typedef struct {
131+
timeUs_t lastUpdateTime;
129132
fpVector3_t accelNEU;
130133
fpVector3_t accelBias;
131134
float calibratedGravityCMSS;
135+
float accWeightFactor;
132136
zeroCalibrationScalar_t gravityCalibration;
133137
} navPosisitonEstimatorIMU_t;
134138

src/main/sensors/acceleration.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,8 +541,12 @@ void accUpdate(void)
541541

542542
// Before filtering check for clipping and vibration levels
543543
if (fabsf(acc.accADCf[X]) > ACC_CLIPPING_THRESHOLD_G || fabsf(acc.accADCf[Y]) > ACC_CLIPPING_THRESHOLD_G || fabsf(acc.accADCf[Z]) > ACC_CLIPPING_THRESHOLD_G) {
544+
acc.isClipped = true;
544545
acc.accClipCount++;
545546
}
547+
else {
548+
acc.isClipped = false;
549+
}
546550

547551
// Calculate vibration levels
548552
for (int axis = 0; axis < XYZ_AXIS_COUNT; axis++) {
@@ -587,6 +591,11 @@ uint32_t accGetClipCount(void)
587591
return acc.accClipCount;
588592
}
589593

594+
bool accIsClipped(void)
595+
{
596+
return acc.isClipped;
597+
}
598+
590599
void accSetCalibrationValues(void)
591600
{
592601
if ((accelerometerConfig()->accZero.raw[X] == 0) && (accelerometerConfig()->accZero.raw[Y] == 0) && (accelerometerConfig()->accZero.raw[Z] == 0) &&

src/main/sensors/acceleration.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ typedef struct acc_s {
5555
float accADCf[XYZ_AXIS_COUNT]; // acceleration in g
5656
float accVibeSq[XYZ_AXIS_COUNT];
5757
uint32_t accClipCount;
58+
bool isClipped;
5859
} acc_t;
5960

6061
extern acc_t acc;
@@ -79,6 +80,7 @@ void accGetMeasuredAcceleration(fpVector3_t *measuredAcc);
7980
void accGetVibrationLevels(fpVector3_t *accVibeLevels);
8081
float accGetVibrationLevel(void);
8182
uint32_t accGetClipCount(void);
83+
bool accIsClipped(void);
8284
void accUpdate(void);
8385
void accSetCalibrationValues(void);
8486
void accInitFilters(void);

0 commit comments

Comments
 (0)