Skip to content

Accelerometer calibration efficiency using magneto 1.4 #508

Description

@brightproject

Unfortunately, I don't expect to receive any responses, as this repository and issue are used for tracking developer issues, not for users of this library.
In this case, I would like to ask you to open DISCUSSIONS.
Otherwise, the purpose of a community for this repo is lost, IMHO🙄

I'm testing the calibration algorithm for the ICM45686 and QMC6309 sensors.

Image

The magneto algorithm is ideal for the magnetometer, but I'm having trouble calibrating the accelerometer.
I got the code from here:

magneto_acc->current_calibration(A_BAinv);

But usually, the accelerometer is simply fixed along the X, Y, and Z axes and the sign is changed, resulting in six measurements.
And with a magnetometer, should the magnetometer calibration also be performed in a stationary state, or what?
In any case, we move the accelerometer sensor, and accelerations involuntarily occur, no matter how carefully we try to move the axes along the table.
Values ​​obtained after calibration:

Image

I would like an explanation of the calibration algorithm as it applies to the accelerometer, because in my experience, it has been inaccurate🙂

// ACCELEROMETER CALIBRATION (stationary positions)
AccelCalibration calibrateAccelerometer(const vector<Vector3f>& accelData) {
    /*
      * The accelerometer is calibrated in STILL positions!
      * Expected positions (in g units):
      * 1. Z up: (0, 0, 1)
      * 2. Z down: (0, 0, -1)
      * 3. Y up: (0, 1, 0)
      * 4. Y down: (0, -1, 0)
      * 5. X up: (1, 0, 0)
      * 6. X down: (-1, 0, 0)
     */
    
    int n = accelData.size();
    if (n < 6) {
        cerr << "Error: At least 6 measurements are required to calibrate the accelerometer" << endl;
        return AccelCalibration();
    }
    
    // Least-squares method for the accelerometer
    // Equation: S * (raw - bias) = ​​reference
    // where reference is the known gravity vector (0, 0, ±1g, etc.)
    
    // We assume that the data is already split into positions
    // In reality, you need to transmit data separately for each position
    
    // Simplified method: calibrating only the offset and scale
    Vector3f minVal(10000, 10000, 10000);
    Vector3f maxVal(-10000, -10000, -10000);
    
    for (const auto& point : accelData) {
        for (int i = 0; i < 3; i++) {
            if (point[i] < minVal[i]) minVal[i] = point[i];
            if (point[i] > maxVal[i]) maxVal[i] = point[i];
        }
    }
    
    AccelCalibration result;
    
    // Bias - midpoint of range
    result.bias = (minVal + maxVal) / 2.0f;
    
    // Scale factors
    // Range should correspond to ±1g = ±9.8 m/s²
    Vector3f range = maxVal - minVal;
    
    // Assume full range = 2g (from -1g to +1g)
    // If the accelerometer sensitivity is, for example, 16384 LSB/g
    result.scale = Matrix3f::Identity();
    result.scale(0,0) = 2.0f / range.x(); // To convert to g
    result.scale(1,1) = 2.0f / range.y();
    result.scale(2,2) = 2.0f / range.z();
    
    result.invScale = result.scale.inverse();
    
    return result;
}

I would be happy to discuss the project and my question @Eirenliel

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions