Skip to content

[Bug]: iOS azimuth is not north-referenced (arbitrary yaw origin), unlike Android #95

Description

@camilleRiquet

Preliminary Bug Check

  • I've searched the issue tracker for similar bug reports.
  • I've checked Google and Stack Overflow for solutions.
  • I've read the plugin's documentation.
  • I'm using the latest plugin version and all dependencies are updated with flutter pub upgrade.
  • I've executed flutter clean.
  • I've tried running the example project.

Plugin Version

0.2.0

Expected Behavior

eulerAngles.azimuth should have the same meaning on Android and iOS - ideally a
north-referenced compass heading where 0 means the device points north.

Actual Behavior

On iOS the azimuth is not a compass heading. Its zero is an arbitrary horizontal
direction set when the sensor starts, and it changes on every cold launch, because
the iOS plugin starts device motion with the default reference frame
(CMAttitudeReferenceFrame.xArbitraryZVertical), which has no compass reference.

On Android the same API returns a magnetic-north / east-north-up heading
(TYPE_ROTATION_VECTOR), so azimuth == 0 when pointing north and is reproducible
across launches.

Root cause: in FlutterRotationSensorPlugin.swift, startDeviceMotionUpdates(to:)
is called without a reference frame, so CoreMotion defaults to the arbitrary one.

The two screenshots above were taken without moving the device: first is Google
Maps, second is my app using this plugin. The heading is consistently off, which
led me to dig into the reference frame.

I've put together a fix and will open a PR alongside this issue so you can see the
proposed approach (opt-in referenceFrame, default behavior unchanged).

That said, it's entirely possible I'm just holding it wrong or missed an existing
setting. If there's already a supported way to get a north-referenced azimuth on
iOS, please point me to it and feel free to close this. Thanks for the plugin!

Image Image

Code Sample

import 'package:flutter/material.dart';
  import 'package:flutter_rotation_sensor/flutter_rotation_sensor.dart';

  void main() => runApp(const MaterialApp(home: AzimuthDemo()));
  
  class AzimuthDemo extends StatefulWidget {
    const AzimuthDemo({super.key});
    @override
    State<AzimuthDemo> createState() => _AzimuthDemoState();
  }
  
  class _AzimuthDemoState extends State<AzimuthDemo> {
    double _azimuthDeg = 0;

    @override
    void initState() {
      super.initState();
      RotationSensor.orientationStream.listen((event) {
        setState(() => _azimuthDeg = event.eulerAngles.azimuth * 180 / 3.1415926535);
      });
    }

    @override
    Widget build(BuildContext context) => Scaffold(
          body: Center(
            // Point the device north and read this. On iOS the value differs on
            // each cold launch; on Android it stays ~0.
            child: Text('azimuth: ${_azimuthDeg.toStringAsFixed(1)}°'),
          ),
        );
  }

Steps to Reproduce

  1. Run the code sample on a physical iOS device.
  2. Point the device at magnetic north (cross-check with a known compass), note the
    displayed azimuth.
  3. Fully kill the app and relaunch it.
  4. Point at north again: the value differs from step 2.
  5. Repeat on Android: the value stays ~0° across launches.

Platform Details

iOS 26.5.1

Flutter SDK Version

3.35.7

Logs

This is a behavioral issue, not a crash: there is no exception in the logs.
  Evidence is the azimuth value while physically pointing north, on stock 0.2.0:
    launch 1: ~270°
    launch 2: ~130°   (different reference, same physical direction)
  On Android the same test stays ~0° across launches.

Flutter Doctor Output

[✓] Flutter (Channel stable, 3.35.7, on macOS 26.3.1 25D771280a darwin-arm64, locale fr-FR) [495ms]
    • Flutter version 3.35.7 on channel stable at /Users/camille/fvm/versions/3.35.7
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision adc9010625 (8 months ago), 2025-10-21 14:16:03 -0400
    • Engine revision 035316565a
    • Dart version 3.9.2
    • DevTools version 2.48.0
    • Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-lldb-debugging

[✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0) [2,3s]
    • Android SDK at /Users/camille/Library/Android/sdk
    • Emulator version 36.4.10.0 (build_id 15004761) (CL:N/A)
    • Platform android-36.1, build-tools 36.0.0
    • Java binary at: /Users/camille/Library/Java/JavaVirtualMachines/ms-21.0.9/Contents/Home/bin/java
      This JDK is specified in your Flutter configuration.
      To change the current JDK, run: `flutter config --jdk-dir="path/to/jdk"`.
    • Java version OpenJDK Runtime Environment Microsoft-12574443 (build 21.0.9+10-LTS)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 26.3) [1 619ms]
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 17C529
    • CocoaPods version 1.16.2

[✓] Chrome - develop for the web [25ms]
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2025.3) [24ms]
    • Android Studio at /Users/camille/Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 21.0.9+-14649483-b1163.86)

[✓] IntelliJ IDEA Ultimate Edition (version 2025.3.2) [23ms]
    • IntelliJ at /Users/camille/Applications/IntelliJ IDEA.app
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart


[✓] Network resources [595ms]
    • All expected network resources are available.

• No issues found!

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions