测量非固定 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
}
现在,我并不是说这是最好的解决方案,但它应该可以满足您的需求。
免责声明
将使用传感器融合(包括磁力计)的设备绑在金属框架上可能会产生不一致的结果。由于您的罗盘航向在这里无关紧要,我建议使用不涉及磁力计的传感器融合方法。
我的目标是制作一个 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
}
现在,我并不是说这是最好的解决方案,但它应该可以满足您的需求。
免责声明
将使用传感器融合(包括磁力计)的设备绑在金属框架上可能会产生不一致的结果。由于您的罗盘航向在这里无关紧要,我建议使用不涉及磁力计的传感器融合方法。