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

Dynamic Sfusion #363

Open
wants to merge 103 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
5cc67f2
sfusion: Use MBE
kounocom Jul 14, 2024
9c3bb73
sfusion: Tune MBE parameters
kounocom Jul 14, 2024
bfa3df9
sfusion: Unify full-scale ranges for all sensors (1000DPS/4G)
kounocom May 29, 2024
d383d45
sfusion: Perform custom motionless calibration before gyro offset
kounocom Jul 14, 2024
6b53da1
LSM6DSV: Increase accel ODR to 240Hz
kounocom Aug 21, 2024
9f52744
LSM6DSO: Increase accel ODR to 208Hz
kounocom Aug 21, 2024
ea1dfbd
BMI270: Increase accel ODR to 200Hz
kounocom Aug 21, 2024
1e0fc4a
sfusion: Adjust VQF params
kounocom Aug 21, 2024
04895aa
sfusion: Disable calibration entirely
kounocom Aug 21, 2024
9275f62
Skip loading sensor calibration
gorbit99 Aug 25, 2024
5c26f04
Put temperature into the FIFO wherever possible
gorbit99 Sep 11, 2024
28f37ef
Average temperatures and calculate change from that
gorbit99 Sep 11, 2024
52c84cc
Make biasForgettingTime temperature dependant
gorbit99 Sep 11, 2024
52ab595
Moved over some lines I missed
gorbit99 Sep 11, 2024
c627d0f
Decouple direct temperature sampling and sending
gorbit99 Sep 11, 2024
4171284
Add temperature stability constants for LSMs
kounocom Sep 11, 2024
4d992d6
Increase trust for MBE
kounocom Sep 11, 2024
e0c219b
Added per sensor VQF params
gorbit99 Sep 11, 2024
5da7022
Merge branch 'random-dev-branch-do-not-use' of https://github.com/kou…
gorbit99 Sep 11, 2024
aeb0291
There's definitely a better way to do this
kounocom Sep 12, 2024
f9caa07
Fix crash
gorbit99 Sep 12, 2024
7cfaa3e
Merge branch 'random-dev-branch-do-not-use' of https://github.com/kou…
gorbit99 Sep 12, 2024
4caaec7
Fix shaky tracker issue
gorbit99 Sep 12, 2024
4b4e055
Added non-blocking calibration
gorbit99 Sep 14, 2024
dcea19b
Don't use non-blocking calibration without USE_NONBLOCKING_CALIBRATION
gorbit99 Sep 14, 2024
a6ea9c0
Default to non-blocking calibration
kounocom Sep 16, 2024
01e97b1
Fifo overrun detection for bmi270
gorbit99 Sep 16, 2024
27b28d5
Fixed oddities during calibration
gorbit99 Sep 16, 2024
e80aaed
Fixed calibrations being calculated improperly
gorbit99 Sep 16, 2024
35344c2
Add the ability to calibrate all accel axes
gorbit99 Sep 16, 2024
7eda85a
Skip accel until next rest
gorbit99 Sep 16, 2024
fab0e3a
Calibrate gyro at 2 temperatures
gorbit99 Sep 16, 2024
7755b56
Lerp gyro offset between temperatures
gorbit99 Sep 16, 2024
5042735
Calibrate ZRO change rate
gorbit99 Sep 16, 2024
c14a0c6
make it 10x worse i guess
kounocom Sep 17, 2024
9b24282
Update more vqf params
kounocom Sep 17, 2024
498db44
Only print the calibration that was performed
gorbit99 Sep 17, 2024
60212a2
Blink LED when calibration step completed
gorbit99 Sep 17, 2024
c23ce1e
Merge branch 'random-dev-branch-do-not-use' of https://github.com/kou…
gorbit99 Sep 17, 2024
63bfa55
use logger
kounocom Sep 17, 2024
0040998
don't log that
kounocom Sep 17, 2024
68695a1
Fix BMI270 temperature reading
gorbit99 Sep 17, 2024
f7391b7
overclock 8266 by default
kounocom Sep 17, 2024
1b40787
Merge branch 'random-dev-branch-do-not-use' of https://github.com/kou…
kounocom Sep 17, 2024
c004563
reset defines
kounocom Sep 17, 2024
174e484
Implement getActiveSensorCount
gorbit99 Sep 17, 2024
c343959
Merge branch 'random-dev-branch-do-not-use' of https://github.com/kou…
gorbit99 Sep 17, 2024
cae480c
Merge branch 'random-dev-branch-do-not-use' of https://github.com/kou…
kounocom Sep 17, 2024
3fcc5d3
Cap TPS when esp8266 & aux
kounocom Sep 17, 2024
f18dfa8
overclock in platformio-tools
kounocom Sep 17, 2024
7bb5c36
Automatically expand the gyro calibration
gorbit99 Sep 18, 2024
4f026d2
Separate LSM6DS3 and LSM6DS3TR-C
kounocom Sep 18, 2024
dacbf76
Unify IMU params further
kounocom Sep 18, 2024
fc55aad
Merge branch 'dynamic-sfusion' of https://github.com/kounocom/SlimeVR…
kounocom Sep 18, 2024
54dc7a8
Refactor nonblocking calibration code
gorbit99 Sep 18, 2024
0dbd452
Merge branch 'dynamic-sfusion' of https://github.com/kounocom/SlimeVR…
gorbit99 Sep 18, 2024
8a63326
In theory this works?
gorbit99 Sep 25, 2024
9c2055c
Actually allow the calibration to be cancelled
gorbit99 Sep 29, 2024
8500fee
Add delay into calibration steps
gorbit99 Sep 29, 2024
9798738
Make rest detection more sensitive
kounocom Sep 29, 2024
f219cc3
Always limit TPS with aux (now to 90)
kounocom Sep 29, 2024
db71a05
change to 4g, fill in missing stuff elsewhere
kounocom Sep 30, 2024
44e2aaf
This works better
kounocom Oct 1, 2024
eec8ac6
Actually enable FIFO this time
gorbit99 Oct 1, 2024
bc65001
Use clock
kounocom Oct 1, 2024
1aae55a
Use 8KB FIFO
kounocom Oct 2, 2024
73faa41
Sleep more
kounocom Oct 2, 2024
6515014
Hires mode maybe?
gorbit99 Oct 2, 2024
b84096c
Merge branch 'icm45686-firmware' of https://github.com/gorbit99/Slime…
gorbit99 Oct 2, 2024
6eb1ef9
Use correct sensitivity
kounocom Oct 2, 2024
6f74905
Merge branch 'icm45686-firmware' into dynamic-sfusion
gorbit99 Oct 2, 2024
099fd9a
Stuffs for dynamic
kounocom Oct 2, 2024
1e47ff7
Increase sensitivity when gyro is calibrated + skip accel calibration…
gorbit99 Oct 8, 2024
ea5ea1a
Merge branch 'dynamic-sfusion' of https://github.com/kounocom/SlimeVR…
gorbit99 Oct 8, 2024
5222085
ACTUALLY skip accel calibration
gorbit99 Oct 8, 2024
3d9ad76
Zero out accel calibration
gorbit99 Oct 8, 2024
afb4d32
Whoops
gorbit99 Oct 8, 2024
2f2c248
Adjust VQF params more
kounocom Oct 11, 2024
1faff26
...and some more
kounocom Oct 11, 2024
4950a17
...and then make them actually work per-sensor
kounocom Oct 11, 2024
2ef6306
...and then light the LED when rest is detected, as a debug step
kounocom Oct 11, 2024
f1ac5aa
...and finally, change whatever these do
kounocom Oct 11, 2024
fede1e3
Merge commit 'b278bcfcf4d5bcc4a71d25d4485510c11bd8d530' into dynamic-…
gorbit99 Nov 12, 2024
5457a0d
Merge commit '2946a6a7a69ce2b0052cc5ba44ba020429bce2f3' into dynamic-…
gorbit99 Nov 12, 2024
325a5ce
Merge commit '85dead25f339bc3a6d79a147b6ca0e9e55741f1d' into dynamic-…
gorbit99 Nov 12, 2024
9ab9ee7
Merge commit 'a9f5b1ae8c65e13856d14dacdef5dc341e42f7b5' into dynamic-…
gorbit99 Nov 12, 2024
56a3507
Merge commit 'a4a9778f62d0b962c46898d03e9ce70171a1ca12' into dynamic-…
gorbit99 Nov 12, 2024
35cc25b
Merge commit '50fa801653022f5b2604cfdb06915b6211b28f43' into dynamic-…
gorbit99 Nov 12, 2024
ff5836c
Merge commit '0b882db74f6565fc8b63f6ae638f951dec4441d4' into dynamic-…
gorbit99 Nov 12, 2024
14e3891
Merge commit '628fe209609956c8d5ba8af83cb54d52fdf7e71b' into dynamic-…
gorbit99 Nov 12, 2024
9d96d19
ICM45 implementation
gorbit99 Nov 12, 2024
4ba3b5b
Make sure it builds even without nonblocking calibration
gorbit99 Nov 12, 2024
69951cb
Fix clangformat errors
gorbit99 Nov 12, 2024
ca68392
Apply suggestions from code review
gorbit99 Nov 12, 2024
c7fb10c
define USE_NONBLOCKING_CALIBRATION as true instead
gorbit99 Nov 12, 2024
4ff6e1b
Increase clang format version to 18
gorbit99 Nov 12, 2024
b9aad36
Apply formatting
gorbit99 Nov 12, 2024
7a8d980
Apply even more formatting
gorbit99 Nov 13, 2024
e20c0d2
Even more linting
gorbit99 Nov 13, 2024
49ef1ef
Linting test
gorbit99 Nov 13, 2024
75fc842
Base formatting
gorbit99 Nov 13, 2024
b7e05ca
Manually clear up issues
gorbit99 Nov 13, 2024
8a10e2b
Remove unnecessary change to includes
gorbit99 Nov 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- uses: actions/checkout@v4
- uses: jidicula/[email protected]
with:
clang-format-version: "17"
clang-format-version: "18"
fallback-style: google
# Disable clang-tidy for now
# - name: Get clang-tidy
Expand Down
58 changes: 14 additions & 44 deletions lib/vqf/vqf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,41 +18,6 @@

inline vqf_real_t square(vqf_real_t x) { return x*x; }


VQFParams::VQFParams()
: tauAcc(3.0)
, tauMag(9.0)
#ifndef VQF_NO_MOTION_BIAS_ESTIMATION
, motionBiasEstEnabled(true)
#endif
, restBiasEstEnabled(true)
, magDistRejectionEnabled(true)
, biasSigmaInit(0.5)
, biasForgettingTime(100.0)
, biasClip(2.0)
#ifndef VQF_NO_MOTION_BIAS_ESTIMATION
, biasSigmaMotion(0.1)
, biasVerticalForgettingFactor(0.0001)
#endif
, biasSigmaRest(0.03)
, restMinT(1.5)
, restFilterTau(0.5)
, restThGyr(2.0)
, restThAcc(0.5)
, magCurrentTau(0.05)
, magRefTau(20.0)
, magNormTh(0.1)
, magDipTh(10.0)
, magNewTime(20.0)
, magNewFirstTime(5.0)
, magNewMinGyr(20.0)
, magMinUndisturbedTime(0.5)
, magMaxRejectionTime(60.0)
, magRejectionFactor(2.0)
{

}

VQF::VQF(vqf_real_t gyrTs, vqf_real_t accTs, vqf_real_t magTs)
{
coeffs.gyrTs = gyrTs;
Expand Down Expand Up @@ -917,16 +882,8 @@ void VQF::setup()

coeffs.biasP0 = square(params.biasSigmaInit*100.0);
// the system noise increases the variance from 0 to (0.1 °/s)^2 in biasForgettingTime seconds
coeffs.biasV = square(0.1*100.0)*coeffs.accTs/params.biasForgettingTime;

#ifndef VQF_NO_MOTION_BIAS_ESTIMATION
vqf_real_t pMotion = square(params.biasSigmaMotion*100.0);
coeffs.biasMotionW = square(pMotion) / coeffs.biasV + pMotion;
coeffs.biasVerticalW = coeffs.biasMotionW / std::max(params.biasVerticalForgettingFactor, vqf_real_t(1e-10));
#endif

vqf_real_t pRest = square(params.biasSigmaRest*100.0);
coeffs.biasRestW = square(pRest) / coeffs.biasV + pRest;
updateBiasForgettingTime(params.biasForgettingTime);

filterCoeffs(params.restFilterTau, coeffs.gyrTs, coeffs.restGyrLpB, coeffs.restGyrLpA);
filterCoeffs(params.restFilterTau, coeffs.accTs, coeffs.restAccLpB, coeffs.restAccLpA);
Expand All @@ -941,3 +898,16 @@ void VQF::setup()

resetState();
}

void VQF::updateBiasForgettingTime(float biasForgettingTime) {
coeffs.biasV = square(0.1*100.0)*coeffs.accTs/params.biasForgettingTime;

#ifndef VQF_NO_MOTION_BIAS_ESTIMATION
vqf_real_t pMotion = square(params.biasSigmaMotion*100.0);
coeffs.biasMotionW = square(pMotion) / coeffs.biasV + pMotion;
coeffs.biasVerticalW = coeffs.biasMotionW / std::max(params.biasVerticalForgettingFactor, vqf_real_t(1e-10));
#endif

vqf_real_t pRest = square(params.biasSigmaRest*100.0);
coeffs.biasRestW = square(pRest) / coeffs.biasV + pRest;
}
59 changes: 28 additions & 31 deletions lib/vqf/vqf.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include <stddef.h>

#define VQF_SINGLE_PRECISION
#define VQF_NO_MOTION_BIAS_ESTIMATION
// #define VQF_NO_MOTION_BIAS_ESTIMATION
#define M_PI 3.14159265358979323846
#define M_SQRT2 1.41421356237309504880

Expand Down Expand Up @@ -41,11 +41,6 @@ typedef float vqf_real_t;
*/
struct VQFParams
{
/**
* @brief Constructor that initializes the struct with the default parameters.
*/
VQFParams();

/**
* @brief Time constant \f$\tau_\mathrm{acc}\f$ for accelerometer low-pass filtering in seconds.
*
Expand All @@ -57,7 +52,7 @@ struct VQFParams
*
* Default value: 3.0 s
*/
vqf_real_t tauAcc;
vqf_real_t tauAcc = 3.0;
/**
* @brief Time constant \f$\tau_\mathrm{mag}\f$ for magnetometer update in seconds.
*
Expand All @@ -70,7 +65,7 @@ struct VQFParams
*
* Default value: 9.0 s
*/
vqf_real_t tauMag;
vqf_real_t tauMag = 9.0;

#ifndef VQF_NO_MOTION_BIAS_ESTIMATION
/**
Expand All @@ -79,15 +74,15 @@ struct VQFParams
* If set to true (default), gyroscope bias is estimated based on the inclination correction only, i.e. without
* using magnetometer measurements.
*/
bool motionBiasEstEnabled;
bool motionBiasEstEnabled = true;
#endif
/**
* @brief Enables rest detection and gyroscope bias estimation during rest phases.
*
* If set to true (default), phases in which the IMU is at rest are detected. During rest, the gyroscope bias
* is estimated from the low-pass filtered gyroscope readings.
*/
bool restBiasEstEnabled;
bool restBiasEstEnabled = true;
/**
* @brief Enables magnetic disturbance detection and magnetic disturbance rejection.
*
Expand All @@ -96,22 +91,22 @@ struct VQFParams
* the disturbances exceeds #magMaxRejectionTime, magnetometer-based updates are performed, but with an increased
* time constant.
*/
bool magDistRejectionEnabled;
bool magDistRejectionEnabled = true;

/**
* @brief Standard deviation of the initial bias estimation uncertainty (in degrees per second).
*
* Default value: 0.5 °/s
*/
vqf_real_t biasSigmaInit;
vqf_real_t biasSigmaInit = 0.5;
/**
* @brief Time in which the bias estimation uncertainty increases from 0 °/s to 0.1 °/s (in seconds).
*
* This value determines the system noise assumed by the Kalman filter.
*
* Default value: 100.0 s
*/
vqf_real_t biasForgettingTime;
vqf_real_t biasForgettingTime = 100.0;
/**
* @brief Maximum expected gyroscope bias (in degrees per second).
*
Expand All @@ -121,7 +116,7 @@ struct VQFParams
*
* Default value: 2.0 °/s
*/
vqf_real_t biasClip;
vqf_real_t biasClip = 2.0;
#ifndef VQF_NO_MOTION_BIAS_ESTIMATION
/**
* @brief Standard deviation of the converged bias estimation uncertainty during motion (in degrees per second).
Expand All @@ -130,7 +125,7 @@ struct VQFParams
*
* Default value: 0.1 °/s
*/
vqf_real_t biasSigmaMotion;
vqf_real_t biasSigmaMotion = 0.1125;
/**
* @brief Forgetting factor for unobservable bias in vertical direction during motion.
*
Expand All @@ -140,7 +135,7 @@ struct VQFParams
*
* Default value: 0.0001
*/
vqf_real_t biasVerticalForgettingFactor;
vqf_real_t biasVerticalForgettingFactor = 0.0001;
#endif
/**
* @brief Standard deviation of the converged bias estimation uncertainty during rest (in degrees per second).
Expand All @@ -149,7 +144,7 @@ struct VQFParams
*
* Default value: 0.03 °
*/
vqf_real_t biasSigmaRest;
vqf_real_t biasSigmaRest = 0.03;

/**
* @brief Time threshold for rest detection (in seconds).
Expand All @@ -158,7 +153,7 @@ struct VQFParams
*
* Default value: 1.5 s
*/
vqf_real_t restMinT;
vqf_real_t restMinT = 0.5;
/**
* @brief Time constant for the low-pass filter used in rest detection (in seconds).
*
Expand All @@ -167,7 +162,7 @@ struct VQFParams
*
* Default value: 0.5 s
*/
vqf_real_t restFilterTau;
vqf_real_t restFilterTau = 0.5;
/**
* @brief Angular velocity threshold for rest detection (in °/s).
*
Expand All @@ -176,7 +171,7 @@ struct VQFParams
*
* Default value: 2.0 °/s
*/
vqf_real_t restThGyr;
vqf_real_t restThGyr = 2.0;
/**
* @brief Acceleration threshold for rest detection (in m/s²).
*
Expand All @@ -185,7 +180,7 @@ struct VQFParams
*
* Default value: 0.5 m/s²
*/
vqf_real_t restThAcc;
vqf_real_t restThAcc = 0.5;

/**
* @brief Time constant for current norm/dip value in magnetic disturbance detection (in seconds).
Expand All @@ -196,29 +191,29 @@ struct VQFParams
*
* Default value: 0.05 s
*/
vqf_real_t magCurrentTau;
vqf_real_t magCurrentTau = 0.05;
/**
* @brief Time constant for the adjustment of the magnetic field reference (in seconds).
*
* This adjustment allows the reference estimate to converge to the observed undisturbed field.
*
* Default value: 20.0 s
*/
vqf_real_t magRefTau;
vqf_real_t magRefTau = 20.0;
/**
* @brief Relative threshold for the magnetic field strength for magnetic disturbance detection.
*
* This value is relative to the reference norm.
*
* Default value: 0.1 (10%)
*/
vqf_real_t magNormTh;
vqf_real_t magNormTh = 0.1;
/**
* @brief Threshold for the magnetic field dip angle for magnetic disturbance detection (in degrees).
*
* Default vaule: 10 °
*/
vqf_real_t magDipTh;
vqf_real_t magDipTh = 10.0;
/**
* @brief Duration after which to accept a different homogeneous magnetic field (in seconds).
*
Expand All @@ -228,7 +223,7 @@ struct VQFParams
*
* Default value: 20.0
*/
vqf_real_t magNewTime;
vqf_real_t magNewTime = 20.0;
/**
* @brief Duration after which to accept a homogeneous magnetic field for the first time (in seconds).
*
Expand All @@ -237,21 +232,21 @@ struct VQFParams
*
* Default value: 5.0
*/
vqf_real_t magNewFirstTime;
vqf_real_t magNewFirstTime = 5.0;
/**
* @brief Minimum angular velocity needed in order to count time for new magnetic field acceptance (in °/s).
*
* Durations for which the angular velocity norm is below this threshold do not count towards reaching #magNewTime.
*
* Default value: 20.0 °/s
*/
vqf_real_t magNewMinGyr;
vqf_real_t magNewMinGyr = 20.0;
/**
* @brief Minimum duration within thresholds after which to regard the field as undisturbed again (in seconds).
*
* Default value: 0.5 s
*/
vqf_real_t magMinUndisturbedTime;
vqf_real_t magMinUndisturbedTime = 0.5;
/**
* @brief Maximum duration of full magnetic disturbance rejection (in seconds).
*
Expand All @@ -262,7 +257,7 @@ struct VQFParams
*
* Default value: 60.0 s
*/
vqf_real_t magMaxRejectionTime;
vqf_real_t magMaxRejectionTime = 60.0;
/**
* @brief Factor by which to slow the heading correction during long disturbed phases.
*
Expand All @@ -274,7 +269,7 @@ struct VQFParams
*
* Default value: 2.0
*/
vqf_real_t magRejectionFactor;
vqf_real_t magRejectionFactor = 2.0;
};

/**
Expand Down Expand Up @@ -987,6 +982,8 @@ class VQF
static bool matrix3Inv(const vqf_real_t in[9], vqf_real_t out[9]);
#endif

void updateBiasForgettingTime(float biasForgettingTime);

protected:
/**
* @brief Calculates coefficients based on parameters and sampling rates.
Expand Down
4 changes: 4 additions & 0 deletions platformio-tools.ini
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,22 @@ board = esp12e
[env:BOARD_NODEMCU]
platform = espressif8266 @ 4.2.1
board = esp12e
board_build.f_cpu = 160000000L

[env:BOARD_WEMOSD1MINI]
platform = espressif8266 @ 4.2.1
board = esp12e
board_build.f_cpu = 160000000L

[env:BOARD_TTGO_TBASE]
platform = espressif8266 @ 4.2.1
board = esp12e
board_build.f_cpu = 160000000L

[env:BOARD_WEMOSWROOM02]
platform = espressif8266 @ 4.2.1
board = esp12e
board_build.f_cpu = 160000000L

[env:BOARD_WROOM32]
platform = espressif32 @ 6.7.0
Expand Down
Loading