Position estimation for iOS using accelerometer - ios

In iOS, it is easy to access Linear Acceleration which is equal to subtracting Gravity from Raw acceleration.
I am trying to estimate position by double integrating Linear Acceleration. For that I recorded the data by keeping the phone steady on table.
Then I did double integration in Matlab using cumtrapz but when I plot the position it grows with time.
What am I doing wrong? I was expecting that the position should be 0.

From what I've read this is too error-prone to be useful. Accelerometer based position calculations are subject to small drift errors, which accumulate over time. (If the phone is traveling at 100 kph constant velocity when your app first launches, you can't tell.) All you can measure is acceleration.

There would always been biasing errors from the sensors which can grow with time while integration. Can you calculate the drift of sensor when the device is at rest?. And then try to take the mean of the drift and subtract it from the input so that sensor shows 0 at rest, Then try to double integrate it

Related

Accelerations to Velocity in iOS - wrong sign

I am currently developing an App which should calculate the speed by the accelerations of the device. To achieve this I am using Sensing Kit. The app records data of the users motion and saves it to the local storage. When the user stops the recording it is possible draw the collected accelerations in velocity by time (Three graphs for every axis of the accelerometer).
Sensing Kit uses startAccelerometerUpdates of the CMMotionManager to get the accelerations. To calculate the velocity I do some signal processing and an integration of the acceleration (and multiply it by 9.81 because apple measures the acceleration in increments of gravity). The result is the velocity over the recorded time (Its not very precise but that doesn't matter in my case).
I tested my app by sliding the phone over a table with the screen up and the upper screen side in moving direction. The movement later shown up in the resulting graph of Y-Axis, but it has a negative velocity (The accelerations are negative, too). I expect that the velocity and the acceleration should be positive, because I moved the device in the positive direction of the Y-Axis.
The same happens with the X-Axis wehen I move the phone on the table in the direction of this axis.
I tested it today without Sensing Kit and get same results.
The gravity is always as I expect a negative velocity on the z-Axis, because its an acceleration to the ground.
Can somebody explain to me why the acceleration of the sensor has the wrong sign?
Thank you.
https://developer.apple.com/documentation/foundation/unitacceleration
https://developer.apple.com/documentation/foundation/units_and_measurement
The Foundation library has a function for this and you could use this to convert between UnitAcceleration and UnitSpeed.

Gyroscope non-constant drift under high acceleration

I am trying to implement a Kalman filter combining an accelerometer and the gyroscope in an IMU.
To my knowledge I would expect the gyro to have a constant drift which we will compensate by bringing in the accelerometer.
However, when analyzing the gyroscope independently I do not always observe a constant drift. If we do not have a lot of fast movement/high acceleration, the drift seems correct as seen in the first plot. On the second plot we get the gyro raw values.
At the beginning it can be seen that we offset the gyro by averaging the first 100 readings.
However, when I move the IMU more aggressively, the gyro does no longer have a constant drift. I do not know where this variation of the drift comes from and what would be a state-of-the-art way of solving this issue. I thought of small movements due to a small mounting issue, but if it would be left still, it should keep integrating the degrees at a same rate.
Even zero-mean noise can cause large random walk excursions from anything being constant. Double integration of this noise will cause your compensation to explode. The only good solution may be to use sensor fusion with another independent source of ground truth (optical, magnetic, audio, etc.)

How to getting movement size from 3 axis accelerometer data

I did a lot of experiment using the accelerometer for detecting the movement size(magnitude) just one value from x,y,z acceleration. I am using an iPhone 4 with accelerometer update frequency 1.0 / 50.0 (50HZ), but I've also tried with 100HZ, 150HZ, 200HZ.
Examples:
Acceleration on X axis
Acceleration on Y axis
Acceleration on Z axis
I assume ( I hope I am correct) that the accelerations are the small peaks on the graph, not the big steps. I think from my experiments that the big steps show the device position. If changed the position the step is changed too.
If my previous assumption is correct I need to cut the peaks from the graph and summarize them. Here comes my question how can I cut those peaks without losing the information, the peak sizes.
I know that the high pass filter does this kind of thinks(passes the high peaks and blocks the noise, the small ones, I've read some paper about the filters. But for me the filter cut a lot of information from my "signal"(accelerometer data).
I think that there should be a better way for getting the information out from the data.
I've tried a simple one which looks nice but it isn't correct.
I did this data data using my function magnitude
for i = 2 : length(x)
converted(i-1) = x(i-1) - x(i);
end
Where x is my data and converted array is the result.
The following row generated a the image below, which looks like nice.
xyz = magnitude(datay) + magnitude(dataz) + magnitude(datax)
However the problem with that solution is that if I have continuos acceleration the graph just will show the first point and then goes down. I know that I need somehow better filter, but I am bit confused. Could you give some advice how can I do this properly.
Thanks for your time,
I really appreciate your help
Edit(answers for Zaph question):
What are you trying to accomplish?
I want to measure the movement when the iPhone is placed to desk, chair or bed. The accelerometer is so sensible if I put down a pencil it to a desk it shows me. I want to measure all movement that happens in a specific time.
What are the scale units?
I'm not scaling the data.
When you say "device position" what do you mean, an accelerometer provides movement (in iPhones with gyros)
I am using only the accelerometer. When I put the device like the picture below I got values around -1 on x coordinate, 0.0 on z and y coordinate. This is what I mean as device position.
The measurements that are returned from the accelerometer are acceleration, not position.
I'm not sure what you mean with "big steps" but the peaks show a change of acceleration. The fact that the values are not 0 when holding the device still is from the fact that the gravitation accelerates the device with 9.81 m/s^2 (the magnitude of the acceleration vector).
You are potentially trying to do something quite difficult, especially the with low quality sensors that are embedded in phones. That is, getting the actual coordinate acceleration of the phone.
What you can do, is to detect the time periods when the phone was moved or touched. You can first calculate magnitude (norm) of acceleration signal and then, with a moving window, check areas where sample standard deviation is smaller than some threshold. Determining how the phone moved is more complicated issue. Of course you can check orientation for the stationary areas between movements.

CMDeviceMotion userAcceleration is upside down?

I'm seeing some unexpected readings from the userAcceleration field in CMDeviceMotion. When I look at the raw accelerometer data from CMAccelerometerData, I see that if the iPhone is flat on a table the reading is 1G straight down (1G in -Z axis) and if I drop the iphone (on a soft surface of course) then the acceleromtere reading goes to zero as expected. That's all fine. When I instead use the CMDeviceMotion class, the userAcceleration reading is zero as expected when the iPhone is flat on table. Again this is fine. But when I drop the iPhone and read the CMDeviceManager userAcceleration, the userAcceleration values are 1G straight up (+Z) not down (-Z) as expected. It appears that the userAcceleration readings are actually the exact opposite of what acceleration the device is really experiencing. Has anyone else observed this? Can I just invert (multiply by -1) all the userAcceleration values before I try to integrate for velocity and position, or am I misunerstanding what userAcceleration is reading?
There are some conceptual differences between CMAccelerometerData.acceleration and CMDeviceMotion.userAcceleration
Raw accelerometer data is just the sum of all accelerations measured i.e. a combination of gravity and current acceleration of the device.
Device motion data is the result of sensor fusion of all 3 sensors i.e. accelerometer, gyroscope and magnetometer. Thus bias and errors are eliminated (in theory) and the remaining acceleration data is separated into gravity and acceleration to be used conveniently.
So if you want to compare both you have to check CMAccelerometerData.acceleration against CMDeviceMotion.userAcceleration + CMDeviceMotion.gravity to compare like with like.
In general CMDeviceMotion is your first choice in most cases when you want precise values and hardware independency.
Another thing to consider is the CMAttitudeReferenceFrame you provide when starting Device Motion updates via startDeviceMotionUpdatesUsingReferenceFrame. I am not sure what is the default when using the basic version startDeviceMotionUpdates
You stated that you want to integrate the values to get velocity and position. There are several discussions about this and at the bottom line I can say it's impossible to get reasonable results. See:
Finding distance using accelerometer in iPhone
Getting displacement from accelerometer data with Core Motion
How can I find distance traveled with a gyroscope and accelerometer?
If your app concept forces you to rely on precise results for more than half a second, try to change it.
It turns out the CMAcceleration is not obey the right hand rule, which x is point to left, y is point to the screen bottom, in that case, with a typical right hand system, z axis should point to the upper side,but its not.
It makes me uncomfortable when dealing with motion sensors!

Is it possible to use core motion for distance measurement [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Getting displacement from accelerometer data with Core Motion
Android accelerometer accuracy (Inertial navigation)
I am trying to use core motion user acceleration values, and double integrating them to derive distance covered. I move my iPhone linearly along its Y axis, against a 30 cm log ruler, on the table. First, I let the device be at rest for 10 seconds, and I calculate my offsets along the three axes, by averaging the respective user acceleration values.
The X, Y and Z offsets are subtracted from the acceleration values, when I try calculating the distance covered. After offset subtraction, these values are passed through a low pass filter and a median filter, separately of course. The filters are linear filters, and the cut-off frequency is specified by the number of neighbouring values whose mean is taken in low pass, and median in the median filter. I have experimented with varying values of this number from 1 to 100. In the end, these filtered values are double integrated using trapezoidal rule to get distances. But, the distance calculated is no where close to 30 cm. The closest value I got was some -22 cm(I am wondering why I am getting negative values even though I move the device in positive Y direction). I also came across this:
http://ajnaware.wordpress.com/2008/09/05/accelerating-iphones/
its an old post about the same thing, which says that the accelerometer readings returned appeared to come in quanta of about 0.18m/s^2 (ie. about 0.018g), resulting in a large cumulative error very quickly. Going by that, for this error to really not matter, one will have to accelerate the device by almost 1.8m/s^2, which is practically impossible for distance/length measurement purposes. for small movements, it does not look like there is a possibility of calculating distances by using an optimal filter and a higher order numerical integration method, without an impractical velocity/acceleration constraint like that. Is it possible?
How about using my acceleration vs timestamp data to interpolate a polynomial that grows over time, as I get more and more motion updates, which represents approximately an acceleration vs time curve. Double integration of ths polynomial would be a piece of cake. But, for small distances, the polynomial will have a big error component. Using a predictable known motion that my device will be subjected to, I wish to take a huge number of snapshots (calculated distance vs actual known distance) to calculate my error polynomial in a similar way, and then subtract it from my first polynomial. Can this work?
Although this does not fit StackOverflow, because it's not a question but a discussion, I'll try to sum up my thoughts about it.
As already said, the accelerometer is very inaccurate and you would need very good accuracy for this kind of task, especially if you are trying to measure such short distances. Plus, accelerometers differ from device to device, you will get different results for the same movements with different device. Plus a very huge random error.
My guess is, that you can get rid of a huge part of randomness/error by calibrating the device and making the "measurement move" a couple of times, like 10 times. After that you have enough data to get an average that might get close to the real value.
Calibration is a key part here, you have to think of a clever way to calibrate, like letting the user move the device over different distances in different speeds.
But all this is just theory. I would really like to see your results, but I doubt you get it working good enough even using the best possible filters/algorithms, since there is just too much noise.

Resources