Mahony and Madgwick Orientation Estimation#

This example compares MahonyAHRS and MadgwickAHRS on the same single-sensor recording. Both algorithms estimate orientation directly from IMU data, but they use different feedback mechanisms: Mahony applies proportional-integral feedback, while Madgwick uses a gradient-descent correction step.

Getting input data#

We use a short section of the left foot IMU example data. The data is already aligned to the gaitmap sensor frame and contains accelerometer and gyroscope signals.

import matplotlib.pyplot as plt
import pandas as pd

from gaitmap.example_data import get_healthy_example_imu_data
from gaitmap.trajectory_reconstruction import MadgwickAHRS, MahonyAHRS

imu_data = get_healthy_example_imu_data()["left_sensor"].iloc[500:900]
sampling_frequency_hz = 204.8

Configuring and running both algorithms#

kp controls how strongly the instantaneous accelerometer based correction is applied in Mahony. ki enables an accumulated bias correction term. Madgwick uses beta to control the correction strength.

Inspecting the results#

mahony_q_x mahony_q_y mahony_q_z mahony_q_w madgwick_q_x madgwick_q_y madgwick_q_z madgwick_q_w
sample
396 0.034201 -0.123389 0.009840 0.991720 0.093027 -0.106233 0.008683 0.989942
397 0.036344 -0.117614 0.008073 0.992361 0.094949 -0.100070 0.007148 0.990414
398 0.038364 -0.112578 0.006401 0.992881 0.096649 -0.094321 0.005678 0.990823
399 0.040413 -0.107899 0.004685 0.993329 0.098965 -0.088883 0.004106 0.991105
400 0.042394 -0.103143 0.003031 0.993758 0.100951 -0.083484 0.002615 0.991379


Comparing the quaternion course can help to spot how strongly both filters react to the same movement.

orientation_comparison[["mahony_q_w", "madgwick_q_w"]].plot(figsize=(10, 4))
plt.xlabel("sample")
plt.ylabel("q_w [a.u.]")
plt.title("Mahony vs. Madgwick quaternion estimate")
plt.tight_layout()
plt.show()
Mahony vs. Madgwick quaternion estimate

The rotated accelerometer data is often easier to interpret, because the sensor axes are aligned with the estimated global frame.

rotated_data_comparison[["mahony_acc_z", "madgwick_acc_z"]].plot(figsize=(10, 4))
plt.xlabel("time [s]")
plt.ylabel("acceleration [m/s^2]")
plt.title("Rotated vertical acceleration after orientation estimation")
plt.tight_layout()
plt.show()
Rotated vertical acceleration after orientation estimation

Total running time of the script: ( 0 minutes 4.052 seconds)

Estimated memory usage: 19 MB

Gallery generated by Sphinx-Gallery