How to get Direction in Android (Such as North, West)

前端 未结 4 989
伪装坚强ぢ
伪装坚强ぢ 2020-12-10 16:09

I am new in Android and I want to get direction according to my camera. How can I get direction information according to my camera? Could you give an idea for this?

4条回答
  •  野趣味
    野趣味 (楼主)
    2020-12-10 16:42

    Use the Rotation Vector sensor, which combines the geomagnetic and gravitational sensors. Then use SensorManager.getOrientation to convert from an array of 5 values to an OpenGL-style rotation matrix. As the documentation says, the first value is the compass orientation in radians.

    By itself, this doesn't solve your problem of knowing the compass direction from the perspective of your camera. Rather, it assumes the screen is parallel to the ground, like an old-fashioned pocket compass, and it reports which way the top of the screen is pointed. Thus, if the top of the screen is facing north, the orientation (event.values[0]) is 0. If the top of the screen is pointed straight up, the orientation is undefined. Unfortunately, this is a common case when using your camera.

    In the example listener, I will use an enum to switch between Android's default pocket-compass style orientation and rear camera orientation, so you can see both the use case Android expects and the one you want.

    enum class CompassCoordinateSystem { POCKET_COMPASS, REAR_CAMERA }
    

    Then write a SensorEventListener to track changes. For clarity I did not import android.hardware.SensorManager.* in the code below. All the arrays defined below are populated by SensorManager static methods.

    /** 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)
                }
            }
        }
    }
    

提交回复
热议问题