Fix iterative adjustments of calibration

Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
This commit is contained in:
TheJackiMonster 2023-04-03 15:33:00 +02:00
parent 2c23021a5e
commit 5aa71fb488
No known key found for this signature in database
GPG key ID: D850A5F772E880F9

View file

@ -334,6 +334,66 @@ static void readIMU_from_packet(const device3_packet_type* packet,
#define min(x, y) ((x) < (y)? (x) : (y))
#define max(x, y) ((x) > (y)? (x) : (y))
static void apply_calibration(const device3_type* device,
FusionVector* gyroscope,
FusionVector* accelerometer,
FusionVector* magnetometer) {
FusionMatrix gyroscopeMisalignment;
FusionVector gyroscopeSensitivity;
FusionVector gyroscopeOffset;
FusionMatrix accelerometerMisalignment;
FusionVector accelerometerSensitivity;
FusionVector accelerometerOffset;
FusionMatrix softIronMatrix;
FusionVector hardIronOffset;
if (device->calibration) {
gyroscopeMisalignment = device->calibration->gyroscopeMisalignment;
gyroscopeSensitivity = device->calibration->gyroscopeSensitivity;
gyroscopeOffset = device->calibration->gyroscopeOffset;
accelerometerMisalignment = device->calibration->accelerometerMisalignment;
accelerometerSensitivity = device->calibration->accelerometerSensitivity;
accelerometerOffset = device->calibration->accelerometerOffset;
softIronMatrix = device->calibration->softIronMatrix;
hardIronOffset = device->calibration->hardIronOffset;
} else {
gyroscopeMisalignment = FUSION_IDENTITY_MATRIX;
gyroscopeSensitivity = FUSION_VECTOR_ONES;
gyroscopeOffset = FUSION_VECTOR_ZERO;
accelerometerMisalignment = FUSION_IDENTITY_MATRIX;
accelerometerSensitivity = FUSION_VECTOR_ONES;
accelerometerOffset = FUSION_VECTOR_ZERO;
softIronMatrix = FUSION_IDENTITY_MATRIX;
hardIronOffset = FUSION_VECTOR_ZERO;
}
*gyroscope = FusionCalibrationInertial(
*gyroscope,
gyroscopeMisalignment,
gyroscopeSensitivity,
gyroscopeOffset
);
*accelerometer = FusionCalibrationInertial(
*accelerometer,
accelerometerMisalignment,
accelerometerSensitivity,
accelerometerOffset
);
*magnetometer = FusionCalibrationMagnetic(
*magnetometer,
softIronMatrix,
hardIronOffset
);
}
int device3_calibrate(device3_type* device, uint32_t iterations, bool gyro, bool accel, bool magnet) {
if (!device) {
perror("No device!\n");
@ -392,6 +452,7 @@ int device3_calibrate(device3_type* device, uint32_t iterations, bool gyro, bool
FusionVector magnetometer;
readIMU_from_packet(&packet, &gyroscope, &accelerometer, &magnetometer);
apply_calibration(device, &gyroscope, &accelerometer, &magnetometer);
if (initialized) {
cal_gyroscope = FusionVectorAdd(cal_gyroscope, gyroscope);
@ -399,9 +460,9 @@ int device3_calibrate(device3_type* device, uint32_t iterations, bool gyro, bool
cal_magnetometer[0].axis.x = min(cal_magnetometer[0].axis.x, magnetometer.axis.x);
cal_magnetometer[0].axis.y = min(cal_magnetometer[0].axis.y, magnetometer.axis.y);
cal_magnetometer[0].axis.z = min(cal_magnetometer[0].axis.z, magnetometer.axis.z);
cal_magnetometer[1].axis.x = min(cal_magnetometer[1].axis.x, magnetometer.axis.x);
cal_magnetometer[1].axis.y = min(cal_magnetometer[1].axis.y, magnetometer.axis.y);
cal_magnetometer[1].axis.z = min(cal_magnetometer[1].axis.z, magnetometer.axis.z);
cal_magnetometer[1].axis.x = max(cal_magnetometer[1].axis.x, magnetometer.axis.x);
cal_magnetometer[1].axis.y = max(cal_magnetometer[1].axis.y, magnetometer.axis.y);
cal_magnetometer[1].axis.z = max(cal_magnetometer[1].axis.z, magnetometer.axis.z);
} else {
cal_gyroscope = gyroscope;
cal_accelerometer = accelerometer;
@ -415,23 +476,32 @@ int device3_calibrate(device3_type* device, uint32_t iterations, bool gyro, bool
if (factor > 0.0f) {
if (gyro) {
device->calibration->gyroscopeOffset = FusionVectorMultiplyScalar(
device->calibration->gyroscopeOffset = FusionVectorAdd(
device->calibration->gyroscopeOffset,
FusionVectorMultiplyScalar(
cal_gyroscope,
factor
)
);
}
if (accel) {
device->calibration->accelerometerOffset = FusionVectorMultiplyScalar(
device->calibration->accelerometerOffset = FusionVectorAdd(
device->calibration->accelerometerOffset,
FusionVectorMultiplyScalar(
cal_accelerometer,
factor
)
);
}
if (magnet) {
device->calibration->hardIronOffset = FusionVectorMultiplyScalar(
device->calibration->hardIronOffset = FusionVectorAdd(
device->calibration->hardIronOffset,
FusionVectorMultiplyScalar(
FusionVectorAdd(cal_magnetometer[0], cal_magnetometer[1]),
0.5f
)
);
}
}
@ -499,61 +569,7 @@ int device3_read(device3_type* device, int timeout) {
FusionVector magnetometer;
readIMU_from_packet(&packet, &gyroscope, &accelerometer, &magnetometer);
FusionMatrix gyroscopeMisalignment;
FusionVector gyroscopeSensitivity;
FusionVector gyroscopeOffset;
FusionMatrix accelerometerMisalignment;
FusionVector accelerometerSensitivity;
FusionVector accelerometerOffset;
FusionMatrix softIronMatrix;
FusionVector hardIronOffset;
if (device->calibration) {
gyroscopeMisalignment = device->calibration->gyroscopeMisalignment;
gyroscopeSensitivity = device->calibration->gyroscopeSensitivity;
gyroscopeOffset = device->calibration->gyroscopeOffset;
accelerometerMisalignment = device->calibration->accelerometerMisalignment;
accelerometerSensitivity = device->calibration->accelerometerSensitivity;
accelerometerOffset = device->calibration->accelerometerOffset;
softIronMatrix = device->calibration->softIronMatrix;
hardIronOffset = device->calibration->hardIronOffset;
} else {
gyroscopeMisalignment = FUSION_IDENTITY_MATRIX;
gyroscopeSensitivity = FUSION_VECTOR_ONES;
gyroscopeOffset = FUSION_VECTOR_ZERO;
accelerometerMisalignment = FUSION_IDENTITY_MATRIX;
accelerometerSensitivity = FUSION_VECTOR_ONES;
accelerometerOffset = FUSION_VECTOR_ZERO;
softIronMatrix = FUSION_IDENTITY_MATRIX;
hardIronOffset = FUSION_VECTOR_ZERO;
}
gyroscope = FusionCalibrationInertial(
gyroscope,
gyroscopeMisalignment,
gyroscopeSensitivity,
gyroscopeOffset
);
accelerometer = FusionCalibrationInertial(
accelerometer,
accelerometerMisalignment,
accelerometerSensitivity,
accelerometerOffset
);
magnetometer = FusionCalibrationMagnetic(
magnetometer,
softIronMatrix,
hardIronOffset
);
apply_calibration(device, &gyroscope, &accelerometer, &magnetometer);
gyroscope = FusionOffsetUpdate((FusionOffset*) device->offset, gyroscope);