Getting Gravity from ICM-20948

For Adafruit customers who seek help with microcontrollers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
magicseth
 
Posts: 8
Joined: Wed Oct 11, 2017 12:42 am

Getting Gravity from ICM-20948

Post by magicseth »

I'm working on a project using the ICM-20948 9-DoF sensor.

Is there a library that I can use to get the gravity vector easily? or the motion component with gravity removed?

Thanks!
-s

User avatar
adafruit_support_mike
 
Posts: 67454
Joined: Thu Feb 11, 2010 2:51 pm

Re: Getting Gravity from ICM-20948

Post by adafruit_support_mike »

The device doesn’t calculate gravity for you, but you can get a good approximation by taking a running derivative of the acceleration vector.

Store a copy of the accelerometer values before taking a new reading, then subtract the old values from the new ones. Any difference between them represents a change in acceleration, which has to be the result of an external force.. the three differences are components of a vector proportional to the change in external force. A difference of zero (or near zero) indicates constant acceleration, which comes from two things: a constant external force, and gravity.

External forces have to stop eventually, and tend to drop off quickly for most kinds of motion. A running sum of the differences should be zero most of the time.

If you subtract the running sum from each new reading, you’ll get the gravity vector.

Running sums of digital readings tend to accumulate error over time, so you’ll want to get rid of any long-term nonzero values. An easy way to do that is to multiply the running sum by 0.95 each time you calculate a new value. Any constant offsets will fade to nothing in a reasonable time. You do lose some real information too, so you can adjust the multiplier value for the best compromise. Any value between 0 and 1 will work, with small multipliers dropping to zero quickly but losing a lot of real information, and larger numbers keeping most of the real information but letting errors hang around longer.

User avatar
magicseth
 
Posts: 8
Joined: Wed Oct 11, 2017 12:42 am

Re: Getting Gravity from ICM-20948

Post by magicseth »

Thanks, as always, for a prompt informative response! This all sounds good.

I suppose I would pre-transform the acceleration values by any change in orientation before adding to my existing acceleration values.

I'm (foolheartedly) trying to build a dead reckoning system that works for a few seconds at a time, over a very small distance.

Thanks,
Seth

User avatar
adafruit_support_mike
 
Posts: 67454
Joined: Thu Feb 11, 2010 2:51 pm

Re: Getting Gravity from ICM-20948

Post by adafruit_support_mike »

Yeah, a complete system will also need to handle rotation.

Averaging can handle rotation as long as the change is relatively small from one reading to the next. The gyro readings become more important as the rotation gets faster or the sampling rate gets slower. That's where quaternions become useful.. they make it easier to describe and compare rotations.

You might also want to keep track of the magnetic vector.. that should also stay constant relative to any motion of the board. The gravity vector and magnetic vector define a plane, and you can take their cross product to get a vector perpendicular to that plane.

User avatar
sj_remington
 
Posts: 998
Joined: Mon Jul 27, 2020 4:51 pm

Re: Getting Gravity from ICM-20948

Post by sj_remington »

The gravity vector can be easily derived from the quaternion, but that depends on how the quaternion is defined with respect to the sensor coordinate system.

If you are using the standard Madgwick or Mahony filter, the reference orientation is sensor X North, Y West and Z up, although how "sensor X" etc. is defined is up to the person who wrote the library and interfaced the Madgwick or Mahony filter code.

Within the Madwick or Mahony filter code, the normalized gravity reference vector Up, in the sensor frame of reference, is given by

Code: Select all

  // Estimated direction of Up reference vector
  ux = 2.0f * (q2q4 - q1q3);
  uy = 2.0f * (q1q2 + q3q4);
  uz = q1q1 - q2q2 - q3q3 + q4q4;
Keep in mind that gravity points Up in accelerometer coordinates (along positive Z if X and Y are horizontal).
Useful reference: https://en.wikipedia.org/wiki/Quaternio ... l_rotation

User avatar
sj_remington
 
Posts: 998
Joined: Mon Jul 27, 2020 4:51 pm

Re: Getting Gravity from ICM-20948

Post by sj_remington »

Demo for the ICM-20948, using the Mahony filter, posted at https://github.com/jremington/ICM_20948 ... ahony_AHRS

User avatar
magicseth
 
Posts: 8
Joined: Wed Oct 11, 2017 12:42 am

Re: Getting Gravity from ICM-20948

Post by magicseth »

Thanks for the great pointers!

I ended up plugging in this library: https://github.com/UT2UH/Arduino_ICM209 ... l-Function

Which enables the onboard DMP which calculates linear acceleartion, gravity, and an orientation quaternion.

The quat9 orientation spins for a bit to calibrate, but stabilizes after about 30 seconds if you put it in various orientations.

The values seem pretty good.

Sometimes the values are amazing!!! Super accurate

https://imgur.com/a/NN1CgpG


Sometimes I end up with some bias leading to speed increasing in one direction.

If I multiply the speed by .9 each time, that ends up never being a problem, but then you get the problem that when you slow down, your dead reckoning algorithm thinks that's reverse motion instead of just deccelerting to 0.

Thanks for all the help with the conceptual underpinnings, now comes the hard work of trying to tune it!


-s

User avatar
sj_remington
 
Posts: 998
Joined: Mon Jul 27, 2020 4:51 pm

Re: Getting Gravity from ICM-20948

Post by sj_remington »

Thanks for posting the library link and the video. I've heard that the background sensor calibration in the DMP has been improved and would like to understand what they did. Will experiment with it!

Locked
Please be positive and constructive with your questions and comments.

Return to “Microcontrollers”