Giter Club home page Giter Club logo

ahrs's Introduction

Hi reader 👋

I'm Mario, an Engineer based in Munich, Germany, who plays with sensors, code, and some times artistic creations (although Science is art, isn't it?)

Open Source is the way to go, and I will try to support it one way or another.

Currently playing with...

  • 🛰️ Inertial Sensors.
  • 📈 Data Science.
  • 📹 Computer Vision.
  • 🤖 ROS.

Learning...

  • 💻 Edge AI.
  • 🤟 German Sign Language.
  • 🌮 Mexican Cuisine.

You can write me in Spanish, English, or German (and maybe Dutch). And if you're in town, hit me up for a drink in a Biergarten.

Twitter: Mayitzin Linkedin: MarioGC GitHub Mayitzin

ahrs's People

Contributors

eragooon avatar federicoceratto avatar jaluebbe avatar manuelpalermo avatar mayitzin avatar nasbotond avatar petrinm avatar tokoro10g avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ahrs's Issues

help where is z axis?

ekf = EKF(gyr=gyr_data, acc=acc_data)
ekf.Q.shape
(1000, 4)

i tried :
r = math.atan2(2*(wx+yz),1-2*(xx+yy))
p = math.asin(2*(wy-zz))
y = math.atan2(2*(wz+xy),1-2*(zz+yy))

angleR = r180/math.pi
angleP = p
180/math.pi
angleY = y*180/math.pi
but angleY are 0
any help will be thanks

Unexpected result for attitude estimation

Hi,
I have been experimenting with the ahrs module. First I used example sensor data (ExampleData.mat) and some of the code from https://pypi.org/project/AHRS/ to obtain Euler angles and then compared them with the output from the MATLAB implementation of Madgwick algorithm. The resulting two plots of Euler angles for the same dataset look surprisingly different.
ahrs_python
euler_angles_matlab

Quaternions were computed using this code:

madgwick = ahrs.filters.Madgwick()
Q = np.tile([1., 0., 0., 0.], (data.num_samples, 1))
d2g = ahrs.common.DEG2RAD
for t in range(1, data.num_samples):
   Q[t] = madgwick.updateMARG(Q[t-1], d2g*data.gyr[t], data.acc[t], data.mag[t])

and then the Euler angles were then obtained from them using the transformation function from the quaternions module.
Have I made some mistake?
Thanks,
Marina

pip install from source fails

I have troubles installing the package from source via pip in a new, fresh environment:

pip install git+https://github.com/Mayitzin/ahrs.git

as I get this error:

    ERROR: Command errored out with exit status 1:
     command: 'C:\dev\miniconda\envs\test\python.exe' -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'C:\\Users\\xxx\\AppData\\Local\\Temp\\pip-req-build-rmy_ows9\\setup.py'"'"'; __file__='"'"'C:\\Users\\xxx\\AppData\\Local\\Temp\\pip-req-build-rmy_ows9\\setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base 'C:\Users\xxx\AppData\Local\Temp\pip-pip-egg-info-15_9fo6t'
         cwd: C:\Users\xxx\AppData\Local\Temp\pip-req-build-rmy_ows9\
    Complete output (11 lines):
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "C:\Users\xxx\AppData\Local\Temp\pip-req-build-rmy_ows9\setup.py", line 22, in <module>
        from ahrs.versioning import get_version
      File "C:\Users\xxx\AppData\Local\Temp\pip-req-build-rmy_ows9\ahrs\__init__.py", line 11, in <module>
        from . import common
      File "C:\Users\xxx\AppData\Local\Temp\pip-req-build-rmy_ows9\ahrs\common\__init__.py", line 7, in <module>
        from . import mathfuncs
      File "C:\Users\xxx\AppData\Local\Temp\pip-req-build-rmy_ows9\ahrs\common\mathfuncs.py", line 7, in <module>
        import numpy as np
    ModuleNotFoundError: No module named 'numpy'
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.                                                        

and I suspect the reason is that versioning.py is inside the package and it triggers imports of packages not yet installed. (the setup.py is importing the package itself).

Here there are some suggestions on how to deal with versioning. I believe now the package implements what is described at point 6, which is not recommended. There are some alternative suggestions also here

Difference between AHRSv0.2.2 and v0.3.0RC1's Madgwick

Hi-

I was trying the Madgwick filter both using the version 0.2.2 of AHRS from pypi and the version 0.3.0RC by building the module from source.

I get different results for the following code. The results of the filter for the v0.2.0 seems correct but not for the 0.3.0:

from ahrs.filters import Madgwick
from ahrs.common import Quaternion
import numpy as np
from matplotlib import pyplot as plt

def main():
    num_samples = 10000
    acc = np.zeros((3, num_samples))
    acc[1,:] = -9.81
    gyr = np.zeros((3, num_samples))
    time = np.zeros(num_samples)
    dt = 0.01
    for i in range(1, num_samples):
        time[i]  = time[i-1] + dt

    angles = np.empty((3, num_samples))
    angles[:] = np.NaN

    orientation = Madgwick()
    Q = np.tile([1., 0., 0., 0.], (num_samples, 1))
    for t in range(0, num_samples):
        orientation.Dt = dt
        Q[t] = orientation.updateIMU(Q[t-1], gyr=gyr[:,t], acc=acc[:,t])
        angles[:,t] = Quaternion(Q[t]).to_angles()*180/np.pi

    plt.plot(time, angles.T)
    plt.show()

if __name__ == "__main__":
    main()

What do I do wrong? Thanks :)

Using `scipy` for consistency and efficiency (suggestion)

Hello,

It would be great if this package leveraged on scipy for many of its operations. For instance, using the scipy.constants would significantly reduce duplicating these in ahrs.common.constants. Similarly, scipy.spatial.transforms.Rotation could be used for many of operations in ahrs. This is of course only a suggestion to bring cohesiveness and avoid inconsistencies. I, and likely many other AHRS users, already use scipy as part of processing workflows, so this integration would have many advantages. For example, scipy uses scalar-last convention for representing quaternions, so there's at least an extra step when working with both of these tools.

pip install error

Hi Mario,

I'm having troubles installing your package, here attached the error message shortly after the pip install ahrs command:
catt

i'm dealing with an import error, apparently my raspberry isn't able to find a module called tools.versioning.

how can i deal with it? I've tried both install solutions with pip first and then with git clone.

thanks,
Andrea

Quaternion transformation to Roll-Pitch-Yaw angles

When you see the gyroscope integration, you can see that the Y-axis spins 1 negative turn then 1 positive turn. When you see the estimated and reference orientation, the Yaw simply doesn't follow that. I agree reference Yaw and reconstructed Yaw are similar because their quaternions are very very close. the problem isn't about +-2pi. The problem comes that the to_angles()conversion doesn't get you the real movement.

Originally posted by @anisghaoui in #20 (reply in thread)

Unit of acc, gyr and magnetometer in ExampleData.mat

Hi!, I'm trying to run your program to observe how the IMU filter works, but I can't understand the example data file. I thought the acceleration should be between [-9.8, 9.8], but the data seems to be in the range [-1, 1], what measure unit are you using for the accelerometer, gyroscope and magnetometer? Maybe, this data is in gForce (gravity removed) instead of m/s^2 and that's why it is in that range, but I want to be sure and check it with the author.

Thanks in advance.

How ist measurement noise defined?

I try to use the extended Kalman filter. I have the datasheet of the sensors being used, but I struggle to identify the specific values the ekf() function is looking for.

I am a newbie to sensors and datasheets in general.
Could you help me to identify the values for the following sensor: ICM-20649.

I get the following values for the accelerometer: RMS Noise [mg-rms] TYP (based on accelerometer noise: 285μg/√Hz)

and for the gyroscope: RMS Noise [dps-rms] TYP (based on gyroscope noise: 0.0175dps/√Hz)

and for the magnetometer: 3.2mgauss.

Thanks in advance

Tuple index out of Range - Complimentary filter

I keep getting this tuple index out of range error for the complimentary filter. I am passing in data directly pulled from the MPU9250 sensor that I am using. Just curious what I am doing wrong.
Screenshot 2022-04-05 113056

Screenshot 2022-04-05 113254

Yaw initial angle question

Hello,

I am currently doing an internship in a research laboratory. I would like to use IMU to know the orientation of the hand.

I am currently having problems with the yaw angle. Depending on the algorithm I use I have a different yaw angle at the beginning of my recording (+150° with Madgwick and Fourati // -50° with Complementary filter). I would like to know if it is possible to reset the orientation at the beginning of my recording in order to have a zero yaw, roll and pitch. This will allow me to express the orientation of the hand with respect to an initial reference orientation.

image

image

image

I also have a question about the function
ahrs.utils.metrics.qad
what is the unit of the angular deviation obtained?

MUNICH_HEIGHT is still in meters in PIP package

Hi

The MUNICH_HEIGHT error (it was in meters) was corrected in GitHub, but it is still present if you install the last version of the package from PIP.

Could you release a new version of the package?

Best regards

Broadcasting error in EKF

Hello Sir, I'm facing a broadcasting error in the first iteration, when estimating using EKF. I can't figure why this should happen. This is my code below:

EKF object creation:

                self.ekf = EKF(Dt = sampling_time,magnetic_ref=60.0)
		self.Q_last = acc2q(acc_vec)

I'm using following lines for updating:

		self.Q = self.ekf.update(self.Q_last, gyr=gyro_vec, acc= acc_vec,mag=mag_vec	
                self.Q_last = self.Q

The data of my parameter for 1st iteration:
mag-data [ 32.20800018 -32.30559921 -27.05959892]
acc-data [-0.58654064 3.85064983 8.75533772]
gyro-data [ 0.05772506 -0.00748288 -0.01084254]
Q-last [ 0.97815766 0.20559691 0.02996388 -0.00629804]

Error:
ValueError: operands could not be broadcast together with shapes (6,6) (3,3)
In line:
S = H@[email protected] + self.R # Measurement Prediction Covariance

[BUG] default madgwick gain when using magnetometer is only set if mag data is passed on init

If "mag" data is not passed on init (mag=None) the gain is initialized with the default imu value and used when calling updateMARG function:

self.gain = kwargs.get('gain', 0.033 if self.mag is None else 0.041)

I propose adding two different gain params on init (gain_imu and gain_ahrs), one for each mode, solving this issue and also allowing the use of updateIMU and updateMARG functions on the same initialized filter (ex. using IMU when magnetic distortions are detected on a step and MARG otherwise).

Does this package do position estimation?

The readme specifies that this is used for position and orientation estimation, but the filters seem to only estimate orientations.

Can I use this package for 6-DOF position/orientation estimation?

I am new to AHRS/MARG stuff so please be patient,

TypeError: 'module' object is not callable

Looks like a very interesting toolkit, thanks for sharing it. I've tried to run the Mahony AHRS algorithm on some accel and gyro data I have but keep running into this issue:

Traceback (most recent call last):
File "C:/Users/Ross/AHRS Python Mahony Test.py", line 16, in
orientation = Mahony(gyr=gyro_data, acc=acc_data, frequency=50.0)
TypeError: 'module' object is not callable

My code is below, I'm sure I'm missing something I'm just not sure what it is. If you have any info that would be appreciated.

`
import numpy as np
import pandas as pd
from ahrs.filters import mahony as Mahony

num_samples = 20000 #I have chosen this value just to test. Should be array length

acc_data = pd.read_csv('accel3.csv')
gyro_data = pd.read_csv('gyro3.csv')

orientation = Mahony(gyr=gyro_data, acc=acc_data, frequency=50.0)

orientation = Mahony()
Q = np.tile([1., 0., 0., 0.], (num_samples, 1)) # Allocate for quaternions
for t in range(1, num_samples):
Q[t] = orientation.updateIMU(Q[t-1], gyr=gyro_data[t], acc=acc_data[t])

`

float object annot be interpreted as integer (gyro data)

Hi, I am trying to get the Madgwick filter working with the adafruit npx IMU and a raspberry pi.
When I try to run the script I get this error:
File "AHRS.py", line 24, in
gyr = np.ndarray([gyro_x,gyro_y,gyro_z])
TypeError: 'float' object cannot be interpreted as an integer

Is there something I am not getting?
I tried transforming the data coming from the sensors into integers, but then I get a new error that says: ValueError: negative dimensions are not allowed
Thanks, code below.

import time
import board
import busio
import adafruit_fxos8700
import adafruit_fxas21002c
from ahrs.filters import Madgwick
import numpy as np

#instantiating sensor and BUS
i2c = busio.I2C(board.SCL, board.SDA)
fxos = adafruit_fxos8700.FXOS8700(i2c)
fxas = adafruit_fxas21002c.FXAS21002C(i2c)

filter = Madgwick()

while True:
q = np.ndarray([0,0,0,0])
# Read acceleration & magnetometer.
accel_x, accel_y, accel_z = fxos.accelerometer
mag_x, mag_y, mag_z = fxos.magnetometer
gyro_x, gyro_y, gyro_z = fxas.gyroscope

gyr = np.ndarray([gyro_x,gyro_y,gyro_z])
mag = np.ndarray([mag_x,mag_y,mag_z])
acc = np.ndarray([accel_x,accel_y,accel_z])

q = filter.updateMARG(q, gyr, acc, mag)
print(q)

time.sleep(0.1)

Error in Munich information?

Hi

First of all, thanks for this amazing and helpful library.

In EKF filter, you are using the Munich information in case the magnetic reference is not provided. You are constructing a magnetic model as follows

image

However, according to the WMM class, the height should be in kilometres, but you have defined the MUNICH_HEIGHT in meters.

image

Is it a bug?

Best regards

NED to ENU frame - quaternion math

Hi,
I'm using vectornav IMU fo measurements, here is its math:
https://www.vectornav.com/resources/attitude-transformations

This inertial unit allows to record measurement (accelerometer, gyro, magnetometer), also the unit is returning the orientation angles (yaw, pitch roll) and the quaternions.

So I did try to use measurement values from this unit and calculate (by the use of Madgwick filter from your repo) orientation angles and quaternions. But when I try to compare the quaternions on output from Madgwick filter (your repo) to quaternions on output from vectornav IMU, the results completely differ.

I know that vector nav is using NED reference frame, can you please tell me something about the frame which is used in your algorithm. Like describe here: https://www.vectornav.com/resources/attitude-transformations

I did try to do a transformation NED > ENU, following to this:
https://stackoverflow.com/questions/49790453/enu-ned-frame-conversion-using-quaternions
but it seems to be the wrong solution.

Can you please give me tips on what I'm doing wrong?
Will'be very grateful for any support with this problem.

PS. Here is my data (in mat file) and python code which I was used:
https://wutwaw-my.sharepoint.com/:f:/g/personal/kinga_wezka_pw_edu_pl/EgtvnRx3aF9OvkOpsFCnlOwB_pO8ebbyv9OAmezrGNdjPQ?e=pk0oPQ

Best Regards,
Kinga

Madgwick: Attitude Value Drift and Yaw Alignment Issues

Hello,

I am having a few issues while using the Madgwick() class in this library and was wondering if maybe someone here might be able to assist me.

Setup

I am using an Arduino Nano BLE 33 Sense which uses an LSM9DS1 9-axis iNEMO IMU.

Raw Accelerometer, Gyroscope, and Magnetometer values are read on the arduino, then corrected using calibration values. These values (x, y, z for each sensor) are then sent over USB serial to my host machine at a baud rate of 115,200. The sample rates are below:

  • Accelerometer: 116.79Hz
  • Gyroscope: 116.79
  • Magnetometer: 38.94 Hz

I'm unable to set all three of these sample rates to the same values due to their hardware specifications.

Then in python I am opening a serial connection to the arduino and reading this data in to be processed using the AHRS library.
Each line of output from the arduino is of the form ax,ay,az,gx,gy,gz,mx,my,mz

import serial
import numpy as np
import ahrs

q0 = [1.0, 154.0, -1.0, -0.5] #resting position of device
q_prev = q0
madgewick = ahrs.filters.Madgewick(q0=q0)

while 1:
  ser = serial.Serial('COM12', 115200)
  line = ser.readline().decode('utf8').strip()
  line = [float(x) for x in line.split(',')]
  acc = np.array(line[0:3])
  gyr = np.array(line[3:6])
  mag = np.array(line[6:9])

  attitude = madgwick.updateMARG(q_prev, acc=acc, gyr=gyr, mag=mag)
  q_prev = attitude

I then convert the attitude to yaw/pitch/roll format and use pygame to display a cube which has its orientation set to these values.
I also do some simple value clipping to de-noise the values coming in from the arduino sensor since they hover around +/- 0.25 when stationary.

Problem

When I rotate my arduino, the cube that I am displaying will rotate properly for the most part, but when I stop rotating the arduino, the cube will slowly dift back to what appears to be my q0 value that I set during instantiation of the Madgwick class.
This issue does not occur when I re-instantiate the Madgwick class each time I get new data as shown below:

import serial
import numpy as np
import ahrs

while 1:
  ser = serial.Serial('COM12', 115200)
  line = ser.readline().decode('utf8').strip()
  line = [float(x) for x in line.split(',')]
  acc = np.array(line[0:3])
  gyr = np.array(line[3:6])
  mag = np.array(line[6:9])

  attitude = ahrs.filters.Madgwick(acc=acc, gyr=gyr, mag=mag).Q[-1]

The other problem I have is that the yaw is being heavily influenced by the pitch/roll values. For example, let's say that I rotate my arduino about a central fixed point on the board, similar to an euler's disk (see gif below).
unnamed

When I do this, the yaw will rotate 360 degrees and continue rotating as I continue to pivot the board. I expect a bit of motion along this axis but it should move one direction then reverse and return to the origin, not continue rotating without reversing. Again, refer to the gif above and pay attention to the yellow band on the ring, notice how the yellow part of the ring travels around in a circle.

So my question is this: Am I misunderstanding the fundamentals of the Madgwick functions or am I doing something else completely wrong in this process?

Thank you in advance for your time.

Mahony filter k_I parameter not used correctly

In the documentation of the Mahony filter it is stated that \dot{\hat{q}} is a function of \hat{b} where \hat{b} results from integrating -k_I * w_{meas}.

Howevever, in the code we have:

omega_mes = np.cross(acc/a_norm, v_a)   # Cost function (eqs. 32c and 48a)
b = -self.k_I*omega_mes                 # Estimated Gyro bias (eq. 48c)
Omega = Omega - b + self.k_P*omega_mes  # Gyro correction
p = np.array([0.0, *Omega])
qDot = 0.5*q_prod(q, p)                     # Rate of change of quaternion (eqs. 45 and 48b)

Which does not contain an integration of the b_dot term. In essence, the integral term is disabled (k_I = 0) and k_P has been set to (k_P - k_I). Perhaps the code should be updated to something like:

omega_mes = np.cross(acc/a_norm, v_a)   # Cost function (eqs. 32c and 48a)

bDot = -self.k_I*omega_mes                 # Estimated Gyro bias (eq. 48c)
self.b += bDot * self.Dt

Omega = Omega - self.b + self.k_P*omega_mes  # Gyro correction
p = np.array([0.0, *Omega])
qDot = 0.5*q_prod(q, p)                     # Rate of change of quaternion (eqs. 45 and 48b)

I am happy to make the changes if there is consensus.

Error in Madgwick updateMARG "unexpected keyword argument" when using dt

when I try to use this function the command window alerts me of the argument doesn't exist even if it is mentioned in the documentation.
q = madgwick.updateMARG( q=qprec, gyr=g,acc=a, mag=MagVals, dt=deltat)
In addiction when I tried to use without dt argument I have the following error:
q = madgwick.updateMARG( q=qprec, gyr=g,acc=a, mag=MagVals)
File "/Users/vittoriaattolini/opt/anaconda3/lib/python3.8/site-packages/ahrs/filters/madgwick.py", line 668, in updateMARG
h = q_prod(q, q_prod([0, *m], q_conj(q))) # (eq. 45)
File "/Users/vittoriaattolini/opt/anaconda3/lib/python3.8/site-packages/ahrs/common/orientation.py", line 64, in q_conj
if q.ndim>2 or q.shape[-1]!=4:
AttributeError: 'list' object has no attribute 'ndim'

I followed the documentation indication: qprec is an array of 4 values, g, a and Magvals are array of 3 values

Reference frame orientation for different filters

I'm having some trouble correlating my IMU orientation to world orientation. My sensor (LSM9DS1, but I modify the output on a microcontroller) outputs data in a right-handed system with +z pointing up and +x and +y horizontally. The gryo and accelerometer are definitely aligned. So at rest I read an accelerometer value of [0, 0, 1].

Now when I put my gyroscope data through a RateFilter instance, the z- and y-axis rotations are each flipped. That makes it still right-handed, but is a different orientation than I expected.

Can someone confirm how the world axis are defined for the filters?

This could tie in to #34

All in all I like this package a lot! My thanks to the contributors!

EKF.update() doesn't accept mag data

EKF only works with magnetometer data if the one liner ekf() function is called without using ekf.update().

If mag data is included in the update function, the R covariance matrix isn't initialized properly and is a 3x3 instead of 6x6.

Examples with additional data sources (GPS, pressure sensors)

Thanks for an amazing package! Do you think it would be possible to add some examples using additional data sources, such as GPS (which provide position and speed and sometimes altitude), and barometer? For example integration of these data in EKF / UKF would be very helpful.

Opposite results from Madgwick and AQUA

When used on the same reading Madgwick and AQUA produce opposite results.
This causes spinning in opposite directions.

I can guess that it is just how filters implementation works, but it would be nice if all filters produced the same result.
It should be easy to fix just by flipping the XYZ quaternion result for one on the filters.

Also, didn't test but it is possible that there are more filters that produce one of two results.

Example of rotation:
AQUA
[0.92532097 0.3791205 0.00524886 0.00460348]
Madgwick
[ 0.92497363 -0.3799769 -0.00416885 -0.00489403]

Image example:
bug

help AttributeError: 'Madgwick' object has no attribute 'Q'

from ahrs.filters import Madgwick
>>> madgwick = Madgwick(gyr=gyro_data, acc=acc_data) # Using IMU
The estimated quaternions are saved in the attribute Q.
>>> type(madgwick.Q), madgwick.Q.shape

AttributeError: 'Madgwick' object has no attribute 'Q'

fix import problem

the am2q function is used in the ekf.py file , but not imported
Q[0] = am2q(self.acc[0], self.mag[0]) if self.q0 is None else self.q0/np.linalg.norm(self.q0) in ekf.py line 77.

UKF example

Thanks for an amazing package! Do you think it would be possible to add an example of using an unscented Kalman filter to perform the AHRS estimation?

Yaw static error

Hello,

Thank you for this very useful code.

I'm facing an issue with the yaw estimation using Madgwick/Mahony filters.

I povide ideal sensors measures in ENU frame :

  • aX = [0.0] * n
  • aY = [0.0] * n
  • aZ = [9.81] * n # m/s^2
  • gX = gY = gZ =[0.0] * n # sensor is static
  • mX = [0.0] *n
  • mY = [0.05] * n # mT
  • mZ = [-0.05] *n

Where n is the number of samples set to:

  • n = 10000
    The sampling frequency is set to:
  • Fs = 100

With these inputs, I get null roll, pitch and yaw. I assume then both filters are providing the orientation in ENU frame.

The issue starts when I add some noise to the gyroscope measures, a noise of mean zero and standard deviation of 0.01:
gX += np.random.normal(0, 0.001, n)
gY += np.random.normal(0, 0.001, n)
gZ += np.random.normal(0, 0.001, n)

The estimated yaw presents a static error of -pi/2 with Madgwick and pi/2 with Mahony.
Tuning the filters doesn't fix the issue.

Any ideas?

Thank you

Class constructor with data not working

I tried to get this simple code working but it seems like the constructor is not working correctly:

print(data[GYR].shape)
print(data[ACC].shape)
print(data[MAG].shape)
madgwick = Madgwick(gyr=data[GYR],
                        acc=data[ACC], 
                        mag=data[MAG], 
                        frequency=200)
print(madgwick.Q)

will output:

(11995, 3)
(11995, 3)
(11995, 3)
AttributeError: 'Madgwick' object has no attribute 'Q'

Assumption: In the constructor self.input = args[0] if args else None will always be None as args is always empty with named parameters?

error "Syntax Error" During install

I have the follow error after the install command; sudo -H pip install ahrs
Collecting ahrs
Using cached https://files.pythonhosted.org/packages/37/fd/41a29f8f491b0b87634a874715f56f6bdaa49202e1701e1c588bbf6129dd/AHRS-0.1.2.post3.tar.gz
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "", line 1, in
File "/tmp/pip-build-Tf5165/ahrs/setup.py", line 22, in
from ahrs import get_version
File "ahrs/init.py", line 11, in
from . import common
File "ahrs/common/init.py", line 8, in
from . import orientation
File "ahrs/common/orientation.py", line 619
R = rotation(axes[i], angles[i])@r
^
SyntaxError: invalid syntax

Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-Tf5165/ahrs/

There is an errir in @ symbol in the code.
I'm using the python3.6

Thanks

Mário Assunção

Sandwich product of Quaternion normalizes rotating point

Class: Quaternion

A vector x in 3D can be rotated with the methods rotate() and to_DCM() as:

q = Quaternion([1.0, 2.0, 3.0, 4.0])
x = [1.0, 2.0, 3.0]
# Build rotation R from q and multiply it with x
x1 = q.toDCM()@x    # returns [1.8, 2., 2.6]
# Simplifies the operation above:
x2 = q.rotate(x)    # also returns [1.8, 2., 2.6]

A product q*x*q.conj() is called a sandwich product and it also rotates x by a given q, but cannot be performed because they are different types of data. So, multiply with x as a pure quaternion.

x3 = q*Quaternion(x)*q.conj()   # returns [0.4811, 0.5345, 0.6949]

This product is, however, normalized. As a solution, the two first methods are preferred, but a seamless sandwich product would be nice to have.

Handling negative timesteps

Hello there!

First of all, thank you for providing such an amazing toolbox, I really appreciate the time and effort spent! It helped me out tremendously!
However, when using e.g. madgwick.Dt to set the filters sampling time, negative values are also accepted. It should at least spew a warning to save some time debugging. :)

Cheers!

Handling NaN line causing issue in updateMARG method in madgwick.py

When using updateMARG, it shows the following error error -

TypeError: ufunc 'true_divide' output (typecode 'd') could not be coerced to provided output parameter (typecode 'q') according to the casting rule ''same_kind''

a = a / a_norm instead of a /= a_norm produces no error

the same applies for m /= m_norm as well.

Please see to this issue.

Scale problem with Madgwick

Edit : this issue is irrelevant, I had a data rate of 400 hz, not 200 hz. Lesson : check your data first, don't trust the provider.

Hi,
I have made a test run with Madgwick's filter and I obtained results that are twice as big as they should be. hear me out:

my sampling frequency is 200 hz, default is 100.
I made 90° rotation but Madwick predicts 180° instead.
Going here and dividing it by 2 solves the problem for me.

q += qDot*self.Dt # (eq. 13)

Error in EKF Measurement Model Docs

Hi,

I think I maybe found multiple (sign) errors in the EKF measurent model:
https://ahrs.readthedocs.io/en/latest/filters/ekf.html

In for example in the first row of h(qhat_t), the sign before gy * (qw * qz+qx * qy) has to be gy * (qx * qy-qw * qz).
I have calculated this both manually and with the Symbolic Toolbox of MATLAB and come to the same result.

You can check my calculation by defining your gravity vector g = [gx gy gz]^T and mutliply from left with rotation matrix C(qhat).

Is this a calculation error or have I overlooked something?

Best regards
Max

Unable to use TRIAD filter - TypeError

Following error was observed

\env\lib\site-packages\ahrs\filters\triad.py line 379, in _compute_all num_samples = len(self.w1) TypeError: len() of unsized object

while executing the code

import numpy as np
from ahrs.filters import TRIAD
triad = TRIAD()
triad.v1 = np.array([0.0, 0.0, 1.0])                    # Reference gravity vector (g)
triad.v2 = np.array([21.0097, 1.3335, 43.732])          # Reference geomagnetic field (h)
a = np.array([-2.499e-04, 4.739e-02, 0.9988763])        # Measured acceleration (normalized)
a /= np.linalg.norm(a)
m = np.array([-0.36663061, 0.17598138, -0.91357132])    # Measured magnetic field (normalized)
m /= np.linalg.norm(m)
triad.estimate(w1=a, w2=m)

Python version 3.7.4
Numpy 1.21.0
Windows 10 - 64 bit

Initializing Madgwick from accelerometer and mag alone

Hi,

i'm trying to use this package to estimate heading of a UGV from mag, acc and gyro. The issue i'm having is with the initialization of the filter from mag data and acc data alone assuming tha te UGV is not moving. This filter initialization requires gyro and accelerometer data to be available (with mag in my case). This results in the filter to take a lot of time to converge since the gyro data shows no movement but the mag data is not aligned with initial quaternion. The initialization should allow to use accelerometer and mag data alone. The other option is to compute the initial quaternion from ag and acc data alone, but it would be much simpler to make this part of the filter initialization.

Latest version on pypi

Hello; thanks for a very useful library!

The AngularRate class which I’m trying to use breaks in v0.2 published on pypi, but the refactored version on the master branch seems to work fine. Is there currently a way to download the recent version from pypi? If not, would you consider tagging/publishing the latest version (v0.3) to pypi? Thanks.

comparizon of Madgwick, Mahony and EKF filters

Hi
I have recorded data from my mobile phone (accelerometer, gyroscope, magnetometer). Then I used ahrs library to calculate attitude parameters (quaternions and then conversion to yaw, pitch, roll).

The results for Madgwick and Mahony filters are quite similar but the results of EKF totally differ.

Could you please give me some tip what could be a reason for these different results for EKF filter (I have to use the same data for all filters)

staly_0 1_0 1_0 7

_compute_all skips first element when q0 not None

In method def _compute_all(self): of filters that have a parameter q0, computation is 1 element off.

For example, in the AQUA filter:

Q[0] = self.init_q(self.acc[0], self.mag[0]) if self.q0 is None else self.q0.copy()
for t in range(1, num_samples):  
    Q[t] = self.updateMARG(Q[t-1], self.gyr[t], self.acc[t], self.mag[t])

range(1, num_samples) can produce numbers only from 1, which is good if you are using reading [0] as your starting point.
But when q0 is set, it just skips [0] reading.

It can be very crucial if you send a small number of samples.
I'm trying to use def init() result as a real-time filter by sending only one sample + previous Q as q0 and because of this bug it returns only q0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.