Skip to content

Modernize PiBall: universal Flutter app (iOS/Android/web) + wind-math fixes - #1

Merged
dovaka merged 3 commits into
masterfrom
flutter-rewrite
Aug 1, 2026
Merged

Modernize PiBall: universal Flutter app (iOS/Android/web) + wind-math fixes#1
dovaka merged 3 commits into
masterfrom
flutter-rewrite

Conversation

@dovaka

@dovaka dovaka commented Jun 3, 2026

Copy link
Copy Markdown
Owner

Ground-up rewrite of the 2014 Android/Java pibal theodolite as a Flutter app that runs on iOS, Android, and web from one codebase, with a Material 3 UI. The original Java app is preserved under legacy-android/.

What's new

  • Universal: single Flutter/Dart codebase, builds for iOS, Android, and web.
  • Modern UI: Material 3, dark by default (dawn launches), live azimuth/elevation readout, recording state machine, observation list, and a winds-aloft results table.
  • Sensor fusion in Dart: mirrors Android's getRotationMatrix/getOrientation, so iOS behaves the same.
  • Operator cues: haptic + click warning/read cues (no bundled audio).
  • Keep-awake while recording (wakelock_plus).
  • Magnetic declination: manual entry or "Use my location" — GPS fix (geolocator) + the bundled World Magnetic Model (geomag, WMM-2025, pure Dart).

Wind-math fixes (vs. the original)

Issue in original Fix
Ascent rate hard-coded to 300 ft/min Configurable in Settings
Heading used atan (two quadrants) Uses atan2 (all four)
Reported "wind to", not "wind from" Re-enabled the +180° convention
No true-north correction Magnetic declination (manual or GPS)
Dead "Settings" menu item Real, persisted settings screen

Notes

  • The magnetic_declination native plugin was tried first but ships a broken iOS Swift source that fails the Apple build; replaced with the pure-Dart geomag.
  • Phone magnetometers are far less precise than an optical theodolite — this is a rough field tool (documented in README).

Verification

  • flutter analyze — clean
  • flutter test — 9/9 pass (wind + orientation + declination math)
  • flutter build web — built
  • flutter build ios --no-codesign — built Runner.app

🤖 Generated with Claude Code

Patrick C. Sullivan and others added 3 commits June 2, 2026 19:02
Ground-up port of the 2014 Android/Java pibal theodolite to Flutter with a
Material 3 UI. The original Java app is preserved under legacy-android/.

Orientation (azimuth/elevation) is computed in Dart, mirroring Android's
getRotationMatrix/getOrientation, so it behaves the same on iOS.

Fixes the wind-math bugs from the original:
- ascent rate is now configurable (was hard-coded 300 ft/min)
- heading uses atan2 instead of atan (all four quadrants)
- reports meteorological "wind from" (+180, previously commented out)
- magnetic declination correction (true north)
- the dead Settings menu item is now a real, persisted settings screen

Verified: flutter analyze clean, 7/7 unit tests pass (wind + orientation
math), web and iOS (no-codesign) targets build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Keep the screen awake while recording (wakelock_plus), released on
  stop and dispose.
- "Use my location" in Settings fetches a GPS fix (geolocator) and computes
  magnetic declination from the bundled World Magnetic Model (geomag, WMM-2025).
  Pure Dart, so it works on iOS/Android/web; manual entry still available.
- iOS NSLocationWhenInUseUsageDescription + Android ACCESS_*_LOCATION perms.

Note: the magnetic_declination plugin was evaluated first but ships a broken
iOS Swift source that fails the Apple build, so geomag (pure Dart) is used.

Verified: analyze clean, 9/9 tests pass, web + iOS (no-codesign) build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Correctness:
- Circular (sin/cos) azimuth smoothing — fixes wrong averaging across the
  0/360 deg wrap near magnetic north.
- Flag low-elevation (<6 deg) layers as unreliable instead of emitting bogus
  speeds; clamp tan() so shallow sightings can't yield infinite range.
- Compass interference/calibration warning from magnetic field magnitude.

Field workflow:
- Manual "Capture" during a run; delete/re-take a sighting (recomputes).
- Optional spoken "3-2-1-mark" countdown (flutter_tts), haptics retained.
- Keep-screen-awake error-safe; re-asserts on app resume.

Output:
- Save every profile to History (with GPS + timestamp); review + share as CSV
  (share_plus). Wind-profile chart (speed vs altitude with wind-from arrows),
  toggleable against the table.
- Units toggle: knots/feet or m/s/metres, applied across UI + export.

Other:
- Optional camera Aim screen with crosshair + live AZ/EL overlay.
- App icon + proper "PiBall" display name on iOS/Android/web.
- Widget test for the Start/Stop/Calculate state machine; units tests.
- GitHub Actions CI (analyze + test).

Verified: flutter analyze clean, 18 tests pass, web + iOS (no-codesign) build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dovaka
dovaka merged commit c0f3340 into master Aug 1, 2026
1 check passed
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