需要从Sensor.TYPE_ORIENTATION数据计算旋转向量

8
我需要从Sensor.TYPE_ORIENTATION的数据中计算出旋转向量。
传感器数据定义如下:
- 值必须重新计算以成为正确的3D位置:值[0]:方位角,磁北方向与Y轴之间的角度,绕Z轴旋转(0到359)。 0 = 北,90 = 东,180 = 南,270 = 西 - values1:俯仰,绕X轴旋转(-180到180),当z轴朝向y轴移动时,正值为正。 - 值[2]:滚动,绕Y轴旋转(-90到90),当x轴远离z轴时,正值为正。
我需要所有三个值,例如Z轴值(从0到360度)。 我尝试了很多但无法弄清楚如何做到这一点 :/
(编辑:要查看工作代码中的想法,请查看DroidAR框架的ActionWithSensorProcessing类,您可以在那里看到如何处理不同的事件类型。)
我也尝试使用Sensor.TYPE_ACCELEROMETER和Sensor.TYPE_MAGNETIC_FIELD来自行计算这个3D向量。以下是代码:
final float[] inR = new float[16];
// load inR matrix from current sensor data:
SensorManager.getRotationMatrix(inR, null, gravityValues, geomagneticValues);
float[] orientation = new float[3];
SensorManager.getOrientation(inR, orientation);
mapMagAndAcclDataToVector(orientation); //here i do some *360 stuff
orientetionChanged(orientation); //then the correct values are passed (in theorie)

但是这并没有起作用,我认为这太复杂了。 所以我打赌有一个简单的解决方案来重新计算ensor.TYPE_ORIENTATION的值,使它们成为一个3D旋转向量,但我不知道如何做。如果你知道答案,请告诉我。 编辑: 我应该补充说,我想将这些值传递给OpenGL,以使其与轴对齐,就像这样:
gl.glRotatef(values[1], 1, 0, 0);
gl.glRotatef(values[2], 0, 1, 0);
gl.glRotatef(values[0], 0, 0, 1);

但由于奇怪的值范围,我显然不能这样做。同样的问题也存在于SensorManager.getOrientation获得的值中,因为当你越过地平线时,它们也会翻转。
另一种解决方案是使用inR矩阵计算角度,但我认为必须有更简单的解决方案(?)
2个回答

12

这应该可以工作(使用Sensor.TYPE_MAGNETIC_FIELD和Sensor.TYPE_ACCELEROMETER输入)

switch (event.sensor.getType()) {
    case Sensor.TYPE_MAGNETIC_FIELD:
        magnitude_values = event.values.clone();
        sensorReady = true;
        break;
    case Sensor.TYPE_ACCELEROMETER:
        accelerometer_values = event.values.clone();
    }   

    if (magnitude_values != null && accelerometer_values != null && sensorReady) {
        sensorReady = false;

        float[] R = new float[16];
        float[] I = new float[16];

        SensorManager.getRotationMatrix(R, I, this.accelerometer_values, this.magnitude_values);

        float[] actual_orientation = new float[3];
        SensorManager.getOrientation(R, actual_orientation);
 }

将此代码放入您的onSensorChanged方法中。在actual_orientation向量中,您将拥有指向北方的向量,相对于您的实际位置。

如果您想从摄像机视角检测北方,则需要将代码的最后一行更改为以下内容

float[] outR = new float[16];
SensorManager.remapCoordinateSystem(R, SensorManager.AXIS_X, SensorManager.AXIS_Z, outR);
SensorManager.getOrientation(outR, actual_vals); 

非常感谢您提供的代码,正如您在我的帖子中所看到的,它几乎与我所做的相同。从getOrientation返回的actual_orientation值具有一些奇怪的值范围,它们不是度数或-1到+1之类的值。而且我认为当您旋转设备时(在地平线水平面上的某个位置),仍然存在值翻转的情况。 在这段代码片段之后,您是否对actual_vals进行了任何处理? - Simon
是的,getOrientation返回弧度值。如果您想要角度值,则必须将实际值进行转换。 - hara

4

好的,现在我有一个解决方案,您需要按照以下顺序进行openGL旋转:

gl.glRotatef(values[2], 0, 1, 0);
gl.glRotatef(values[1], 1, 0, 0);
gl.glRotatef(values[0], 0, 0, 1);

结合使用SensorManager.getOrientation,就可以实现这个功能。如果有人知道如何使用Sensor.TYPE_ORIENTATION数据来完成此操作,请告诉我。


我想知道如何使用Sensor.TYPE_ORIENTATION数据来完成这个操作。谢谢。 - jakeoung

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接