protesis_03/imu.cpp

172 lines
5.7 KiB
C++

/*
* imu.cpp
*
* Created on: 09.01.2021
* Author: frank
*/
#include <Arduino.h>
#include "imu.hpp"
inertia inertia_offset;
void initialize_inertia(inertia &inertia, const measurement mpu_measurement) {
inertia_offset.roll_vector_length = roll_vector_length(get_mpu_offset());
inertia_offset.pitch_vector_length = pitch_vector_length(get_mpu_offset());
inertia_offset.yaw_vector_length = yaw_vector_length(get_mpu_offset());
calculate_inertia(inertia, mpu_measurement);
//inertia_offset.roll_vector_length = inertia.roll_vector_length;
//inertia_offset.pitch_vector_length = inertia.pitch_vector_length;
//inertia_offset.yaw_vector_length = inertia.pitch_vector_length;
inertia_offset.roll_acceleration = inertia.roll_acceleration;
inertia_offset.pitch_acceleration = inertia.pitch_acceleration;
inertia_offset.roll_gyroscope = inertia.roll_gyroscope;
inertia_offset.pitch_gyroscope = inertia.pitch_gyroscope;
inertia_offset.vector_length = inertia.vector_length;
inertia.roll_gyroscope = inertia.roll_acceleration;
inertia.pitch_gyroscope = inertia.pitch_acceleration;
}
void calculate_inertia_with_offset_substraction(inertia &inertia,
const measurement mpu_measurement) {
calculate_inertia(inertia, mpu_measurement);
substract_acceleration_offset(inertia);
}
void calculate_inertia(inertia &inertia, const measurement mpu_measurement) {
inertia.vector_length = vector_length_3d(mpu_measurement);
/*inertia.roll_acceleration = asin(
(float) mpu_measurement.acceleration.y / inertia.vector_length)
* -RADIAN_CONST
;
inertia.pitch_acceleration = asin(
(float) mpu_measurement.acceleration.x / inertia.vector_length)
* RADIAN_CONST
;*/
inertia.roll_acceleration = atan2(mpu_measurement.acceleration.y,
mpu_measurement.acceleration.z) * RAD_TO_DEG;
inertia.pitch_acceleration = atan2(-mpu_measurement.acceleration.x,
vector_length_2d(mpu_measurement.acceleration.y,
mpu_measurement.acceleration.z)) * RAD_TO_DEG;
//inertia.roll_acceleration = 180 * (asin(mpu_measurement.acceleration.y / vector_length_3d(mpu_measurement)))/M_PI;
//inertia.pitch_acceleration = 180 * (asin(mpu_measurement.acceleration.x / vector_length_3d(mpu_measurement)))/M_PI;
/*inertia.roll_vector_length = roll_vector_length(mpu_measurement);
inertia.pitch_vector_length = pitch_vector_length(mpu_measurement);
inertia.yaw_vector_length = yaw_vector_length(mpu_measurement);
inertia.roll_acceleration = roll_by_acceleration(inertia, mpu_measurement);
inertia.pitch_acceleration = pitch_by_acceleration(inertia,
mpu_measurement);*/
//TODO Evaluate correctness of dimensions (actually x -> roll, y -> pitch)
inertia.roll_gyroscope += gyroscope_with_precission(
mpu_measurement.gyroscope.x);
inertia.pitch_gyroscope += gyroscope_with_precission(
mpu_measurement.gyroscope.y);
inertia.roll_gyroscope -= inertia.pitch_gyroscope
* sin(gyroscope_with_precission(mpu_measurement.gyroscope.z)) * RAD_TO_DEG; //If the IMU has yawed transfer the pitch angle to the roll angel
inertia.pitch_gyroscope += inertia.roll_gyroscope
* sin(gyroscope_with_precission(mpu_measurement.gyroscope.z)) * RAD_TO_DEG; //If the IMU has yawed transfer the roll angle to the pitch angel
}
void substract_acceleration_offset(inertia &inertia) {
inertia.roll_acceleration -= inertia_offset.roll_acceleration;
inertia.pitch_acceleration -= inertia_offset.pitch_acceleration;
}
void correct_inertia_drift(inertia &inertia) {
inertia.roll_gyroscope = inertia.roll_gyroscope * DRIFT_CORRECTION_RATE_GYRO
+ inertia.roll_acceleration * DRIFT_CORRECTION_RATE_ACCEL;
inertia.pitch_gyroscope = inertia.pitch_gyroscope
* DRIFT_CORRECTION_RATE_GYRO
+ inertia.pitch_acceleration * DRIFT_CORRECTION_RATE_ACCEL;
}
long square(const long value) {
return value * value;
}
double roll_vector_length(const measurement mpu_measurement) {
return vector_length_2d(mpu_measurement.acceleration.y,
mpu_measurement.acceleration.z);
}
double pitch_vector_length(const measurement mpu_measurement) {
return vector_length_2d(mpu_measurement.acceleration.x,
mpu_measurement.acceleration.z);
}
double yaw_vector_length(const measurement mpu_measurement) {
return vector_length_2d(mpu_measurement.acceleration.x,
mpu_measurement.acceleration.y);
}
double roll_by_acceleration(const inertia inertia,
const measurement mpu_measurement) {
long scalar_product = mpu_measurement.acceleration.x
* get_mpu_offset().acceleration.x
+ mpu_measurement.acceleration.z * get_mpu_offset().acceleration.z;
double area = inertia.roll_vector_length
* inertia_offset.roll_vector_length;
/*Serial.print("sp=");
Serial.print(scalar_product);
Serial.print(",a=");
Serial.print(area);
Serial.print(",v=");
Serial.print(inertia_offset.roll_vector_length);
Serial.println();*/
return acos(scalar_product / area) * RADIAN_CONST;
}
double pitch_by_acceleration(const inertia inertia,
const measurement mpu_measurement) {
long scalar_product = mpu_measurement.acceleration.y
* get_mpu_offset().acceleration.y
+ mpu_measurement.acceleration.z * get_mpu_offset().acceleration.z;
double area = inertia.pitch_vector_length
* inertia_offset.pitch_vector_length;
return acos(scalar_product / area) * RADIAN_CONST;
}
double vector_length_2d(const long x, const long y) {
return sqrt((double) square(x) + square(y));
}
double vector_length_3d(measurement const measurement) {
return sqrt(
(double) square(measurement.acceleration.x)
+ square(measurement.acceleration.y)
+ square(measurement.acceleration.z));
}
double acceleration_with_precission(const long value) {
return value * ACCELEROMETER_CONST;
}
double gyroscope_with_precission(const long value) {
return value * GYRO_CONST;
}
inertia get_inertia_offset() {
return inertia_offset;
}