如何在 Android 中获取方向(如北、西)

Posted

技术标签:

【中文标题】如何在 Android 中获取方向(如北、西)【英文标题】:How to get Direction in Android (Such as North, West) 【发布时间】:2012-01-09 02:19:24 【问题描述】:

我是 android 新手,我想根据我的相机获得方向。如何根据我的相机获取方向信息?你能给出一个想法吗?

【问题讨论】:

【参考方案1】:

TYPE_ORIENTATION 已弃用

我们不能再使用方向传感器了,我们可以同时使用磁场传感器和加速度传感器来获得同等的功能。它的工作量更大,但它确实允许继续使用回调来处理方向变化。

加速度计和磁场方位角的转换:

float[] mGravity;
float[] mGeomagnetic;

public void onSensorChanged(SensorEvent event) 

    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];

        if (SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic)) 
            
            // orientation contains azimut, pitch and roll
            float orientation[] = new float[3];
            SensorManager.getOrientation(R, orientation);

            azimut = orientation[0];
        
    

要指向北方,您可以计算旋转度数:

float rotation = -azimut * 360 / (2 * 3.14159f);

【讨论】:

链接似乎无效。你能举个例子或其他链接吗? 当然web.archive.org/web/20180501005730/http://…【参考方案2】:

到目前为止,这对我来说有点用,返回的值在 0 到 360 之间,但我认为北方没有正确校准?我在运行 Android 5.0.1 的 LG G Pad 上使用它

public void onSensorChanged(SensorEvent event) 
    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 outR[] = new float[9];
        float I[] = new float[9];

        boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);
        if (success) 
            float orientation[] = new float[3];

            SensorManager.remapCoordinateSystem(R, SensorManager.AXIS_X, SensorManager.AXIS_Y, outR);

            SensorManager.getOrientation(outR, orientation);
            azimut = orientation[0];

            float degree = (float)(Math.toDegrees(azimut)+360)%360;

            System.out.println("degree " + degree);

我确信我错过了一些东西,但希望这对其他人来说是一个不错的起点。为了达到这一点,我查看了很多其他问题、cmets 等。

【讨论】:

什么是 mGravity? 自从我看到这个@AyushSth 已经有 5 年多了,但我相信它只是一个数组。查看定义 mGravity 和 mGeomagnetic 的答案之前的答案。【参考方案3】:

根据您的相机不确定您的意思,但您可以根据硬件传感器获得它。请参阅以下链接:

Compass Example

还可以查看 this 页面上的传感器 TYPE_ORIENTATION

【讨论】:

TYPE_ORIENTATION 已弃用,请参阅***.com/a/23060896/1480391【参考方案4】:

使用结合了地磁和重力传感器的旋转矢量传感器。然后使用SensorManager.getOrientation 将 5 个值的数组转换为 OpenGL 样式的旋转矩阵。正如文档所说,第一个值是以弧度表示的指南针方向。

这本身并不能解决您从相机的角度了解指南针方向的问题。相反,它假设屏幕与地面平行,就像老式的袖珍指南针一样,它会报告屏幕顶部指向的方向。因此,如果屏幕顶部朝北,则方向 (event.values[0]) 为 0。如果屏幕顶部笔直向上,则方向未定义。不幸的是,这在使用相机时很常见。

在示例监听器中,我将使用枚举在 Android 的默认袖珍罗盘风格方向和后置摄像头方向之间切换,这样您就可以看到 Android 期望的用例和您想要的用例。

enum class CompassCoordinateSystem  POCKET_COMPASS, REAR_CAMERA 

然后写一个SensorEventListener 来跟踪更改。为了清楚起见,我没有在下面的代码中import android.hardware.SensorManager.*。下面定义的所有数组都由 SensorManager 静态方法填充。

/** The latest compass orientation as a 3D vector. */
private var orientation3D = FloatArray(3)
private var coordinateSystem = CompassCoordinateSystem.REAR_CAMERA_ROTATION

fun compassDegrees(): Float = azimuthToDegrees(compassRadians())
fun compassRadians(): Float = orientation3D[0]

/** Convert such that North=0, East=90, South=180, West=270. */
fun azimuthToDegrees(azimuth: Float): Float 
    return ((Math.toDegrees(azimuth.toDouble())+360) % 360).toFloat()


override fun onSensorChanged(event: SensorEvent?) 
    if (event?.sensor?.type == Sensor.TYPE_ROTATION_VECTOR) 
         val rotationMatrix = FloatArray(9)
         SensorManager.getRotationMatrixFromVector(rotationMatrix, event.values)
         when (coordinateSystem) 
            CompassCoordinateSystem.POCKET_COMPASS -> SensorManager.getOrientation(rotationMatrix, orientation3D)
            CompassCoordinateSystem.REAR_CAMERA -> 
                val rearCameraMatrix = FloatArray(9)
                // The axis parameters for remapCoordinateSystem() are
                // from an example in that method's documentation
                SensorManager.remapCoordinateSystem(rotationMatrix,
                    SensorManager.AXIS_X, 
                    SensorManager.AXIS_Z, 
                    rearCameraMatrix)
                SensorManager.getOrientation(rearCameraMatrix, orientation3D)
            
        
    

【讨论】:

不清楚你的变量指的是什么。旋转向量、mValuesOrientation 等 @JaswantSingh:我重写了这个例子,不仅仅是为了修正变量,而是为了纠正相机方向。 我发现这个答案非常有用

以上是关于如何在 Android 中获取方向(如北、西)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Xamarin.Android 中获取指南针方向

如何从两个地方的纬度和经度获得一个地方到另一个地方的方向?

为了获得方向,哪种方法更好?

使用 PHP 从输入的城市和方向获取城市列表

如何在 android 上使用 google map api 获取 google 驾驶指令?

如何在不使用谷歌地图 api 的情况下获取方向箭头