Skip to content

Fix iOS Motion accel: match Android units + sign convention#70

Merged
GenericJam merged 2 commits into
masterfrom
fix/ios-motion-accel-units
Jul 11, 2026
Merged

Fix iOS Motion accel: match Android units + sign convention#70
GenericJam merged 2 commits into
masterfrom
fix/ios-motion-accel-units

Conversation

@GenericJam

Copy link
Copy Markdown
Owner

What

Mob.Motion documents accel as m/s² with gravity included, but the iOS NIF was emitting CoreMotion's userAcceleration + gravity verbatim. That value is:

  1. in G (~1.0 at rest), not m/s² (~9.81) like Android's SensorManager.TYPE_ACCELEROMETER; and
  2. in iOS's own sign convention — CoreMotion's gravity vector points down, so at rest the up-axis reads −g. Android reports specific force (proper acceleration), a_coord − g_field, so at rest the up-axis reads +g.

So iOS accel was off from Android by both a scale factor and a sign. Any tilt- or shake-driven UI barely moved on iOS, and moved backwards when it did (found via a mascot whose pupils follow gravity — nearly still on iOS, then inverted once scaled).

Fix

Emit (userAcceleration − gravity) × 9.80665. That is exactly Android's a_coord − g_field: +g on the up-axis at rest, m/s², correct for both the static tilt term and the dynamic linear term — not merely a rest-time negation of the old value. gyro (rad/s) and mag (µT) already matched Android and are untouched.

Verified against known rest orientations:

Orientation Android iOS after fix
Flat, face-up (0, 0, +9.81) az = (0 − (−1.0))×9.81 = +9.81
Upright portrait (0, +9.81, 0) ay = (0 − (−1.0))×9.81 = +9.81

The underlying diagnosis (units + sign) was confirmed on a physical iPhone via an app-level patch that made a tilt UI track correctly on both axes; iOS Simulator has no motion hardware, so device verification of this exact NIF happens when a consuming app rebuilds --native against a release carrying it.

Also documents the accel convention explicitly in the Mob.Motion moduledoc so it's a stated cross-platform contract.

Note on mix.lock

Master's committed mix.lock is out of sync with mix.exs — the dev-tooling deps (recon, ex_ast, reach, sourceror) are declared but weren't locked, so mix format/mix compile (and the pre-push hook) can't run on a fresh checkout of master. The 4-line mix.lock addition here is just mix deps.get re-locking them; it's required for this branch to build and is unrelated to the accel change.

GenericJam and others added 2 commits July 10, 2026 22:36
`Mob.Motion` documents `accel` as m/s² with gravity included, but the iOS
NIF emitted `userAcceleration + gravity` straight from CoreMotion — which is
in G (~1.0, not ~9.81) AND uses iOS's own sign convention: the gravity vector
points down, so at rest the up-axis reads -g. Android's SensorManager reports
specific force (proper acceleration), a_coord - g_field, so at rest the up-axis
reads +g. The two were off by both a scale factor and a sign, so any tilt- or
shake-driven UI (e.g. a mascot whose pupils follow gravity) barely moved on iOS
and moved backwards when it did.

Emit `(userAcceleration - gravity) * 9.80665` instead. That is exactly Android's
a_coord - g_field: +g on the up-axis at rest, m/s², correct for both the static
tilt term and the dynamic linear term (not merely a rest-time negation). gyro
(rad/s) and mag (µT) already matched and are unchanged.

Also document the `accel` convention explicitly in the moduledoc so it's a
stated cross-platform contract, not folklore.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The accel normalization is ObjC inside the CoreMotion callback — no host
seam to unit-test, and the iOS Simulator delivers no motion data, so it's
not integration-testable off a physical device. Guard it the way
Mob.NifDeclarationTest guards the NIF tables: parse ios/mob_nif.m and assert
each accel axis SUBTRACTS gravity (Android specific-force sign, not iOS's
inverted `+ gravity`) and scales G→m/s². Fails on a revert to the old form.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@GenericJam GenericJam merged commit fdebfd8 into master Jul 11, 2026
4 checks passed
@GenericJam GenericJam deleted the fix/ios-motion-accel-units branch July 11, 2026 04:46
GenericJam added a commit that referenced this pull request Jul 11, 2026
Ships #70: Mob.Motion iOS `accel` now matches Android's m/s² units and
specific-force sign convention — (userAcceleration - gravity) * 9.80665
instead of the raw CoreMotion userAcceleration + gravity (G, inverted).
Fixes tilt/shake UIs that barely moved and moved backwards on iOS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant