Measuring vertical movement of non-fixed Android device

会有一股神秘感。 提交于 2019-12-11 13:57:10

问题


My goal is to make an Android mobile app (SDK16+) that measures road quality while riding a bike.

I have found a Sensor fusion demo for Android that I assume will do all the measurements for me.

How can I get only the vertical movement when the phone is not fixed in a certain orientation?


回答1:


The problem

The problem here is that you have two systems of coordinates, the dx, dy, dz, of your device and the wX, wY, wZ of the world around you. The relationship between the two changes as you move your device around.

Another way to formulate your question would be to say:

Given a sensor reading [dx, dy, dz], how do I find the component of the reading which is parallel to wZ?

A solution

Luckily, the orientation sensors (such as Android's own ROTATION_VECTOR sensor) provide the tools for transformation between these two coordinate systems.

For example, the output of the ROTATION_VECTORsensor comes in the form of an axis-angle representation of the rotation your device has from some certain "base" rotation fixed in the world frame (see also: Quaternions).

Android the provides the method SensorManager#getRotationMatrixFromVector(float[] R, float[] rotationVector), which takes axis-angle representation from your sensor and translates it into a rotation matrix. A rotation matrix is used to transform a vector given in one frame of reference to another (in this case [ World -> Device ]).

Now, you want to transform a measurement in the device frame into the world frame? No problem. One nifty characteristic of rotation matrices is that the inverse of the rotation matrix is the rotation matrix of the opposite transformation ([Device -> World] in our case). Another, even niftier thing is that the inverse of a rotation matrix simply is it's transpose.

So, your code could follow the lines of:

public void findVerticalComponentOfSensorValue() {
    float[] rotationVectorOutput = ... // Get latest value from ROTATION_VECTOR sensor
    float[] accelerometerValue = ... // Get latest value from ACCELEROMETER sensor

    float[] rotationMatrix = new float[9]; // Both 9 and 16 works, depending on what you're doing with it
    SensorManager.getRotationMatrixFromVector(rotationMatrix, rotationVectorOutput);

    float[] accelerationInWorldFrame = matrixMult(
            matrixTranspose(rotationMatrix), 
            accelerometerValue); 
    // Make your own methods for the matrix operations or find an existing library

    accelerationInWorldFrame[2] // This is your vertical acceleration
}

Now, I'm not saying this is the best possible solution, but it should do what you're after.

Disclaimer

Strapping a device that uses sensor fusion including a magnetometer to a metal frame may produce inconsistent results. Since your compass heading doesn't matter here, I'd suggest using a sensor fusion method that doesn't involve the magnetometer.



来源:https://stackoverflow.com/questions/31268852/measuring-vertical-movement-of-non-fixed-android-device

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!