我正在实施指南针,从SensorManager.getRotationMatrix
获取读数(请参阅下面的代码)。
我有imageView
使用RotateAnimation
轮换。
除了一个问题外,指南针和动画工作正常:
通过SensorManager.getOrientation
我得到了三个值的数组 - 方位角,俯仰和滚动。我只使用保持方位角值的array[0]
如果我将手机保持平直并在Z轴(方位角)上转动 - 它可以完美地工作。但是,当我将手机倾斜到X或Y轴(俯仰或滚动)时,指南针会关闭正确的测量值。换句话说 - 当倾斜俯仰或倾斜时 - 它会严重影响方位角的读数。
所以,总结我的问题 - 如何阻止Pitch / Roll读数的干扰(虽然我根本不在代码中解决它们) - 或者,我做错了什么?
提前致谢!
以下是我的大部分代码:
public class MainActivity extends Activity implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor accelerometer;
private Sensor magnetometer;
private float[] mGravity;
private float[] mGeomagnetic;
float avgRead[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
private TextView tvCurrAzim;
private ImageView ivCompass;
private float currentDegree = 0f;
private float azimuth;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
tvCurrAzim = (TextView) findViewById(R.id.tvaz);
ivCompass = (ImageView) findViewById(R.id.imageView1);
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
accelerometer = mSensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
magnetometer = mSensorManager
.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}
// Compass Sensor Methods:
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
@Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
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 orientation[] = new float[3];
SensorManager.getOrientation(R, orientation);
//Creating a running smooth average of readings
avgRead[0] = avgRead[1];
avgRead[1] = avgRead[2];
avgRead[2] = avgRead[3];
avgRead[3] = avgRead[4];
avgRead[4] = avgRead[5];
avgRead[5] = avgRead[6];
avgRead[6] = avgRead[7];
avgRead[7] = avgRead[8];
avgRead[8] = orientation[0]; // orientation contains: azimuth, pitch and roll
azimuth = (avgRead[0] + avgRead[1] + avgRead[2] + avgRead[3]
+ avgRead[4] + avgRead[5] + avgRead[6] + avgRead[7] + avgRead[8]) / 9;
azimuth = Math.round(azimuth * 360 / (2 * 3.14159f));
if (azimuth < 0 && azimuth > -180)
azimuth += 360;
}
}
tvCurrAzim.setText(Float.toString(azimuth));
// get the angle around the z-axis rotated
// create a rotation animation (reverse turn degree degrees)
if (-azimuth - currentDegree > 180)
azimuth = azimuth - 360;
RotateAnimation ra = new RotateAnimation(currentDegree, -azimuth,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
// how long the animation will take place
ra.setDuration(50);
// set the animation after the end of the reservation status
ra.setFillAfter(true);
// Start the animation
ivCompass.startAnimation(ra);
currentDegree = -azimuth;
}
@Override
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
@Override
protected void onResume() {
super.onResume();
mSensorManager.registerListener(this, accelerometer,
SensorManager.SENSOR_DELAY_UI);
mSensorManager.registerListener(this, magnetometer,
SensorManager.SENSOR_DELAY_UI);
}
}