Rotation Vector Sensor in Mobile Apps
Use the fused rotation-vector / device-attitude sensor to get drift-free orientation on iOS and Android.
The rotation vector — called "device attitude" on iOS — is the single most useful motion signal in a smartphone. It fuses the accelerometer, gyroscope and magnetometer into a quaternion that describes the device's 3D orientation in the world. AR frameworks, compass apps and 3D viewers all build on top of it.
Key Takeaways
- Returns orientation as a unit quaternion (x, y, z, w) or roll/pitch/yaw in radians.
- Drift-free: the magnetometer corrects yaw, the accelerometer corrects pitch and roll.
- iOS exposes it via `CMDeviceMotion.attitude`; Android via `TYPE_ROTATION_VECTOR` (or `GAME_ROTATION_VECTOR` without the magnetometer).
- Use it for AR, compass overlays, 360° video viewers and panorama capture UIs.
Rotation Vector at a Glance
What It Is & How It Works
What it is. A virtual sensor that outputs the orientation of the device as a quaternion. Internally the OS runs a Kalman / complementary filter that combines the gyroscope (fast but drifting), accelerometer (slow but absolute "down") and magnetometer (slow but absolute "north").
How it works. Subscribe to a stream and you get either a quaternion or a rotation matrix. Convert to roll/pitch/yaw with a one-line helper if you need Euler angles.
Units & signal. Quaternion components are unitless and unit-norm. Euler angles in radians (Android `getOrientation`) or degrees (iOS via small conversion).
What You Can Build With It
AR placement
Anchor virtual objects so they stay world-fixed when the device moves.
Example: A "preview furniture in your room" feature in a retail app.
Compass with tilt compensation
Use yaw from the rotation vector instead of computing heading from raw mag values.
Example: A compass that stays accurate even when held at an angle.
360° / panorama viewers
Drive the camera angle in a 3D scene directly from the device attitude.
Example: A real-estate app that lets users explore a 360° living room photo by tilting.
Stabilised camera UIs
Counter-rotate UI overlays so the horizon stays level on screen.
Example: A photography app that draws a fixed horizon line over the viewfinder.
Permissions & Setup
iOS prompts for Motion & Fitness on first use. Android requires no runtime permission, though some OEMs require enabling location services for the magnetometer to be calibrated.
iOS · Info.plist
NSMotionUsageDescription
Android · AndroidManifest.xml
No special permission keys required.
Code Examples
Setup
- Expo: `npx expo install expo-sensors` (use `DeviceMotion.rotation`)
- iOS: `CMMotionManager.startDeviceMotionUpdates(using:to:)` — pick a reference frame
- Android: `Sensor.TYPE_ROTATION_VECTOR` (or `TYPE_GAME_ROTATION_VECTOR` without magnetometer)
import { useEffect, useState } from 'react';
import { DeviceMotion } from 'expo-sensors';
export function useAttitude() {
const [r, setR] = useState({ alpha: 0, beta: 0, gamma: 0 });
useEffect(() => {
DeviceMotion.setUpdateInterval(50);
const sub = DeviceMotion.addListener(({ rotation }) => {
if (rotation) setR(rotation); // radians: alpha=yaw, beta=pitch, gamma=roll
});
return () => sub.remove();
}, []);
return r;
}Tip: With Newly, you describe the feature you want and the AI agent wires up the sensor, permissions, and UI for you. Try it free.
Best Practices
Use quaternions internally
Quaternions avoid gimbal lock and interpolate smoothly. Convert to Euler only for display.
Pick the right reference frame on iOS
`xMagneticNorthZVertical` is the right default for compass / AR. Use `xArbitraryZVertical` if you don't care about absolute heading and don't want magnetometer dependency.
Use GAME_ROTATION_VECTOR when magnetometer is unreliable
Android's `TYPE_GAME_ROTATION_VECTOR` skips the magnetometer — perfect for indoors or near interference.
Throttle updates for UI
AR / 3D rendering can use 60+ Hz, but plain UI updates only need 15–30 Hz to feel smooth.
Common Pitfalls
Coordinate frame surprises
iOS, Android and OpenGL each use slightly different axes. A direct copy of values between them causes mirrored / upside-down behaviour.
Mitigation: Pick one library that normalises (Expo, Three.js, ARKit/ARCore) and stick with its conventions.
Mixing degrees and radians
Half the APIs use radians, half use degrees, and one or two report only quaternions.
Mitigation: Wrap everything in a small helper that returns one consistent unit.
Magnetometer dragging the result
Indoor or near steel, the magnetometer can yank yaw 30°+.
Mitigation: Switch to `GAME_ROTATION_VECTOR` (or iOS `xArbitraryZVertical`) for indoor scenes that don't need true north.
Forgetting devices without a magnetometer
A few cheap tablets ship without one — `TYPE_ROTATION_VECTOR` may then be unavailable.
Mitigation: Feature-detect and gracefully fall back to `GAME_ROTATION_VECTOR` or accelerometer-only tilt.
When To Use It (And When Not To)
Good fit
- AR object placement and 3D pose tracking
- Tilt-compensated compass and heading overlays
- 360° image / video viewers
- Stabilising on-screen indicators against device rotation
Look elsewhere if…
- Step counting or activity recognition — use linear acceleration
- Background updates on iOS without entitlement
- Devices missing a magnetometer if you need true north
- Computing translation — orientation only, no position
Frequently Asked Questions
What is the difference between rotation vector and quaternion?
Android's rotation vector is essentially the imaginary part of a unit quaternion. You can pass it to `getRotationMatrixFromVector` to get a usable 3x3 matrix or compute the full quaternion with one extra step.
Why does my AR scene tilt when I walk near a fridge?
Magnetic interference is corrupting the yaw correction. Switch to `GAME_ROTATION_VECTOR` (Android) or `xArbitraryZVertical` (iOS) when absolute heading isn't required.
Should I subscribe to the rotation vector or build my own fusion?
Use the platform sensor unless you have very specific needs (sub-degree pose for industrial AR). The vendor implementations are tuned for the device's chip.
Does this drift?
Pitch and roll are absolute (anchored by gravity); yaw is absolute when the magnetometer is reliable. Without a magnetometer, yaw will drift slowly — that's why `GAME_ROTATION_VECTOR` exists.
Build with the Rotation Vector on Newly
Ship a rotation vector-powered feature this week
Newly turns a description like “use the rotation vector to ar placement” into a real React Native app — permissions, native modules and UI included. Full source code is yours, and you can publish to the App Store and Google Play directly from the dashboard.
Want a deeper dive on the underlying APIs? See Expo Sensors, Apple Core Motion and Android sensor framework.
