xioTechnologies / Fusion

MIT License
1.07k stars 255 forks source link

Best delta time + calibration #58

Closed ladislas closed 1 year ago

ladislas commented 1 year ago

Hi team!

First I want to thank you all for the great library. We just started using it with our LSM6DSOX and the results are very good.

We have a few questions to make sure we use the library to the best of its abilities.

Best delta time

What would be the best delta time between calls to FusionAhrsUpdateNoMagnetometer?

In our testing setup we used 80ms with good accuracy but we are wondering what the limit would be.

Dynamic delta time

This one is a bit related to the previous one.

In our case, we are using the library with an RTOS (MbedOS) with different parts of the product running in different threads (LEDs animations, video, IMU, etc.)

The IMU thread is sleeping for 80ms between each iterations. Because of scheduling and thread priority, the delay can be 80ms ±10ms.

In the advanced example, we saw that delta time can be dynamic but is a ±10ms variation too much for the algorithm?

Calibration

To improve precision, we want to calibrate the gyroscope, especially the z rotation Offset.

We recorded ~3000 samples for 5 minutes and calculated the average gz to set in gyroscopeOffset.

Is that what we are supposed to do?

Regarding Misalignment, we are not sure how to handle that so we want to enter the "default" values.

Would that be 0.0f everywhere?

const FusionMatrix gyroscopeMisalignment = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};

Regarding Sensitivity our guess is that the default is 1.0f, is that okay?

const FusionVector gyroscopeSensitivity = {1.0f, 1.0f, 1.0f};

Difference between FusionCalibrationInertial and FusionOffsetUpdate

In the advanced example, the following happen:

gyroscope = FusionCalibrationInertial(gyroscope, gyroscopeMisalignment, gyroscopeSensitivity, gyroscopeOffset);

// then

gyroscope = FusionOffsetUpdate(&offset, gyroscope);

What is the difference between the two? It seems that we are applying the offset correction twice, is that the case? Is that intended?

Thanks a lot for your kind help :)

xioTechnologies commented 1 year ago

Ideally, deltaTime should be calculated as the difference between two timestamps where each timestamp is obtained using the gyroscope data ready interrupt. This would achieve timing calculation errors inline with your system clock error. For example, 0.002% (20 ppm). Alternatively, could use the nominal sample period of the sensor as a constant value for deltaTime. The LSM6DSOX sample clock error appears to not be specified in the datasheet but it would likely be around 0.5%. This is significantly better than the 12.5% (80 ms ±10 ms) you are currently expecting.

It is not clear from your description if you system is guaranteed to process every gyroscope sample, or if some samples may be discarded due to the jitter in task scheduling. It is essential that you process every gyroscope sample.

If you are unable to provide a specific value for the misalignment argument of FusionCalibrationInertial then you should use FUSION_IDENTITY_MATRIX. If you are unable to provide a specific value for sensitivity then you should use FUSION_VECTOR_ONES. For example, if you only wanted to apply gyroscopeOffset then you would use the following expression.

gyroscope = FusionCalibrationInertial(gyroscope, FUSION_IDENTITY_MATRIX , FUSION_VECTOR_ONES, gyroscopeOffset);

Note that this expression is equivalent to gyroscope = FusionVectorSubtract(gyroscope, gyroscopeOffset); and would typically compile to the same machine code due to the use of the definitions FUSION_IDENTITY_MATRIX and FUSION_VECTOR_ONES.

FusionCalibrationInertial applies fixed calibration parameters, FusionOffsetUpdate is the gyroscope offset correction algorithm. The following is copied from the README.

"The gyroscope offset correction algorithm provides run-time calibration of the gyroscope offset to compensate for variations in temperature and fine-tune existing offset calibration that may already be in place. This algorithm should be used in conjunction with the AHRS algorithm to achieve best performance."

ladislas commented 1 year ago

@xioTechnologies thank you so much for the detailed answer!

It is not clear from your description if you system is guaranteed to process every gyroscope sample, or if some samples may be discarded due to the jitter in task scheduling.

gyro ODR is 52Hz so yes, a lot of samples are discarded. When reading the data from the sensor, we get the latest.

It is essential that you process every gyroscope sample.

I didn't know that, so it's something we'll need to change.

deltaTime should be calculated as the difference between two timestamps where each timestamp is obtained using the gyroscope data ready interrupt.

LSM6DSOX can be read on data ready, either gyroscope or accelerometer.

From my understanding, it is mandatory for the gyroscope to be "driving" the system.

LSM6DSOX lets us configure the ODR as we want: 12.5Hz, 26Hz, 52Hz, 104Hz, 208Hz, 416Hz

Our current setup is using 52Hz -- 💡 do you think it's enough? Can we go lower?

💡 Is the fusion algorithm ISR/Interrupt safe? and if not, is it okay to do the calculation outside of ISR/Interrupt context using an event queue?

If you are unable to provide a specific value for the misalignment argument of FusionCalibrationInertial then you should use FUSION_IDENTITY_MATRIX. If you are unable to provide a specific value for sensitivity then you should use FUSION_VECTOR_ONES. For example, if you only wanted to apply gyroscopeOffset then you would use the following expression.

Thank you very much for that.

FusionCalibrationInertial applies fixed calibration parameters, FusionOffsetUpdate is the gyroscope offset correction algorithm.

understood, thanks.

We'll rework our system using Fusion and I'll keep you posted on our results.

Once again thanks a lot for your kind help :)

xioTechnologies commented 1 year ago

The minimum algorithm update rate (i.e. gyroscope ODR) for your application would be determined by the kind of motion you expect, and how much error you are willing to accept. I cannot comment on this without knowing more about your application.

Fusion can be used in ISRs and multithreaded applications provided that you implement appropriate safety. For example, two processes should not access an instance of FusionAhrs at the same time.

ladislas commented 1 year ago

I cannot comment on this without knowing more about your application.

Right! Sorry about that! :)

To give you more context: we are developing a smart spherical robotic educational tool for children with special needs. Think Sphero but bigger with more features.

https://leka.io

We have different use cases:

  1. ask the user to spin the robot x times and have the robot react when the number of rotations has been reached. Rotation by hand is usually slow.

  2. have the robot spin 3 times in 5 seconds on its own using its motors and stop when the number of rotations has been reached.

  3. stabilize the robot when the user interacts with it: if the user tilts or rolls the robot, the robot can sense that and react accordingly to return to its stable position

All those movements are fairly "slow" but as they are performed by humans, they are far from perfect, for example when rotating the robot, it's not linear and continuous: you put your hand on the robot, rotate as much as you can, stop, lift your hand, put it back, start rotating again.

xioTechnologies commented 1 year ago

It sounds like your application does not require accurate orientation measurment. An algorithm update rate of 52 Hz may be acceptable but you would need to test this. I suggest that your tests include impacts and jerks that may occur during use, as this is the kind of motion that can cause issues with a low update rate.