ahrs icon indicating copy to clipboard operation
ahrs copied to clipboard

Does the unit of magnetometer influence the estimated result with EKF?

Open czhaneva opened this issue 1 year ago • 4 comments

The description of EKF requires "nT", but the ecompass function in _compute_all function requires "mT", while the update function requires "nT", It's very strange that the same variable requires different units in the same class, which makes me very confused about which unit to use.

czhaneva avatar Oct 10 '24 04:10 czhaneva

Not really.

In almost all estimators (EKF included) and in the ecompass function the measured magnetic field is normalized, so that their magnitude (norm) will always be equal to 1.

What is of importance in those implementations is the direction of the field, not the magnitude. In this case, their normalization makes the magnetic intensity irrelevant. So, the result will be the same if you give the magnetic field as mT, nT, T, or uT.

However, you're right about discrepancies in documentation. I'll change it so that it conforms to the standards of the World Magnetic Model.

Thanks for the observation,

Mario.

Mayitzin avatar Oct 10 '24 09:10 Mayitzin

Thanks for your relpy, I'm new to AHRS, I'd like to ask for some help too. I'm working with orientation estimation using ACC+GYRO+MAG

  1. The frequency of these three sensors are different, the frequency of ACC/Gyro is 100Hz, while the frequency of Mag is 40Hz, How do I use them in sync?
  2. The mag signal is not always reliable, the sensor can output a flag to show the reliability of mag, so I'd like to use ACC+GYRO when the mag is unreliable, and use ACC+GYRO+MAG when the mag is reliable, Is there any algorithm that can support me to switch like this?
  3. I think if I was updating the results with actual intervals, would it be more accurate than if I were using a fixed interval, and would that have a big impact on accuracy?
  4. What kind of data preprocessing can help improve accuracy? Like some low-pass filtering on the original signal?

czhaneva avatar Oct 10 '24 09:10 czhaneva

Hi, going point by point here:

  1. That sounds very familiar to #115. In that case my suggestion was to interpolate the values with splines, or extrapolate them if you are allowed to "predict" the values. I left a couple of links for it in that issue.

  2. There are a some algorithms that you might try:

    • AQUA estimates the orientation independently from ACC+GYRO and from MAG. Its last step fuses them with an adaptive gain to obtain a final quaternion. This gain, however, acts over the quaternion computed from the acceleration. So, you will have a gain "trusting" the ACC, not the MAG.
    • The classic Complementary Filter also fuses the independently estimated orientations from GYRO and ACC+MAG, and allows you to control the "amount of blend" with the parameter gain, where 1 uses GYRO only, and 0 uses ACC+MAG only. Values between 0 and 1 determine how much the filter "trust" each estimation. But notice, it has ACC and MAG together. If you don't trust MAG, it won't trust ACC either. Besides, the complementary filter is helpful for orientations between $-\frac{\pi}{2}$ and $\frac{\pi}{2}$. Anything beyond that cannot be handled.
    • The EKF can be used, and in this case you could change the measurement noise covariance matrix R. Roughly speaking, it encodes "how much noise" does your sensor have. The last three elements of its diagonal tell you how much of this noise is expected from the magnetometer along the X-, Y-, and Z-axis, respectively. If it is too much noise, these values will be larger. If your magnetometer is perfect, which none is, these values will be equal to zero. By default in this implementation, the variances of each axis of the magnetometer are set to be equal to $0.8^2$ (squared, because variance is the square of the standard deviation). You can either make measurements and estimate this standard deviation with tools like NumPy, or simply tweak these values at every update step.
    • The Factored Quaternion Algorithm (FQA) might be the simplest solution for you. It is similar to AQUA, but in this case it independently estimates three different quaternions based on the Horizontal coordinate system: one for the elevation (angle about X-axis), one for the roll (angle about Y-axis), and one for the azimuth (angle about Z-axis). FQA finally blends them with a single product among the three. If there is a magnetic measurement you don't trust, you can simply set MAG to None for that measurement, and it will return a quaternion based on ACC+GYRO only.
  3. Sampling your sensor signals at irregular intervals (asynchronous sampling) is always preferred over forced synchronized signals (synchronous sampling), because those measurements are closer to the events. However, you would have to update your system at every measurement, which would increase the computation by orders of magnitude, and your performance will decrease dramatically. Besides, Shogo Arai et al proved that if you are sampling at high enough frequency (whether asynchronous or synchronous), there is no difference in the accuracy. So, my suggestion would be first to try increasing the sampling frequency, synchronize your measurements to have a fixed interval, and do the estimations.

  4. Low-pass filtering is the best way to improve your sensor signals, especially for real-time applications. I would also include a calibration for the GYRO and MAG beforehand. The GYRO calibration methods will usually give you each axis' bias, whereas the MAG calibration (called Hard and Soft Iron calibration) gives you the scale and bias errors. Even without noise, these parameters (scale and bias) will cause your estimations to drift immediately, or simply give you wrong estimations. So, basically: Always calibrate your sensors before any estimations.

I hope I could give you some tips here. For further questions, don't hesitate to write.

Mario.

Mayitzin avatar Oct 10 '24 11:10 Mayitzin

Your answer helped me a lot, but I still have some questions and need your help.

  1. I will try to interpolate the values with splines.
  2. According to your answers, I have modified the example of EKF. Can both of the following implementations choose whether to consider the magnetometer signal when updating based on the confidence of the magnetometer? By the way, is there a common value (1? 10? 100?) for the noise of MAG that makes EKF not trust MAG in implementation two?
import numpy as np
from ahrs.filters import EKF
from ahrs.common.orientation import acc2q
ekf = EKF()
num_samples = 1000              # Assuming sensors have 1000 samples each
Q = np.zeros((num_samples, 4))  # Allocate array for quaternions
Q[0] = acc2q(acc_data[0])       # First sample of tri-axial accelerometer
for t in range(1, num_samples):
    # >>> impl one >>>
    if mag_conf[t] < 0.3:
        Q[t] = ekf.update(Q[t-1], gyr_data[t], acc_data[t], mag=None, dt=timestamp[t]-timestamp[t-1]) # update without MAG
    else:
        Q[t] = ekf.update(Q[t-1], gyr_data[t], acc_data[t], mag_data[t], dt=timestamp[t]-timestamp[t-1]) # update with MAG
    # <<< impl one <<<

    # >>> impl two >>>
    if mag_conf[t] < 0.3:
        set_ekf_mag_noise_with_larger_num()  # A function which increases the noise of the MAG in EKF
    else:
       set_ekf_mag_noise_with_small_num()  # A function which decreases the noise of the MAG in EKF

    Q[t] = ekf.update(Q[t-1], gyr_data[t], acc_data[t], mag_data[t]) 
    # <<< impl two <<<
  1. For some reason the maximum sampling frequency for the ACC and GYRO sensors is 100Hz, while the maximum sampling frequency for the MAG is 40Hz, if I want to update based on the actual time interval, can I make dt = the actual time interval in each update step to achieve it?
  2. For the GYRO, I can detect the stable period to get the offset. In my scenario, I only need to detect the relative angle change, for example, whether it turns left, right, or backward. In this scenario, is it still necessary to calibrate the magnetometer? If I don't calibrate the magnetometer, will it have a big impact on the accuracy of the result?

czhaneva avatar Oct 10 '24 15:10 czhaneva