# IMU数据获取

可通过Android原生的api获取并显示加速度计、陀螺仪和磁力计的数据，详情请参考demo中的IMUActivity。

对于需要设备姿态（如旋转角度）的应用，直接使用原始传感器数据非常复杂。Android 提供了软件传感器，它自动融合了多个硬件传感器的数据，结果更平滑、更准确。

游戏旋转矢量传感器 (Game Rotation Vector)

这是最适合游戏和实时姿态跟踪的传感器，它不使用磁力计，因此不受磁场干扰，但无法提供绝对的方向（如指北）。

```kotlin
// 在 onCreate 中获取传感器
private var gameRotationVectorSensor: Sensor? = null

// 在 onCreate 方法内添加：
gameRotationVectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR)

// 在 onResume 中注册
gameRotationVectorSensor?.let {
    sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_FASTEST)
}

// 在 onSensorEvent 中处理数据
Sensor.TYPE_GAME_ROTATION_VECTOR -> {
    // event.values 包含4个分量：[x*sin(θ/2), y*sin(θ/2), z*sin(θ/2), cos(θ/2)]
    // 这是一个四元数(Quaternion)，表示旋转
    val x = event.values[0]
    val y = event.values[1]
    val z = event.values[2]
    val w = event.values[3]
    // 可以将四元数转换为欧拉角（俯仰角、横滚角、偏航角）以便于理解
    // 注意：由于不使用磁力计，偏航角是相对值，会漂移。
}
```

将四元数转换为欧拉角（简单示例）

```kotlin
private fun quaternionToEuler(x: Float, y: Float, z: Float, w: Float): FloatArray {
    val euler = FloatArray(3)

    // 俯仰角 (pitch, X轴旋转)
    val sinP = 2.0f * (w * x + y * z)
    val cosP = 1.0f - 2.0f * (x * x + y * y)
    euler[0] = Math.atan2(sinP.toDouble(), cosP.toDouble()).toFloat()

    // 横滚角 (roll, Y轴旋转)
    val sinR = 2.0f * (w * y - z * x)
    euler[1] = if (Math.abs(sinR) >= 1) {
        (Math.PI / 2).toFloat() * Math.signum(sinR)
    } else {
        Math.asin(sinR.toDouble()).toFloat()
    }

    // 偏航角 (yaw, Z轴旋转)
    val sinY = 2.0f * (w * z + x * y)
    val cosY = 1.0f - 2.0f * (y * y + z * z)
    euler[2] = Math.atan2(sinY.toDouble(), cosY.toDouble()).toFloat()

    // 将弧度转换为角度（可选）
    euler[0] = Math.toDegrees(euler[0].toDouble()).toFloat()
    euler[1] = Math.toDegrees(euler[1].toDouble()).toFloat()
    euler[2] = Math.toDegrees(euler[2].toDouble()).toFloat()

    return euler
}
```

采样率常量在 `registerListener` 时，你可以选择不同的采样率：

* `SENSOR_DELAY_FASTEST`：最快，尽可能高的频率。
* `SENSOR_DELAY_GAME`：适合游戏的速率。
* `SENSOR_DELAY_NORMAL`：默认速率，适合屏幕方向改变。
* `SENSOR_DELAY_UI`：适合用户界面变化。

最佳实践：总是记得在 `onPause()` 中调用 `sensorManager.unregisterListener(this)` 来避免后台耗电。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://rayneo.gitbook.io/rayneo-devdoc/x-xi-lie/android-kai-fa/neng-li-jie-shao/imu-shu-ju-huo-qu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
