Files
SlimeVR-Tracker-ESP/src/sensors/SensorFusion.h
Przemyslaw Romaniak ea00bebedd SoftFusion sensor framework with BMI, ICM, LSM6, MPU sensor implementations (#322)
* Update readme to mention BMI270 support.

* Soft fusion sensor initial code, wip

* Soft fusion ICM-42688-P lazy WIP implementation.

* sfusion: Cleanup, implemented sensor frequency calibration

* icm42688: add more comments, basic driver (no hw filtering) should be working

* sfustion: compilation fix

* sfusion: start calibration when upside down

* cleanup: remove confusing had data flag

* sensor manager: use unique_ptr instead of raw pointers

* sfusion: big refactoring wip

* sfusion: make aux work, at least sfusion sensors should now be functional

* sfusion: lightweight implementation of BMI270 sensor, no sensitivity cal yet

* sfusion: BMI270: added CRT and gyro zx factor. should be functionally equivalent to the old driver

* Added lsm6dsv

* Trying to work around esp32c3 compilation problem, not liking that solution

* sfusion: fix problems found after rebase

* Update README.md

* Bump Arduino core to 3.0 to match GCC12

* Remove fast pin swapping that is no longer compatible with arduino core v3

* Bring back fast pin swapping

* Update platformio-tools.ini

* Fix accel timescale (calibration no longer takes forever)

* Fix non-sfusion sensors

* Added LSM6DSO and DSR support and refactored DSV support

* Removed template float param from the implementation

* sfusion: port MPU6050 driver wip, not expecting to be functional yet

* sfusion: add headers specifying main code owners

* connection: fix warning

* update README.md

* fshelper: fixed ESP8266 regression caused by abstracting FS access

* sfusion: fix error on merge

* bno080: differentiate bno080, bno085, bno086 again

* sfusion: final touches

* restore hadData functionality, implementing it in every sensor, made configured flag bno-only

* fix address supplement in non-sfusion sensors, do i2c bus reset for all sensors

* sfusion: make MPU6050 driver use normal MPU6050 ImuID, change eatSamplesAndReturn function to take ms instead of seconds

* sfusion: hotfix, don't apply sensorOffset, it's applied in sensor base

* Log FIFO overruns on LSMs

* Reset the soft watchdog while eating or collecting calibration samples

Resolves an issue where the soft watchdog would trigger.

* Fix missing word in comment, switch to constexpr

* Update esp32/esp8266

---------

Co-authored-by: Gorbit99 <gorbitgames@gmail.com>
Co-authored-by: nekomona <nekomona@nekomona.com>
Co-authored-by: nekomona <nekomona@163.com>
Co-authored-by: unlogisch04 <98281608+unlogisch04@users.noreply.github.com>
Co-authored-by: kounocom <meia@kouno.xyz>
Co-authored-by: Kubuxu <oss@kubuxu.com>
2024-06-25 13:57:18 +03:00

134 lines
4.6 KiB
C++

#ifndef SLIMEVR_SENSORFUSION_H
#define SLIMEVR_SENSORFUSION_H
#include "globals.h"
#include "sensor.h"
#define SENSOR_DOUBLE_PRECISION 0
#define SENSOR_FUSION_TYPE SENSOR_FUSION_VQF
#define SENSOR_FUSION_MAHONY 1
#define SENSOR_FUSION_MADGWICK 2
#define SENSOR_FUSION_BASICVQF 3
#define SENSOR_FUSION_VQF 4
#if SENSOR_FUSION_TYPE == SENSOR_FUSION_MAHONY
#define SENSOR_FUSION_TYPE_STRING "mahony"
#elif SENSOR_FUSION_TYPE == SENSOR_FUSION_MADGWICK
#define SENSOR_FUSION_TYPE_STRING "madgwick"
#elif SENSOR_FUSION_TYPE == SENSOR_FUSION_BASICVQF
#define SENSOR_FUSION_TYPE_STRING "bvqf"
#elif SENSOR_FUSION_TYPE == SENSOR_FUSION_VQF
#define SENSOR_FUSION_TYPE_STRING "vqf"
#endif
#define SENSOR_USE_MAHONY (SENSOR_FUSION_TYPE == SENSOR_FUSION_MAHONY)
#define SENSOR_USE_MADGWICK (SENSOR_FUSION_TYPE == SENSOR_FUSION_MADGWICK)
#define SENSOR_USE_BASICVQF (SENSOR_FUSION_TYPE == SENSOR_FUSION_BASICVQF)
#define SENSOR_USE_VQF (SENSOR_FUSION_TYPE == SENSOR_FUSION_VQF)
#include "../motionprocessing/types.h"
#include "mahony.h"
#include "madgwick.h"
#include <vqf.h>
#include <basicvqf.h>
namespace SlimeVR
{
namespace Sensors
{
#if SENSOR_USE_VQF
struct SensorVQFParams: VQFParams {
SensorVQFParams() : VQFParams() {
#ifndef VQF_NO_MOTION_BIAS_ESTIMATION
motionBiasEstEnabled = true;
#endif
tauAcc = 2.0f;
restMinT = 2.0f;
restThGyr = 0.6f; // 400 norm
restThAcc = 0.06f; // 100 norm
}
};
#endif
class SensorFusion
{
public:
SensorFusion(sensor_real_t gyrTs, sensor_real_t accTs=-1.0, sensor_real_t magTs=-1.0)
: gyrTs(gyrTs),
accTs( (accTs<0) ? gyrTs : accTs ),
magTs( (magTs<0) ? gyrTs : magTs )
#if SENSOR_USE_MAHONY
#elif SENSOR_USE_MADGWICK
#elif SENSOR_USE_BASICVQF
, basicvqf(gyrTs, ((accTs<0) ? gyrTs : accTs),
((magTs<0) ? gyrTs : magTs))
#elif SENSOR_USE_VQF
, vqf(vqfParams, gyrTs, ((accTs<0) ? gyrTs : accTs),
((magTs<0) ? gyrTs : magTs))
#endif
{}
void update6D(sensor_real_t Axyz[3], sensor_real_t Gxyz[3], sensor_real_t deltat=-1.0f);
void update9D(sensor_real_t Axyz[3], sensor_real_t Gxyz[3], sensor_real_t Mxyz[3], sensor_real_t deltat=-1.0f);
void updateAcc(const sensor_real_t Axyz[3], sensor_real_t deltat=-1.0f);
void updateMag(const sensor_real_t Mxyz[3], sensor_real_t deltat=-1.0f);
void updateGyro(const sensor_real_t Gxyz[3], sensor_real_t deltat=-1.0f);
bool isUpdated();
void clearUpdated();
sensor_real_t const * getQuaternion();
Quat getQuaternionQuat();
sensor_real_t const * getGravityVec();
sensor_real_t const * getLinearAcc();
void getLinearAcc(sensor_real_t outLinAccel[3]);
Vector3 getLinearAccVec();
static void calcGravityVec(const sensor_real_t qwxyz[4], sensor_real_t gravVec[3]);
static void calcLinearAcc(const sensor_real_t accin[3], const sensor_real_t gravVec[3], sensor_real_t accout[3]);
protected:
sensor_real_t gyrTs;
sensor_real_t accTs;
sensor_real_t magTs;
#if SENSOR_USE_MAHONY
Mahony<sensor_real_t> mahony;
#elif SENSOR_USE_MADGWICK
Madgwick<sensor_real_t> madgwick;
#elif SENSOR_USE_BASICVQF
BasicVQF basicvqf;
#elif SENSOR_USE_VQF
SensorVQFParams vqfParams {};
VQF vqf;
#endif
// A also used for linear acceleration extraction
sensor_real_t bAxyz[3]{0.0f, 0.0f, 0.0f};
#if SENSOR_USE_MAHONY || SENSOR_USE_MADGWICK
// Buffer M here to keep the behavior of BMI160
sensor_real_t bMxyz[3]{0.0f, 0.0f, 0.0f};
bool accelUpdated = false;
#endif
bool magExist = false;
sensor_real_t qwxyz[4]{1.0f, 0.0f, 0.0f, 0.0f};
bool updated = false;
bool gravityReady = false;
sensor_real_t vecGravity[3]{0.0f, 0.0f, 0.0f};
bool linaccelReady = false;
sensor_real_t linAccel[3]{0.0f, 0.0f, 0.0f};
#if ESP32
sensor_real_t linAccel_guard; // Temporary patch for some weird ESP32 bug
#endif
};
}
}
#endif // SLIMEVR_SENSORFUSION_H