Android的俯仰和横滚问题 [英] Android Pitch and Roll Issue

查看:137
本文介绍了Android的俯仰和横滚问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为Android倾斜的应用程序。我有一个问题,肖像和放大器;风景模式。当节距= 90度(在手机上端),甚至稍前的辊值去疯狂时出现了辊没有物理变化。我一直没能找到一个解决这个问题。如果任何人都可以在正确的方向指向我,那将是AP preciated。

下面是一个简短的code转储,所以你知道它是不是一个加速度计误差。

 最后SensorEventListener mEventListener =新SensorEventListener(){
     公共无效onAccuracyChanged(传感器传感器,诠释精度){}
 公共无效onSensorChanged(SensorEvent事件){
     setListners(的SensorManager,mEventListener);

      SensorManager.getRotationMatrix(mRotationMatrix,空,mValues​​Accel,mValues​​Magnet);
     SensorManager.getOrientation(mRotationMatrix,mValues​​Orientation);


        同步(本){

            开关(event.sensor.getType()){
                案例Sensor.TYPE_ACCELEROMETER:

                    System.arraycopy(event.values​​,0,mValues​​Accel,0,3);

                    长actualTime = System.currentTimeMillis的();

                    //灵敏度延迟
                    如果(actualTime  -  lastUpdate< 250){
                        返回;
                        }
                    其他 {
                        sysAzimuth =(int)的Math.toDegrees(mValues​​Orientation [0]);
                        sysPitch =(int)的Math.toDegrees(mValues​​Orientation [1]);
                        sysRoll =(int)的Math.toDegrees(mValues​​Orientation [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:机器人=htt​​p://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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆