Skip to content

Repository files navigation

WildlifeAlert

A native iOS driving app that warns drivers about wildlife-collision risk zones — deer, elk, and moose corridors — in real time, using MapKit navigation, live Firestore-backed hotspot data, and an on-device machine learning model trained on real state crash records.

Think Waze, but for animal strikes: it warns you before you enter a known collision corridor, not after.

What it does

  • Turn-by-turn navigation (MapKit) with a live risk gauge that updates as you drive — pick live GPS or simulate the drive for testing/demos
  • Speed- and direction-aware alerts: warnings fire ahead of a hotspot based on your current speed and whether you're actually approaching it — not just because you're nearby, and not if you're driving away
  • Background alerting: region monitoring wakes the app even when it's backgrounded or killed, with local notifications
  • A transparent risk score, not a black box: severity, distance decay, time-of-day (dawn/dusk peaks), season (fall rut), weather, live traffic pace, recent crowdsourced sightings, and a machine learning prediction are all shown as separate, named factors — never a single unexplained number
  • Haptics, audio-ducked voice alerts, dark/night-mode-biased map styling, and a pre-trip risk summary before you even start driving

The data — real, not synthetic

Every hotspot is derived from real, publicly published state crash records — not hand-picked guesses:

State Source Real records Animal-collision records
Iowa Iowa DOT Crash Data (SOR) 606,986 85,398
Illinois Illinois DOT Crashes (7 years) 114,386
Virginia VDOT CrashData Basic 1,130,302 61,653
Massachusetts MassDOT IMPACT (2019–2025) 864,000+ 25,047
Tennessee TDOT Crashes (2021–2025) 767,000+ 32,164

Hotspots are derived by density-based clustering (DBSCAN, tuned per state) of the real animal-collision coordinates, with genuine road-segment geometry — most corridors are rendered as a buffered polyline along the actual road, not a generic circle.

States that were checked and found not usable are documented, not silently skipped: Ohio, Pennsylvania, Minnesota, Wisconsin, Utah, Kentucky, and Colorado all lack a public, no-login bulk-download crash dataset as of this writing. That's stated plainly in the code rather than papered over.

The model — honestly evaluated

A GradientBoostingClassifier trained on the real crash data above, blended with the transparent rule-based engine (not a replacement for it). An earlier version of this model reported a ROC AUC of 0.867 — that number had label leakage (it used cluster-derived features to predict cluster-derived labels). After a proper spatial cross-validation fix:

  • Honest ROC AUC: 0.8205 — down from the leaky 0.867, which is the expected and correct direction for fixing a leak, not a regression
  • Species features (deer/elk/moose) carry ~zero predictive importance, because none of the five source datasets have a real species field — worth knowing if you're deciding what to trust the model on
  • Full methodology and every known limitation: scratchpad_data/training_evaluations_v3.json

Why the model isn't asked about weather

The unit tests caught the model predicting lower collision probability in fog, rain, and snow than in clear conditions — the opposite of the app's own safety logic. That's not a bug in the blend arithmetic; it's the training data telling the truth about the wrong thing. Nearly all driving happens in clear weather, so clear weather accumulates the most crash records, and raw event frequency swamped per-mile risk in what the model learned.

Rather than let that quietly cancel out the visibility penalty, RiskEngine queries the model at a fixed "clear" reference — the modal training condition, where it's best calibrated — and applies the weather multiplier once to the blended score. The model still contributes the signal it genuinely learned (hour-of-day, corridor severity, and month account for ~88% of its feature importance); weather is left to the rule that actually means visibility and reaction time. testWeather_worseWeatherNeverLowersFinalScore pins the invariant so it can't regress.

Project structure

WildlifeAlert/          # iOS app source (Swift, MapKit, CoreML)
WildlifeAlertTests/      # XCTest coverage for the risk engine and alert logic
scripts/                 # Python data pipeline: sourcing, clustering, training, CoreML export
scratchpad_data/         # Cluster results, training metrics, hotspot candidates (small JSON only —
                         # raw multi-GB CSVs and model binaries are gitignored)

Building

Requires XcodeGen and a Firebase project (Firestore) of your own.

xcodegen generate
open WildlifeAlert.xcodeproj

You'll need your own WildlifeAlert/GoogleService-Info.plist (gitignored) from a Firebase project with a wildlifeHotspots collection seeded via the scripts in scripts/.

Tests

31 XCTest cases covering RiskEngine (distance decay, time-of-day, season, weather, traffic pace, sightings, severity ordering, ML blending) and AlertManager (approach detection, speed-scaled lead distance, de-duplication).

xcodebuild test -project WildlifeAlert.xcodeproj -scheme WildlifeAlert -destination 'platform=iOS Simulator,name=iPhone 17 Pro'

Retraining the model

cd scripts
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt  # scikit-learn, coremltools, pandas
python3 wildlife_data_v3.py      # download + cache real state crash data
python3 cluster_hotspots_v3.py   # per-state density-aware clustering
python3 train_risk_model_v3.py   # leakage-audited training with honest spatial CV
python3 export_coreml_v3.py      # export to WildlifeRiskModel.mlpackage

Known limitations

  • Real corridor data currently covers 5 states. Everywhere else the app reports "Area conditions" — a rule-based-only estimate from the location-independent factors (dawn/dusk, season, weather, speed), explicitly labeled "No corridor data here" and drawn in a neutral color rather than the green→red risk ramp. It is deliberately never green: this build previously showed a flat green 0% outside those five states, which stated as fact that a driver in California at dusk in the rain had zero collision risk. Absence of data is not evidence of safety, and the UI now says which one it's showing you
  • CarPlay support is scaffolded but non-functional — it requires Apple's manual CarPlay Navigation entitlement approval
  • WeatherKit requires a paid Apple Developer Program team; on a free/personal team the app falls back to deterministic mock weather automatically

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages