42

I am developing application for car acceleration tracking. I used standard accelerometer, calibrating it in specific position beforehand.

Then, assuming phone's orientation is not changing, I logged the accelerometer data for a specified time and calculated move parameters, one of which is the car's speed at the end of the test.

It works rather well, on a straight, horizontal road: error of a few percent.

But then I found out, that in API-level 10 there is a virtual sensor called TYPE_LINEAR_ACCELERATION and, as far as I understand, it must do what I need: filter gravity, orientation changes - so I may use it and get pure linear acceleration of mobile device.

BUT in real life..

I made a simple application, that does a little test:

//public class Accelerometer implements SensorEventListener { ...
public void onSensorChanged(SensorEvent se) 
{
    if(!active)
        return;

    lastX = se.values[SensorManager.DATA_X];
    lastY = se.values[SensorManager.DATA_Y];
    lastZ = se.values[SensorManager.DATA_Z];
    long now = System.currentTimeMillis();
    interval = now - lastEvetn;
    lastEvetn = now;
    out.write(Float.toString(lastX) + ";" + 
                    Float.toString(lastY) + ";" + 
                    Float.toString(lastZ) + ";" + 
                    Long.toString(interval) + "\n");
}

I bind a listener with the following parameters:

  mSensorManager.registerListener(linAcc,
                mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION),
                SensorManager.SENSOR_DELAY_GAME);

It works OK, but when I analyzed data dump, calculating speed like V = V0 + AT, where V0 = 0 at first, then - speed of interval before this, A = acceleration (SQRT (x*x+y*y+z*z)) (t = time of interval), eventually I get a very low speed - three times less than real speed.

Changing Sensor type to TYPE_ACCELEROMETER, calibrating and using same formula to calculate speed - I get good results, much closer to reality.

So, the question is:

What does Sensor.TYPE_LINEAR_ACCELERATION really show?

Where am I wrong, or is something wrong with Sensor.TYPE_LINEAR_ACCELERATION implementation?

I used Samsung Nexus S phone.

MasterAM
  • 16,283
  • 6
  • 45
  • 66
Maep
  • 833
  • 1
  • 10
  • 16
  • Very interesting! The Sensor.TYPE_LINEAR_ACCELERATION does exactly what you write. Why do you compute the length of the acceleration (SQRT (x*x+y*y+z*z)? How well did you test your previous method? Just a few measurements? What I find really interesting is that your previous method produces fairly precise results. These sensors can track velocity for less than a second, that is why I am surprised. Even though it is for position, the velocity isn't any better, see [link](http://stackoverflow.com/questions/7829097/android-accelerometer-accuracy-inertial-navigation/7835988#7835988). – Ali Oct 22 '11 at 17:56
  • Hi. If sensor shows acceleration in x,y,z directions, then value of A is SQRT(x*x+y*y+z*z). If sensor shows something other - that is the question. what it shows? – Maep Oct 23 '11 at 01:35
  • If sensor shows something other - that is the question. what it shows? My previous method was tested many times, with different speeds. In car, where position of phone is well fixed - it works rather accurate, it NEVER give mistake more then 10%. It's a result, i think. That why i dont't understand - why linear accelerometer behaves so strange... If you are interested in, i can send you source code of working method. – Maep Oct 23 '11 at 01:42
  • 1
    You understood linear acceleration correctly, it is exactly what you wrote. I still do not understand why you need SQRT(x*x+y*y+z*z). Please check [my code](http://szte-wsn.svn.sourceforge.net/viewvc/szte-wsn/private/ali/periodic/Model.hpp?revision=2596&view=markup), from lines 134 and 148, `v0` is initial velocity, `v` is velocity. The **length** of the acceleration is never needed when you compute velocity, so please post your code showing why you use it. – Ali Oct 23 '11 at 07:28
  • thanx for your code. "length" of acceleration is value of acceleration itself. so, computing velocity without being interested in it's direction - requires value of acceleration. If i have acceleration vector (1,5,4), v0 = 0, time = 1 second, v = 0+6.48 = 6.48 m/s. Vx = 1m/s, Vy=5 m/s, Vz = 4 m/s, but |v| = 6,48 m/s – Maep Oct 23 '11 at 15:51
  • here is a part of code, it cannon be very useful private void calc(){ //averagePoint - average acceleration of experiment acceleration = this.x*averagePoint.getX() + this.y*averagePoint.getY() + this.z*averagePoint.getZ(); acceleration = acceleration / ((float)Math.sqrt(averagePoint.getForce())); float t = ((float)interval / 1000f); speedAfter = speedBefore + acceleration * t; distance = speedBefore*t + acceleration*t*t/2; } – Maep Oct 23 '11 at 15:52
  • SORRY i don't understand yet, how to mark code in comment:( – Maep Oct 23 '11 at 15:55
  • Here is my code, that works with TYPE_ACCELEROMETER sensor http://maephv.blogspot.com/2011/10/android-computing-speed-and-distance.html – Maep Oct 24 '11 at 03:48
  • You need the acceleration **vector** in the computation and not its length. Imagine the following: the car is accelerating with 1m/s^2 for 1s, then with -1m/s^2 for 1s (deceleration). The change in velocity is zero, however if you use the length of the acceleration then you compute something else. In other words: if you use just the length then you cannot distinguish acceleration from deceleration, for example. I had a quick look at your code but I failed to understand what's going on. – Ali Oct 25 '11 at 21:20
  • Ali, in my program i compute projection of vector at average vector, and it's signed. So, in that case, it will work correct. Anyway, i tested linear_accelerometer with straight, constant-accelerated moving - no result. My code with type_accelerometer works fine – Maep Oct 26 '11 at 01:51
  • 1
    OK, my mistake, I did not understand that part, sorry. – Ali Oct 26 '11 at 07:16
  • Thanx anyway..let's wait new Android, maybe they fix it:) – Maep Oct 30 '11 at 07:26
  • Here's what I've noticed trying to use TYPE_LINEAR_ACCELERATION. When I rotate the device around one axis, the acceleration component that's most affected by the rotation doesn't seem to correctly distinguish between acceleration and deceleration. For example, I will see the X component of the acceleration start around zero, increase to 2 or 3, then decrease back to zero when I stop the rotation. I would expect the X component to increase, peak, decrease back through zero and go negative, peak in the negative direction, and finally return back to zero when I stop the rotation. – Neal Stublen Dec 02 '11 at 16:05
  • Sorry @Maep I didn't get your explanation of differentiating acceleration from deceleration. "in my program i compute projection of vector at average vector, and it's signed". Can you elaborate on it more please – Nazerke Mar 26 '13 at 20:20
  • @Maep can u pls share mathemathical code to calculate distance using accelerometer ??? – Erum Oct 17 '14 at 05:57

6 Answers6

23

Very interesting question!!!!

I'm developing somethig similar to your application. What i found about TYPE_LINEAR_ACCELERATION isn't happy for me.

1) TYPE_LINEAR_ACCELERATION, TYPE_GRAVITY, ecc are implemented only for Android 2.3 (and up) So i have Android 2.2 and i can't test them.

2) TYPE_LINEAR_ACCELERATION isn't so accurate as it would be, because there are some simple problem when substract the gravity. In fact is a "sensor fusion" that uses accelerometer and orientation to know where is directed the gravity and then subs. it.

Here i found a very usefull answer that explain it:

https://groups.google.com/forum/#!topic/android-developers/GOm9yhTFZaM

TYPE_ACCELEROMETER uses the accelerometer and only the accelerometer. It returns raw accelerometer events, with minimal or no processing at all.

TYPE_GYROSCOPE (if present) uses the gyroscope and only the gyroscope. Like above, it returns raw events (angular speed un rad/s) with no processing at all (no offset / scale compensation).

TYPE_ORIENTATION is deprecated. It returns the orientation as yaw/ pitch/roll in degres. It's not very well defined and can only be relied upon when the device has no "roll". This sensor uses a combination of the accelerometer and the magnetometer. Marginally better results can be obtained using SensorManager's helpers. This sensor is heavily "processed".

TYPE_LINEAR_ACCELERATION, TYPE_GRAVITY, TYPE_ROTATION_VECTOR are "fused" sensors which return respectively the linear acceleration, gravity and rotation vector (a quaternion). It is not defined how these are implemented. On some devices they are implemented in h/w, on some devices they use the accelerometer + the magnetometer, on some other devices they use the gyro.

On Nexus S and Xoom, the gyroscope is currently NOT used. They behave as if there was no gyro available, like on Nexus One or Droid. We are planing to improve this situation in a future release.

Currently, the only way to take advantage of the gyro is to use TYPE_GYROSCOPE and integrate the output by hand.

I hope this helps,

Mathias

Anyway, in various place on the web i found no best word about phone sensor and their potential, due to the fact that aren't accurate...

Some more precision can be reached using Kalman filter, but i have no idea how...

Lal
  • 14,726
  • 4
  • 45
  • 70
Lork
  • 889
  • 3
  • 12
  • 24
  • i have android 2.3.4, but linear acceleration does not work. anyway, accelerometer makes pretty good results. I compare it with GPS, and i can say - for short-time data requesting, accelerometer is better: GPS has lags and is not refreshed frequently. Look at my graph here: blue is accelerometer data, red - GPS, black label - car speed at the end of experiment checked by speedometer. I continue working on that method to improve accuracy http://img84.imageshack.us/img84/6991/accpn.png – Maep Nov 21 '11 at 13:55
  • @Maep : you seem to get good result from accelerometer. Could you please help me out here - http://stackoverflow.com/questions/12926459/calculating-distance-using-linear-acceleration-android – Ashwin Oct 17 '12 at 03:47
  • Helpful, but not usable with NDK. In the NDK there does not seem to be a GRAVITY type. There is ASENSOR_TYPE_ACCELEROMETER but no ASENSOR_TYPE_GRAVITY. Some sources warn against getting it in JAVA and lobbing it to C via JNI, as it eats far too much battery. – Bram Jul 16 '14 at 02:13
  • @Lork do you know how to detect the moviment of TOP to Bottom? I mean like smash your device? – Skizo-ozᴉʞS ツ Jan 25 '16 at 15:21
5

TYPE_LINEAR_ACCELERATION doesn't show the "raw" data from the sensor, it shows data that was processed by hi-frequency filter, so the constant acceleration like gravity or any other slowly changing acceleration cannot pass through the filter.

Your car has pretty constant acceleration that cannot pass the filter. If you change your acceleration very fast pressing the brakes then pressing the accelerometer pedal then back to the brakes then TYPE_LINEAR_ACCELERATION would show the pretty correct result, otherwise it always shows less then the real acceleration value.

Use TYPE_ACCELEROMETER and then remove G (9.81) manually. Actually, you have to measure G yourself when the real acceleration is 0 and then use TYPE_ACCELEROMETER value as G. In my case it is 9.6.

TYPE_ACCELEROMETER is good for the fast changing acceleration that lasts less then 1 second like moving you hand emulating a box or sword fighting.

Dmitry
  • 51
  • 1
  • 1
5

I realize my answer is pretty late. I bumped into this thread while hunting for some info on TYPE_LINEAR_ACCELERATION.

It is not right to do a = sqrt(ax^2+ay^2+az^2) and then do v=u+at. That will work only when v and a are in the exact same direction. And any deviation would make the errors add up. Acceleration and velocity are vector quantities, and should be treated as such. You should do vx=ux+axt, vy=uy+ayt and vz=uz+azt. and then v= sqrt(vx^2+vy^2+vz^2).

sudP
  • 171
  • 3
  • 11
  • what ux, axt, uy, ayt, uz, azt, vx,vy and vz variables are? what represent every one? – angel Aug 16 '16 at 18:54
  • ux is x component of initial velocity. ax is x component of acceleration. vx is x component of final velocity, And so on – sudP Aug 17 '16 at 01:17
2

TYPE_LINEAR_ACCELERATION is a three dimensional vector indicating acceleration along each device axis, not including gravity. TYPE_ACCELEROMETER = TYPE_GRAVITY + TYPE_LINEAR_ACCELERATION

Evgeny Karpov
  • 2,386
  • 26
  • 16
1

As @thxmxx says, the TYPE_LINEAR_ACCELERATION vector is given in the device coordinate frame. Therefore, to estimate velocity in the inertial (world) coordinate frame, you need to rotate by the estimated device orientation before integrating.

However, even if you do that, it's unlikely that the estimated velocity will be accurate for long. Suppose your acceleration estimate is consistently off by 0.1 m/s^2 in the device x-axis. This is around 1/100 the acceleration of gravity - it's a small error relative to the magnitude of accelerations the device is meant to measure. Then, after sitting still for ten seconds, your velocity estimate will be 1 m/s in the device x-axis.

Even small errors add up to form big ones. If you further integrate your velocity estimate to form a position estimate, errors will compound even faster.

To get a reliable velocity estimate, you need either:

  • A sensor that measures speed, like a pitot/static system on an aircraft or a wheel odometer on a car.
  • A sensor that measures position, like GPS, LIDAR, or vision-based SLAM, and a sensor fusion algorithm that uses the sequence of position estimates over time to correct drift in the velocity estimate.
  • An extremely accurate IMU like the type used in missiles.

The second option is the most useful for phone-based applications.

japreiss
  • 11,111
  • 2
  • 40
  • 77
0

You should multiply your absolute vector you get from TYPE_LINEAR_ACCELERATION by the inverted matrix from TYPE_ROTATION_VECTOR.

thxmxx
  • 447
  • 4
  • 9