DEV Community

HarmonyOS
HarmonyOS

Posted on

How to implement compass functionality with efficient sensor handling

Read the original article:How to implement compass functionality with efficient sensor handling

Context

Compass functionality is a common requirement in navigation, fitness, and outdoor applications. In HarmonyOS, the ROTATION_VECTOR sensor can be used to detect the device's orientation in real-time and calculate the azimuth (the angle between the device's forward direction and magnetic north).

Description

This implementation uses the sensor.SensorId.ROTATION_VECTOR to access device orientation. It computes the azimuth (0°–360°) from quaternion values (x, y, z, w) and updates a UI with this direction. The azimuth value is also used to rotate a compass image accordingly.

The app listens to sensor updates at a defined interval and stops listening when the page disappears. Additionally, permission for the accelerometer must be declared in the app’s configuration.

Solution

Permission Declaration

"requestPermissions": [
    {
      "name": "ohos.permission.ACCELEROMETER"
    }
]
Enter fullscreen mode Exit fullscreen mode

Sensor Setup

sensor.on(sensor.SensorId.ROTATION_VECTOR, (data) => {
  const { x, y, z, w } = data
  const siny_cosp = 2 * (w * z + x * y)
  const cosy_cosp = 1 - 2 * (y * y + z * z)
  const azimuthRad = Math.atan2(siny_cosp, cosy_cosp)
  const azimuthDeg = (azimuthRad * 180 / Math.PI + 360) % 360

  this.azimuth = Math.round(azimuthDeg)
}, {
  interval: 100_000_000 // 100ms
})
Enter fullscreen mode Exit fullscreen mode

Lifecycle Management

aboutToAppear() {
  this.onPageShow()
}

aboutToDisappear() {
  sensor.off(sensor.SensorId.ROTATION_VECTOR)
}
Enter fullscreen mode Exit fullscreen mode

UI Update

Text(`Azimuth: ${this.azimuth}°`)
Image($r('app.media.compass'))
  .rotate({ angle: -this.azimuth })
Enter fullscreen mode Exit fullscreen mode

Key Takeaways

  • Use ROTATION_VECTOR for smooth compass readings without magnetic field noise.
  • Convert quaternion values to azimuth using trigonometric formulas.
  • Use sensor.on() and sensor.off() in lifecycle methods for clean resource usage.
  • Declare sensor permissions (ACCELEROMETER) in module.json5 to avoid permission errors.

Additional Resources

https://developer.huawei.com/consumer/en/doc/harmonyos-guides/arkui-overview?source=post_page-----ac19ba17e6c0---------------------------------------

Written by Ahmet Furkan Sevim

Top comments (0)