如果 phone 缓慢移动,旋转传感器没有反应
Rotation sensor not reacting if phone is moved slowly
我正在尝试从传感器管理器读取方位角、俯仰角和横滚角。出于某种原因,如果我非常缓慢地移动 phone,方位角、俯仰和横滚值不会更新,只有当我移动 phone 足够强时它们才会更新 .换句话说,如果我非常缓慢地移动 phone,我可以进行完整的 90 度旋转而不会获得任何新值。
我看到它在这条线上得到了 'stuck',如果 phone 移动得太慢,这条线将 return false:
SensorManager.getRotationMatrix( R, I, mGravity, mGeomagnetic );
似乎如果没有明显的加速器力,那么旋转也不会更新。
这是我的代码:
mSensorManager = (SensorManager)activityContext.getSystemService(Context.SENSOR_SERVICE);;
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME);
这是 onSensorChanged 事件:
@Override
public void onSensorChanged(SensorEvent event)
{
if (event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION)
mGravity = event.values;
if (event.sensor.getType() == Sensor.TYPE_ORIENTATION)
mGeomagnetic = event.values;
if (mGravity != null && mGeomagnetic != null)
{
// The code is triggering to this point fine
float R[] = new float[9];
float I[] = new float[9];
float forceX = Float.valueOf(((float)((float)mGravity[0] ) ) ) / (float)4.0;
float forceY = Float.valueOf(((float)((float)mGravity[1] ) ) ) / (float)4.0;
float forceZ = Float.valueOf(((float)((float)mGravity[2] ) ) ) / (float)4.0;
boolean success = SensorManager.getRotationMatrix( R, I, mGravity, mGeomagnetic );
if (success) // <-- this is only triggering if phone is moved fast enough
{
float orientation[] = new float[3];
SensorManager.getOrientation(R, orientation);
rotation_degrees_x = ((float)Math.toDegrees( orientation[0] ) + (float)180.0 ) / (float)360.0;
rotation_degrees_y = ((float)Math.toDegrees( orientation[1] ) + (float)180.0 ) / (float)360.0;
rotation_degrees_z = ((float)Math.toDegrees( orientation[2] ) + (float)180.0 ) / (float)360.0;
}
mGeomagnetic = null;
mGravity = null;
}
}
我还看到以下条件不断触发:
if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE)
所以我在条件中添加了以下行:
Log.d( "ROTATIONDEBUG", "TYPE_MAGNETIC_FIELD: " + mGeomagnetic[0] + "\t" + mGeomagnetic[1] + "\t" + mGeomagnetic[1] );
并得到一些反映旋转中最细微变化的值:
TYPE_MAGNETIC_FIELD: 23.5 20.7 20.7
TYPE_MAGNETIC_FIELD: 23.2 22.2 22.2
TYPE_MAGNETIC_FIELD: 23.0 24.9 24.9
TYPE_MAGNETIC_FIELD: 22.4 27.5 27.5
TYPE_MAGNETIC_FIELD: 21.5 29.2 29.2
TYPE_MAGNETIC_FIELD: 21.6 30.2 30.2
TYPE_MAGNETIC_FIELD: 21.1 32.1 32.10
TYPE_MAGNETIC_FIELD: 20.7 34.8 34.8
TYPE_MAGNETIC_FIELD: 20.7 34.7 34.7
TYPE_MAGNETIC_FIELD: 20.9 35.0 35.0
TYPE_MAGNETIC_FIELD: 20.6 36.0 36.0
但无法理解为什么他们不一起工作并且 SensorManager.getRotationMatrix 行 return 是错误的..
我下载了一些罗盘和传感器测试应用程序,它们都可以检测到这个 光 运动,所以我猜我的代码有问题。
编辑:
我尝试了一个不同的代码示例,但它给了我完全相同的结果:
SensorEventListener sensorEventListener = new SensorEventListener() {
float[] mGravity;
float[] mGeomagnetic;
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
mGravity = event.values;
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
mGeomagnetic = event.values;
if (mGravity != null && mGeomagnetic != null) {
float R[] = new float[9];
float I[] = new float[9];
boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);
if (success) {
float orientationData[] = new float[3];
SensorManager.getOrientation(R, orientationData);
azimuth = orientationData[0];
pitch = orientationData[1];
roll = orientationData[2];
}
}
}
};
到目前为止我看到这个模式:
如果我直接从下面的条件中读取值,我可以获得 'detailed/sensitive' 变化:
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
mGeomagnetic = event.values;
但是如果我尝试使用 getRotationMatrix,它只会 return 正确,如果用加速度计检测到足够的力:
boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);
如何让 SensorManager.getRotationMatrix 触发而不考虑加速度计值?或者如何将这些 RAW 值转换为度数?
有什么提示吗?谢谢!
事实证明,通过将 SENSOR_DELAY_GAME 更改为 SENSOR_DELAY_NORMAL 并仅使用常规 TYPE_GYROSCOPE,解决了问题,即使是最轻微的移动也会触发!
我正在尝试从传感器管理器读取方位角、俯仰角和横滚角。出于某种原因,如果我非常缓慢地移动 phone,方位角、俯仰和横滚值不会更新,只有当我移动 phone 足够强时它们才会更新 .换句话说,如果我非常缓慢地移动 phone,我可以进行完整的 90 度旋转而不会获得任何新值。
我看到它在这条线上得到了 'stuck',如果 phone 移动得太慢,这条线将 return false:
SensorManager.getRotationMatrix( R, I, mGravity, mGeomagnetic );
似乎如果没有明显的加速器力,那么旋转也不会更新。
这是我的代码:
mSensorManager = (SensorManager)activityContext.getSystemService(Context.SENSOR_SERVICE);;
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME);
这是 onSensorChanged 事件:
@Override
public void onSensorChanged(SensorEvent event)
{
if (event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION)
mGravity = event.values;
if (event.sensor.getType() == Sensor.TYPE_ORIENTATION)
mGeomagnetic = event.values;
if (mGravity != null && mGeomagnetic != null)
{
// The code is triggering to this point fine
float R[] = new float[9];
float I[] = new float[9];
float forceX = Float.valueOf(((float)((float)mGravity[0] ) ) ) / (float)4.0;
float forceY = Float.valueOf(((float)((float)mGravity[1] ) ) ) / (float)4.0;
float forceZ = Float.valueOf(((float)((float)mGravity[2] ) ) ) / (float)4.0;
boolean success = SensorManager.getRotationMatrix( R, I, mGravity, mGeomagnetic );
if (success) // <-- this is only triggering if phone is moved fast enough
{
float orientation[] = new float[3];
SensorManager.getOrientation(R, orientation);
rotation_degrees_x = ((float)Math.toDegrees( orientation[0] ) + (float)180.0 ) / (float)360.0;
rotation_degrees_y = ((float)Math.toDegrees( orientation[1] ) + (float)180.0 ) / (float)360.0;
rotation_degrees_z = ((float)Math.toDegrees( orientation[2] ) + (float)180.0 ) / (float)360.0;
}
mGeomagnetic = null;
mGravity = null;
}
}
我还看到以下条件不断触发:
if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE)
所以我在条件中添加了以下行:
Log.d( "ROTATIONDEBUG", "TYPE_MAGNETIC_FIELD: " + mGeomagnetic[0] + "\t" + mGeomagnetic[1] + "\t" + mGeomagnetic[1] );
并得到一些反映旋转中最细微变化的值:
TYPE_MAGNETIC_FIELD: 23.5 20.7 20.7
TYPE_MAGNETIC_FIELD: 23.2 22.2 22.2
TYPE_MAGNETIC_FIELD: 23.0 24.9 24.9
TYPE_MAGNETIC_FIELD: 22.4 27.5 27.5
TYPE_MAGNETIC_FIELD: 21.5 29.2 29.2
TYPE_MAGNETIC_FIELD: 21.6 30.2 30.2
TYPE_MAGNETIC_FIELD: 21.1 32.1 32.10
TYPE_MAGNETIC_FIELD: 20.7 34.8 34.8
TYPE_MAGNETIC_FIELD: 20.7 34.7 34.7
TYPE_MAGNETIC_FIELD: 20.9 35.0 35.0
TYPE_MAGNETIC_FIELD: 20.6 36.0 36.0
但无法理解为什么他们不一起工作并且 SensorManager.getRotationMatrix 行 return 是错误的..
我下载了一些罗盘和传感器测试应用程序,它们都可以检测到这个 光 运动,所以我猜我的代码有问题。
编辑: 我尝试了一个不同的代码示例,但它给了我完全相同的结果:
SensorEventListener sensorEventListener = new SensorEventListener() {
float[] mGravity;
float[] mGeomagnetic;
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
mGravity = event.values;
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
mGeomagnetic = event.values;
if (mGravity != null && mGeomagnetic != null) {
float R[] = new float[9];
float I[] = new float[9];
boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);
if (success) {
float orientationData[] = new float[3];
SensorManager.getOrientation(R, orientationData);
azimuth = orientationData[0];
pitch = orientationData[1];
roll = orientationData[2];
}
}
}
};
到目前为止我看到这个模式:
如果我直接从下面的条件中读取值,我可以获得 'detailed/sensitive' 变化:
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
mGeomagnetic = event.values;
但是如果我尝试使用 getRotationMatrix,它只会 return 正确,如果用加速度计检测到足够的力:
boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);
如何让 SensorManager.getRotationMatrix 触发而不考虑加速度计值?或者如何将这些 RAW 值转换为度数?
有什么提示吗?谢谢!
事实证明,通过将 SENSOR_DELAY_GAME 更改为 SENSOR_DELAY_NORMAL 并仅使用常规 TYPE_GYROSCOPE,解决了问题,即使是最轻微的移动也会触发!