-
Notifications
You must be signed in to change notification settings - Fork 199
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 7f4fc8c
Showing
5 changed files
with
323 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
= Madgwick Library = | ||
|
||
This library wraps the official implementation of MadgwickAHRS algorithm to get orientation of an object based on accelerometer and gyroscope readings | ||
|
||
== License == | ||
|
||
Copyright (c) Arduino LLC. All right reserved. | ||
|
||
This library is free software; you can redistribute it and/or | ||
modify it under the terms of the GNU Lesser General Public | ||
License as published by the Free Software Foundation; either | ||
version 2.1 of the License, or (at your option) any later version. | ||
|
||
This library is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
Lesser General Public License for more details. | ||
|
||
You should have received a copy of the GNU Lesser General Public | ||
License along with this library; if not, write to the Free Software | ||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
|
||
|
||
Implementation of Madgwick's IMU and AHRS algorithms. | ||
See: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms | ||
|
||
Date Author Notes | ||
29/09/2011 SOH Madgwick Initial release | ||
02/10/2011 SOH Madgwick Optimised for reduced CPU load | ||
19/02/2012 SOH Madgwick Magnetometer measurement is normalised |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
####################################### | ||
# Syntax Coloring Map For WiFi | ||
####################################### | ||
|
||
####################################### | ||
# Datatypes (KEYWORD1) | ||
####################################### | ||
|
||
Madgwick KEYWORD1 | ||
|
||
####################################### | ||
# Methods and Functions (KEYWORD2) | ||
####################################### | ||
|
||
update KEYWORD2 | ||
updateIMU KEYWORD2 | ||
getPitch KEYWORD2 | ||
getYaw KEYWORD2 | ||
getRoll KEYWORD2 | ||
|
||
|
||
####################################### | ||
# Constants (LITERAL1) | ||
####################################### | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
name=Madgwick | ||
version=1.0 | ||
author=Arduino | ||
maintainer=Arduino <[email protected]> | ||
sentence=Helpers for MadgwickAHRS algorithm | ||
paragraph=This library wraps the official implementation of MadgwickAHRS algorithm to get orientation of an object based on accelerometer and gyroscope readings | ||
category=Data Processing | ||
url=http://arduino.cc/en/Reference/XXXXXX | ||
architectures=* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
//===================================================================================================== | ||
// MadgwickAHRS.c | ||
//===================================================================================================== | ||
// | ||
// Implementation of Madgwick's IMU and AHRS algorithms. | ||
// See: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms | ||
// | ||
// Date Author Notes | ||
// 29/09/2011 SOH Madgwick Initial release | ||
// 02/10/2011 SOH Madgwick Optimised for reduced CPU load | ||
// 19/02/2012 SOH Madgwick Magnetometer measurement is normalised | ||
// | ||
//===================================================================================================== | ||
|
||
//--------------------------------------------------------------------------------------------------- | ||
// Header files | ||
|
||
#include "MadgwickAHRS.h" | ||
#include <math.h> | ||
|
||
//--------------------------------------------------------------------------------------------------- | ||
// Definitions | ||
|
||
|
||
|
||
//==================================================================================================== | ||
// Functions | ||
|
||
//--------------------------------------------------------------------------------------------------- | ||
// AHRS algorithm update | ||
|
||
void Madgwick::update(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz) { | ||
float recipNorm; | ||
float s0, s1, s2, s3; | ||
float qDot1, qDot2, qDot3, qDot4; | ||
float hx, hy; | ||
float _2q0mx, _2q0my, _2q0mz, _2q1mx, _2bx, _2bz, _4bx, _4bz, _2q0, _2q1, _2q2, _2q3, _2q0q2, _2q2q3, q0q0, q0q1, q0q2, q0q3, q1q1, q1q2, q1q3, q2q2, q2q3, q3q3; | ||
|
||
// Use IMU algorithm if magnetometer measurement invalid (avoids NaN in magnetometer normalisation) | ||
if((mx == 0.0f) && (my == 0.0f) && (mz == 0.0f)) { | ||
updateIMU(gx, gy, gz, ax, ay, az); | ||
return; | ||
} | ||
|
||
// Rate of change of quaternion from gyroscope | ||
qDot1 = 0.5f * (-q1 * gx - q2 * gy - q3 * gz); | ||
qDot2 = 0.5f * (q0 * gx + q2 * gz - q3 * gy); | ||
qDot3 = 0.5f * (q0 * gy - q1 * gz + q3 * gx); | ||
qDot4 = 0.5f * (q0 * gz + q1 * gy - q2 * gx); | ||
|
||
// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation) | ||
if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) { | ||
|
||
// Normalise accelerometer measurement | ||
recipNorm = invSqrt(ax * ax + ay * ay + az * az); | ||
ax *= recipNorm; | ||
ay *= recipNorm; | ||
az *= recipNorm; | ||
|
||
// Normalise magnetometer measurement | ||
recipNorm = invSqrt(mx * mx + my * my + mz * mz); | ||
mx *= recipNorm; | ||
my *= recipNorm; | ||
mz *= recipNorm; | ||
|
||
// Auxiliary variables to avoid repeated arithmetic | ||
_2q0mx = 2.0f * q0 * mx; | ||
_2q0my = 2.0f * q0 * my; | ||
_2q0mz = 2.0f * q0 * mz; | ||
_2q1mx = 2.0f * q1 * mx; | ||
_2q0 = 2.0f * q0; | ||
_2q1 = 2.0f * q1; | ||
_2q2 = 2.0f * q2; | ||
_2q3 = 2.0f * q3; | ||
_2q0q2 = 2.0f * q0 * q2; | ||
_2q2q3 = 2.0f * q2 * q3; | ||
q0q0 = q0 * q0; | ||
q0q1 = q0 * q1; | ||
q0q2 = q0 * q2; | ||
q0q3 = q0 * q3; | ||
q1q1 = q1 * q1; | ||
q1q2 = q1 * q2; | ||
q1q3 = q1 * q3; | ||
q2q2 = q2 * q2; | ||
q2q3 = q2 * q3; | ||
q3q3 = q3 * q3; | ||
|
||
// Reference direction of Earth's magnetic field | ||
hx = mx * q0q0 - _2q0my * q3 + _2q0mz * q2 + mx * q1q1 + _2q1 * my * q2 + _2q1 * mz * q3 - mx * q2q2 - mx * q3q3; | ||
hy = _2q0mx * q3 + my * q0q0 - _2q0mz * q1 + _2q1mx * q2 - my * q1q1 + my * q2q2 + _2q2 * mz * q3 - my * q3q3; | ||
_2bx = sqrt(hx * hx + hy * hy); | ||
_2bz = -_2q0mx * q2 + _2q0my * q1 + mz * q0q0 + _2q1mx * q3 - mz * q1q1 + _2q2 * my * q3 - mz * q2q2 + mz * q3q3; | ||
_4bx = 2.0f * _2bx; | ||
_4bz = 2.0f * _2bz; | ||
|
||
// Gradient decent algorithm corrective step | ||
s0 = -_2q2 * (2.0f * q1q3 - _2q0q2 - ax) + _2q1 * (2.0f * q0q1 + _2q2q3 - ay) - _2bz * q2 * (_2bx * (0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (-_2bx * q3 + _2bz * q1) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + _2bx * q2 * (_2bx * (q0q2 + q1q3) + _2bz * (0.5f - q1q1 - q2q2) - mz); | ||
s1 = _2q3 * (2.0f * q1q3 - _2q0q2 - ax) + _2q0 * (2.0f * q0q1 + _2q2q3 - ay) - 4.0f * q1 * (1 - 2.0f * q1q1 - 2.0f * q2q2 - az) + _2bz * q3 * (_2bx * (0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (_2bx * q2 + _2bz * q0) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + (_2bx * q3 - _4bz * q1) * (_2bx * (q0q2 + q1q3) + _2bz * (0.5f - q1q1 - q2q2) - mz); | ||
s2 = -_2q0 * (2.0f * q1q3 - _2q0q2 - ax) + _2q3 * (2.0f * q0q1 + _2q2q3 - ay) - 4.0f * q2 * (1 - 2.0f * q1q1 - 2.0f * q2q2 - az) + (-_4bx * q2 - _2bz * q0) * (_2bx * (0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (_2bx * q1 + _2bz * q3) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + (_2bx * q0 - _4bz * q2) * (_2bx * (q0q2 + q1q3) + _2bz * (0.5f - q1q1 - q2q2) - mz); | ||
s3 = _2q1 * (2.0f * q1q3 - _2q0q2 - ax) + _2q2 * (2.0f * q0q1 + _2q2q3 - ay) + (-_4bx * q3 + _2bz * q1) * (_2bx * (0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (-_2bx * q0 + _2bz * q2) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + _2bx * q1 * (_2bx * (q0q2 + q1q3) + _2bz * (0.5f - q1q1 - q2q2) - mz); | ||
recipNorm = invSqrt(s0 * s0 + s1 * s1 + s2 * s2 + s3 * s3); // normalise step magnitude | ||
s0 *= recipNorm; | ||
s1 *= recipNorm; | ||
s2 *= recipNorm; | ||
s3 *= recipNorm; | ||
|
||
// Apply feedback step | ||
qDot1 -= beta * s0; | ||
qDot2 -= beta * s1; | ||
qDot3 -= beta * s2; | ||
qDot4 -= beta * s3; | ||
} | ||
|
||
// Integrate rate of change of quaternion to yield quaternion | ||
q0 += qDot1 * (1.0f / sampleFreq); | ||
q1 += qDot2 * (1.0f / sampleFreq); | ||
q2 += qDot3 * (1.0f / sampleFreq); | ||
q3 += qDot4 * (1.0f / sampleFreq); | ||
|
||
// Normalise quaternion | ||
recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3); | ||
q0 *= recipNorm; | ||
q1 *= recipNorm; | ||
q2 *= recipNorm; | ||
q3 *= recipNorm; | ||
} | ||
|
||
//--------------------------------------------------------------------------------------------------- | ||
// IMU algorithm update | ||
|
||
void Madgwick::updateIMU(float gx, float gy, float gz, float ax, float ay, float az) { | ||
float recipNorm; | ||
float s0, s1, s2, s3; | ||
float qDot1, qDot2, qDot3, qDot4; | ||
float _2q0, _2q1, _2q2, _2q3, _4q0, _4q1, _4q2 ,_8q1, _8q2, q0q0, q1q1, q2q2, q3q3; | ||
|
||
// Rate of change of quaternion from gyroscope | ||
qDot1 = 0.5f * (-q1 * gx - q2 * gy - q3 * gz); | ||
qDot2 = 0.5f * (q0 * gx + q2 * gz - q3 * gy); | ||
qDot3 = 0.5f * (q0 * gy - q1 * gz + q3 * gx); | ||
qDot4 = 0.5f * (q0 * gz + q1 * gy - q2 * gx); | ||
|
||
// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation) | ||
if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) { | ||
|
||
// Normalise accelerometer measurement | ||
recipNorm = invSqrt(ax * ax + ay * ay + az * az); | ||
ax *= recipNorm; | ||
ay *= recipNorm; | ||
az *= recipNorm; | ||
|
||
// Auxiliary variables to avoid repeated arithmetic | ||
_2q0 = 2.0f * q0; | ||
_2q1 = 2.0f * q1; | ||
_2q2 = 2.0f * q2; | ||
_2q3 = 2.0f * q3; | ||
_4q0 = 4.0f * q0; | ||
_4q1 = 4.0f * q1; | ||
_4q2 = 4.0f * q2; | ||
_8q1 = 8.0f * q1; | ||
_8q2 = 8.0f * q2; | ||
q0q0 = q0 * q0; | ||
q1q1 = q1 * q1; | ||
q2q2 = q2 * q2; | ||
q3q3 = q3 * q3; | ||
|
||
// Gradient decent algorithm corrective step | ||
s0 = _4q0 * q2q2 + _2q2 * ax + _4q0 * q1q1 - _2q1 * ay; | ||
s1 = _4q1 * q3q3 - _2q3 * ax + 4.0f * q0q0 * q1 - _2q0 * ay - _4q1 + _8q1 * q1q1 + _8q1 * q2q2 + _4q1 * az; | ||
s2 = 4.0f * q0q0 * q2 + _2q0 * ax + _4q2 * q3q3 - _2q3 * ay - _4q2 + _8q2 * q1q1 + _8q2 * q2q2 + _4q2 * az; | ||
s3 = 4.0f * q1q1 * q3 - _2q1 * ax + 4.0f * q2q2 * q3 - _2q2 * ay; | ||
recipNorm = invSqrt(s0 * s0 + s1 * s1 + s2 * s2 + s3 * s3); // normalise step magnitude | ||
s0 *= recipNorm; | ||
s1 *= recipNorm; | ||
s2 *= recipNorm; | ||
s3 *= recipNorm; | ||
|
||
// Apply feedback step | ||
qDot1 -= beta * s0; | ||
qDot2 -= beta * s1; | ||
qDot3 -= beta * s2; | ||
qDot4 -= beta * s3; | ||
} | ||
|
||
// Integrate rate of change of quaternion to yield quaternion | ||
q0 += qDot1 * (1.0f / sampleFreq); | ||
q1 += qDot2 * (1.0f / sampleFreq); | ||
q2 += qDot3 * (1.0f / sampleFreq); | ||
q3 += qDot4 * (1.0f / sampleFreq); | ||
|
||
// Normalise quaternion | ||
recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3); | ||
q0 *= recipNorm; | ||
q1 *= recipNorm; | ||
q2 *= recipNorm; | ||
q3 *= recipNorm; | ||
} | ||
|
||
//--------------------------------------------------------------------------------------------------- | ||
// Fast inverse square-root | ||
// See: http://en.wikipedia.org/wiki/Fast_inverse_square_root | ||
|
||
float Madgwick::invSqrt(float x) { | ||
float halfx = 0.5f * x; | ||
float y = x; | ||
long i = *(long*)&y; | ||
i = 0x5f3759df - (i>>1); | ||
y = *(float*)&i; | ||
y = y * (1.5f - (halfx * y * y)); | ||
return y; | ||
} | ||
|
||
//==================================================================================================== | ||
// END OF CODE | ||
//==================================================================================================== |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
//===================================================================================================== | ||
// MadgwickAHRS.h | ||
//===================================================================================================== | ||
// | ||
// Implementation of Madgwick's IMU and AHRS algorithms. | ||
// See: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms | ||
// | ||
// Date Author Notes | ||
// 29/09/2011 SOH Madgwick Initial release | ||
// 02/10/2011 SOH Madgwick Optimised for reduced CPU load | ||
// | ||
//===================================================================================================== | ||
#ifndef MadgwickAHRS_h | ||
#define MadgwickAHRS_h | ||
#include <math.h> | ||
#define sampleFreq 512.0f // sample frequency in Hz | ||
#define betaDef 0.1f // 2 * proportional gain | ||
|
||
//---------------------------------------------------------------------------------------------------- | ||
// Variable declaration | ||
class Madgwick{ | ||
private: | ||
float invSqrt(float x); | ||
volatile float beta = betaDef; // algorithm gain | ||
volatile float q0 = 1.0f; | ||
volatile float q1 = 0.0f; | ||
volatile float q2 = 0.0f; | ||
volatile float q3 = 0.0f; // quaternion of sensor frame relative to auxiliary frame | ||
|
||
//--------------------------------------------------------------------------------------------------- | ||
// Function declarations | ||
public: | ||
Madgwick(void){}; | ||
void update(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz); | ||
void updateIMU(float gx, float gy, float gz, float ax, float ay, float az); | ||
float getPitch(){return atan2(2 * q2 * q3 - 2 * q0 * q1, 2 * q0 * q0 + 2 * q3 * q3 - 1);}; | ||
float getRoll(){return -1 * asin(2 * q1 * q3 + 2 * q0 * q2);}; | ||
float getYaw(){return atan2(2 * q1 * q2 - 2 * q0 * q3, 2 * q0 * q0 + 2 * q1 * q1 - 1);}; | ||
}; | ||
#endif | ||
|
||
//===================================================================================================== | ||
// End of file | ||
//===================================================================================================== |