Adafruit driver converted to Mbed OS 6.x.

Dependents:   Adafruit-BNO055-test

Committer:
simonscott
Date:
Wed Sep 16 19:48:33 2015 +0000
Revision:
0:22c544c8741a
First version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
simonscott 0:22c544c8741a 1 /*
simonscott 0:22c544c8741a 2 Inertial Measurement Unit Maths Library
simonscott 0:22c544c8741a 3 Copyright (C) 2013-2014 Samuel Cowen
simonscott 0:22c544c8741a 4 www.camelsoftware.com
simonscott 0:22c544c8741a 5
simonscott 0:22c544c8741a 6 This program is free software: you can redistribute it and/or modify
simonscott 0:22c544c8741a 7 it under the terms of the GNU General Public License as published by
simonscott 0:22c544c8741a 8 the Free Software Foundation, either version 3 of the License, or
simonscott 0:22c544c8741a 9 (at your option) any later version.
simonscott 0:22c544c8741a 10
simonscott 0:22c544c8741a 11 This program is distributed in the hope that it will be useful,
simonscott 0:22c544c8741a 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
simonscott 0:22c544c8741a 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
simonscott 0:22c544c8741a 14 GNU General Public License for more details.
simonscott 0:22c544c8741a 15
simonscott 0:22c544c8741a 16 You should have received a copy of the GNU General Public License
simonscott 0:22c544c8741a 17 along with this program. If not, see <http://www.gnu.org/licenses/>.
simonscott 0:22c544c8741a 18 */
simonscott 0:22c544c8741a 19
simonscott 0:22c544c8741a 20
simonscott 0:22c544c8741a 21 #ifndef IMUMATH_QUATERNION_HPP
simonscott 0:22c544c8741a 22 #define IMUMATH_QUATERNION_HPP
simonscott 0:22c544c8741a 23
simonscott 0:22c544c8741a 24 #include <stdlib.h>
simonscott 0:22c544c8741a 25 #include <string.h>
simonscott 0:22c544c8741a 26 #include <stdint.h>
simonscott 0:22c544c8741a 27 #include <math.h>
simonscott 0:22c544c8741a 28
simonscott 0:22c544c8741a 29 #include "vector.h"
simonscott 0:22c544c8741a 30
simonscott 0:22c544c8741a 31
simonscott 0:22c544c8741a 32 namespace imu
simonscott 0:22c544c8741a 33 {
simonscott 0:22c544c8741a 34
simonscott 0:22c544c8741a 35
simonscott 0:22c544c8741a 36
simonscott 0:22c544c8741a 37 class Quaternion
simonscott 0:22c544c8741a 38 {
simonscott 0:22c544c8741a 39 public:
simonscott 0:22c544c8741a 40 Quaternion()
simonscott 0:22c544c8741a 41 {
simonscott 0:22c544c8741a 42 _w = 1.0;
simonscott 0:22c544c8741a 43 _x = _y = _z = 0.0;
simonscott 0:22c544c8741a 44 }
simonscott 0:22c544c8741a 45
simonscott 0:22c544c8741a 46 Quaternion(double iw, double ix, double iy, double iz)
simonscott 0:22c544c8741a 47 {
simonscott 0:22c544c8741a 48 _w = iw;
simonscott 0:22c544c8741a 49 _x = ix;
simonscott 0:22c544c8741a 50 _y = iy;
simonscott 0:22c544c8741a 51 _z = iz;
simonscott 0:22c544c8741a 52 }
simonscott 0:22c544c8741a 53
simonscott 0:22c544c8741a 54 Quaternion(double w, Vector<3> vec)
simonscott 0:22c544c8741a 55 {
simonscott 0:22c544c8741a 56 _w = w;
simonscott 0:22c544c8741a 57 _x = vec.x();
simonscott 0:22c544c8741a 58 _y = vec.y();
simonscott 0:22c544c8741a 59 _z = vec.z();
simonscott 0:22c544c8741a 60 }
simonscott 0:22c544c8741a 61
simonscott 0:22c544c8741a 62 double& w()
simonscott 0:22c544c8741a 63 {
simonscott 0:22c544c8741a 64 return _w;
simonscott 0:22c544c8741a 65 }
simonscott 0:22c544c8741a 66 double& x()
simonscott 0:22c544c8741a 67 {
simonscott 0:22c544c8741a 68 return _x;
simonscott 0:22c544c8741a 69 }
simonscott 0:22c544c8741a 70 double& y()
simonscott 0:22c544c8741a 71 {
simonscott 0:22c544c8741a 72 return _y;
simonscott 0:22c544c8741a 73 }
simonscott 0:22c544c8741a 74 double& z()
simonscott 0:22c544c8741a 75 {
simonscott 0:22c544c8741a 76 return _z;
simonscott 0:22c544c8741a 77 }
simonscott 0:22c544c8741a 78
simonscott 0:22c544c8741a 79 double w() const
simonscott 0:22c544c8741a 80 {
simonscott 0:22c544c8741a 81 return _w;
simonscott 0:22c544c8741a 82 }
simonscott 0:22c544c8741a 83 double x() const
simonscott 0:22c544c8741a 84 {
simonscott 0:22c544c8741a 85 return _x;
simonscott 0:22c544c8741a 86 }
simonscott 0:22c544c8741a 87 double y() const
simonscott 0:22c544c8741a 88 {
simonscott 0:22c544c8741a 89 return _y;
simonscott 0:22c544c8741a 90 }
simonscott 0:22c544c8741a 91 double z() const
simonscott 0:22c544c8741a 92 {
simonscott 0:22c544c8741a 93 return _z;
simonscott 0:22c544c8741a 94 }
simonscott 0:22c544c8741a 95
simonscott 0:22c544c8741a 96 double magnitude() const
simonscott 0:22c544c8741a 97 {
simonscott 0:22c544c8741a 98 double res = (_w*_w) + (_x*_x) + (_y*_y) + (_z*_z);
simonscott 0:22c544c8741a 99 return sqrt(res);
simonscott 0:22c544c8741a 100 }
simonscott 0:22c544c8741a 101
simonscott 0:22c544c8741a 102 void normalize()
simonscott 0:22c544c8741a 103 {
simonscott 0:22c544c8741a 104 double mag = magnitude();
simonscott 0:22c544c8741a 105 *this = this->scale(1/mag);
simonscott 0:22c544c8741a 106 }
simonscott 0:22c544c8741a 107
simonscott 0:22c544c8741a 108
simonscott 0:22c544c8741a 109 Quaternion conjugate() const
simonscott 0:22c544c8741a 110 {
simonscott 0:22c544c8741a 111 Quaternion q;
simonscott 0:22c544c8741a 112 q.w() = _w;
simonscott 0:22c544c8741a 113 q.x() = -_x;
simonscott 0:22c544c8741a 114 q.y() = -_y;
simonscott 0:22c544c8741a 115 q.z() = -_z;
simonscott 0:22c544c8741a 116 return q;
simonscott 0:22c544c8741a 117 }
simonscott 0:22c544c8741a 118
simonscott 0:22c544c8741a 119 void fromAxisAngle(Vector<3> axis, double theta)
simonscott 0:22c544c8741a 120 {
simonscott 0:22c544c8741a 121 _w = cos(theta/2);
simonscott 0:22c544c8741a 122 //only need to calculate sine of half theta once
simonscott 0:22c544c8741a 123 double sht = sin(theta/2);
simonscott 0:22c544c8741a 124 _x = axis.x() * sht;
simonscott 0:22c544c8741a 125 _y = axis.y() * sht;
simonscott 0:22c544c8741a 126 _z = axis.z() * sht;
simonscott 0:22c544c8741a 127 }
simonscott 0:22c544c8741a 128
simonscott 0:22c544c8741a 129 void fromMatrix(Matrix<3> m)
simonscott 0:22c544c8741a 130 {
simonscott 0:22c544c8741a 131 float tr = m(0, 0) + m(1, 1) + m(2, 2);
simonscott 0:22c544c8741a 132
simonscott 0:22c544c8741a 133 float S = 0.0;
simonscott 0:22c544c8741a 134 if (tr > 0)
simonscott 0:22c544c8741a 135 {
simonscott 0:22c544c8741a 136 S = sqrt(tr+1.0) * 2;
simonscott 0:22c544c8741a 137 _w = 0.25 * S;
simonscott 0:22c544c8741a 138 _x = (m(2, 1) - m(1, 2)) / S;
simonscott 0:22c544c8741a 139 _y = (m(0, 2) - m(2, 0)) / S;
simonscott 0:22c544c8741a 140 _z = (m(1, 0) - m(0, 1)) / S;
simonscott 0:22c544c8741a 141 }
simonscott 0:22c544c8741a 142 else if ((m(0, 0) < m(1, 1))&(m(0, 0) < m(2, 2)))
simonscott 0:22c544c8741a 143 {
simonscott 0:22c544c8741a 144 S = sqrt(1.0 + m(0, 0) - m(1, 1) - m(2, 2)) * 2;
simonscott 0:22c544c8741a 145 _w = (m(2, 1) - m(1, 2)) / S;
simonscott 0:22c544c8741a 146 _x = 0.25 * S;
simonscott 0:22c544c8741a 147 _y = (m(0, 1) + m(1, 0)) / S;
simonscott 0:22c544c8741a 148 _z = (m(0, 2) + m(2, 0)) / S;
simonscott 0:22c544c8741a 149 }
simonscott 0:22c544c8741a 150 else if (m(1, 1) < m(2, 2))
simonscott 0:22c544c8741a 151 {
simonscott 0:22c544c8741a 152 S = sqrt(1.0 + m(1, 1) - m(0, 0) - m(2, 2)) * 2;
simonscott 0:22c544c8741a 153 _w = (m(0, 2) - m(2, 0)) / S;
simonscott 0:22c544c8741a 154 _x = (m(0, 1) + m(1, 0)) / S;
simonscott 0:22c544c8741a 155 _y = 0.25 * S;
simonscott 0:22c544c8741a 156 _z = (m(1, 2) + m(2, 1)) / S;
simonscott 0:22c544c8741a 157 }
simonscott 0:22c544c8741a 158 else
simonscott 0:22c544c8741a 159 {
simonscott 0:22c544c8741a 160 S = sqrt(1.0 + m(2, 2) - m(0, 0) - m(1, 1)) * 2;
simonscott 0:22c544c8741a 161 _w = (m(1, 0) - m(0, 1)) / S;
simonscott 0:22c544c8741a 162 _x = (m(0, 2) + m(2, 0)) / S;
simonscott 0:22c544c8741a 163 _y = (m(1, 2) + m(2, 1)) / S;
simonscott 0:22c544c8741a 164 _z = 0.25 * S;
simonscott 0:22c544c8741a 165 }
simonscott 0:22c544c8741a 166 }
simonscott 0:22c544c8741a 167
simonscott 0:22c544c8741a 168 void toAxisAngle(Vector<3>& axis, float& angle) const
simonscott 0:22c544c8741a 169 {
simonscott 0:22c544c8741a 170 float sqw = sqrt(1-_w*_w);
simonscott 0:22c544c8741a 171 if(sqw == 0) //it's a singularity and divide by zero, avoid
simonscott 0:22c544c8741a 172 return;
simonscott 0:22c544c8741a 173
simonscott 0:22c544c8741a 174 angle = 2 * acos(_w);
simonscott 0:22c544c8741a 175 axis.x() = _x / sqw;
simonscott 0:22c544c8741a 176 axis.y() = _y / sqw;
simonscott 0:22c544c8741a 177 axis.z() = _z / sqw;
simonscott 0:22c544c8741a 178 }
simonscott 0:22c544c8741a 179
simonscott 0:22c544c8741a 180 Matrix<3> toMatrix() const
simonscott 0:22c544c8741a 181 {
simonscott 0:22c544c8741a 182 Matrix<3> ret;
simonscott 0:22c544c8741a 183 ret.cell(0, 0) = 1-(2*(_y*_y))-(2*(_z*_z));
simonscott 0:22c544c8741a 184 ret.cell(0, 1) = (2*_x*_y)-(2*_w*_z);
simonscott 0:22c544c8741a 185 ret.cell(0, 2) = (2*_x*_z)+(2*_w*_y);
simonscott 0:22c544c8741a 186
simonscott 0:22c544c8741a 187 ret.cell(1, 0) = (2*_x*_y)+(2*_w*_z);
simonscott 0:22c544c8741a 188 ret.cell(1, 1) = 1-(2*(_x*_x))-(2*(_z*_z));
simonscott 0:22c544c8741a 189 ret.cell(1, 2) = (2*(_y*_z))-(2*(_w*_x));
simonscott 0:22c544c8741a 190
simonscott 0:22c544c8741a 191 ret.cell(2, 0) = (2*(_x*_z))-(2*_w*_y);
simonscott 0:22c544c8741a 192 ret.cell(2, 1) = (2*_y*_z)+(2*_w*_x);
simonscott 0:22c544c8741a 193 ret.cell(2, 2) = 1-(2*(_x*_x))-(2*(_y*_y));
simonscott 0:22c544c8741a 194 return ret;
simonscott 0:22c544c8741a 195 }
simonscott 0:22c544c8741a 196
simonscott 0:22c544c8741a 197
simonscott 0:22c544c8741a 198 // Returns euler angles that represent the quaternion. Angles are
simonscott 0:22c544c8741a 199 // returned in rotation order and right-handed about the specified
simonscott 0:22c544c8741a 200 // axes:
simonscott 0:22c544c8741a 201 //
simonscott 0:22c544c8741a 202 // v[0] is applied 1st about z (ie, roll)
simonscott 0:22c544c8741a 203 // v[1] is applied 2nd about y (ie, pitch)
simonscott 0:22c544c8741a 204 // v[2] is applied 3rd about x (ie, yaw)
simonscott 0:22c544c8741a 205 //
simonscott 0:22c544c8741a 206 // Note that this means result.x() is not a rotation about x;
simonscott 0:22c544c8741a 207 // similarly for result.z().
simonscott 0:22c544c8741a 208 //
simonscott 0:22c544c8741a 209 Vector<3> toEuler() const
simonscott 0:22c544c8741a 210 {
simonscott 0:22c544c8741a 211 Vector<3> ret;
simonscott 0:22c544c8741a 212 double sqw = _w*_w;
simonscott 0:22c544c8741a 213 double sqx = _x*_x;
simonscott 0:22c544c8741a 214 double sqy = _y*_y;
simonscott 0:22c544c8741a 215 double sqz = _z*_z;
simonscott 0:22c544c8741a 216
simonscott 0:22c544c8741a 217 ret.x() = atan2(2.0*(_x*_y+_z*_w),(sqx-sqy-sqz+sqw));
simonscott 0:22c544c8741a 218 ret.y() = asin(-2.0*(_x*_z-_y*_w)/(sqx+sqy+sqz+sqw));
simonscott 0:22c544c8741a 219 ret.z() = atan2(2.0*(_y*_z+_x*_w),(-sqx-sqy+sqz+sqw));
simonscott 0:22c544c8741a 220
simonscott 0:22c544c8741a 221 return ret;
simonscott 0:22c544c8741a 222 }
simonscott 0:22c544c8741a 223
simonscott 0:22c544c8741a 224 Vector<3> toAngularVelocity(float dt) const
simonscott 0:22c544c8741a 225 {
simonscott 0:22c544c8741a 226 Vector<3> ret;
simonscott 0:22c544c8741a 227 Quaternion one(1.0, 0.0, 0.0, 0.0);
simonscott 0:22c544c8741a 228 Quaternion delta = one - *this;
simonscott 0:22c544c8741a 229 Quaternion r = (delta/dt);
simonscott 0:22c544c8741a 230 r = r * 2;
simonscott 0:22c544c8741a 231 r = r * one;
simonscott 0:22c544c8741a 232
simonscott 0:22c544c8741a 233 ret.x() = r.x();
simonscott 0:22c544c8741a 234 ret.y() = r.y();
simonscott 0:22c544c8741a 235 ret.z() = r.z();
simonscott 0:22c544c8741a 236 return ret;
simonscott 0:22c544c8741a 237 }
simonscott 0:22c544c8741a 238
simonscott 0:22c544c8741a 239 Vector<3> rotateVector(Vector<2> v) const
simonscott 0:22c544c8741a 240 {
simonscott 0:22c544c8741a 241 Vector<3> ret(v.x(), v.y(), 0.0);
simonscott 0:22c544c8741a 242 return rotateVector(ret);
simonscott 0:22c544c8741a 243 }
simonscott 0:22c544c8741a 244
simonscott 0:22c544c8741a 245 Vector<3> rotateVector(Vector<3> v) const
simonscott 0:22c544c8741a 246 {
simonscott 0:22c544c8741a 247 Vector<3> qv(this->x(), this->y(), this->z());
simonscott 0:22c544c8741a 248 Vector<3> t;
simonscott 0:22c544c8741a 249 t = qv.cross(v) * 2.0;
simonscott 0:22c544c8741a 250 return v + (t * _w) + qv.cross(t);
simonscott 0:22c544c8741a 251 }
simonscott 0:22c544c8741a 252
simonscott 0:22c544c8741a 253
simonscott 0:22c544c8741a 254 Quaternion operator * (Quaternion q) const
simonscott 0:22c544c8741a 255 {
simonscott 0:22c544c8741a 256 Quaternion ret;
simonscott 0:22c544c8741a 257 ret._w = ((_w*q._w) - (_x*q._x) - (_y*q._y) - (_z*q._z));
simonscott 0:22c544c8741a 258 ret._x = ((_w*q._x) + (_x*q._w) + (_y*q._z) - (_z*q._y));
simonscott 0:22c544c8741a 259 ret._y = ((_w*q._y) - (_x*q._z) + (_y*q._w) + (_z*q._x));
simonscott 0:22c544c8741a 260 ret._z = ((_w*q._z) + (_x*q._y) - (_y*q._x) + (_z*q._w));
simonscott 0:22c544c8741a 261 return ret;
simonscott 0:22c544c8741a 262 }
simonscott 0:22c544c8741a 263
simonscott 0:22c544c8741a 264 Quaternion operator + (Quaternion q) const
simonscott 0:22c544c8741a 265 {
simonscott 0:22c544c8741a 266 Quaternion ret;
simonscott 0:22c544c8741a 267 ret._w = _w + q._w;
simonscott 0:22c544c8741a 268 ret._x = _x + q._x;
simonscott 0:22c544c8741a 269 ret._y = _y + q._y;
simonscott 0:22c544c8741a 270 ret._z = _z + q._z;
simonscott 0:22c544c8741a 271 return ret;
simonscott 0:22c544c8741a 272 }
simonscott 0:22c544c8741a 273
simonscott 0:22c544c8741a 274 Quaternion operator - (Quaternion q) const
simonscott 0:22c544c8741a 275 {
simonscott 0:22c544c8741a 276 Quaternion ret;
simonscott 0:22c544c8741a 277 ret._w = _w - q._w;
simonscott 0:22c544c8741a 278 ret._x = _x - q._x;
simonscott 0:22c544c8741a 279 ret._y = _y - q._y;
simonscott 0:22c544c8741a 280 ret._z = _z - q._z;
simonscott 0:22c544c8741a 281 return ret;
simonscott 0:22c544c8741a 282 }
simonscott 0:22c544c8741a 283
simonscott 0:22c544c8741a 284 Quaternion operator / (float scalar) const
simonscott 0:22c544c8741a 285 {
simonscott 0:22c544c8741a 286 Quaternion ret;
simonscott 0:22c544c8741a 287 ret._w = this->_w/scalar;
simonscott 0:22c544c8741a 288 ret._x = this->_x/scalar;
simonscott 0:22c544c8741a 289 ret._y = this->_y/scalar;
simonscott 0:22c544c8741a 290 ret._z = this->_z/scalar;
simonscott 0:22c544c8741a 291 return ret;
simonscott 0:22c544c8741a 292 }
simonscott 0:22c544c8741a 293
simonscott 0:22c544c8741a 294 Quaternion operator * (float scalar) const
simonscott 0:22c544c8741a 295 {
simonscott 0:22c544c8741a 296 Quaternion ret;
simonscott 0:22c544c8741a 297 ret._w = this->_w*scalar;
simonscott 0:22c544c8741a 298 ret._x = this->_x*scalar;
simonscott 0:22c544c8741a 299 ret._y = this->_y*scalar;
simonscott 0:22c544c8741a 300 ret._z = this->_z*scalar;
simonscott 0:22c544c8741a 301 return ret;
simonscott 0:22c544c8741a 302 }
simonscott 0:22c544c8741a 303
simonscott 0:22c544c8741a 304 Quaternion scale(double scalar) const
simonscott 0:22c544c8741a 305 {
simonscott 0:22c544c8741a 306 Quaternion ret;
simonscott 0:22c544c8741a 307 ret._w = this->_w*scalar;
simonscott 0:22c544c8741a 308 ret._x = this->_x*scalar;
simonscott 0:22c544c8741a 309 ret._y = this->_y*scalar;
simonscott 0:22c544c8741a 310 ret._z = this->_z*scalar;
simonscott 0:22c544c8741a 311 return ret;
simonscott 0:22c544c8741a 312 }
simonscott 0:22c544c8741a 313
simonscott 0:22c544c8741a 314 private:
simonscott 0:22c544c8741a 315 double _w, _x, _y, _z;
simonscott 0:22c544c8741a 316 };
simonscott 0:22c544c8741a 317
simonscott 0:22c544c8741a 318
simonscott 0:22c544c8741a 319 };
simonscott 0:22c544c8741a 320
simonscott 0:22c544c8741a 321 #endif