What is the working mechanism of SENSOR_TYPE_GRAVI

2019-07-07 09:09发布

I have a 3-D acceleration vector (a, b, c) obtained from an Android phone accelerometer.

I wish to calculate the angle between this vector (a, b, c) and the gravity vector, which points exactly downwards.

I notice that in Android, there is a way of getting gravity vector under the context of the phone coordinate system instead of the world coordinate system. By simply use sensor type SENSOR_TYPE_GRAVITY, I can get the 3-D gravity vector (d, e, f). Since both vectors are under the same coordinate system, the phone coordinate system. By simple vector inner product, their angle can be easily found.

After finding this angle, even if we move from the phone coordinate system to the real world coordinate system, the angle remains unchanged.

My question:

What is the working mechanism behind the SENSOR_TYPE_GRAVITY?

I don't think there is another hardware that measures the gravity. Thus, it is just the acclerometer who measures the gravity. How is the gravity extracted our of the resultant accleration?

I am asking because I am concerned with the accuracy of this way of getting the gravity.

If it is inaccurate, I can implement a LPF to filter the DC component, the gravity, out by myself. I am not sure whether getting it from SENSOR_TYPE_GRAVITY is more accurate than I do it myself.

================================== UPDATES =======================================

Just to clarify, can I get the BOTH acceleration and gravity data correctly with the following codes?

By correctly, I mean do the acceleration and the gravity belong to one same particular time instant? I need to use the values at ONE time instant. So the situation where the acceleration is for time=13:12:00 and the gravity is for a later time, say time=13:12:01 is NOT desired.

public void onSensorChanged(SensorEvent event) { 

    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { 
        acceleration[0] = event.values[0];
        acceleration[1] = event.values[1];
        acceleration[2] = event.values[2];
    }

    if (event.sensor.getType() == Sensor.TYPE_GRAVITY) {
        gravity[0] = event.values[0];
        gravity[1] = event.values[1];
        gravity[2] = event.values[2];
    }

}

1条回答
Fickle 薄情
2楼-- · 2019-07-07 09:35

The three sensors Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_GRAVITY and Sensor.TYPE_LINEAR_ACCELERATION are related by the equation

"Sensor.TYPE_ACCELEROMETER" =  "Sensor.TYPE_GRAVITY" + "Sensor.TYPE_LINEAR_ACCELERATION"

If you register for updates for all three, what you find is that Sensor.TYPE_ACCELEROMETER always arrives first, followed by Sensor.TYPE_GRAVITY and Sensor.TYPE_LINEAR_ACCELERATION, and that the values always satisfy that equation. Internally, Android is using filtering, and in particular a Kalman filter, to separate the two.

A low pass filter is a simple way of doing something similar. However, a lot of thought will have gone into the Android mechanism, so I'm sure that if a low pass filter was better, then Android would have implemented that.

查看更多
登录 后发表回答