IMU Data Fusing: Complementary, Kalman, and Mahony Filter

An inertial measurement unit, or IMU, measures accelerations and rotation rates, and possibly earth’s magnetic field, in order to determine a body’s attitude. Anyone who is serious about reading this article is likely familiar with the topic, and the need of data fusing, and I shouldn’t spend more words on this. I should however – since this is going to be a long article – spend some words on what this article is about:

The literature on the web (and I should say that the web is my only source of information) on the topic is abundant. It appears however that it is based to a greater or lesser extent on some few works, e.g. by Colton [SC], Premerlani and Bizard [PB], Starlino [St], Lauszus [La], Mahony [RM] and Madgwick [SM], which – so it seems – have become standard references (for hobbiests!). The number of different algorithms and implementation details given there is somewhat confusing, but – even though different buzz words are certainly used – it is not always obvious to what extend they are different. This article presents an analysis and comparison of the data fusing filters described in these works, in order to understand better their behavior, and differences and similarities. As a corollary simplified and/or improved algorithms surface. The article considers 6DOF IMUs only.

Three basic filter approaches are discussed, the complementary filter, the Kalman filter (with constant matrices), and the Mahony&Madgwick filter. The article starts with some preliminaries, which I find relevant. It then considers the case of a single axis (called one dimensional or 1D). First the most simplest method is discussed, where gyro bias is not estimated (called 1st order). Then gyro bias estimation is included (called 2nd order). Finally, the complete situation of three axes (called 3D) is considered, and some approximations and improvements are evaluated.

1. Preliminaries
1.1. Notes on Kinematics and IMU Algorithms
1.2. Discretization and Implementation Issues
1.3. Kalman Filter with Constant Matrices
2. 1D IMU Data Fusing – 1st Order (wo Drift Estimation)
2.1. Complementary Filter
2.2. Kalman Filter
2.3. Mahony&Madgwick Filter
2.4. Comparison & Conclusions
3. 1D IMU Data Fusing – 2nd Order (with Drift Estimation)
3.1. Kalman Filter
3.2. Mahony&Madgwick Filter
3.3. Comparison
3.4. Complementary Filter
3.5. Summary on 1D Filters
4. 3D IMU Data Fusing with Mahony Filter
4.1. „Original“ Mahony Filter
4.2. 2D Mahony Filter and Simplifications
4.3. Premerlani & Bizard’s IMU Filter
5. Further 3D Filters
IMU Implementations

Notation: The discrete time step is denoted as \Delta t, and n or k is used as time-step index. The estimate of a quantity is indicated by a hat, e.g. \hat{x}, which will however often be dropped for simplicity, whenever confusion seems impossible. Bold symbols represent vectors or matrices in \mathbb{R}^3 (vectors and matrices in e.g. state space won’t be bold), and quaternions.

A note: Madgwick’s scheme is significantly different in some aspects to Mahony’s but shares his feedback loop idea. Moreover, Madgwick presented C code for Mahony’s filter, which I found very useful. That’s why I denote Mahony’s approach as Mahony&Madgwick filter. Madgwick’s steepest decent scheme will be looked at only very briefly below.

1. Preliminaries

1.1. Notes on Kinematics and IMU Algorithms
The task of attitude estimation corresponds to evaluating (computationally) the kinematic equation for the rotation of a body:

\dot{\bf{R}} = {\bf{R}} {\boldsymbol{\Omega}}_\times    with    {\boldsymbol{\Omega}}_\times = {\boldsymbol{\omega}} {\bf{J}} = \left( \begin{array}{ccc} 0 & -\omega_z & \omega_y \\ \omega_z & 0 & -\omega_x \\ -\omega_y & \omega_x & 0 \end{array} \right),    Eq. (1.1)

where {\boldsymbol{\omega}} = (\omega_x,\omega_y,\omega_z)^T is the rotation rate vector measured in the body-fixed reference frame, and the rotation {\bf{R}} represents the orientation of the body-fixed reference frame as observed in the earth reference frame. For any vector {\bf{v}}, the coordinates {\bf{v}}_{earth} with respect to the earth frame become in the body-fixed frame {\bf{v}}_{body} = {\bf{R}}^T {\bf{v}}_{earth}, which evolve as \dot{\bf{v}}_{body} = {\boldsymbol{\Omega}}^T_\times {\bf{v}}_{body} = - ({\boldsymbol{\omega}} \times {\bf{v}}_{body}) (the minus sign comes in here since {\boldsymbol{\omega}} is expressed in the body-fixed coordinate system).

As simple as it may appear, equation Eq. (1.1) presents us with some fundamental issues:

(1) Equation (1.1) is non-linear. This can complicate filter design enormously.

(2) Equation (1.1) is susceptible to numerical errors. Well, numerical errors are present in any calculation performed on a micro processor, but in most cases they are well-behaved in the sense that they do not accumulate. However, for Eq. (1) the errors continuously grow if no counter-measures are taken, and {\bf{R}} eventually ceases to represent a rotation. Importantly, this is related to the global non-commutativity of rotations (in 3 dimensions) and hence is fundamental. It is here where cool buzz words such as direction cosine matrix (DCM) or quaternions enter the game.

(3) The rotation {\bf{R}} can be represented in several ways [RO], and each representation has its own set of advantages and disadvantages. Most well-known are the representations by a rotation matrix or DCM, Euler angles and related angles (Cardan, Tait-Brian), axis and angle, and quaternions, but some more exist. Obviously, the algorithm will depend a lot on which representation is chosen.

You may note, no words were yet spend on measurement noise and data fusing; I haven’t added it to the list since it’s not really rooted in Eq. (1.1), although it’s of course an important point – and in fact the topic of this article.

Anyhow, since the challenges are alike, all algorithms presented by the above authors exhibit a similar structure:

(T1) Integrate rate of change of the DCM, Euler angles, quaternion, or whatever is used to represent {\bf{R}}.
For (T1) the DCM, quaternion, and Euler angle representations were used, or – if only the direction was required – the „gravity“ vector {\bf{d}} = - {\bf{R}}^T {\bf{e}}_z.

(T2) Take care that the numerical representation of {\bf{R}} represents in fact a „real“ physical rotation.
Several strategies were presented. In [PB] and [St2] the DCM is renormalized by subtracting the errors for the x and y directions to equal parts, in [RM07] the matrix exponential and Rodriguez formulas or alternatively 2nd-order Runge-Kutta is suggested, and in [RM08] and [SM] the common approach of quaternion normalizing is employed. In the MultiWii code (and in [St1]) the drastic approach of neglecting this step altogether is taken; that is, it is left to the data fusing step to ensure the properness of the estimated attitude.

(T3) Improve the attitude estimate by fusing accelerometer and gyroscope data.
This is the crucial (and intelectually most challenging) step, since it decides about the actual quality of the filter in terms of filter performance. The task is to compute from a given attitude {\bf{R}} and measured acceleration vector {\bf{a}} an improved attitude estimate {\bf{R}}^{improved}, or formally to identify a function {\bf{R}}^{improved} = f( {\bf{R}}, {\bf{a}}). In the above mentioned articles three approaches were taken, which are refereed here to as the complementary filter, Kalman filter, and Mahony&Madgwick filter.

The present article is about task T3; tasks T1 and T2 are not discussed.

1.2. Discretization and Implementation Issues
Well, it’s not big news that for a given system, described by e.g. a continuous-time transfer function G(s), there are many different possible implementations in computer code, and that they do not all show identical performance even though they are derived from one and the same function G(s).

One reason for arriving at different implementations is that there is no universal rule for converting a continuous- time transfer function G(s) to a discrete-time transfer function H(z), since it’s approximative. The conversion from G(s) to H(z) is thus not unique, and typical choices are:

backward difference: s = \dfrac{1}{\Delta t} ( 1 - z^{-1} ), Eq. (1.2)    
bilinear transformation, expansion of ln(z): s = \dfrac{2}{\Delta t} \dfrac{ 1 - z^{-1} }{  1 + z^{-1} }, Eq. (1.3)
impulse invariance transformation: \dfrac{ G(z) }{1 - z^{-1}} = Z\left( \dfrac{G(s)}{s} \right), Eq. (1.4)

Another reason is that a given discrete-time transfer function H(z) can be implemented in different ways, and the different implementations possibly show different behavior in various aspects, such as stability and high-frequency noise. The topic is not simple, and is beyond my competences, but the basic principle is clear.

Let’s consider as an example, since it’s so familiar, the PID controller G(s) = K_p + \frac{1}{s} K_i + s K_d. Using backward difference one finds H(z) = K_p + \frac{K_i \Delta t}{1 - z^{-1}} + \frac{K_d}{\Delta t}(1 - z^{-1}), which can be implemented by first evaluating I_n = \frac{K_i \Delta t}{1 - z^{-1}} x_n and then y_n = K_p x_n + I_n + \frac{K_d}{\Delta t}(1 - z^{-1}) x_n, or by directly solving y_n= H(z) x_n. In the first case one obtains the positional PID algorithm

I_n = I_{n-1} + K_i \Delta t x_n,         Eq. (1.5a)
y_n = K_p x_n + I_n + \dfrac{K_d}{\Delta t}( x_n - x_{n-1} ),   Eq. (1.5b)

while the second case leads to the velocity PID algorithm

y_n = y_{n-1} + K_p ( x_n - x_{n-1} ) + K_i \Delta t x_n + \dfrac{K_d}{\Delta t}( x_n + 2x_{n-1} - x_{n-2} ).    Eq. (1.6)

Both derive from the same function H(z), or G(s), but differ e.g. with regards to wind up, overflow of internal variables, number of storage elements and so on.

Corollary #1: In the positional PID algorithm, Eq. (1.5), the order of the two equations can be reversed,
y_n = K_p x_n + I_{n-1} + \dfrac{K_d}{\Delta t}( x_n - x_{n-1} ),   Eq. (1.7a)
I_n = I_{n-1} + K_i \Delta t x_n,            Eq. (1.7b)
with an irrelevant change of the parameter K_p \rightarrow K_p + K_i \Delta t. That is, the order of their execution or implementation in code is irrelevant.

1.3. Kalman Filter with Constant Matrices
The Kalman filter [KA] takes noise into account via covariance matrices, which are updated regularly at each time step using relatively complicated equations. However, if they would be constant with time, then the Kalman filter equations would simplify enormously. I don’t know for which conditions exactly these matrices become constant, but intuitively it seems reasonable that they are constant for „usual“ systems, e.g., one would not expect the noise spectra of the gyro and accelerometer to vary quickly. Anyhow, in the following they will be assumed to be constant, as well as the system matrices.

The (discrete-time) Kalman filter applies to systems modeled in phase space as

x_k = A x_{k-1} + B u_{k} + w,   Eq. (1.8a)
z_k = H x_{k} + v.         Eq. (1.8b)

Here, x_k ist the state space vector, u_k the control vector, and z_k the measurement vector. I’ve dropped the time-step index on the other quantities to emphasize their constant spectra. A subtlety occurs here: Sometimes Eq. (1.8a) is written with u_{k}, but most times with u_{k-1}. In real implementations I would use the latest control vector u_{k} as only this makes sense to me, but I honestly have no idea whether that’s good or bad. The Kalman filter equations are then

\hat{x}^{-}_k = A \hat{x}_{k-1} + B u_{k},      Eq. (1.9a)
\hat{x}_k = \hat{x}^{-}_k + K ( z_k - H \hat{x}^{-}_k ),    Eq. (1.9b)

where \hat{x}^{-}_k is the predicted and \hat{x}_k the updated state estimate.

A general issue with the Kalman filter is that for one and the same system usually several distinct state space models can be set up, and hence distinct Kalman filters derived.

Comment: In contrast to the situation for the PID controller (Corollary #1) it is not obvious how to reverse the order in Eq. (1.9). In fact, Eq. (1.9) has a clear „philosophy“: One first advances the previous estimate \hat{x}_{k-1} according to the systems dynamics, and then applies the correction/improvement due to the latest measurement.

Comment: Equation (1.9b) has the looks of feedback with error z_k - H \hat{x}^{-}_k, it can however be reformulated as
\begin{array}{rcl}   \hat{x}_k &=& (1-KH) \hat{x}^{-}_k + K  z_k \\[0.3em]     &=& (1-KH)A \hat{x}_{k-1}  + (1-KH)B u_k +  K z_k   ,\end{array}    Eq. (1.10)
and then pretty much looks like a complementary filter. This is an important observation! A Kalman filter with constant matrices and a complementary filter are conceptually similar.

2. 1D IMU Data Fusing – 1st Order (wo Drift Estimation)

In this chapter we will consider the simplest case of IMU data fusing, namely that of fusing the angles for a single axis as determined from the time-integrated rotation rate and accelerometer data, without explicitly estimating the gyro’s drift. It has relevance for applications, but here it is of interest mainly as a „warm up“, and because it provides some insight which will help us to better understand the more advanced cases below.

In the following, \theta denotes the estimated angle (except in Chapter 2.2), a the angle calculated from the accelerometer measurements, and \omega the rotation rate measured by the gyro.

2.1. Complementary Filter
The complementary filter fuses the accelerometer and integrated gyro data by passing the former through a 1st-order low pass and the latter through a 1st-order high pass filter and adding the outputs. An excellent discussion of the complementary filter is given in [RM05][RM08], and at a more elementary level in [SC]. The transfer function reads

\theta = \dfrac{1}{1+Ts} a +  \dfrac{Ts}{1+Ts} \dfrac{1}{s} \omega = \dfrac{a + T \omega}{1+Ts},    Eq. (2.1)

where T determines the filter cut-off frequencies. Using backward difference yields 1+Ts = (1+\frac{T}{\Delta t}) - \frac{T}{\Delta t} z^{-1}. Insertion into Eq. (2.1) and rearrangement leads to our final result

\theta_k = \alpha( \theta_{k-1} + \omega_k \Delta t ) + (1-\alpha) a_k    Eq. (2.2)

where \alpha = \frac{T}{\Delta t} /( 1 + \frac{T}{\Delta t} ). This relation can be implemented in code in several ways; three of them were discussed in [SC] (though only #3 makes sense). For better comparison with the other cases below, the result is reformulated as

\theta_k = \alpha \theta_{k-1}  + (1-\alpha) a_k + \alpha \omega_k \Delta t.    Eq. (2.3)

2.2. Kalman Filter
In the simple case considered here the state space model of the system is simply

\begin{array}{rcl}   \theta_k &=& \theta_{k-1} + \omega_k \Delta t \\[0.5em]  z_k   &=& a_k \end{array}    Eq. (2.4)

The state vectors become x = (\theta), u = (\omega), and the matrices A= (1), B=(\Delta t), H=(1), K=(K_0). With that the Kalman equations read

\begin{array}{rcl}   \hat{\theta}^{-}_k &=& \hat{\theta}_{k-1} + \omega_k \Delta t \\[0.5em]  \hat{\theta}_k   &=& (1-K_0) \hat{\theta}^{-}_k + K_0 a_k \end{array}    Eq. (2.5)

These equations can also be expressed as

\hat{\theta}_k = \alpha \hat{\theta}_{k-1} + (1-\alpha) a_k + \alpha \omega_k \Delta t    Eq. (2.6)

with \alpha= 1 - K_0.

2.3. Mahony&Madgwick Filter
Here data fusing is done with a P controller and an integrating process, where the „accelerometer“ angle a becomes the setpoint and the rotation rate \omega a disturbance (of type d_1). The transfer function is thus

\theta = K_p \dfrac{1}{s} ( a - \theta ) +  \dfrac{1}{s} \omega,    Eq. (2.7)

where a - \theta is the error input to the P controller. Rearranging this equation for \theta yields exactly the transfer function of the complementary filter, Eq. (2.1), which from standard arguments of control theory is however not surprising (see e.g. [RM08]).

The controller Eq. (2.7) is usually implemented by first rearranging it to \theta = \frac{1}{s} \left[ K_p(a-\theta)+\omega \right], then separating it into e = a - \theta and \theta = \frac{1}{s}( K_p e + \omega ), and finally discretizing it as

\begin{array}{rcl}   e_k &=& a_k - \theta_{k-1} \\[0.5em] \theta_k  &=& \theta_{k-1} + (K_p e_k + \omega_k)\Delta t \end{array}    Eq. (2.8)

That is, for the Mahony&Madgwick filter one arrives at the update law

\theta_k = \alpha \theta_{k-1}  + (1-\alpha) a_k + \omega_k \Delta t,    Eq. (2.9)

with \alpha = 1 - K_p \Delta t.

It is worthwhile to elaborate a bit further on the controller aspect. For a (simple) controller on finds in general that

y = \dfrac{G_c G_p}{1 + G_c G_p} r +  \dfrac{G_p}{1 + G_c G_p} d_1 +  \dfrac{1}{1 + G_c G_p} d_2,    Eq. (2.10)

where G_c(s) and G_p(s) are the controller and process transfer functions, respectively (the other symbols should be obvious). The conversion of the complementary filter transfer function, Eq. (2.1), into the controller form, Eq. (2.7), is accomplished by multiplying the nominator and denominator in Eq. (2.1) by 1/s:

\theta = \dfrac{1}{1+Ts} a +  \dfrac{Ts}{1+Ts} \dfrac{1}{s} \omega = \dfrac{ K_p \frac{1}{s} }{ 1 + K_p \frac{1}{s} } a +   \dfrac{ \frac{1}{s} }{ 1 + K_p \frac{1}{s} } \omega,    Eq. (2.11)

and identifying G_c(s) = K_p = 1/T and G_p(s) = 1/s. Equations (2.1) and (2.7) are identical, but the former is expressed in terms of polynomials in s while the latter is expressed in terms of polynomials in 1/s.

2.4. Comparison and Conclusions
A couple of observations can be made from the above findings.

(1) The complementary and Kalman filter lead to identical update equations, Eqs. (2.2) and (2.6), and are thus identical, also as regards the transfer functions.

(2) The complementary and Mahony&Madgwick filters are described by identical transfer functions.

(3) From (1) and (2) it follows that all three filters are identical at the level of the transfer function.

(4) Despite (3) the algorithm of the Mahony&Madgwick filter is not identical to that of the complementary and/or Kalman filter, see Eq. (2.9) and Eqs. (2.2), (2.6).

It is worthwhile to discuss the last point further. For convenience the two update laws are reproduced:

\theta_k = \alpha \theta_{k-1}  + (1-\alpha) a_k + \alpha \omega_k \Delta t,    Eqs. (2.2),(2.6)
\theta_k = \alpha \theta_{k-1}  + (1-\alpha) a_k + \omega_k \Delta t.     Eq. (2.9)

One can look at the difference in two ways. Firstly, Eqs. (2.2,6) may be read to say that the angle is first advanced by integrating the rotation rate to give an updated angle and then filtered with a_k to give an improved angle. This may be expressed by the bracketing \theta_k = \alpha [ \theta_{k-1}  + \omega_k \Delta t ] + (1-\alpha) a_k. In contrast, Eq. (2.9) may be read to say that the angle is first filtered with a_k and then advanced by integrating the rotation rate, corresponding to the bracketing \theta_k = [\alpha \theta_{k-1}  + (1-\alpha) a_k] + \omega_k \Delta t. Secondly, the equations can be rearranged into the algorithms

complementary or Kalman filter (1D, 1st order) Mahony&Madgwick filter (1D, 1st order)
\theta^{-}_k = \theta_{k-1}  + \omega_k \Delta t     Eq. (2.12)
e^{-}_k = a_k - \theta^{-}_k
\theta_k = \theta^{-}_k + K_0 e^{-}_k
\theta^{-}_k = \theta_{k-1}  + \omega_k \Delta t     Eq. (2.13)
e_k = a_k - \theta_{k-1}
\theta_k = \theta^{-}_k + K_p \Delta t e_k

They are essentially identical, except of the important difference that on the left the feedback error uses the updated angle \theta^{-}_k while on the right it uses the previous angle estimate \theta_{k-1}! The two algorithms cannot be directly converted into each other, even though they derive from the same transfer function, which should be considered a characteristic feature expressing the different underlying „philosophies“.

3. 1D IMU Data Fusing – 2nd Order (with Drift Estimation)

In this chapter the single-axis filters will be improved by explicitly taking into account the bias/drift of the gyro sensors. To the best of my knowledge, a complementary filter accomplishing this task has not been described before, and hence the order of the discussion of the filters is changed as compared to Chapter 2.

3.1. Kalman Filter
As suggested in [La], the state space model of the system is extended to:

\begin{array}{rcl}  \theta_k &=& \theta_{k-1} + ( \omega_k \mp b_{k-1})\Delta t \\[0.5em] b_k &=& b_{k-1} \\[0.5em]  z_k   &=& a_k \end{array}    Eq. (3.1)

where b represents the gyro bias. One would naturally introduce it such that it corrects the measured rotation rate as \omega_k - b_{k-1}, i.e. with a „-“ sign in Eq. (3.1). However, we will also allow for a „+“ sign for reasons, which will become clear later on. The state vectors and matrices become

  x = \begin{pmatrix} \theta \\ b \end{pmatrix},   u = (\omega),   A = \begin{pmatrix} 1 & \mp \Delta t \\ 0 & 1 \end{pmatrix},   B = \begin{pmatrix} \Delta t \\ 0 \end{pmatrix},   z = (a),   H = \begin{pmatrix} 1 & 0 \end{pmatrix},   K = \begin{pmatrix} K_0 \\ K_1 \end{pmatrix},    Eq. (3.2)

and the Kalman equations are derived as

\begin{array}{rcl}  \hat{\theta}^{-}_k &=& \hat{\theta}_{k-1} + (\omega_k \mp \hat{b}_{k-1})\Delta t \\[0.5em]  \hat{\theta}_k   &=& (1-K_0) \hat{\theta}^{-}_k + K_0 a_k \\[0.5em]  \hat{b}_k &=&  \hat{b}_{k-1} + K_1 ( a_k  - \hat{\theta}^{-}_k ). \end{array}    Eq. (3.3)

As before these equations can be reexpressed, yielding the update laws

\begin{array}{rcl}  \hat{\theta}_k  &=& \alpha \hat{\theta}_{k-1} + (1-\alpha) a_k + \alpha  (\omega_k \mp \hat{b}_{k-1})\Delta t  \\[0.5em]  \hat{b}_k &=&  \hat{b}_{k-1} + K_1 ( a_k  - \hat{\theta}^{-}_k ) \end{array}    Eq. (3.4)

with \alpha= 1-K_0. The similarity to the 1st order result, Eq. (2.6), is obvious. The measured rotation rate is corrected by the estimated bias, which in turn is obtained by integrating the „error“ a_k  - \hat{\theta}^{-}_k.

Corollary #2: The effect of changing the sign in the bias correction to „+“ should be noted. The corrected rotation rate is given as \omega_k + \hat{b}_{k-1}, as expected, but the bias update law in Eqs. (3.3) and (3.4) is not altered! The outcome is thus not equivalent to a variable substitution \hat{b}_{k} \rightarrow -\hat{b}_{k}.

Comment: One could also start from a state space vector x = ( \theta, \omega )^T as suggested by [KA1][KA3][KA4], which however leads to obviously improper filters in our case (thus: it’s one thing to derive a Kalman filer but another thing to get one that’s working properly ;-)).

3.2. Mahony&Madgwick Filter
The gyro drift estimation is facilitated by using a PI controller [RM08], and the transfer function is accordingly

\theta = \left( K_p + K_i \dfrac{1}{s}\right)\dfrac{1}{s} ( a - \theta ) +  \dfrac{1}{s} \omega,    Eq. (3.5)

Following again the standard implementation (positional PID algorithm) one separates Eq. (3.5) into e = a - \theta, I =  K_i \frac{1}{s} e, and \theta = \frac{1}{s}( K_p e + I + \omega ), and discretizes it as

\begin{array}{rcl}   e_k &=& a_k - \theta_{k-1} \\[0.5em]  I_k &=& I_{k-1} + K_i \Delta t e_k \\[0.5em]  \theta_k  &=& \theta_{k-1} + (K_p e_k + I_k + \omega_k)\Delta t \end{array}    Eq. (3.6)

This results in the update laws

\begin{array}{rcl}   I_k &=& I_{k-1} + K_i \Delta t  (a_k - \theta_{k-1}) \\[0.5em]  \theta_k  &=& \alpha \theta_{k-1} + (1-\alpha) a_k + (\omega_k + I_k)\Delta t \end{array}    Eq. (3.7)

with \alpha = 1 - K_p \Delta t.

Here Corollary #1 is recalled, which tells that the sequence of the two equations in Eq. (3.7) can be reversed (with an insignificant parameter change).

3.3. Comparison
Comparing the update laws for \theta_k for the 2nd order Kalman and Mahony&Madgwick filters shows the same aspects discussed in Chapter 2.4. This shall be further emphasized by contrasting again the rearranged algorithms:

Kalman filter (1D, 2nd order) Mahony&Madgwick filter (1D, 2nd order)
\theta^{-}_k = \theta_{k-1}  + (\omega_k + b_{k-1}) \Delta t     Eq. (3.8)
e^{-}_k = a_k - \theta^{-}_k
\theta_k = \theta^{-}_k + K_0 e^{-}_k
b_k = b_{k-1} + K_1 e^{-}_k
\theta^{-}_k = \theta_{k-1} + (\omega_k + I_{k-1}) \Delta t     Eq. (3.9)
e_k = a_k - \theta_{k-1}
\theta_k = \theta^{-}_k + K'_p \Delta t e_k
I_k = I_{k-1} + K_i \Delta t e_k

It should be noted that in order to arrive at these equations the sign in the bias estimation in the Kalman filter was changed to „+“ (Corollary #2), and the order of equations in the Mahony&Madgwick filter was reversed (Corollary #1) and K'_p = K_p + K_i \Delta t was introduced.

The two update laws are essentially identical, except of the important difference that the Kalman filter uses the updated angle \theta^{-}_k in the error while the Mahony&Madgwick filter uses the previous angle estimate \theta_{k-1}, as observed before for the 1st order filters (Chapter 2.4).

3.4. Complementary Filter
A complementary filter is easily derived by solving the transfer function of the Mahony&Madgwick filter for the angle \theta, which yields

\theta = \dfrac{1 + \frac{K_p}{K_i} s}{1 + \frac{K_p}{K_i} s + \frac{1}{K_i} s^2} a +  \dfrac{ \frac{1}{K_i} s^2}{1 + \frac{K_p}{K_i} s + \frac{1}{K_i} s^2} \dfrac{1}{s} \omega.    Eq. (3.10)

Obviously, and not unexpectedly, this complementary filter is build from 2nd order filters. Note that the filter acting on the acceleration data actually consists of a low-pass plus band-pass filter.

This result has interesting consequences. Being 2nd order filters, the frequency response of the acceleration and rotation rate filters are characterized by the resonance frequency and damping factor

\omega_0 = \sqrt K_i,     \xi = \dfrac{ K_p }{ 2 \sqrt K_i }.    Eq. (3.11)

The damping factor determines the overshoot at the resonance frequency. For high-pass (and low-pass) filters the frequency response is flat (and the step response non-oscillatory) for \xi \ge 1. This suggests the criterion

K_i \le \dfrac{ 1 }{ 4 } K_p^2    Eq. (3.12)

in order to avoid overshoot in the gyro channel. In order to minimize also overshoot in the accelerometer channel, the damping should be somewhat larger than that; \xi \approx 2 might be a good compromise between smooth frequency response and fast bias estimation. Accordingly, as a rule of thumb K_i \approx 0.05 \dots 0.1 \, K^2_p.

Note that – unless K_i is set to very small values – the crossover frequency is determined now by K_i (or the inverse square root of it), and not by K_p as in the 1st order case! It could in fact be appropriate to use the parameters \omega_0 or T = 2 \pi / \sqrt{K_i} and \xi instead of K_p and K_i; the tuning of the filter might be more intuitive to the user.

These considerations obviously also apply to the Mahony&Madgwick filter, and the Kalman filter.

The complementary filter may be implemented as in Eq. (3.6), or with any of the algorithms used with advantage for digital filters. The direct form II would be a typical choice (see e.g. here).

3.5. Summary on 1D Filters
As lengthy as it was, the above detailed discussion in chapters 2 and 3 of different approaches to the data fusing for a single axis result in a very short summary:

The three considered different approaches are in fact not that different, even in the 2nd order case.

As a bonus a criterion for the choice of the bias estimator gain K_i or K_1, respectively, has been obtained, as well as a potentially easier and/or more flexible direct implementation as a complementary filter.

There is a difference between the Kalman and Mahony&Madgwick filters in how the error is calculated. This may be interpreted as conceptually different „philosophies“, but besides that it’s not clear to me if this has also practical consequences, such as different stability properties or high-frequency noise. (Does anyone know?)

4. 3D IMU Data Fusing with Mahony Filter

In this chapter we will discuss data fusing filters for the three-axis problem, which involve the full non-linear kinematic equation, Eq. (1.1). I have seen various Kalman filters which were designed for this case, but because of the non- linearity they are much more complicated, and require much more computational power (which is potentially beyond reach for standard hobby micro controllers). They go beyond the scope of this articles (and my competences), and are thus not further considered. This leaves us with Mahony’s „complementary filter on SO(3)“ [RM05].

When thinking about how to merge gyro and accelerometer data it becomes quickly clear that the problem lies in the different tensorial nature of the rotation rate vector {\boldsymbol{\omega}} and acceleration vector {\bf{a}}, and the fact that {\bf{a}} describes only a direction. Mahony described an elegant way to cope with both.

4.1. „Original“ Mahony Filter
Mahony’s idea was to correct the input to the kinematic equation Eq. (1.1), which is the rotation rate vector {\boldsymbol{\omega}}, by some correction vector \delta{\boldsymbol{\omega}}, which is provided by a PI controller, where the error vector {\bf{e}} driving the PI controller is determined by some means from the previously estimated attitude and the accelerometer vector {\bf{a}}. Mahony suggested to use {\bf{e}} = {\bf{a}} \times {\bf{d}}, where {\bf{d}} is the direction of the gravity vector as given by the estimated attitude. Mahony’s algorithm [RM08][SM2], reads

\begin{array}{rcl} {\boldsymbol{\omega}}' &=& {\boldsymbol{\omega}} + \left( K_p  + K_i \dfrac{1}{s} \right) \; {\bf{a}} \times {\bf{d}} \\[0.75em] {\bf{R}} &=&  \dfrac{1}{s}{\bf{R}} {\boldsymbol{\Omega}}'_{\times} \end{array}.    Eq. (4.1)

or, as an algorithmic template:

  1. measure {\boldsymbol{\omega}} and {\bf{a}} (optionally normalize {\bf{a}})
  2. determine gravity vector {\bf{d}} from the current attitude estimate (in the DCM representation {\bf{d}} =  -{\bf{R}}^T {\bf{e}}_z)
  3. calculate error vector {\bf{e}} = {\bf{a}} \times {\bf{d}}
  4. apply PI controller to get rotation rate correction; \delta{\boldsymbol{\omega}} = ( K_p  + K_i \frac{1}{s} ){\bf{e}}
  5. calculate corrected rotation rate {\boldsymbol{\omega}}' = {\boldsymbol{\omega}} + \delta{\boldsymbol{\omega}}
  6. integrate rate of change using {\boldsymbol{\omega}}' (in the DCM representation \dot{{\bf{R}}} =  {\bf{R}} {\boldsymbol{\Omega}}'_{\times})
  7. repeat with step 1

It should be noted that steps 2 and 6 can readily be expressed in terms of quaternions, and hence tasks T1 and T2 be elegantly accomplished [RO1]. The algorithm in quaternion form is given in the Appendix.

Step 4 could be implemented in code as {\bf{I}}_n = {\bf{I}}_{n-1} + K_i \Delta t {\bf{e}}_n and \delta{\boldsymbol{\omega}}_n = K_p {\bf{e}}_n + {\bf{I}}_n. Step 6 would be implemented in the DCM representation as {\bf{R}}_n = {\bf{R}}_{n-1} + {\bf{R}}_{n-1} {\boldsymbol{\Omega}}'_{\times} \Delta t.

As regards the proper tuning of the filter gains K_p and K_i not much is said in the original literature. However, although I can’t „proof“ this, it seems reasonable that the conclusion inferred in Chapter 3.4 for the single-axis case applly also to the three-axis case.

4.2. 2D Mahony Filter and Simplifications
In many practical cases one doesn’t need to know the attitude including yaw, but the direction of the gravity vector is sufficient. In this case the calculations can be significantly simplified.

The quantity of interest is then {\bf{d}} =  -{\bf{R}}^T {\bf{e}}_z; the full rotation matrix {\bf{R}} itself is not needed. The kinematic equation implies for {\bf{d}} the dynamics

\dot{\bf{d}} = {\boldsymbol{\Omega}}'^T_{\times} {\bf{d}} = {\bf{d}} \times {\boldsymbol{\omega}}'    Eq. (4.2)

where in the second step it was used that {\boldsymbol{\Omega}}_{\times} is a skew-symmetric matrix, and a prime was added to the rotation rate in anticipation of Mahony’s algorithm. The rate of change is hence given by {\bf{d}} \times {\boldsymbol{\omega}}' = {\bf{d}} \times {\boldsymbol{\omega}} + {\bf{d}} \times \delta{\boldsymbol{\omega}}, where thanks to linearity the correction vector is obtained by applying the controller to the error {\bf{E}} = {\bf{d}} \times ( {\bf{a}} \times  {\bf{d}} ). The Mahony filter simplifies to

\dot{\bf{d}} = {\bf{d}} \times {\boldsymbol{\omega}} + ( K_p  + K_i \frac{1}{s} ) {\bf{E}}.    Eq. (4.3)

The Mahony filter reduces to applying the single-axis filter of Chapter 3 to each of the three axes independently. It can further be simplified by noting that {\bf{d}} \times ( {\bf{a}} \times  {\bf{d}} ) = {\bf{a}} d^2  - {\bf{d}} ( {\bf{a}} \cdot {\bf{d}} ) and that both {\bf{d}} and {\bf{a}} can be normalized. In addition one can assume that {\bf{d}} is a good estimate of {\bf{a}}. Thus, {\bf{a}} \cdot {\bf{d}} \approx 1 and {\bf{E}} = {\bf{a}} - {\bf{d}}. The Mahony filter becomes

{\bf{d}} = \dfrac{1}{s}{\bf{d}} \times {\boldsymbol{\omega}} + \left( K_p  + K_i \dfrac{1}{s} \right) \dfrac{1}{s} ({\bf{a}} - {\bf{d}}).    Eq. (4.4)

The striking similarity to the single-axis case, Eqs. (3.5)-(3.7), is obvious.

The result is useful. First, the overall simplification in terms of code size and speed is quite significant. One first calculates {\bf{d}} \times {\boldsymbol{\omega}} and then applies the 2nd order single-axis filter separately to each coordinate. Task T2 cannot easily be achieved, and the MultiWii approach suggests itself here. Having settled on the MultiWii approach, this in turn however means, that Mahony’s filter can be implemented by simply extending the 1st order filters used there to 2nd order filters.

As a little exercise we briefly calculate the low-angle approximation to Eq. (4.4), which holds when the body is nearly horizontally oriented (within \pm 30^\circ or so). Then one may assume d_z \approx -1, and the pitch and roll angles are approximately \theta_x \approx d_x and \theta_y \approx -d_y. One obtains

\dot{\theta}_x = \omega_y + \theta_y \omega_z +  ( K_p  + K_i \frac{1}{s} )( a_x - \theta_x),    \dot{\theta}_y = \omega_x - \theta_x \omega_z +  ( K_p  + K_i \frac{1}{s} )( a_y - \theta_y).    Eq. (4.5)

There is a cross coupling to the yaw rate \omega_z. This is exactly the result found by Shane [SC]. Furthermore, the single-axis filter equations apply separately to each angle.

4.3. Premerlani & Bizard’s IMU Filter
Premerlani and Bizard described in great detailed an IMU algorithm in [PB], which was later taken up also by Starlino [ST2] (providing also C code).

Premerlani and Bizard followed Mahony’s algorithm very closely, with one exception. Mahony presented the algorithm for both the DCM and quaternion representations [RM05] (the discussion in the above uses DCM language, Madgwick’s C code which is reproduced below in the Appendix uses quaternions). In the DCM version Mahony suggested e.g. using matrix exponentials and Rodriguez‘ formula to handle task T2 [RM07]. Premerlani and Bizard used Mahony’s algorithm in the DCM form, but introduced a simpler approach for task T2 or the reorthogonalization of the DCM. With the DCM written as

{\bf{R}}^T = \begin{pmatrix} \\ {\bf{r}}_x \, {\bf{r}}_y \, {\bf{r}}_z \\ \\ \end{pmatrix}

it goes as follows (where I incorporated an obvious improvement suggested in [ST2])

  1. calculate a correction magnitude \delta r = \frac{1}{2} {\bf{r}}_x {\bf{r}}_y
  2. correct the x and y column vectors in the DCM as
    {\bf{r}}'_x = {\bf{r}}_x - \delta r \, {\bf{r}}_y
    {\bf{r}}'_y = {\bf{r}}_y - \delta r \, {\bf{r}}_x
  3. normalize these column vectors, using a simplified Taylor expansion based method: {\bf{r}}''_\alpha = \frac{1}{2} \left( 3 - |{\bf{r}}'_\alpha|^2 \right) {\bf{r}}'_\alpha
  4. calculate a new z column vector as {\bf{r}}''_z = {\bf{r}}''_x \times {\bf{r}}''_y
  5. the reorthogonalized DCM is then {\bf{R}}^T = \begin{pmatrix} {\bf{r}}''_x \, {\bf{r}}''_y \, {\bf{r}}''_z  \end{pmatrix}

Comment: The coordinate vector {\bf{r}}_i (with i=x,y,z) represents the coordinates of the i-th basis vector of the earth frame as measured in the body-fixed frame.

5. Further 3D Filters

Madgwick’s IMU Filter

Madgwick has presented an interesting approach, which is based on formulating task T3 as a minimization problem and solving it with a gradient technique [SM]. I will argue here that this approach is – IMHO – not appropriate for IMUs which are using only gyro and accelerometer data (6DOF IMU).

Madgwick uses a quaternion approach to represent the attitude, which immediately poses the problem of how to convert the measured acceleration vector {\bf{a}} into a quaternion. Madgwick has described the problem in clear detail: A body’s attitude (quaternion) cannot be unambiguously represented by a direction (vector) since any rotation of the body around that direction gives the same vector but a different quaternion. The solution manifold is a „line“ and not a „point“. Or plainly: The body’s yaw angle is totally undetermined.

To tackle this problem he suggested to determine that rotation, which brings the gravity vector {\bf{g}}^{earth} = -{\bf{e}}_z in the earth frame in coincidence with the measured acceleration {\bf{g}}^{body} = {\bf{a}} in the body frame, that is to find the rotation {\bf{R}}_a for which {\bf{a}} = - {\bf{R}}^T_a {\bf{e}}_z, or the quaternion {\bf{q}}_a for which {\bf{a}} = - {\bf{q}}^{-1}_a {\bf{e}}_z {\bf{q}}_a, respectively. Converting the measured vector to a quaternion is very desirable since then data fusing could be done directly on quaternions, which has favorable mathematical properties [RO2]. In order to determine this rotation computationally, Madgwick suggested to formulate it as minimization problem and to solve it iteratively by the method of steepest decent.

This approach has two problems. The exact solution is not unique but there are infinitely many, and not the exact solution is calculated. One can hence expect that the yaw angle in the computed attitude {\bf{q}}_a is not only arbitrary, but determined by the noise introduced by the incomplete steepest decent. The yaw angle fluctuates.

At this point one could analyze the algorithm (reproduced below) by asking: Let’s assume that our gyro and accelerometer data is perfect and exact, what is then the algorithm doing? Clearly, one would expect the algorithm to produce the exact attitude, and the data fusing filter not to introduce any corrections. For the filters described in the above this is obviously fulfilled, e.g. in Mahony’s filter the error vector is zero, {\bf{e}} = 0. In Madgwick’s filter, the correction step \delta{\bf{s}} is however not zero (since {\bf{a}} = - {\bf{q}}^{-1} {\bf{e}}_z {\bf{q}}). That is, the filter in fact pushes the estimated attitude away from the correct attitude. In my opinion this is a signature of the noise mentioned before.

Due to these reasons I believe that Madgwick’s approach is not appropriate for implementing a 6DOF IMU.

It has to be stressed however that the comments do NOT apply to the case, where accelerometer and magnetometer data are used (9DOF IMU). This case is fundamentally different since the measured data span a two-dimensional sub space and hence allow to determine a unique, unambiguous attitude. Madgwick’s algorithm could in fact be an excellent choice for this case (but I can’t tell).

Appendix: References

[SC] Fun with the Complementary Filter [link] and The Balance Filter (Jun. ’07) [.pdf] – by Shane Colton
[PB] Direction Cosine Matrix IMU: Theory (May ’09) [.pdf] – by William Premerlani, Paul Bizard,
see also the google repository gentlenav [link] (it hosts also some of Mahony’s papers)
[St1] A Guide To using IMU (Accelerometer and Gyroscope Devices) in Embedded Applications (Dez. ’09) [link] – by Starlino
[St2] DCM Tutorial – An Introduction to Orientation Kinematics (May ’11) [link] – by Starlino (or as [.pdf])
[La] A practical approach to Kalman filter and how to implement it (Sep. ’12) [link] – by Lauszus, TKJ Electronics

Mahony’s papers:
[RM05] Complementary filter design on the special orthogonal group SO(3) (Dec. ’05) [.pdf] – by Robert Mahony, Tarek Hamel, Jean-Michel Pflimlin
[RM07] Complementary filter design on the Special Euclidean group SO(3) (’07) [.pdf] – by Grant Baldwin, Robert Mahony, Jochen Trumpf, Tarek Hamel, Thibault Cheviron
[RM08] Nonlinear Complementary Filters on the Special Orthogonal Group (Jun. ’08) [link] – by Robert Mahony, Tarek Hamel, Jean-Michel Pflimlin (it is also hosted on gentlenav)

Madgwick’s report and codes:
[SM1] An efficient orientation filter for inertial and inertial/magnetic sensor arrays (Apr.’10) [.pdf] – by Sebastian Madgwick (internal report on his thesis and MARG)
[SM2] Codes and Resources: Open source IMU and AHRS algorithms [link] (original repository imumargalgorithm30042010sohm)

Kalman filter:
[KA1] Kalman Filtering (June ’01) – by Dan Simon
[KA2] An Introduction to the Kalman Filter – by Greg Welch, Gary Bishop (or here)
[KA3] Understanding the Basis of the Kalman Filter Via a Simple and Intuitive Derivation (Sep. ’12) – by Ramsey Faragher
[KA4] What is the Kalman Filter and How can it be used for Data Fusion? (Dec. ’05) – by Sandra Mau (Note: This ref should be considered with caution, I added it because the first two presented filters are of pedagogical value, but otherwise the work shouldn’t be taken seriously)

Rotation representations:
[RO1] Representing Attitude: Euler Angles, Unit Quaternions, and Rotation Vectors – by James Diebel (excellent!)
[RO2] Rotation Representations and Performance Issues – by David Eberly
[RO3] Rotation formalisms in three dimensions [link] – Wikipedia
[RO4] on Euler, Tait-Bryan and Cardan angles see Euler Angles [link] – Wikipedia
[RO5] Application of Quaternions to Computation with Rotations – by Eugene Salamin

[LTB] Other MARG/AHRS/IMU/INS Open Code Projects – by Lewis De Payne (Lew’s Tech Blog)
[SHO] Quaternions – by Ken Shoemake
[WTH] A Comparison of Complementary and Kalman Filtering – by Walter T. Higgins

Appendix: IMU Implementations

MultiWii 2.2   (code:

  1. measure {\boldsymbol{\omega}} and {\bf{a}}
  2. normalize {\bf{a}}
  3. integrate rate of change for estimated gravity vector using \dot{{\bf{d}}} =  {\bf{d}} \times {\boldsymbol{\omega}}
    {\bf{d}}_n = {\bf{d}}_{n-1} +  {\bf{d}}_{n-1} \times {\boldsymbol{\omega}} \Delta t  = {\bf{d}}_{n-1} +  \begin{pmatrix} d_y \omega_z - d_z \omega_y \\ d_z \omega_x - d_x \omega_z \\ d_x \omega_y - d_y \omega_x   \end{pmatrix}  \Delta t
    Note: d_x ist defined negative in the code
  4. apply complementary filter if |{\bf{a}}|-1 < 0.15
    Note: not sure if there is an error in the implementation, seems so, but the intention is clear
  5. calculate angles
    \theta_{pitch} = \operatorname{atan2} \left( \dfrac{d_x}{d_z} \right)
    \theta_{roll} = \operatorname{atan2} \left( \dfrac{ d_y}{ \sqrt{ d^2_x + d^2_y } } \right)
  6. repeat with step 1

In my opinion the key point in the MultiWii code is that there is no explicit effort to ensure that the attitude estimate is SO(3) compatible (e.g. by reorthogonalizing a DCM or normalizing a quaternion). Hence, task T2 to correct for errors in the rate integration due to the gyro’s imperfections is entirely left to the effectiveness of the complementary filter; there is no explicit effort.

I must admit that I never really looked into the KK code – it’s ASM and I always had something better to do with my time… however, there is enough information on the web to piece things together. If it’s incorrect what I’m saying, then … well, then it doesn’t matter, then „KK“ is just my label to denote this possible algorithm:

\theta_{pitch,n} = \theta_{pitch,n-1} + \left( \omega_{pitch} + \theta_{roll,n-1} \omega_{yaw} \right)\Delta t +  K_p ( a_{pitch} - \theta_{pitch,n-1})

\theta_{roll,n} = \theta_{roll,n-1} + \left( \omega_{roll} - \theta_{pitch,n-1} \omega_{yaw} \right) \Delta t +  K_p ( a_{roll} - \theta_{roll,n-1})

In my opinion the characteristic feature of this code is that the linear approximation, as described in Chapter 4.2, Eq. (4.5), is implemented, together with a simple complementary filter for each axis.

Mahony’s Filter in Quaternion Form as Implemented by Madgwick   (code:

  1. measure {\boldsymbol{\omega}} and {\bf{a}}
  2. normalize {\bf{a}}
  3. get estimated gravity vector {\bf{d}} from quaternion {\bf{q}} (representing {\bf{R}})
    {\bf{d}} =  \operatorname{Im}\left[ {\bf{q}}^{-1} {\bf{e}}_z {\bf{q}} \right]= 2 \begin{pmatrix}  q_1 q_3 - q_0 q_2  \\ q_0 q_1 + q_2 q_3  \\  q^2_0 + q^2_3 - \frac{1}{2} \end{pmatrix}
  4. calculate error vector {\bf{e}}
    {\bf{e}} = {\bf{a}} \times {\bf{d}}
  5. calculate I term (which is a vector too)
    {\bf{I}}_n = {\bf{I}}_{n-1} + K_i \Delta t  {\bf{e}}
  6. calculate P term and add everything together
    {\boldsymbol{\omega}}' =  {\boldsymbol{\omega}} + K_p {\bf{e}} + {\bf{I}}_n
  7. integrate rate of change using \dot{{\bf{q}}} = \frac{1}{2} {\bf{q}} \otimes {\boldsymbol{\omega}}'
    {\bf{q}}_n = {\bf{q}}_{n-1} + \frac{1}{2} {\bf{q}}_{n-1} \otimes {\boldsymbol{\omega}}' \Delta t =  {\bf{q}}_{n-1} + \dfrac{1}{2} \begin{pmatrix} -q_1 \omega'_x - q_2 \omega'_y - q_3 \omega'_z \\ q_0 \omega'_x + q_2 \omega'_z - q_3 \omega'_y \\  q_0 \omega'_y - q_1 \omega'_z + q_3 \omega'_x \\ q_0 \omega'_z + q_1 \omega'_y - q_2 \omega'_x \end{pmatrix} \Delta t
  8. normalize quaternion {\bf{q}}
  9. repeat with step 1

Madgwick’s 6DOF IMU Filter (wo gyro drift correction)   (code:

  1. measure {\boldsymbol{\omega}} and {\bf{a}}
  2. normalize {\bf{a}}
  3. calculate rate of change \delta{\bf{q}}
    \delta{\bf{q}} = \frac{1}{2}  {\bf{q}} \otimes {\boldsymbol{\omega}} = \dfrac{1}{2} \begin{pmatrix} -q_1 \omega_x - q_2 \omega_y - q_3 \omega_z \\ q_0 \omega_x + q_2 \omega_z - q_3 \omega_y \\  q_0 \omega_y - q_1 \omega_z + q_3 \omega_x \\ q_0 \omega_z + q_1 \omega_y - q_2 \omega_x \end{pmatrix}
  4. calculate corrective step \delta{\bf{s}}
    \delta{\bf{s}} =  \begin{pmatrix} 4 q_0  q^2_ 2+ 2 q_2 a_x + 4 q_0 q^2_1 - 2 q_1 a_y \\ 4 q_1 q^2_3 - 2 q_3 a_x + 4 q^2_0 q_1 - 2 q_0 a_y - 4 q_1 + 8 q^3_1 + 8 q_1 q^2_2 + 4 q_1 a_z \\ 4 q^2_0 q_2 + 2 q_0 a_x + 4 q_2 q^2_3 - 2 q_3 a_y - 4 q_2 + 8 q_2 q^2_1 + 8 q^3_2 + 4 q_2 a_z \\ 4 q^2_1 q_3 - 2 q_1 a_x + 4  q^2_2 q_3 - 2 q_2 a_y \end{pmatrix}
  5. normalize \delta{\bf{s}}
  6. add P term
    \delta{\bf{q}}' = \delta{\bf{q}}  - \beta  \delta{\bf{s}}
  7. integrate rate of change using \dot{{\bf{q}}} =  \delta{\bf{q}}'
    {\bf{q}}_n = {\bf{q}}_{n-1} +  \delta{\bf{q}}' \Delta t
  8. normalize quaternion {\bf{q}}
  9. repeat with step 1

Note: Since in step 4 the quaternion is normalized, the calculation can be enormously simplified to:
\delta{\bf{s}} =  4 (q^2_1 + q^2_2) {\bf{q}} + 2 \begin{pmatrix}  q_2 a_x -  q_1 a_y \\  - q_3 a_x - q_0 a_y  + 2 q_1 a_z \\  +  q_0 a_x - q_3 a_y + 2 q_2 a_z \\  - q_1 a_x  -  q_2 a_y \end{pmatrix}

25 Kommentare

  1. Pingback: PES4 | Andreas' Blog

Hinterlasse einen Kommentar