简体   繁体   English

Android获得相对于地平线的角度

[英]Android get angle relative to horizons

I've been working on trying to get the angle of an Android device (which I assume is being held with the back of the device parallel to the ground) relative to the horizon. 我一直在尝试相对于水平线获取Android设备的角度(我假设该设备的背面与地面平行)。 I've been using the Rotation Vector sensor but the values I'm getting are too ambiguous to be of use. 我一直在使用“旋转矢量”传感器,但是得到的值太模糊而无法使用。

For example, when I tilt the device to the right (from the position stated above, with little to no tilt in other directions), I get the following values: 例如,当我将设备向右倾斜(从上述位置,在其他方向上几乎没有倾斜)时,得到以下值:

X = 0.4
Y = -0.4
Z = -0.06

For similar tests (eg tilt to the left, tilt so the top of the phone faces downwards/upwards), I get equally confusing results. 对于类似的测试(例如,向左倾斜,倾斜使得手机顶部朝下/朝上),我得到的结果同样令人困惑。

To be very specific about what I expect: I expected that I would see a significant change in one axis (as I'm only rotating in one axis) and minimal to no change on the others. 要具体说明我的期望:我希望我会看到一个轴的显着变化(因为我仅在一个轴上旋转),而在其他轴上则几乎没有变化。 This way, I could figure out if a person was tilting left, right, up, down, or a combination (eg right/down, left/up, etc.). 这样,我可以弄清楚一个人是在向左,向右,向上,向下还是组合倾斜(例如,向右/向下,向左/向上等)。 With these values, it's near impossible for me to ascertain this data. 有了这些值,我几乎无法确定这些数据。

I tagged this question with the math tag as it may be that I need to use the Rotation vector matrix or do some other mathematical transformation in order to get the values in the format I need them in. If that is the case, I would appreciate guidance as to what algorithms/formulae I need, hence the tag. 我用math标签标记了这个问题,因为可能我需要使用旋转矢量矩阵或进行其他数学转换才能以所需的格式获取值。如果是这种情况,我将不胜感激有关我需要哪种算法/公式的指导,因此也提供了标签。

Below is my prototype code if you'd like to test for yourself (this was run on a Nexus 5 running Android 5.0.1): 如果您想自己进行测试,以下是我的原型代码(该代码在运行Android 5.0.1的Nexus 5上运行):

MainActivity.xml: MainActivity.xml:

<TextView
    android:textAppearance="?android:attr/textAppearanceMedium"
    android:id="@+id/xAxis"
    android:text="Medium Text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceMedium"
    android:text="Medium Text"
    android:id="@+id/yAxis"
    android:layout_gravity="center" />
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceMedium"
    android:text="Medium Text"
    android:id="@+id/zAxis"
    android:layout_gravity="center" />
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/dir"/>
<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/calibrate"
    android:text="Calibrate"/>

</LinearLayout>

MainActivity.java: MainActivity.java:

package com.example.rotationvectortest; 包com.example.rotationvectortest;

import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.text.DecimalFormat;


public class MainActivity extends Activity implements SensorEventListener     {

private SensorManager sensorManager;
private Sensor sensor;
private TextView xAxisView;
private TextView yAxisView;
private TextView zAxisView;
private TextView mDir;
private Button mCalibrate;

float x = 0;
float y = 0;
float z = 0;

boolean cal = false;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    xAxisView = (TextView) findViewById(R.id.xAxis);
    yAxisView = (TextView) findViewById(R.id.yAxis);
    zAxisView = (TextView) findViewById(R.id.zAxis);
    mDir = (TextView) findViewById(R.id.dir);
    mCalibrate = (Button) findViewById(R.id.calibrate);
    mCalibrate.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            cal = true;
        }
    });
    xAxisView.setText("X = 0.0");
    yAxisView.setText("Y = 0.0");
    zAxisView.setText("Z = 0.0");
    sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
    sensorManager.registerListener(this, sensor, 50000);

}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

@Override
public void onSensorChanged(SensorEvent event) {

    if (cal) {
        x = event.values[0];
        y = event.values[1];
        z = event.values[2];
        cal = false;
    }

    DecimalFormat format = new DecimalFormat("#.##");
    xAxisView.setText("X = " + format.format(event.values[0] - x));
    yAxisView.setText("Y = " + format.format(event.values[1] - y));
    zAxisView.setText("Z = " + format.format(event.values[2] - z));

}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {

}
}

AndroidManifest.xml: AndroidManifest.xml中:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rotationvectortest" >
<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:screenOrientation="portrait">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

</manifest>

So the values you get from the rotation vector are are based off of internal coordinates, and are essentially useless when it comes to understanding the devices' angle relative to the ground (or some other fixed point in the world). 因此,您从旋转矢量获得的值是基于内部坐标的,对于了解设备相对于地面(或世界上其他固定点)的角度而言,实际上是没有用的。

If you pass the data provided to you by the rotation vector sensor in SensorManager 's getRotationMatrixFromVector() call, the first three values are the azimuth, pitch, and roll (ie angles in the x,y, and z axes respectively) of the device. 如果您在SensorManagergetRotationMatrixFromVector()调用中传递由旋转矢量传感器提供的数据,则前三个值分别是传感器的方位角,俯仰和横滚(即分别在x,y和z轴上的角度)。设备。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM