我需要设备的方位角和滚动值的增强现实应用程序,我正在工作。我得到旋转矩阵-从getRotationMatrix -使用加速度计和磁场。由于这是一个AR应用程序,我需要渲染的对象,不会改变他们在现实世界中的位置(通过摄像头看到),当设备被移动。
问题是,当物理滚动装置时(为了观察俯仰值的变化),我可以观察到方位方向值的变化,尽管这应该是稳定的。此外,只有当俯仰发生变化时,方位角才会偏离,并在停止滚动时返回到原来的值。因此,为了澄清,当我开始滚动时,方位角也开始变化,当滚动停止时,方位角慢慢返回到正确的值。我不明白为什么方位角会这样。
下面是获取传感器数据并计算旋转矩阵的代码。
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
switch (sensorEvent.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
accel = lowPass(sensorEvent.values.clone(), accel);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
magnet = lowPass(sensorEvent.values.clone(), magnet);
break;
}
if (accel == null || magnet == null)
return;
if (!SensorManager.getRotationMatrix(rotationMatrix, null, accel, magnet))
return;
SensorManager.remapCoordinateSystem(rotationMatrix, SensorManager.AXIS_Z,
SensorManager.AXIS_MINUS_X, outRotationMatrix); // Remapping because the device is held in landscape.
SensorManager.getOrientation(outRotationMatrix, orientationValues);
currentOrientation = (float) (Math.toDegrees(orientationValues[0]) + this.getDeclination()); //Azimuth; (Degrees);
eyeLevelInclination = (float) Math.toDegrees(orientationValues[1]); //Pitch; (Degrees); down is 90 , up is -90.
deviceOrientation = (float) Math.toDegrees(orientationValues[2]);
sendSensorBroadcast();
}因此,在上面的代码中,currentOrientation (负责水平稳定呈现的AR对象)在设备滚动期间发生了变化,而只有eyeLevelInclination应该进行更改(负责垂直稳定呈现的AR对象)。
我还使用低通滤波器来稳定传感器数据。虽然我不认为这是造成方位变化的原因,但我把它的代码放在这里,不管-
static final float ALPHA = 0.15f;
/**
* @see Adapted from http://blog.thomnichols.org/2011/08/smoothing-sensor-data-with-a-low-pass-filter
*/
protected float[] lowPass( float[] input, float[] output ) {
if ( output == null ) return input;
for ( int i=0; i<input.length; i++ ) {
output[i] = output[i] + ALPHA * (input[i] - output[i]);
}
return output;
}如果问题不是很清楚的话,很抱歉。要解释这个问题有点难。
编辑:我尝试使用原始值,而不是通过低通滤波器,方位仍然改变。我注意到渲染的对象在改变音高时沿着对角线走,而此时它只应该垂直向上或向下。当我物理地改变设备的俯仰时,它是对角移动的,因为方位角和俯仰角都在变化,引起对角线运动。也许我的轴心出了什么问题?
发布于 2014-04-08 21:16:06
看到我如何能够找到解决这个问题的办法,我开始研究其他可能的处理传感器的方法。我找到了一种更好的处理传感器数据的方法,它不仅消除了方位抖动,而且还需要一个过滤器来平滑传感器的值:
我没有使用Sensor.TYPE_ACCELEROMETER和Sensor.TYPE_MAGNETIC_FIELD值来计算旋转矩阵,而是使用Sensor.TYPE_ROTATION_VECTOR传感器。然后,从这里得到旋转矩阵,就像前面所做的那样,从它得到定向数组。
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
switch (sensorEvent.sensor.getType()) {
case Sensor.TYPE_ROTATION_VECTOR:
rotationMatrix=new float[16];
SensorManager.getRotationMatrixFromVector(rotationMatrix, sensorEvent.values);
}
SensorManager.remapCoordinateSystem(rotationMatrix, SensorManager.AXIS_X,
SensorManager.AXIS_Z, outRotationMatrix); // Remap coordinate System to compensate for the landscape position of device
SensorManager.getOrientation(outRotationMatrix, orientationValues);
currentOrientation = (float) (Math.toDegrees(orientationValues[0]) + this.getDeclination()); //Azimuth; (Degrees);
eyeLevelInclination = (float) Math.toDegrees(orientationValues[1]); //Pitch; (Degrees); down is 90 , up is -90.
deviceOrientation = (float) Math.toDegrees(orientationValues[2]); // Roll;
sendSensorBroadcast(); // Let other classes know of update to sensor data.正如你在上面的问题中看到的,我使用一个低通滤波器来平滑方位角和俯仰值,但是这已经不需要了,因为没有任何滤波,这些值是非常平滑的。另外,方位角的晃动现在几乎消失了。我说这几乎是因为你可能还能看到一些它的发生,但它几乎不明显,也许大约半度。
我被这个问题困扰了一段时间,希望这也能帮助到其他人。
发布于 2014-04-02 16:21:18
不管设备是什么方向(肖像或风景及其变化),如果你对后面的摄像机方向感兴趣,那么你必须打电话给
SensorManager.remapCoordinateSystem(rotationMatrix, SensorManager.AXIS_X,
SensorManager.AXIS_Z, outRotationMatrix);上面的调用与getOrientation一起给出了后摄像头相对于磁北的方向,而不依赖于设备的方向(肖像、景观或两者之间的任何东西)。
https://stackoverflow.com/questions/22794011
复制相似问题