Java 无论屏幕方向如何,如何获得正确的方向(磁方向)?
我想得到当前的磁方向,而不考虑当前的屏幕方向(横向或纵向) 我找到了一个例子,但它不是独立的,对吧?也没有帮我。我也读过 这是我目前使用的方法,我不想使用这种不推荐的方法(简短): 但最后一部分肯定是错的!在这种情况下,如何正确使用较新的方法Java 无论屏幕方向如何,如何获得正确的方向(磁方向)?,java,android,android-sensors,bearing,digital-compass,Java,Android,Android Sensors,Bearing,Digital Compass,我想得到当前的磁方向,而不考虑当前的屏幕方向(横向或纵向) 我找到了一个例子,但它不是独立的,对吧?也没有帮我。我也读过 这是我目前使用的方法,我不想使用这种不推荐的方法(简短): 但最后一部分肯定是错的!在这种情况下,如何正确使用较新的方法getRotationMatrix()?(与方向无关)还是只需使用基于旋转矩阵的event.values[]数组的其他值?还是我需要“重新映射坐标”?那么,实现这一目标的正确方法是什么呢 我正在为具有360°屏幕旋转和API级别11+的设备开发 我知道这些问
getRotationMatrix()
?(与方向无关)还是只需使用基于旋转矩阵的event.values[]
数组的其他值?还是我需要“重新映射坐标”?那么,实现这一目标的正确方法是什么呢
我正在为具有360°屏幕旋转和API级别11+的设备开发
我知道这些问题经常被问到,但我不能简单地将他们的答案转移到我的问题上。
传感器。如果设备是平的,则类型_方向
会贬值,并且只有在设备是平的情况下才有效。当使用传感器时,类型_方向
,轴承(方位角)是设备Y轴
指向的方向。因此,如果设备保持垂直,Y轴
指向用作轴承的方向没有意义。只有计算后摄像头指向的方向才有意义。要找到该方向,必须使用传感器。输入磁场和传感器。输入重力或传感器。输入加速计。如果使用传感器。键入加速计,则必须过滤加速计值。使用这些传感器,在调用
getOrientation
之前,先调用getRotationMatrix
,然后调用remapCoordinateSystem(inR、X轴、Z轴、outR)
。为了得到一个稳定的方向,你应该保持该方向的历史记录,然后计算平均值。对于使用类型_重力检查的实现我认为此代码可能会帮助您:
//get orientation
private int getScreenOrientation() {
int rotation = getWindowManager().getDefaultDisplay().getRotation();
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
int height = dm.heightPixels;
int orientation;
// if the device's natural orientation is portrait:
if ((rotation == Surface.ROTATION_0
|| rotation == Surface.ROTATION_180) && height > width ||
(rotation == Surface.ROTATION_90
|| rotation == Surface.ROTATION_270) && width > height) {
switch(rotation) {
case Surface.ROTATION_0:
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
case Surface.ROTATION_90:
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
break;
case Surface.ROTATION_180:
orientation =
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
break;
case Surface.ROTATION_270:
orientation =
ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
break;
default:
Log.e(TAG, "Unknown screen orientation. Defaulting to " +
"portrait.");
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
}
}
// if the device's natural orientation is landscape or if the device
// is square:
else {
switch(rotation) {
case Surface.ROTATION_0:
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
break;
case Surface.ROTATION_90:
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
case Surface.ROTATION_180:
orientation =
ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
break;
case Surface.ROTATION_270:
orientation =
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
break;
default:
Log.e(TAG, "Unknown screen orientation. Defaulting to " +
"landscape.");
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
break;
}
}
return orientation;
}
好的,我终于设法让代码工作了 首先,我注册了一个
传感器。输入磁场和传感器。输入重力:(就像Hoan Nguyen说的!)
我使用SensorEventListner
进行计算:
private SensorEventListener mSensorEventListener = new SensorEventListener() {
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_GRAVITY) {
mGravity = event.values.clone();
} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
mMagnetic = event.values.clone();
}
if (mGravity != null && mMagnetic != null) {
/* Create rotation Matrix */
float[] rotationMatrix = new float[9];
if (SensorManager.getRotationMatrix(rotationMatrix, null,
mGravity, mMagnetic)) {
/* Compensate device orientation */
// http://android-developers.blogspot.de/2010/09/one-screen-turn-deserves-another.html
float[] remappedRotationMatrix = new float[9];
switch (getWindowManager().getDefaultDisplay()
.getRotation()) {
case Surface.ROTATION_0:
SensorManager.remapCoordinateSystem(rotationMatrix,
SensorManager.AXIS_X, SensorManager.AXIS_Y,
remappedRotationMatrix);
break;
case Surface.ROTATION_90:
SensorManager.remapCoordinateSystem(rotationMatrix,
SensorManager.AXIS_Y,
SensorManager.AXIS_MINUS_X,
remappedRotationMatrix);
break;
case Surface.ROTATION_180:
SensorManager.remapCoordinateSystem(rotationMatrix,
SensorManager.AXIS_MINUS_X,
SensorManager.AXIS_MINUS_Y,
remappedRotationMatrix);
break;
case Surface.ROTATION_270:
SensorManager.remapCoordinateSystem(rotationMatrix,
SensorManager.AXIS_MINUS_Y,
SensorManager.AXIS_X, remappedRotationMatrix);
break;
}
/* Calculate Orientation */
float results[] = new float[3];
SensorManager.getOrientation(remappedRotationMatrix,
results);
/* Get measured value */
float current_measured_bearing = (float) (results[0] * 180 / Math.PI);
if (current_measured_bearing < 0) {
current_measured_bearing += 360;
}
/* Smooth values using a 'Low Pass Filter' */
current_measured_bearing = current_measured_bearing
+ SMOOTHING_FACTOR_COMPASS
* (current_measured_bearing - compass_last_measured_bearing);
/* Update normal output */
visual_compass_value.setText(String.valueOf(Math
.round(current_bearing))
+ getString(R.string.degrees));
/*
* Update variables for next use (Required for Low Pass
* Filter)
*/
compass_last_measured_bearing = current_measured_bearing;
}
}
}
};
private SensorEventListener mssensoreventlistener=new SensorEventListener(){
@凌驾
精度更改时的公共无效(传感器,int精度){
}
@凌驾
传感器更改时的公共无效(传感器事件){
if(event.sensor.getType()==sensor.TYPE\u重力){
mGravity=event.values.clone();
}else if(event.sensor.getType()==sensor.TYPE\u磁场){
mmamagnetic=event.values.clone();
}
if(mGravity!=null和&mmamagnetic!=null){
/*创建旋转矩阵*/
float[]旋转矩阵=新的float[9];
如果(SensorManager.getRotationMatrix)(rotationMatrix,null,
经理(磁性){
/*补偿装置定向*/
// http://android-developers.blogspot.de/2010/09/one-screen-turn-deserves-another.html
float[]remappedRotationMatrix=新float[9];
开关(getWindowManager().getDefaultDisplay())
.getRotation()){
外壳表面旋转0:
SensorManager.剩余协调系统(旋转矩阵,
SensorManager.AXIS_X,SensorManager.AXIS_Y,
再成形矩阵);
打破
外壳表面旋转90度:
SensorManager.剩余协调系统(旋转矩阵,
SensorManager.AXIS_Y,
SensorManager.AXIS_减去X,
再成形矩阵);
打破
外壳表面旋转180度:
SensorManager.剩余协调系统(旋转矩阵,
SensorManager.AXIS_减去X,
SensorManager.AXIS_减去Y,
再成形矩阵);
打破
外壳表面。旋转_270:
SensorManager.剩余协调系统(旋转矩阵,
SensorManager.AXIS_减去Y,
SensorManager.AXIS_X,重新显示矩阵);
打破
}
/*计算方向*/
浮动结果[]=新浮动[3];
SensorManager.getOrientation(重新映射到StationMatrix,
结果);
/*获取测量值*/
浮子电流测量值轴承=(浮子)(结果[0]*180/数学PI);
if(当前测得的轴承<0){
当前测得的轴承+=360;
}
/*使用“低通滤波器”平滑值*/
当前测量的轴承=当前测量的轴承
+平滑因子罗盘
*(当前测量的方位-罗盘上次测量的方位);
/*更新正常输出*/
视觉罗盘值.setText(字符串.valueOf(数学
.圆形(当前_轴承))
+getString(R.string.degrees));
/*
*更新变量以供下次使用(低通要求
*过滤器)
*/
罗盘上一次测量的方位=当前测量的方位;
}
}
}
};
我在这里发布了同样的问题:但答案对我来说并不适用。也许你运气更好。你还需要它吗?因为可能我们“必须使用事件的其他值。值[]数组?”基于屏幕旋转?不,我取消了该项目(一些AR内容),因为结果表明,大多数
/**
* Initialize the Sensors (Gravity and magnetic field, required as a compass
* sensor)
*/
private void initSensors() {
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
Sensor mSensorGravity = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
Sensor mSensorMagneticField = sensorManager
.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
/* Initialize the gravity sensor */
if (mSensorGravity != null) {
Log.i(TAG, "Gravity sensor available. (TYPE_GRAVITY)");
sensorManager.registerListener(mSensorEventListener,
mSensorGravity, SensorManager.SENSOR_DELAY_GAME);
} else {
Log.i(TAG, "Gravity sensor unavailable. (TYPE_GRAVITY)");
}
/* Initialize the magnetic field sensor */
if (mSensorMagneticField != null) {
Log.i(TAG, "Magnetic field sensor available. (TYPE_MAGNETIC_FIELD)");
sensorManager.registerListener(mSensorEventListener,
mSensorMagneticField, SensorManager.SENSOR_DELAY_GAME);
} else {
Log.i(TAG,
"Magnetic field sensor unavailable. (TYPE_MAGNETIC_FIELD)");
}
}
private SensorEventListener mSensorEventListener = new SensorEventListener() {
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_GRAVITY) {
mGravity = event.values.clone();
} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
mMagnetic = event.values.clone();
}
if (mGravity != null && mMagnetic != null) {
/* Create rotation Matrix */
float[] rotationMatrix = new float[9];
if (SensorManager.getRotationMatrix(rotationMatrix, null,
mGravity, mMagnetic)) {
/* Compensate device orientation */
// http://android-developers.blogspot.de/2010/09/one-screen-turn-deserves-another.html
float[] remappedRotationMatrix = new float[9];
switch (getWindowManager().getDefaultDisplay()
.getRotation()) {
case Surface.ROTATION_0:
SensorManager.remapCoordinateSystem(rotationMatrix,
SensorManager.AXIS_X, SensorManager.AXIS_Y,
remappedRotationMatrix);
break;
case Surface.ROTATION_90:
SensorManager.remapCoordinateSystem(rotationMatrix,
SensorManager.AXIS_Y,
SensorManager.AXIS_MINUS_X,
remappedRotationMatrix);
break;
case Surface.ROTATION_180:
SensorManager.remapCoordinateSystem(rotationMatrix,
SensorManager.AXIS_MINUS_X,
SensorManager.AXIS_MINUS_Y,
remappedRotationMatrix);
break;
case Surface.ROTATION_270:
SensorManager.remapCoordinateSystem(rotationMatrix,
SensorManager.AXIS_MINUS_Y,
SensorManager.AXIS_X, remappedRotationMatrix);
break;
}
/* Calculate Orientation */
float results[] = new float[3];
SensorManager.getOrientation(remappedRotationMatrix,
results);
/* Get measured value */
float current_measured_bearing = (float) (results[0] * 180 / Math.PI);
if (current_measured_bearing < 0) {
current_measured_bearing += 360;
}
/* Smooth values using a 'Low Pass Filter' */
current_measured_bearing = current_measured_bearing
+ SMOOTHING_FACTOR_COMPASS
* (current_measured_bearing - compass_last_measured_bearing);
/* Update normal output */
visual_compass_value.setText(String.valueOf(Math
.round(current_bearing))
+ getString(R.string.degrees));
/*
* Update variables for next use (Required for Low Pass
* Filter)
*/
compass_last_measured_bearing = current_measured_bearing;
}
}
}
};