Skip to content

Commit

Permalink
add tiltcompensate
Browse files Browse the repository at this point in the history
  • Loading branch information
jeki committed May 6, 2021
1 parent 5e4da4f commit af9a153
Show file tree
Hide file tree
Showing 6 changed files with 335 additions and 31 deletions.
110 changes: 79 additions & 31 deletions imuUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
#include "webUtils.h"
#include <LittleFS.h>
#include "fileUtils.h"
extern "C" {
#include "quaternion.h"
}

MPU9250_DMP imu;
static char imuTxtBuffer[140];

float qw,qx,qy,qz;
float ax,ay,az, mx, my, mz;
vector3d_t dmpEuler;
float fHeading[2];

int intPin = 14;
Expand Down Expand Up @@ -42,7 +46,7 @@ void printIMUData(void)
if (millis() - printTime > printTimeLimit) {
if (print_flag) {
sprintf(imuTxtBuffer, "{\"qw\":%.4f,\"qx\":%.4f,\"qy\":%.4f,\"qz\":%.4f,\"r\":%.2f,\"p\":%.2f,\"y\":%.2f,\"ax\":%.4f,\"ay\":%.4f,\"az\":%.4f,\"h\":%.2f}",
qw, qx, qy, qz, imu.roll, imu.pitch, imu.yaw, ax, ay, az, fHeading[0]);
qw, qx, qy, qz, (float)dmpEuler[VEC3_X], (float)dmpEuler[VEC3_Y], (float)dmpEuler[VEC3_Z], ax, ay, az, fHeading[0]);
SSEBroadcastTxt(imuTxtBuffer);
print_flag = false;
}
Expand All @@ -63,7 +67,7 @@ void printIMUData(void)
imu_update_fail_log_flag = false;
}
} else {
Serial.println("imu raw:"+ String(imu.roll) + "," + String(imu.pitch) + "," + String(imu.yaw) + "\t" + String(imu.ax)+ "," + String(imu.ay)+ "," + String(imu.az) + ";" + String(imu.mx)+ "," + String(imu.my)+ "," + String(imu.mz)+"," + String(update_compass_flag) +"\t" + String(fHeading[0], 2));
Serial.println("imu raw:"+ String(dmpEuler[VEC3_X]) + "," + String(dmpEuler[VEC3_Y]) + "," + String(dmpEuler[VEC3_Z]) + "\t" + String(imu.ax)+ "," + String(imu.ay)+ "," + String(imu.az) + ";" + String(imu.mx)+ "," + String(imu.my)+ "," + String(imu.mz)+"," + String(update_compass_flag) +"\t" + String(fHeading[0], 2));
}
}
}
Expand Down Expand Up @@ -171,6 +175,73 @@ void imu_send_mag_calib(void) {
SSEBroadcastTxt(imuTxtBuffer);
}

int imu_calcHeading(void) {
vector3d_t fusedEuler;
quaternion_t dmpQuat;
quaternion_t magQuat;
quaternion_t unfusedQuat;
float deltaDMPYaw;
float deltaMagYaw;
double magYaw;
float newYaw;

// // heading in x direction
// fHeading[1] = imu.calcCompassHeadingTiltY(-imu.ay, imu.ax, imu.az, mx, -my, mz);
// fHeading[1]*= 180.0 / PI;

// heading in y direction
// fHeading[1] = imu.calcCompassHeadingTilt(imu.ax, -imu.ay, imu.az, my, -mx, -mz);
// fHeading[1] = imu.calcAzimuth((double)imu.pitch, (double)imu.roll, my, mx, mz);

qw = imu.calcQuat(imu.qw);
qx = imu.calcQuat(imu.qx);
qy = imu.calcQuat(imu.qy);
qz = imu.calcQuat(imu.qz);

ax = imu.calcAccel(imu.ax);
ay = imu.calcAccel(imu.ay);
az = imu.calcAccel(imu.az);

dmpQuat[QUAT_W] = (double)qw;
dmpQuat[QUAT_X] = (double)qx;
dmpQuat[QUAT_Y] = (double)qy;
dmpQuat[QUAT_Z] = (double)qz;
quaternionNormalize(dmpQuat);
quaternionToEuler(dmpQuat, dmpEuler);

fusedEuler[VEC3_X] = dmpEuler[VEC3_X];
fusedEuler[VEC3_Y] = -dmpEuler[VEC3_Y];
fusedEuler[VEC3_Z] = 0;

eulerToQuaternion(fusedEuler, unfusedQuat);

magQuat[QUAT_W] = 0;
magQuat[QUAT_X] = (double)my;
magQuat[QUAT_Y] = -(double)mx;
magQuat[QUAT_Z] = (double)mz;

tiltCompensate(magQuat, unfusedQuat);

// deltaDMPYaw = (float)-dmpEuler[VEC3_Z] + lastDMPYaw;
// lastDMPYaw = (float)dmpEuler[VEC3_Z];

magYaw = -atan2(magQuat[QUAT_Y], magQuat[QUAT_X]);
fHeading[1] = (float)magYaw * 180.0f / (float)PI;

if(fHeading[1] - fHeading[0] > 180.0f) {
fHeading[0] += 360;
} else {
if(fHeading[0] - fHeading[1] > 180.0f) {
fHeading[0] -= 360;
}
}

// add LPF for smoother result
fHeading[0] = (fHeading[0] * 14.0f + fHeading[1] * 2.0f) / 16.0f;

return 0;
}

void imu_loop(void) {
if (magCalibFlag) {
magCal_nonblocking(magBias,magScale);
Expand All @@ -190,43 +261,20 @@ void imu_loop(void) {
{
// computeEulerAngles can be used -- after updating the
// quaternion values -- to estimate roll, pitch, and yaw
imu.computeEulerAnglesZYX(false);
// imu.computeEulerAnglesZYX(false);

// After calling dmpUpdateFifo() the ax, gx, mx, etc. values
// are all updated.
// Quaternion values are, by default, stored in Q30 long
// format. calcQuat turns them into a float between -1 and 1
qw = imu.calcQuat(imu.qw);
qx = imu.calcQuat(imu.qx);
qy = imu.calcQuat(imu.qy);
qz = imu.calcQuat(imu.qz);

ax = imu.calcAccel(imu.ax);
ay = imu.calcAccel(imu.ay);
az = imu.calcAccel(imu.az);

// // heading in x direction
// fHeading[1] = imu.calcCompassHeadingTiltY(-imu.ay, imu.ax, imu.az, mx, -my, mz);
// fHeading[1]*= 180.0 / PI;

// heading in y direction
// fHeading[1] = imu.calcCompassHeadingTilt(imu.ax, -imu.ay, imu.az, my, -mx, -mz);
fHeading[1] = imu.calcAzimuth((double)imu.pitch, (double)imu.roll, my, mx, mz);
fHeading[1]*= 180.0 / PI;

if(fHeading[1] - fHeading[0] > 180.0f) {
fHeading[0] += 360;
if (imu_calcHeading() < 0) {
imu_update_fail_flag = true;
print_flag = false;
} else {
if(fHeading[0] - fHeading[1] > 180.0f) {
fHeading[0] -= 360;
}
imu_update_fail_flag = false;
print_flag = true;
}

// add LPF for smoother result
fHeading[0] = (fHeading[0] * 14.0f + fHeading[1] * 2.0f) / 16.0f;

imu_update_fail_flag = false;
print_flag = true;
} else {
imu_update_fail_flag = true;
}
Expand Down
131 changes: 131 additions & 0 deletions quaternion.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
////////////////////////////////////////////////////////////////////////////
//
// This file is part of linux-mpu9150
//
// Copyright (c) 2013 Pansenti, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
// Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "quaternion.h"

void quaternionNorm(quaternion_t q, double *n)
{
*n = sqrtf(q[QUAT_W] * q[QUAT_W] + q[QUAT_X] * q[QUAT_X] +
q[QUAT_Y] * q[QUAT_Y] + q[QUAT_Z] * q[QUAT_Z]);
}

void quaternionNormalize(quaternion_t q)
{
double length;

quaternionNorm(q, &length);

if (length == 0)
return;

q[QUAT_W] /= length;
q[QUAT_X] /= length;
q[QUAT_Y] /= length;
q[QUAT_Z] /= length;
}

void quaternionToEuler(quaternion_t q, vector3d_t v)
{
// fix roll near poles with this tolerance
double pole = (double)M_PI / 2.0 - 0.05;

double qysqr = q[QUAT_Y] * q[QUAT_Y];

double sinr_cosp = 2.0 * (q[QUAT_W] * q[QUAT_X] + q[QUAT_Y] * q[QUAT_Z]);
double cosr_cosp = 1.0 - 2.0 * (q[QUAT_X] * q[QUAT_X] + qysqr);
double sinp = 2.0 * (q[QUAT_W] * q[QUAT_Y] - q[QUAT_Z] * q[QUAT_X]);

double siny_cosp = 2.0 * (q[QUAT_W] * q[QUAT_Z] + q[QUAT_X] * q[QUAT_Y]);
double cosy_cosp = 1.0 - 2.0 * (qysqr + q[QUAT_Z] * q[QUAT_Z]);

// Keep t2 within range of asin (-1, 1)
sinp = sinp > 1.0 ? 1.0 : sinp;
sinp = sinp < -1.0 ? -1.0 : sinp;

v[VEC3_Y] = asin(sinp);

if ((v[VEC3_Y] < pole) && (v[VEC3_Y] > -pole)) {
v[VEC3_X] = atan2(sinr_cosp, cosr_cosp);
}

v[VEC3_Z] = atan2(siny_cosp, cosy_cosp);
}

void eulerToQuaternion(vector3d_t v, quaternion_t q)
{
double cosX2 = cos(v[VEC3_X] / 2.0);
double sinX2 = sin(v[VEC3_X] / 2.0);
double cosY2 = cos(v[VEC3_Y] / 2.0);
double sinY2 = sin(v[VEC3_Y] / 2.0);
double cosZ2 = cos(v[VEC3_Z] / 2.0);
double sinZ2 = sin(v[VEC3_Z] / 2.0);

q[QUAT_W] = cosX2 * cosY2 * cosZ2 + sinX2 * sinY2 * sinZ2;
q[QUAT_X] = sinX2 * cosY2 * cosZ2 - cosX2 * sinY2 * sinZ2;
q[QUAT_Y] = cosX2 * sinY2 * cosZ2 + sinX2 * cosY2 * sinZ2;
q[QUAT_Z] = cosX2 * cosY2 * sinZ2 - sinX2 * sinY2 * cosZ2;

quaternionNormalize(q);
}

void quaternionConjugate(quaternion_t s, quaternion_t d)
{
d[QUAT_W] = s[QUAT_W];
d[QUAT_X] = -s[QUAT_X];
d[QUAT_Y] = -s[QUAT_Y];
d[QUAT_Z] = -s[QUAT_Z];
}

void quaternionMultiply(quaternion_t qa, quaternion_t qb, quaternion_t qd)
{
vector3d_t va;
vector3d_t vb;
double dotAB;
vector3d_t crossAB;

va[VEC3_X] = qa[QUAT_X];
va[VEC3_Y] = qa[QUAT_Y];
va[VEC3_Z] = qa[QUAT_Z];

vb[VEC3_X] = qb[QUAT_X];
vb[VEC3_Y] = qb[QUAT_Y];
vb[VEC3_Z] = qb[QUAT_Z];

vector3DotProduct(va, vb, &dotAB);
vector3CrossProduct(va, vb, crossAB);

qd[QUAT_W] = qa[QUAT_W] * qb[QUAT_W] - dotAB;
qd[QUAT_X] = qa[QUAT_W] * vb[VEC3_X] + qb[QUAT_W] * va[VEC3_X] + crossAB[VEC3_X];
qd[QUAT_Y] = qa[QUAT_W] * vb[VEC3_Y] + qb[QUAT_W] * va[VEC3_Y] + crossAB[VEC3_Y];
qd[QUAT_Z] = qa[QUAT_W] * vb[VEC3_Z] + qb[QUAT_W] * va[VEC3_Z] + crossAB[VEC3_Z];
}

void tiltCompensate(quaternion_t magQ, quaternion_t unfusedQ)
{
quaternion_t unfusedConjugateQ;
quaternion_t tempQ;

quaternionConjugate(unfusedQ, unfusedConjugateQ);
quaternionMultiply(magQ, unfusedConjugateQ, tempQ);
quaternionMultiply(unfusedQ, tempQ, magQ);
}
44 changes: 44 additions & 0 deletions quaternion.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
////////////////////////////////////////////////////////////////////////////
//
// This file is part of linux-mpu9150
//
// Copyright (c) 2013 Pansenti, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
// Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef MPUQUATERNION_H
#define MPUQUATERNION_H

#include "vector3d.h"

#define QUAT_W 0
#define QUAT_X 1
#define QUAT_Y 2
#define QUAT_Z 3

typedef double quaternion_t[4];

void quaternionNormalize(quaternion_t q);
void quaternionToEuler(quaternion_t q, vector3d_t v);
void eulerToQuaternion(vector3d_t v, quaternion_t q);
void quaternionConjugate(quaternion_t s, quaternion_t d);
void quaternionMultiply(quaternion_t qa, quaternion_t qb, quaternion_t qd);
void tiltCompensate(quaternion_t magQ, quaternion_t unfusedQ);

#endif /* MPUQUATERNION_H */

File renamed without changes.
37 changes: 37 additions & 0 deletions vector3d.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
////////////////////////////////////////////////////////////////////////////
//
// This file is part of linux-mpu9150
//
// Copyright (c) 2013 Pansenti, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
// Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "vector3d.h"

void vector3DotProduct(vector3d_t a, vector3d_t b, double *d)
{
*d = a[VEC3_X] * b[VEC3_X] + a[VEC3_Y] * b[VEC3_Y] + a[VEC3_Z] * b[VEC3_Z];
}

void vector3CrossProduct(vector3d_t a, vector3d_t b, vector3d_t d)
{
d[VEC3_X] = a[VEC3_Y] * b[VEC3_Z] - a[VEC3_Z] * b[VEC3_Y];
d[VEC3_Y] = a[VEC3_Z] * b[VEC3_X] - a[VEC3_X] * b[VEC3_Z];
d[VEC3_Z] = a[VEC3_X] * b[VEC3_Y] - a[VEC3_Y] * b[VEC3_X];
}

Loading

0 comments on commit af9a153

Please sign in to comment.