测量非固定 Android 设备的垂直运动

Measuring vertical movement of non-fixed Android device

我的目标是制作一个 Android 移动应用程序 (SDK16+),在骑自行车时测量道路质量。

我找到了一个 Sensor fusion demo for Android,我认为它可以为我完成所有测量。

当phone没有固定在某个方向时,如何只得到垂直移动?

问题

这里的问题是你有两个坐标系,你设备的 dx、dy、dz 和你周围世界的 wX、wY、wZ。当您四处移动设备时,两者之间的关系会发生变化。

提出问题的另一种方法是:

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

一个解决方案

幸运的是,方向传感器(例如 Android 自己的 ROTATION_VECTOR 传感器)提供了在这两个坐标系之间进行转换的工具。

例如,ROTATION_VECTOR传感器的输出形式为 axis-angle representation of the rotation your device has from some certain "base" rotation fixed in the world frame (see also: Quaternions)。

Android 提供了方法 SensorManager#getRotationMatrixFromVector(float[] R, float[] rotationVector),它从您的传感器获取轴角表示并将其转换为 rotation matrix。旋转矩阵用于将一个参考系中给定的矢量转换为另一个参考系(在本例中为 [World -> Device])。

现在,您想将设备坐标系中的测量值转换到世界坐标系中吗?没问题。旋转矩阵的一个漂亮特征是旋转矩阵的逆是相反变换的旋转矩阵(在我们的例子中是 [Device -> World])。另一个更有趣的事情是旋转矩阵的逆就是它的转置。

因此,您的代码可以遵循以下行:

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
}

现在,我并不是说这是最好的解决方案,但它应该可以满足您的需求。

免责声明

将使用传感器融合(包括磁力计)的设备绑在金属框架上可能会产生不一致的结果。由于您的罗盘航向在这里无关紧要,我建议使用不涉及磁力计的传感器融合方法。