Calculating GForce when device is not completely level - ios

Using iOS Core Motion I am reading the GForce applied to a device, however if the device is not completely level then the readings are not as accurate.
Say I want the force applied on the Y axis but the phone is not 100% flat. Is there a calculation that can be done using the other axis to correct the figure account for the slight angle?

Related

Simulate fixed axis for iphone accelerometer

I'm making an app in which the user can move their devices left, right, up, and down in order to view an image. The way I'm doing this is by reading in the accelerometer data to calculate how far in each direction the user moved the device. The issue is that these readings are heavily influenced by the tilt of the device, because the axis change slightly with every tiny tilt. I know the gyroscope measures the rotational accelerations, so is there a way I could use those readings to take tilt out of the picture and fix the axis so they are the same at whatever angle the user holds the device? I realize this is a very eloborate problem, so if you don't understand something feel free to ask

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.

Is Apple's iPhone magnetometer calibration working properly?

I'm currently developing an iPhone App (on iPhone 5, iOS 7, Xcode 5) which requires a very accurate determination of the current attitude. The "attitude" of CMDeviceMotion does not fulfil these requirements because Apple's sensor fusion algorithm seems to rely too much on the gyroscope which drifts away rather fast (in my experience). That's why I decided to read out the bare sensor data and later I want to combine it within a sensor fusion algorithm by myself.
When asking for magnetometer data one has two possibilities:
via CMMagnetometerData in CMMotionManager
via CMCalibratedMagneticField in CMDeviceMotion about which Apple says
The CMCalibratedMagneticField returned by this property gives you the total magnetic field in the device’s vicinity without device bias. Unlike the magneticField property of the CMMagnetometer class, these values reflect the earth’s magnetic field plus surrounding fields, minus device bias.
In principle (2.) is exactly what I want.
There is a very simple test if magnetometer data is calibrated properly. For simplicity one can restrict oneself to two dimensions. When the device lies on it's back, the combination B_x^2 + B_y^2 must be constant, independent of the direction the device is pointing to. It must just equal the horizontal component of the Earth's magnetic field (assuming no other fields in the vicinity of the device). Thus, when performing a 360 degrees turn of the device which lies on it's back, the measured data B_y over B_x should display a circle. See here for details.
Now the point: the data of CMCalibratedMagneticField does NOT result in a circle!
Does anyone have an explanation for that? Or does anyone know, how the CMCalibratedMagneticField comes about? Is the magnetometer calibrated in the sense of the link from above when performing the "eight-shaped" movement of the device or what is the movement good for?
Btw. why the "eight-shaped" movement and not flipping the device around it's three axis, which would allow a calibration as described in the link from above?
I would be very glad for any clarification with this issue... Thanks!
There is a problem with the magnetometer in iOS 7, it has an error of +-7º. Try using the 7.1 beta version.
EDIT
The magnetometer has zero-drift over time, but is pretty inaccurate for sudden changes in position. The accelerometer and gyroscope on the other hand adjust quickly for sudden changes but, being inertial sensors, they lose accuracy over a period of time.
So when CMCalibratedMagneticField tries compensate for your rotational motion it uses data from the gyroscope and accelerometer. This is when the accelerometer and gyroscope's +-7º error creeps in and throws your circle off track. Check this answer and this wikipedia article for more info.
As regards to the figure of eight:
Both do the same thing, they orient the "North" of your device in each direction in hope of cancelling out magnetic interference. Flipping your device along all three axes will work better but it is harder to perform and not as easily understood by the user.
Hope this helps.

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!

CoreMotion attitude affected by linear motion

I'm developing an app that has to use very small changes in gyroscope data.
The problem is that while keeping the device flat on the table and accelerating it horizontally, CoreMotion seems to also perceive that linear acceleration as angular acceleration.
The pitch and roll values, coming directly from deviceMotion, change with a maximum amount of 3 degrees and come back to the default value while decelerating.
I would have expected only one angle (yaw) to change since you can rotate the device that way while keeping it horizontal.
It does not matter which reference attitude I use.
The same issue seems to affect the quaternion of deviceMotion.attitude. At first I thought this was an effect of the sensor fusion algorithm used in CoreMotion, but rotationRate coming from CMGyroData (which should be raw data) changes aswel.
Has anyone noticed this problem before?

Resources