Reading here: Android Sensors - Which of them get direct input? ,
I am wondering if anyone has experience or a technically detailed link about the accuracy of the linear acceleration versus just manual processing of the acceleration raw data. E.g., do the new phones have dedicated hardware chips for filtering out gravity, or are most devices just going to filter the same raw source?
Update, proposed answer for someone to confirm if they have such a device (Xoom,Nexus S,?):
"If the device has gyro, or possibly multiple accelerometers, then the returned values for gravity (G) versus external linear acceleration (L) can be fundamentally more accurate than any processing on accelerometer data alone. Without extra sensors, e.g. as on most phones, one could in principle post-process the Acceleration (A) to attempt separation as accurately as what the device is returning for A = G+L"
It seems, the gravity/lin. acceleration can be calculated by a low-pass-filter - just as described in the Android-Documentation.
However only filtering the last value will not do it. I get acceptable results by averaging the accelerometer values of ca. 200ms (for moderate movement, this will still screw up, e.g. when you flip your phone fast between your fingers).
Your proposed answer is most likely correct.
You can check the statistics of several smartphone models on Android fragmentation.
For many models the power consumption of the lin. acceleration and gravity sensor is just the sum of accelerometer, gyroscope and magnetometer.
The gyroscope lets you recognize fast angular movement and it can be used to improve the gravity value, which is not possible with just the low-pass-filter. For the magnetometer im not sure if it really gets you more information.
On my phone (HTC One S) the gravity sensor uses just as much power as the accelerometer, but is still better than my simple filter. So either it is another hardware sensor or probably they use different weights on it. I tried to weight acc-data stronger, if their absolute value is closer to gravity, which is nice but was still not as good as the actual gravity sensor.
For compatibility reasons I would suggest to use a low-pass-filter for gravity if possible, as still not every smartphone has a gyroscope or mentioned sensors.
Related
I want to get as accurate data from the built in accelerometer in an Android phone as possible. I want to track two dimensional movement in x and y axis and even the small movements must be registered.
When I look at the data from the accelerometer / linear acceleration when the phone is flat on a table it changes a lot when i should be zero.
I have looked at Kalman filters, it seems like a good approach but I am having problems setting up a model.
1. Is a Kalman filter the way to go to get as accurate data as possible from an accelerometer?
2. Will a Kalman filter work? Maybe i have misunderstood but it seems like the acceleration or the velocity must be constant?
3. How do I set up the model for using Kalman filter? I'm having trouble understanding (among other things) what the process noise is?
A Kalman filter applies when all measurements (of acceleration in this case) are equal to the true value plus a measurement error. The measurement error is the process noise. For for the original Kalman filter to apply the noise must be normally distributed, i.e. sometimes the error will be positive, sometimes negative, and on average zero.
If you jerk your android phone quickly back and forth, there'll be large accelerations. I'd suggest recording the accelerometer readings in that kind of action, and reviewing by eye to see whether it looks like there's the readings are indeed subject to some kind of normally distributed process noise. My guess is that the answer will be "No", i.e. I expect they readings when plotted on a graph will be smooth-ish. But if they're not smooth, a Kalman filter could be useful.
If you're trying to use accelerometer readings to work out location, I think your project is doomed to failure. Acceleration is the 2nd derivative of position with respect to time, and I've never heard of anyone being able to integrate the readings with sufficient accuracy to be at all useful.
I have applied a Kalman filter successfully to GPS readings on an Android phone to improve the location estimate. See Smooth GPS data for code that implements a Kalman filter for that. I subsequently wondered whether velocity and perhaps acceleration data could be used to improve the location estimate. Although I never followed up on that idea, see https://dsp.stackexchange.com/questions/8860/more-on-kalman-filter-for-position-and-velocity for the maths that I was considering using.
The optimal way of using all the sensor inputs (GPS, accelerometer, gyroscope, etc) to get a good estimate of location is a very hard (and interesting) problem. To find out more, the key phrase to search for is "Sensor fusion". On this subject, there's an old youtube video at http://www.youtube.com/watch?v=C7JQ7Rpwn2k .
You might find this thread useful. I came across the same issues
We think the variance when lying flat might be an issue with Gimbal lock confusing the calculations but thats just a theory right now. We've also noticed the covariance in each axis alters depending on the orientation of the device, which might be gimbal lock interference too, but again just a theory
Implement a Kalman filter to smooth data from deviceOrientation API
Does gravity sensor return right values if device is in motion? I thought that gravity sensor use accelerometer to recognize gravitation direction. Are these two sensors different piece of hardware?
The Gravity sensor is what Android calls a 'software sensor' and calculates its values using more than one hardware sensor.
The software Gravity sensor is only available if the device has a gyroscope.
By combining accelerometer data with gyroscope data, the acceleration due to moving the device can be filtered out to leave the pure gravity signal. So yes, it will return the right value under motion.
Thus, the Gravity sensor gives a much better signal for device orientation than just the accelerometer on its own.
Combining sensor values is called sensor fusion and important for high quality measurement values.
The Android Documentation describes the Gravity Sensor.
Unfortunately, many Android devices lack a Gyroscope, and thus, will have no Gravity sensor either. This leaves you with a sub optimal signal from just the accelerometer alone, giving a lower quality user experience compared to Android devices with both sensors, and lower quality experience compared to iOS devices.
You can block installations on incompatible devices by using a Google Play requirement specification as follows:
<uses-feature android:name="android.hardware.sensor.gyroscope" />
Albert Einstein answered this question in 1911
A little reflection will show that the law of the equality of the inertial and gravitational mass is equivalent to the assertion that the acceleration imparted to a body by a gravitational field is independent of the nature of the body. For Newton's equation of motion in a gravitational field, written out in full, it is:
(Inertial mass) \cdot (Acceleration) = (Intensity of the gravitational field) \cdot (Gravitational mass).
It is only when there is numerical equality between the inertial and gravitational mass that the acceleration is independent of the nature of the body.
— Albert Einstein
We cannot differentiate the measurement of acceleration from the measurement of gravity since they are equivalent to the observer. Even if the Android had two sensors they would both be measuring the same thing.
I've been trying to find up (or down, which wouldn't be much harder to find, just multiply up by -1) on android with no good solution. I need a vector pointing up in the same coordinates system than the one used by the accelerometer. This way, I will be able to:
remove the force added by gravity to the output of the accelerometer
determinate if the device has shaken in a vertical direction or not.
Gravity Sensor:
First, I thought of using the gravity sensor, which would've been the simplest solution. But! my device did not have a gravity sensor...
Magnetic Field Sensor: So, I thought of using the magnetic field sensor to find two vectors pointing north at two different positions but with the same orientation, after what I calculated the cross product of both the vectors to try and find a vector pointing up or down. It didn't work (or it seemed like it didn't).
Magnetic Field with Accelerometer: Then, I thought of doing the cross product but, this time, with a vector provided by the magnetic field sensor and one provided by accelerometer. I couldn't find how to, because the accelerometer points a bit downward when the user is accelerating, because of the gravitational pull.
So, I came to the conclusion that I would need to use the orientation sensor to do so, or only to rely on a low-pass filter....
Put simply, how do I determinate what is the vector pointing up in the coordinates system used by the accelerometer if I have these sensors:
orientation
accelerometer
magnetic field
Unfortunately your problem isn't particularly simple. I'm not familiar enough with the Android API and perhaps if you look around you'll find something which attempts to isolate the gravity acceleration from the external device acceleration (I know there are sensor fusion algorithms that do this with some degree of success).
The core of the problem is that the acceleration due to gravity and the local acceleration on the device are indistinguishable (there is no such thing a a gravity sensor). An accelerometer simply records the total acceleration acting on the device, which is the sum of ALL accelerations. It is not trivial to isolate the gravity vector, but the methods I have seen mainly involve using the gyroscope as the magnetometer is simply too inaccurate and contains too much latency.
Instead I suggest that you either assume that the local forces on the device are negligible and therefore your acceleration IS the gravity vector. Or alternatively as you mentioned, use a low pass filter which for most purposes will suffice (and is a common way of defining DOWN for the purposes of sensor fusion and augmented reality).
All the best!
The magnetic field is not horizontal, which is why your solutions with the magnetometer didn't work. This is called the magnetic dip. Generally speaking if you want to determine the up/down vector you should not rely on the magnetic field because other solutions are easier to implement and more precise.
The two main solutions to find the up/down vector are:
Low-pass on the accelerometer. This may not be precise enough for your purposes.
Sensor fusion on the gyroscope and accelerometer. This will be precise enough, but requires a good head for math to implement (i.e.: matrices or quaternions)
Good luck!
I am trying to determine the benefit of making use of Android's Linear Acceleration data as opposed to simply applying a low pass filter as presented in Androids API reference and discussed in this other stackoverflow question.
I am asking as I am trying to get hold of a free app that records Linear Acceleration (as well as fullfils my other requirements (sampling rate, writing data to file etc...)). I haven't been able to find one, so I have considered just using an app that records using the standard accelerometer and then I'll simply apply the low pass filter to the data. Alternatively I could just write my own app to do what I need - but I don't have much experience in Android dev and this will take some time.
I have explored this subject at some length and I may be able to help point you in the right direction.
As others have mentioned, only some phones have implemented TYPE_LINEAR_ACCELERATION and TYPE_GRAVITY and they usually are equipped with a gyroscope. A Droid Razr even has a gyroscope, but they never bothered to implement it or TYPE_LINEAR_ACCELERATION. I believe the GS2 has TYPE_LINEAR_ACCELERATION implemented, but no gyroscope so they must have used the magnetic sensor or some sort of low-pass filter. It can be frustrating.
On most phones with a gyroscope there is some sort of fusion between the acceleration sensor and gyroscope (probably a complementary filter to compensate for drift and then quaternions or cardan angles to isolate gravity). These fusions and filters can be implemented differently and use different hardware, etc... Latency and accuracy are going to vary among devices, so TYPE_LINEAR_ACCELERATION isn't always going to produce the same results.
If you do not have a phone with TYPE_LINEAR_ACCELERATION, you are stuck with TYPE_ACCELERATION, which cannot separate gravity (tilt) from linear acceleration.
One option is to apply the low-pass filter. This may or may not work depending on your application. I have written a free application to help developers and other interested parties explore the low-pass filter option.
Another option is to just measure the tilt of the device when it is static and then apply that gravity measurement while the device is not static. If the device isn't changing the orientation often, this can be an excellent option because it is really fast and simple.
An excellent alternative sensor fusion option is to use the magnetic sensor instead of a gyroscope. This option will work on almost all devices assuming the magnetic field isn't under the effects of hard or soft iron distortions.
I have implemented all of these approaches in the open source project Acceleration Explorer
I am needing to implement a shake recognizer, and I am using the accelerometer on the device to that. However, when I check the values I get from the sensor, it appears that they vary wildly from device to device. For instance, I get a value range of 0-8 as force (after some calculations) on one device, and on the other 0 - 4.
So it looks like they have very different ranges.
Is there anything I can do to make these ranges equal. Or are there some variables that I can use to somehow calculate what a fairly hard shake would be?
According to specification accelerometer should return Measures the acceleration force in m/s2. So it should be calibrated. One thing you could check however is the Sensor class's getMaximumRange() and getResolution()
The physical placement of the chip on the pcb and the securing of the pcb within the device and the construction of the device could all lead to different damping effects in responce to your shaking input force.
You don't say how your processing the sensor data there may well be effects related to sampleing and filtering performed at the driver level.
You clearly need to be flexible in your code with the range of values you expect and test on a good range of devices.
The sensor should be calibrated.
Apparently it isn't. If the gain in the different directions (that is x, y, z) is not significantly different then it is enough to look for sudden changes in the length^2 of the accelerometer vector: x^2+y^2+z^2.
If the gains are also significantly different then you have no choice but to write an app for accelerometer calibration...
By the way, you are not the first one to report gross inaccuracies, see for example Android: the range of z-value in the accelerometer sensor are different on different devices.