Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP][IMU] Correct calibration of Gyroscope #57

Merged
merged 2 commits into from Apr 17, 2018

Conversation

CTCaer
Copy link
Contributor

@CTCaer CTCaer commented Apr 16, 2018

Plus some other fixes

@wormyrocks, @mfosse, @JibbSmart


### Gyroscope - Rotation (in revolutions/s)

The equation will become:

`acc_vector_component = acc_raw_component * acc_coeff * 0.0027777778`
`acc_vector_component = (acc_raw_component - uint16_to_int16(cal_gyro_offset)) * acc_coeff * 0.0027777778`
Copy link

@JibbSmart JibbSmart Apr 17, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks to me like it's using the gyro offset in calculation of an acceleration vector. Should it actually be a gyro vector (gyro_raw_component, etc), given its context?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy paste mistake, I will fix it

@JibbSmart
Copy link

Hi @CTCaer, thanks for including me in this.

It looks like a typo at lines 137 and 145, with acc_vector_component being used with gyro offsets. But otherwise the changes about offset look good to me.

However, for my own education's sake: it's not clear to me why gyro offset is used to calculate the gyro coefficient, or at least not why it's used as is:
If the gyro offset is positive, the coefficient will be larger (since it'll have a smaller denominator), increasing the range of the output once it's multiplied by the coefficient. But if the gyro offset is negative, the coefficient will be smaller (due to a larger denominator), decreasing the range of the output once it's multiplied by the coefficient. It's not clear to me why this should be the case. My intuition says there should be some symmetry around zero.

Thanks for your help!

@CTCaer
Copy link
Contributor Author

CTCaer commented Apr 17, 2018

@JibbSmart
Thank you for catching this. I most of the times read with my mind, so I didn't catch these.

Well for ACC it's clear why.
For GYRO, I don't know. It's what Switch does. And it seems it works well if the motion controls are calibrated.
It makes sense if that is not an offset though. I mean if the sensor is not capable to let's say output 0. Then, it works as a scaler-offset again.

There's a lot mumbo jumbo in the decompiled switch code though. I will check the code again, before proceeding with an OK.

@CTCaer CTCaer changed the title [IMU] Correct calibration of Gyroscope [WIP][IMU] Correct calibration of Gyroscope Apr 17, 2018
@dekuNukem dekuNukem merged commit 66935b7 into dekuNukem:master Apr 17, 2018
@CTCaer
Copy link
Contributor Author

CTCaer commented Apr 17, 2018

@dekuNukem
This was WIP and not for merge yet. But well anyway.
The changes are correct, compared with Switch-style usage.

@JibbSmart
I found out that the value is used in the coeff as a scaler, like acc.
The reason for this, is drift cancellation. Mitigates the noise from the chip, temperature, etc.
And of course for this to work, the calibration data should be correct.

So basically the simple way is:
gyro_cal_coeff = 936.0f /13371.0f
gyro_comp = (gyro_raw - cal_gyro_offset) * gyro_cal_coeff

And the simple drift mitigation way:
gyro_cal_coeff = 936.0f / (13371.0f - (float)uint16_to_int16(cal_gyro_offset))
gyro_comp = (gyro_raw - cal_gyro_offset) * gyro_cal_coeff

So it seems that the noise is also scaled by rotation. And that's why it is also used for scaling, additionally to offset (for still noise removal).
Maybe we should add a mention about this.

@JibbSmart
Copy link

JibbSmart commented Apr 17, 2018

@CTCaer
Thanks for the explanation! So, if I understand correctly, the greater the offset, the greater the noise at calibrated zero, and this is to compensate?
I'm afraid I still don't understand why, for example, an offset of -5 should have a smaller-than-normal coefficient and an offset of +5 should have a larger-than-normal coefficient. I would've expected to use the absolute offset somewhere in there rather than the signed offset for a multiplier.

EDIT: Though I understand you're just going with what the Switch does

@CTCaer
Copy link
Contributor Author

CTCaer commented Apr 18, 2018

Actually bigger and smaller coefficients.

I really don't know why they chose to do this. No matter how I look at the calibration code, it's what it does. And it seems to work well for me.
Maybe they want to mitigate edge cases where the offset changes the vector component sign because a 16bit variable used?

Also the code constantly uses zero drift recalibration algorithms when it detects stillness.

And indeed what I wrote is mostly the switch usage scenario.
An advanced solution will not calibrate through spi and will use its own calibration method, based on gain values, gyro/acc settings, acc/gyro deadzones, acc horizontal offset, etc, when they instruct the user to place the controller on a flat surface. And ofcourse onthefly calibration and zerodrift mitigations, which are not yet discussed here.

I will again study the code though. Maybe I'm really missing something.

@CTCaer CTCaer deleted the patch-1 branch April 18, 2018 10:46
@CTCaer
Copy link
Contributor Author

CTCaer commented Apr 18, 2018

@JibbSmart
So there is sth more in the end.
The vector component is multiplied with an additional value.

But, I can't decode the exact value..

@JibbSmart
Copy link

@CTCaer

Actually bigger and smaller coefficients.

= 936.0f / (13371.0f - (float)uint16_to_int16(cal_gyro_offset))
-5 gives a denominator of 13371.0f - (-5), which is 13376.
+5 gives a denominator of 13371.0f - (+5), which is 13366.
A larger denominator gives a smaller result, so it is indeed smaller and larger :) Maybe it looked like I was talking about the offset to the denominator (13371.0f - 5; 13371 + 5, respectively, ignoring that the offset is subtracted and not added), which would make it bigger and smaller.

And it seems to work well for me.

I can't really tell the difference between constant coefficients and using the offset in the coefficient calculation. Offseting the raw output is the most important thing, it seems. The offsets make such a tiny difference to the coefficient.

The difference is much smaller than the (still tiny) error I'm actually getting from the Switch's calibration, so I'm happy to ignore it for my purposes (as a gyro mouse, which only needs to turn x and y rotational velocities into x and y mouse movements multiplied by a user-defined sensitivity), although I imagine the exact details are probably important for accurately estimating real world changes in orientation (which I'm not doing).

Maybe they want to mitigate edge cases where the offset changes the vector component sign because a 16bit variable used?

That seems plausible.

Also the code constantly uses zero drift recalibration algorithms when it detects stillness.

Wow, the Switch does this itself? I thought it was just something game developers were doing. Thanks for the info!

I noticed it in Splatoon 2, and especially DOOM, where tracking distant slow targets while keeping a steady hand (movements that look like drift to the console/game), the aimer would stop as it recalibrates. Then I actually stop moving my hand and it'd drift in the opposite direction until it detects the drift-like motion and "stillness" of the controller and recalibrates again.

I quite dislike it, and much prefer games would encourage people to put down the controller like you describe. It's not hard, the game doesn't have to do it itself (the Switch has the option in system settings, although it can be nice to do it oneself and be more confident it's properly calibrated), and it's something I've got going in my project that treats Switch controllers and DualShock 4s the same. And the gyro bias changes so slowly over time that one calibration will last multiple play sessions (so it's nice that the JoyCons save their calibration through spi!).

So there is sth more in the end.
The vector component is multiplied with an additional value.

But, I can't decode the exact value..

Interesting! I'm curious if you do manage to decode it at some point, but I'm satisfied that I've got useful results already.

Thank you so much for all the clear explanations :) I'm happy with what I have working, so please don't feel any pressure to decode anything else on my account.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants