Similar to this question: CMDeviceMotion userAcceleration drift
I'm using CMDeviceMotion.userAcceleration in iOS5 SDK to plot its x, y, z components over time. Like the above post, I see z acceleration component shows always small positive values (0.005 - 0.015) while x and y components are centering along zero (-0.005 - 0.005) when my iPhone 4s is sitting on a flat surface.
This small bias keeps adding up to the estimated velocity (which I compute by integrating the acceleration data) even when my phone is not moving a bit. Is there any known way to remove this bias from the accelerometer data? I cannot simply subtract the bias from z component because it seems that the bias spreads over x y and z along the gravity axis if the device is in some arbitrary orientation.
I know that the data in CMDeviceMotion.userAcceleration has already factored out the gravity using Gyro data but wonder if there is any effective way to remove this residual bias?
First, you need some external reference that does not drift such as GPS. Then you have to perform sensor fusion (Kalman filter comes to mind). Otherwise you cannot remove the bias and the integration error will grow indefinitely.
UPDATE: You cannot get relative displacement just by integrating the acceleration, see my answer to Android accelerometer accuracy (Inertial navigation). However, I give some examples there what you actually can do.
If you check my answer you will see that it is the gyro white noise that makes the integration hopeless.
Old question, but I wanted to share some insight. Part of the bias in the accelerometers actually does not come from any inaccuracies in the sensors, but from an oversight in the calculations that Apple does. The calculations assume that gravity always is 1 G (which is by definition 9.80665 m/s2). Any left-over must then be user acceleration.
However, gravity varies slightly all over the world. If the gravity in your area is not exactly 9.80665 m/s2, then there will be a small bias in the user acceleration, which is detectable with a low-pass filter. Such a bias can removed with the following calculation:
- (void) handleDeviceMotion:(CMDeviceMotion *)m atTime:(NSDate *)time
{
// calculate user acceleration in the direction of gravity
double verticalAcceleration = m.gravity.x * m.userAcceleration.x +
m.gravity.y * m.userAcceleration.y +
m.gravity.z * m.userAcceleration.z;
// update the bias in low pass filter (bias is an object variable)
double delta = verticalAcceleration - bias;
if (ABS(delta) < 0.1) bias += 0.01 * delta;
// remove bias from user acceleration
CMAcceleration acceleration;
acceleration.x = m.userAcceleration.x - bias * m.gravity.x;
acceleration.y = m.userAcceleration.y - bias * m.gravity.y;
acceleration.z = m.userAcceleration.z - bias * m.gravity.z;
// do something with acceleration
}
Mind you, even with that bias removed, there is still a lot of noise, and there could also be a manufacturing bias different for each accelerometer chip. Therefore, you will still have a hard time deriving velocity and certainly position from this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With