sfwa / TRICAL

Straightforward UKF-based scale and bias calibration for magnetometers (and other tri-axial field sensors).
http://au.tono.my/log/20131213-trical-magnetometer-calibration.html
MIT License
35 stars 17 forks source link

Clarification about using TRICAL_estimate_update() #8

Open RafigRzayev opened 2 years ago

RafigRzayev commented 2 years ago

Hi,

I am getting X, Y, Z values from magnetometer in uT units.

I am using following tool to identify magnetic field in my location, and the value is 50uT (though my calibrated reading are usually around ~55uT).

I don't understand which value should be used for expected_fieldargument in TRICAL_estimate_update(&global_instance, sensor_reading, expected_field). Can you please tell me what values should be put there?

Below is the pseudocode that I am using, can you please check that the usage is correct?

TRICAL_instance_t global_instance;

int main(void) {
  TRICAL_init(&global_instance);
  TRICAL_norm_set(&global_instance, 50.0);
  TRICAL_noise_set(&global_instance, 1.5);

  float bias_estimate[3];
  float scale_estimate[9];
  float sensor_reading[3];
  float expected_field[3];

  // for holding data received from magnetometer, in uT.
  float mag_x, mag_y, mag_z;

  while(true) {
    // get the latest sensor reading
    read_magnetometer(mag_x, mag_y, mag_z);
    sensor_reading[0] = mag_x;
    sensor_reading[1] = mag_y;
    sensor_reading[2] = mag_z;

    // What should be passed to expected field?
    TRICAL_estimate_update(&global_instance, sensor_reading, expected_field);

    TRICAL_estimate_get(&global_instance, bias_estimate, scale_estimate);

    printf("[%f %f %f]\n", bias_estimate[0], bias_estimate[1], bias_estimate[2]);
   }

return 0;
}
RafigRzayev commented 2 years ago

@bobayka can you please help? Looks like the repository is not very active.

Here you wrote that your input range is [-1,1]. Did you scale the input by the maximum?

Also, you said that no zeros are allowed in the input. It is strange :( . Did you write ifstatement to avoid zeros?

RafigRzayev commented 2 years ago

@Lelelo1 Maybe you can help? Do you know which values to pass to the function?

Lelelo1 commented 2 years ago

As far as I came to understand it. The expected field is from world magnetic model. You can check what the earth magnetic field is supposed to be in your location with Launch Single Point Calculator

If you point your device to north it should print that vector when there is none or little magnetic distortion. The coordinate system of the vector from world magnetic model and the measurement in the application needs to match.

Its used in a kalman filter, in _trical_measurement_calibrate method in filter.c. It means deviating values are filtered out.

RafigRzayev commented 2 years ago

Thank you very much for your help. I was using the same calculator and for me the "Total field" is calculated as 50,325.0 nT, which is ~50uT.

That's why I did following: TRICAL_norm_set(&global_instance, 50.0);

But in the TRICAL_estimate_update function, it expects a 3-element vector, not a single value:

/*
TRICAL_estimate_update
Updates the calibration estimate of `instance` based on the new data in
`measurement`, and the current field direction estimate `reference_field`.
Call this function with each reading you receive from your sensor.
*/
void TRICAL_estimate_update(TRICAL_instance_t *instance,
float measurement[3], float reference_field[3]);

I tried with reference_field = {50,50,50}, but the calculated bias was always [0,0,0].

I found one repo which uses the function, but is really difficult to understand what is going on there.

Which values did you use for the reference_field[3](expected field)?

Lelelo1 commented 2 years ago

X: North Component Y: East Component Z: Vertical Component

√(x2 + y2 + z2). Is same as norm (50)

It could look like this the vector: 16,505.3, -1,509.8, 47,844.4 total field (norm) 50,611.4

For latitude: 57.698745, longitude: 11.966936

RafigRzayev commented 2 years ago

So I can make up any combination of 3 values which by formula will provide 50?

Can I use fixed vector always? Or should it be updated according to something else?

RafigRzayev commented 2 years ago

In the repository mentioned above, they use following:

TRICAL_estimate_update(instance, mag_value_f, expected_field_f);

Where expected_field_fcomes from:

    float mag_value_f[3], expected_field_f[3];
...
    quaternion_vector3_multiply_d(expected_field, attitude, wmm_field);
    vector_f_from_d(expected_field_f, expected_field, 3u);
Lelelo1 commented 2 years ago

So I can make up any combination of 3 values which by formula will provide 50?

No

That vector represent a arrow pointing the direction earths magnetic field in 3d. For instance ENU coordinate system means east component is x, north component is y, and vertical component is z.

When there is no distortion all measurements become like a sphere, all of them having length(norm) of 50. The norm depend on how near earth's poles you are

I recommend you collect the first measurement and use it as expected field instead. It assumes you are in spot with little magnetic distortion. Then you can test to distort measurement with some metal near sensor of the device. The kalman filter should block those values and application should still be accurate depending how well the Kalman is made

RafigRzayev commented 2 years ago

Thank you for clarification. Then, if I understood correctly, I will do following:

Can you confirm?

RafigRzayev commented 2 years ago

I tried with your values for demo purposes, the bias doesn't change. It is always 0, 0, 0.

I wrote an example which you can run on your pc. I recorded the magnetometer values, and saved them in a header file to be used as an input for the TRICAL.

Here is the link

I am sorry for taking your time. I would appreciate if you can take a look. The program output is not normal: it prints NaN and ones .

Lelelo1 commented 2 years ago

I have stopped programming this kind of stuff. So I can’t look at it in detail.

But I can tell you that bias is distortion

RafigRzayev commented 2 years ago

Ok, I understand :)

Thank you very much for your help.

If I will get it working I will post updates here.

RafigRzayev commented 2 years ago

Found two repositories that are using TRICAL, which can serve as a reference, though it looks a little complicated:

https://github.com/sfwa/fcs/blob/master/fcs/hardware/platform/cpuv1-ioboardv1.c

https://github.com/paparazzi/paparazzi/blob/3d79153821e811a68ea62db08a13105173748bd3/sw/airborne/modules/calibration/mag_calib_ukf.c