Skip to content

Apply gravity compensation to accelerometer readings - #138

Open
bjornhbengtsson wants to merge 6 commits into
integration/state-estims-telemetryfrom
feature/gravity-compensated-acceleration
Open

Apply gravity compensation to accelerometer readings#138
bjornhbengtsson wants to merge 6 commits into
integration/state-estims-telemetryfrom
feature/gravity-compensated-acceleration

Conversation

@bjornhbengtsson

@bjornhbengtsson bjornhbengtsson commented Jul 21, 2026

Copy link
Copy Markdown

Description

Adds quaternion vector rotation helpers and uses the current body to world attitude estimate to remove gravity from accelerometer measurements before velocity integration.

Changes

  • Document the attitude quaternion as a body to world rotation.
  • Add world to body vector rotation:
    • v_body = conjugate(q) * v_world * q
  • Add body-to-world vector rotation:
    • v_world = q * v_body * conjugate(q)
  • Define gravity in the world frame along +Z.
  • Rotate world gravity into the body frame.
  • Subtract body-frame gravity from body-frame accelerometer measurements.
  • Rotate the resulting linear acceleration back into the world frame.
  • Integrate world-frame linear acceleration into world-frame velocity.
  • Correct the microseconds-to-seconds conversion so it uses floating-point division, so values smaller than one second are preserved instead of being truncated to zero by integer division.
  • Replace powf(x, 2) calls with direct multiplication, because it's computationally zoomier.

Frame convention

state_estimate->attitude represents the body to world rotation.

v_world = q * v_body * conjugate(q)
v_body  = conjugate(q) * v_world * q

The gravity-compensation path is now:

g_world
-> world to body rotation
g_body

accel_measured_body - g_body
= accel_linear_body

accel_linear_body
-> body-to-world rotation
accel_linear_world

accel_linear_world * dt
-> world-frame velocity

Issue Link

github.com//issues/139

child: SunDevilRocketry/Flight-Computer-Firmware#304

Testing

  • [] Passes existing unit tests
  • Unit tests modified (link the test changes as a child PR)
  • Integration test performed

The corresponding quaternion and gravity-compensation tests cover:

Identity world-to-body rotation
Identity body-to-world rotation
Body-to-world-to-body round trip
Positive 90-degree yaw rotation
Stationary identity attitude producing zero linear acceleration after gravity subtraction

Local test result:

Passes: 26
Fails: 0
Result: PASS

Other

Leave any additional notes here

Reviewer Checklist

Standards

  • Follows FCF Architectural Standards
  • Follows SDR Coding Standards
  • Code complexity/function Size is minimized
  • Code is testable
  • Code is readable and commented properly
  • License terms are respected

Error Handling

  • Potentially unsafe functions return a status code
  • Error returns properly handled

Memory

  • Stack allocated memory is scoped correctly
  • Heap allocated memory is avoided
  • Globally allocated memory is minimized except when necessary
  • Pointers are used correctly
  • Concurrency has been considered

Performance

  • Rate limiters are respected
  • Busy waiting is avoided
  • "Delay" calls are not used in performance sensitive code

@ETSells

ETSells commented Jul 22, 2026

Copy link
Copy Markdown
Member

Linked child PR. Please remember to do that going forward so we can navigate between dependent code easier!

@ETSells ETSells left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@NArmistead Gonna want you to spot check the math here, but I'm happy from a software design perspective.

The one change request on the child PR is to move the tests into this repo.

Comment thread math_sdr/math_sdr.c Outdated
QUAT vector_world
)
{
QUAT attitude_conj = quat_conj(attitude);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: format

@bjornhbengtsson

Copy link
Copy Markdown
Author

Video resource if anyone wants extra study material on the subject of frame rotations: https://youtu.be/4WKghhPzonE?is=AnQzI4YVkjorqC7R

@NArmistead

Copy link
Copy Markdown
Contributor

Video resource if anyone wants extra study material on the subject of frame rotations: https://youtu.be/4WKghhPzonE?is=AnQzI4YVkjorqC7R

dr shane ross!!! 🗣️🗣️🗣️🗣️

@NArmistead NArmistead left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Math looks good too but I want to wait until we try it on hardware before we merge. Unless you already did that then go ahead and send it. Also thanks for writing unit tests for this and getting that set up for mod although I have one non-critical request for remaning the test folder

Comment thread sensor/sensor.c
Comment on lines +610 to +612
velo_x * velo_x +
velo_y * velo_y +
velo_z * velo_z

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

yeah thanks

Comment thread math_sdr/math_sdr.c Outdated
(
quat_mult(attitude, vector_body),
attitude_conj
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

rare case where i wish we had operator overloading

Comment thread sensor/sensor.c Outdated
float accel_x = imu_converted->accel_x;
float accel_y = imu_converted->accel_y;
float accel_z = imu_converted->accel_z;
/* The world frame defines gravity in the +Z direction. */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we should probably mention somewhere that we use NED

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

done

Comment thread math_sdr/math_sdr.c
Comment on lines +314 to +318
return quat_mult
(
quat_mult(attitude, vector_body),
attitude_conj
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this is hard to read but I think the comment explains it
one of the rare cases where I kinda wish we had operator overloading lol

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

only thing I would maybe like you to change is to rename the "test" folder to "_test" to be consistent with driver

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

+1 tbh, I did that in driver to make it not look like we had a driver named test. would be good here since the test framework submodule doesnt live in mod and that might be ambiguous

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

done

@bjornhbengtsson

Copy link
Copy Markdown
Author

Sounds good. Haven't tested it on hardware

@NArmistead

Copy link
Copy Markdown
Contributor

@bjornhbengtsson actually can we wait to merge this and #142 until #134 goes in? most of that PR is reviewed and ready so we don't want to creep it too much

@bjornhbengtsson

Copy link
Copy Markdown
Author

Yup we can wait. And if you want to wait on reviewing Mahony for Kalman that's cool. I'm deep into Kalman by now

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.

3 participants