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

pbio/imu: Implement 3D attitude and fusion of IMU data. #270

Merged
merged 20 commits into from
Dec 3, 2024
Merged

Conversation

laurensvalk
Copy link
Member

This is an exciting update that implements 3D attitude estimation for the gyro with fusion of accelerometer data.

The main changes:

  • Implement 3D attitude estimation.
  • Implement fusion with accelerometer data.
  • Improve heading estimation for hub.imu.heading(). Now heading will still be close to the correct value when you drive across ramps or lift it from the table.
  • Implement hub.imu.tilt() to use the new fused gyro data. This should be much less noisy than the pure accelerometer result, and it is no longer affected by horizontal or vertical acceleration.
  • Implement hub.imu.orientation() which gives you the rotation matrix of your robot. This is almost always more useful than some kind of (non-)singular angular representation. We'll add some examples to show why this is useful. You could always extract your favorite angular representation from the rotation matrix elements.
  • Add calibration options for gyro and accelerometer offset and bias.

Things that still need to be done:

  • Replace the (still temporary) hub.imu.update_heading_calibration() with an interactive routine that estimates the 3D calibration constants.
  • Make improvements for robustness. Since the new additions depend on user calibration constants saved on flash, we'll want to make sure nothing can go wrong (like zero division or singularities for some attitudes) if the user sets unexpected calibration values.
  • See how well everything works in practice in different use cases.
  • Verify that the 3D heading estimation is no worse than the pure 1D integration. If it is, we need to consider making that separately available.

Other notes:

  • I did not use a standard fusion algorithm. Since we don't have any magnetic sensors and since most LEGO robots don't fly, I think we can benefit from a simpler algorithm that makes use of some of the assumptions that we can make about LEGO robots. Roughly, it works like this:
  • The angular velocity bias is currently still estimated independently as a long term moving average. Since we can make the robot sit still (unlike a drone mid flight), this works quite well.
  • Attitude estimation works by converting the angular velocity to the quaternion rate of change and integrating it over time.
  • Fusion happens by steering the estimated gravity vector towards the measured gravity vector when the hub is (close to) stationary, as if connecting them by a virtual spring.
  • The initial quaternion is set to align with the first available gravity sample (with an arbitrary initial heading).

These flags will later be used to test which calibration has been done already.

We can use the same flag to optionally set settings, rather than use NAN to indicate nothing set.
Since this is done in quite a few functions, this should make the build size smaller and the code easier to follow.
Since this is done in quite a few functions, this should make the build size smaller and the code easier to follow.
@coveralls
Copy link

coveralls commented Oct 25, 2024

Coverage Status

coverage: 56.385% (-0.4%) from 56.81%
when pulling 77eb752 on imu
into 4d457a1 on master.

When the hub first boots, it is good to have an initial value for the bias to help suppress drift during the first nonstationary seconds.

As an estimate, we can use the bias first saved on the previous boot.
When starting from the latest sample as we did before, the odds are higher that we start on an outlier and have to restart, or allow larger errors.
Now that it is a bit less sensitive to outliers, we can reduce this value. See pybricks/support#1105
@laurensvalk
Copy link
Member Author

laurensvalk commented Dec 2, 2024

To get this over the line, perhaps we should restore 1D heading and also keep the original heading correction setting available since people are using it. (In addition to the new 3D stuff).

We can make the 3D-based heading the default as it gets more testing organically, instead of having it sit here as a pull request for a long time.

This way we can introduce the feature gradually, defaulting to the current 1D behavior.
This makes the calibration user routine simpler, so we can do everything from raw data.
Not all hubs will need all modules.
This allows model-specific correction when calibration doesn't fully cover it, which is particularly useful in hubs mounted at a slight tilt.
For example, Technic Hub does not need light matrix code.

Also remove single-axis calibration routine. To be replaced with 3D calibration routine.
This works on Prime Hub, Technic Hub, and Essential Hub, but the instructions are still specific to Prime Hub.
@laurensvalk laurensvalk merged commit 77eb752 into master Dec 3, 2024
38 checks passed
@dlech dlech deleted the imu branch December 3, 2024 15:24
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.

2 participants