Android的俯仰和横滚问题 [英] Android Pitch and Roll Issue
问题描述
我正在为Android倾斜的应用程序。我有一个问题,肖像和放大器;风景模式。当节距= 90度(在手机上端),甚至稍前的辊值去疯狂时出现了辊没有物理变化。我一直没能找到一个解决这个问题。如果任何人都可以在正确的方向指向我,那将是AP preciated。
下面是一个简短的code转储,所以你知道它是不是一个加速度计误差。
最后SensorEventListener mEventListener =新SensorEventListener(){
公共无效onAccuracyChanged(传感器传感器,诠释精度){}
公共无效onSensorChanged(SensorEvent事件){
setListners(的SensorManager,mEventListener);
SensorManager.getRotationMatrix(mRotationMatrix,空,mValuesAccel,mValuesMagnet);
SensorManager.getOrientation(mRotationMatrix,mValuesOrientation);
同步(本){
开关(event.sensor.getType()){
案例Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values,0,mValuesAccel,0,3);
长actualTime = System.currentTimeMillis的();
//灵敏度延迟
如果(actualTime - lastUpdate< 250){
返回;
}
其他 {
sysAzimuth =(int)的Math.toDegrees(mValuesOrientation [0]);
sysPitch =(int)的Math.toDegrees(mValuesOrientation [1]);
sysRoll =(int)的Math.toDegrees(mValuesOrientation [2]);
//反转方向-1
间距=(sysPitch - pitchCal)* - 1;
卷=(sysRoll - rollCal);
方位角= sysAzimuth;
lastUpdate = actualTime;
}
我找到了我一直在寻找,旋转矩阵。
我是用欧拉角(滚动,俯仰,偏航)的俯仰和侧滚。当手机在年底90度,X和Z平原是相同的手机去疯狂,与欧拉角的根本缺陷。
我需要使用旋转矩阵的俯仰和横滚度通过getRotationMatrix
这是所有;)
XML:
< XML版本=1.0编码=UTF-8&GT?;
<! - 这个文件是RES /布局/ main.xml中 - >
< RelativeLayout的
的xmlns:机器人=http://schemas.android.com/apk/res/android
机器人:layout_width =FILL_PARENT
机器人:layout_height =FILL_PARENT>
<按钮机器人:ID =@ + ID /更新机器人:文本=更新值
机器人:layout_width =WRAP_CONTENT
机器人:layout_height =WRAP_CONTENT
机器人:的onClick =doUpdate/>
<按钮机器人:ID =@ + ID /节目机器人:文本=显示我!
机器人:layout_width =WRAP_CONTENT
机器人:layout_height =WRAP_CONTENT
机器人:的onClick =doShow机器人:layout_toRightOf =@ ID /更新/>
< TextView的机器人:ID =@ + ID / preferred机器人:TEXTSIZE =20SP
机器人:layout_width =WRAP_CONTENT
机器人:layout_height =WRAP_CONTENT
机器人:layout_below =@ ID /更新/>
< TextView的机器人:ID =@ + ID /方向机器人:TEXTSIZE =20SP
机器人:layout_width =WRAP_CONTENT
机器人:layout_height =WRAP_CONTENT
机器人:layout_below =@ ID / preferred/>
< / RelativeLayout的>
code:
包YOURPACKAGE;
进口android.app.Activity;
进口android.content.Intent;
进口android.hardware.Sensor;
进口android.hardware.SensorEvent;
进口android.hardware.SensorEventListener;
进口android.hardware.SensorManager;
进口android.net.Uri;
进口android.os.Build;
进口android.os.Bundle;
进口android.view.View;
进口android.view.WindowManager;
进口android.widget.TextView;
公共类YOURCLASS扩展活动实现SensorEventListener {
私有静态最后字符串变量=VirtualJax;
私人的SensorManager经理;
私人传感器加速;
私人传感器罗盘;
私人传感器确定;
私人的TextView preferred;
私人TextView的方向;
私人布尔准备= FALSE;
私人浮法[] accelValues =新的浮动[3];
私人浮法[] compassValues =新的浮动[3];
私人浮法[] INR =新的浮动[9];
私人浮法[] inclineMatrix =新的浮动[9];
私人浮法[] orientationValues =新的浮动[3];
私人浮法[] prefValues =新的浮动[3];
私人浮动mAzimuth;
私人双人mInclination;
私人诠释柜台;
私人诠释mRotation;
@覆盖
公共无效的onCreate(包savedInstanceState){
super.onCreate(savedInstanceState);
的setContentView(R.layout.main);
preferred =(TextView中)findViewById(R.id. preferred);
定向=(TextView中)findViewById(R.id.orientation);
经理=(的SensorManager)this.getSystemService(SENSOR_SERVICE);
加速= mgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
罗盘= mgr.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
东方= mgr.getDefaultSensor(Sensor.TYPE_ORIENTATION);
窗口管理器窗口=(窗口管理器)
this.getSystemService(WINDOW_SERVICE);
INT apiLevel =的Integer.parseInt(Build.VERSION.SDK);
如果(apiLevel&所述; 8){
mRotation = window.getDefaultDisplay()getOrientation()。
}
其他 {
mRotation = window.getDefaultDisplay()getRotation()。
}
}
@覆盖
保护无效onResume(){
mgr.registerListener(这一点,加速,
SensorManager.SENSOR_DELAY_GAME);
mgr.registerListener(这一点,指南针,
SensorManager.SENSOR_DELAY_GAME);
mgr.registerListener(此,东方,
SensorManager.SENSOR_DELAY_GAME);
super.onResume();
}
@覆盖
保护无效的onPause(){
mgr.unregisterListener(此,加速度);
mgr.unregisterListener(这一点,指南针);
mgr.unregisterListener(本,东方);
super.onPause();
}
公共无效onAccuracyChanged(传感器传感器,诠释精度){
// 忽略
}
公共无效onSensorChanged(SensorEvent事件){
//需要同时获得加速度计和指南针
//才可以决定我们orientationValues
开关(event.sensor.getType()){
案例Sensor.TYPE_ACCELEROMETER:
的for(int i = 0;我3;;我++){
accelValues [I] = event.values [I];
}
如果(compassValues [0]!= 0)
准备好= TRUE;
打破;
案例Sensor.TYPE_MAGNETIC_FIELD:
的for(int i = 0;我3;;我++){
compassValues [I] = event.values [I];
}
如果(accelValues [2]!= 0)
准备好= TRUE;
打破;
案例Sensor.TYPE_ORIENTATION:
的for(int i = 0;我3;;我++){
orientationValues [I] = event.values [I];
}
打破;
}
如果(!准备好)
返回;
如果(SensorManager.getRotationMatrix(
INR,inclineMatrix,accelValues,compassValues)){
//取得了良好的旋转矩阵
SensorManager.getOrientation(INR,prefValues);
mInclination = SensorManager.getInclination(inclineMatrix);
//显示每10个值
如果(计数器++%10 == 0){
doUpdate(空);
计数器= 1;
}
}
}
公共无效doUpdate(查看视图){
如果(!准备好)
返回;
mAzimuth =(浮点)Math.toDegrees(prefValues [0]);
如果(mAzimuth℃,){
mAzimuth + = 360.0f;
}
弦乐味精=的String.Format(
preferred:\ nazimuth(Z):%7.3f \ npitch(Ⅹ):%7.3f \ nroll(Y):%7.3f,
mAzimuth,Math.toDegrees(prefValues [1]),
Math.toDegrees(prefValues [2]));
preferred.setText(MSG);
味精=的String.Format(
方向感应器:\ nazimuth(Z):%7.3f \ npitch(X):%7.3f \ nroll(Y):%7.3f,
orientationValues [0],
orientationValues [1],
orientationValues [2]);
orientation.setText(MSG);
preferred.invalidate();
orientation.invalidate();
}
公共无效doShow(查看视图){
// google.streetview:cbll = 30.32454,-81.6584&安培; CBP = 1,偏航俯仰,, 1.0
//偏航=从北度顺时针
//对于偏航我们可以使用mAzimuth或orientationValues [0]。
//
//间距=度向上或向下。 -90正在直线上升,
// +90正在直降
//除了间距不能正常工作
意向意图=新的意图(Intent.ACTION_VIEW,Uri.parse(
google.streetview:cbll = 30.32454,-81.6584&安培; CBP = 1,+
Math.round(orientationValues [0])+,, 0,1.0
));
startActivity(意向);
返回;
}
}
I am working on a tilt app for Android. I am having an issue with Portrait & landscape mode. When the pitch = 90 degrees (phone on end) and even slightly before the roll value goes crazy when there has been no physical change in roll. I have not been able to find a solution to this problem. If anyone can point me in the right direction, it would be appreciated.
Here’s a short code dump, so you know it is not an accelerometer error.
final SensorEventListener mEventListener = new SensorEventListener(){
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
public void onSensorChanged(SensorEvent event) {
setListners(sensorManager, mEventListener);
SensorManager.getRotationMatrix(mRotationMatrix, null, mValuesAccel, mValuesMagnet);
SensorManager.getOrientation(mRotationMatrix, mValuesOrientation);
synchronized (this) {
switch (event.sensor.getType()){
case Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values, 0, mValuesAccel, 0, 3);
long actualTime = System.currentTimeMillis();
//Sensitivity delay
if (actualTime - lastUpdate < 250) {
return;
}
else {
sysAzimuth = (int)Math.toDegrees(mValuesOrientation[0]);
sysPitch = (int)Math.toDegrees(mValuesOrientation[1]);
sysRoll = (int)Math.toDegrees(mValuesOrientation[2]);
//invert direction with -1
pitch = (sysPitch - pitchCal)*-1;
roll = (sysRoll - rollCal);
azimuth = sysAzimuth;
lastUpdate = actualTime;
}
I found what I was looking for, Rotational Matrices.
I was using Euler angles (roll, pitch, yaw) for the pitch and roll. When the phone is on end 90 degrees, the x and z plain are the same and the phone goes crazy, a fundamental flaw with Euler angles.
I need to get the pitch and roll degrees using Rotational Matrices via getRotationMatrix
Here it is for all ;)
XML:
<?xml version="1.0" encoding="utf-8"?>
<!-- This file is res/layout/main.xml -->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<Button android:id="@+id/update" android:text="Update Values"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="doUpdate" />
<Button android:id="@+id/show" android:text="Show Me!"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="doShow" android:layout_toRightOf="@id/update" />
<TextView android:id="@+id/preferred" android:textSize="20sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/update" />
<TextView android:id="@+id/orientation" android:textSize="20sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/preferred" />
</RelativeLayout>
Code:
package YOURPACKAGE;
import android.app.Activity;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
public class YOURCLASS extends Activity implements SensorEventListener {
private static final String TAG = "VirtualJax";
private SensorManager mgr;
private Sensor accel;
private Sensor compass;
private Sensor orient;
private TextView preferred;
private TextView orientation;
private boolean ready = false;
private float[] accelValues = new float[3];
private float[] compassValues = new float[3];
private float[] inR = new float[9];
private float[] inclineMatrix = new float[9];
private float[] orientationValues = new float[3];
private float[] prefValues = new float[3];
private float mAzimuth;
private double mInclination;
private int counter;
private int mRotation;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
preferred = (TextView)findViewById(R.id.preferred);
orientation = (TextView)findViewById(R.id.orientation);
mgr = (SensorManager) this.getSystemService(SENSOR_SERVICE);
accel = mgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
compass = mgr.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
orient = mgr.getDefaultSensor(Sensor.TYPE_ORIENTATION);
WindowManager window = (WindowManager)
this.getSystemService(WINDOW_SERVICE);
int apiLevel = Integer.parseInt(Build.VERSION.SDK);
if(apiLevel <8) {
mRotation = window.getDefaultDisplay().getOrientation();
}
else {
mRotation = window.getDefaultDisplay().getRotation();
}
}
@Override
protected void onResume() {
mgr.registerListener(this, accel,
SensorManager.SENSOR_DELAY_GAME);
mgr.registerListener(this, compass,
SensorManager.SENSOR_DELAY_GAME);
mgr.registerListener(this, orient,
SensorManager.SENSOR_DELAY_GAME);
super.onResume();
}
@Override
protected void onPause() {
mgr.unregisterListener(this, accel);
mgr.unregisterListener(this, compass);
mgr.unregisterListener(this, orient);
super.onPause();
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// ignore
}
public void onSensorChanged(SensorEvent event) {
// Need to get both accelerometer and compass
// before we can determine our orientationValues
switch(event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
for(int i=0; i<3; i++) {
accelValues[i] = event.values[i];
}
if(compassValues[0] != 0)
ready = true;
break;
case Sensor.TYPE_MAGNETIC_FIELD:
for(int i=0; i<3; i++) {
compassValues[i] = event.values[i];
}
if(accelValues[2] != 0)
ready = true;
break;
case Sensor.TYPE_ORIENTATION:
for(int i=0; i<3; i++) {
orientationValues[i] = event.values[i];
}
break;
}
if(!ready)
return;
if(SensorManager.getRotationMatrix(
inR, inclineMatrix, accelValues, compassValues)) {
// got a good rotation matrix
SensorManager.getOrientation(inR, prefValues);
mInclination = SensorManager.getInclination(inclineMatrix);
// Display every 10th value
if(counter++ % 10 == 0) {
doUpdate(null);
counter = 1;
}
}
}
public void doUpdate(View view) {
if(!ready)
return;
mAzimuth = (float) Math.toDegrees(prefValues[0]);
if(mAzimuth < 0) {
mAzimuth += 360.0f;
}
String msg = String.format(
"Preferred:\nazimuth (Z): %7.3f \npitch (X): %7.3f\nroll (Y): %7.3f",
mAzimuth, Math.toDegrees(prefValues[1]),
Math.toDegrees(prefValues[2]));
preferred.setText(msg);
msg = String.format(
"Orientation Sensor:\nazimuth (Z): %7.3f\npitch (X): %7.3f\nroll (Y): %7.3f",
orientationValues[0],
orientationValues[1],
orientationValues[2]);
orientation.setText(msg);
preferred.invalidate();
orientation.invalidate();
}
public void doShow(View view) {
// google.streetview:cbll=30.32454,-81.6584&cbp=1,yaw,,pitch,1.0
// yaw = degrees clockwise from North
// For yaw we can use either mAzimuth or orientationValues[0].
//
// pitch = degrees up or down. -90 is looking straight up,
// +90 is looking straight down
// except that pitch doesn't work properly
Intent intent=new Intent(Intent.ACTION_VIEW, Uri.parse(
"google.streetview:cbll=30.32454,-81.6584&cbp=1," +
Math.round(orientationValues[0]) + ",,0,1.0"
));
startActivity(intent);
return;
}
}
这篇关于Android的俯仰和横滚问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!