xioTechnologies / Fusion

MIT License
913 stars 230 forks source link

Proper way of calling FusionAhrsUpdate with accel, gyro and mag all having different update rates #170

Closed lvdlvd closed 1 week ago

lvdlvd commented 1 week ago

Apologies if this is obvious, but i get implausible results if i do this naively, and i can't find authoritative documentation on the matter.

i have an accelerometer sampling at 100Hz, a gyroscope at 400Hz and a magnetometer at about 150Hz without a common clock base, i.e. they have each their own free running oscilattors, but the samples come in with accurate timestamps.

Looking inside the FusionAhrsUpdate function, it seems to be able to deal with the accel and mag missing, so depending on which sensor data is coming in, i call it as below: whenever i get the accel or the mag, i re-use the last gyro:

/* struct FusionSample { fstype: accel/gyro/mag,  uint64_t us timestamp, float xyz[3] } */

static uint64_t     last_us        = 0;
static FusionVector last_gyroscope = {{0.0f, 0.0f, 0.0f}};

int fusion_update(struct FusionSample *fs) {
    float dt= 1E-6 * (float)(fs->us - last_us) ;
    switch (fs->fstype) {
    case GYRO:
        FusionVector gyro = FusionCalibrationInertial(fs->xyz, gyroscopeMisalignment, gyroscopeSensitivity, gyroscopeOffset);
        last_gyroscope    = FusionOffsetUpdate(&offset, gyro);
        FusionAhrsUpdate(&ahrs, last_gyroscope, FUSION_VECTOR_ZERO, FUSION_VECTOR_ZERO, dt);
        break;

    case ACCEL:
        FusionVector accel = FusionCalibrationInertial(fs->xyz, accelerometerMisalignment, accelerometerSensitivity, accelerometerOffset);
        FusionAhrsUpdate(&ahrs, last_gyroscope, accel, FUSION_VECTOR_ZERO, dt);
        break;

    case MAGN:
        FusionVector magn = FusionCalibrationMagnetic(fs->xyz, softIronMatrix, hardIronOffset);     
        FusionAhrsUpdate(&ahrs, last_gyroscope, FUSION_VECTOR_ZERO, magn, dt);
        break;
    }

    last_us = fs->us;
    return 1;
}

help much appreciated.

xioTechnologies commented 1 week ago

You should call FusionAhrsUpdate for each new gyroscope measurement and use the most recent accelerometer and magnetometer measurements at that time. The deltaTime value should correspond to the gyroscope. This is the correct way to combine asynchronously sampled sensors. The errors associated with the phasing will be negligible.

lvdlvd commented 1 week ago

Thanks for your swift reply!