Flutter & Mobil İle İleri Düzey İvmeölçer Hareket Algılama Sistemi Nasıl Yapılır?

Flutter & Mobil İle İleri Düzey İvmeölçer Hareket Algılama Sistemi Nasıl Yapılır?
Flutter & Mobil İle İleri Düzey İvmeölçer Hareket Algılama Sistemi Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Projeye başlamadan önce Flutter SDK'nızın güncel (3.24 ve üzeri) olduğundan emin olmalısınız. Donanım sensörlerine erişim sağlamak için sensors_plus kütüphanesini kullanacağız. Bu kütüphane, ivmeölçer, jiroskop ve manyetometre verilerine çapraz platform desteği sunar.

Pubspec.yaml dosyanıza gerekli bağımlılığı ekleyerek başlayın:

dependencies:
  flutter:
    sdk: flutter
  sensors_plus: ^6.0.0

Bağımlılığı ekledikten sonra terminalde flutter pub get komutunu çalıştırın. Ayrıca, Android için AndroidManifest.xml ve iOS için Info.plist dosyalarında sensör kullanım izinlerinin tanımlı olduğundan emin olun. Özellikle iOS tarafında NSMotionUsageDescription anahtarını eklemek, uygulamanızın reddedilmemesi için zorunludur.

Adım Adım İvmeölçer Verisini Okuma

İvmeölçer, cihazın üç eksendeki (x, y, z) ivmesini metre/saniye kare (m/s²) cinsinden ölçer. Hareket algılama sisteminin temeli, bu akışı sürekli dinlemek ve veriyi uygun bir örnekleme hızında (sampling rate) işlemektir.

import 'package:sensors_plus/sensors_plus.dart';

void listenToAccelerometer() {
  accelerometerEventStream().listen((AccelerometerEvent event) {
    print("X: ${event.x}, Y: ${event.y}, Z: ${event.z}");
  });
}

Yukarıdaki kod, sensörden gelen ham veriyi konsola yazdırır. Ancak, gerçek bir sistemde bu veriyi doğrudan kullanmak yerine bir "buffer" (tampon bellek) içinde toplamak ve ardından işlemek daha sağlıklı bir yaklaşımdır.

Sinyal İşleme ve Gürültü Filtreleme

Sensör verileri doğası gereği gürültülüdür. Küçük el titremeleri veya sensörün hassasiyeti, yanlış pozitif sonuçlara yol açabilir. "Low-pass filter" (alçak geçiren filtre) kullanarak yüksek frekanslı gürültüleri elemek, hareket algılama sisteminizin doğruluğunu artırır.

double alpha = 0.8;
double gravityX = 0, gravityY = 0, gravityZ = 0;

void applyLowPassFilter(AccelerometerEvent event) {
  gravityX = alpha * gravityX + (1 - alpha) * event.x;
  gravityY = alpha * gravityY + (1 - alpha) * event.y;
  gravityZ = alpha * gravityZ + (1 - alpha) * event.z;
  
  double linearAccelerationX = event.x - gravityX;
  // Bu değer, yerçekiminden arındırılmış saf hareketi temsil eder.
}

Bu yöntem, cihazın durduğu anlardaki yerçekimi etkisini veriden ayırarak, sadece kullanıcının yaptığı harekete odaklanmanızı sağlar.

Hareket Kalıpları (Gesture) Algılama Mantığı

İleri düzey bir sistemde, belirli bir hareketin (örneğin sallama veya belirli bir yöne çevirme) gerçekleştiğini anlamak için eşik değerleri (threshold) kullanırız. Aşağıdaki örnekte, cihazın anlık ivmesinin belirli bir değerin üzerine çıkıp çıkmadığını kontrol ediyoruz.

bool detectShake(AccelerometerEvent event) {
  double acceleration = event.x * event.x + event.y * event.y + event.z * event.z;
  double threshold = 250.0; // Eşik değerini ihtiyaca göre kalibre edin.
  
  if (acceleration > threshold) {
    return true;
  }
  return false;
}

Bu mantık, basit bir "sallama" hareketini algılamak için yeterlidir. Ancak daha karmaşık hareketler için "State Machine" (Durum Makinesi) yapısını kurmanız önerilir.

Karşılaştırmalı Sensör Veri İşleme Yöntemleri

Yöntem Avantaj Dezavantaj
Ham Veri Düşük gecikme (latency) Çok fazla gürültü içerir
Low-Pass Filtre Durağan hareketleri temizler Hızlı hareketlerde gecikme yaratır
Kalman Filtresi Yüksek doğruluk İşlemci yükü fazladır

Performans ve Pil Yönetimi İçin İpuçları

Sensörleri sürekli dinlemek, mobil cihazlarda ciddi bir pil tüketimine neden olur. Uygulamanız arka plana geçtiğinde sensör dinleyicisini mutlaka kapatmalısınız. Ayrıca, StreamSubscription nesnesini yönetmek, bellek sızıntılarını (memory leak) önlemek için kritiktir.

late StreamSubscription _subscription;

@override
void dispose() {
  _subscription.cancel(); // Bellek sızıntısını önlemek için stream'i kapatın.
  super.dispose();
}

Kritik Uyarı: Sensör verilerini işlerken UI thread'ini (arayüz iş parçacığı) meşgul etmeyin. Çok yoğun matematiksel hesaplamalar yapmanız gerekiyorsa, bu işlemleri compute fonksiyonu ile ayrı bir isolate (izole iş parçacığı) üzerinde gerçekleştirin.

Sıkça Sorulan Sorular

İvmeölçer verisi neden sürekli değişiyor?

İvmeölçer, cihazın yerçekimi ivmesini de ölçer. Cihaz sabit dursa bile z ekseninde yaklaşık 9.8 m/s² değerini görmeniz normaldir.

Farklı cihazlarda sensör hassasiyeti değişir mi?

Evet, her üreticinin sensör kalitesi farklıdır. Bu nedenle, uygulamanızda her zaman kullanıcıya özel kalibrasyon imkanı sunmalı veya eşik değerlerini dinamik belirlemelisiniz.

Arka planda hareket algılama mümkün mü?

Evet, ancak bunun için platforma özel servisler (Android'de Foreground Service, iOS'te Background Tasks) kullanmanız gerekir. Standart bir stream, uygulama kapandığında duracaktır.

En iyi örnekleme hızı nedir?

Genel hareket algılama için 60Hz (saniyede 60 örnek) yeterlidir. Daha yüksek hızlar pil tüketimini artırırken, daha düşük hızlar hareketin kaçırılmasına neden olabilir.

Sensör verilerini nasıl test ederim?

Fiziksel cihazlar en doğru sonucu verir. Emülatörlerde sensör simülasyonu sınırlıdır, bu yüzden geliştirme sürecinde gerçek cihaz kullanmanızı öneririz.

Yasal Sorumluluk Reddi: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Hareket algılama sistemleri, güvenlik veya sağlıkla ilgili kritik kararlar (örneğin düşme algılama) için kullanıldığında, profesyonel testlerden geçirilmiş, hata payı hesaplanmış ve donanım üreticisi spesifikasyonlarına uygun şekilde optimize edilmiş olmalıdır. Yazılım hatalarından doğabilecek sonuçlardan geliştirici sorumludur.

İleri Düzey Hareket Sınıflandırma: TensorFlow Lite Entegrasyonu

İvmeölçer verilerini ham değerlerle işlemek, basit "sallama" (shake) hareketleri için yeterli olsa da, karmaşık kullanıcı davranışlarını (yürüme, merdiven çıkma, bisiklet sürme) ayırt etmek için yetersiz kalır. Bu noktada, toplanan sensör verilerini bir zaman serisi (time-series) olarak ele alıp, eğitilmiş bir makine öğrenmesi modeline beslemek en profesyonel yaklaşımdır.

Flutter projenize tflite_flutter paketini ekleyerek, önceden eğitilmiş bir model ile gerçek zamanlı sınıflandırma yapabilirsiniz. Aşağıdaki örnek, sensörden gelen verilerin nasıl bir "input tensor" yapısına dönüştürüleceğini göstermektedir:

import 'package:tflite_flutter/tflite_flutter.dart';

// Sensör verilerini modelin beklediği 3D dizi formatına dönüştürme
List prepareInput(List x, List y, List z) {
  List input = [];
  for (int i = 0; i < 50; i++) { // 50 örneklem genişliğinde bir pencere
    input.add([x[i], y[i], z[i]]);
  }
  return input;
}

// Model tahmini çalıştırma
void classifyMovement(Interpreter interpreter, List input) {
  var output = List.filled(1 * 3, 0).reshape([1, 3]);
  interpreter.run(input, output);
  print("Tahmin edilen hareket: ${output[0]}");
}

Üretim Ortamı İçin Hata Ayıklama ve Kalibrasyon Stratejileri

Uygulamanızı farklı cihazlarda yayına almadan önce, donanım varyasyonlarını yönetmek kritik bir süreçtir. Sensör sapmaları (bias) ve gürültü oranları cihazdan cihaza ciddi farklılıklar gösterebilir. Üretim aşamasında şu stratejileri izlemek, hata payını minimize eder:

  • Sensör Kalibrasyon Paneli: Kullanıcıya, cihazı düz bir zemine koymasını söyleyen ve "sıfırlama" (offset) değerlerini hesaplayan bir kalibrasyon sihirbazı sunun.
  • Veri Günlüğü (Logging): Hatalı algılamaların yaşandığı durumlarda, sensör verilerini yerel bir dosyaya (CSV formatında) kaydederek, geliştirme ortamında bu verileri "replay" (tekrar oynatma) yöntemiyle test edin.
  • Eşik Değer Dinamikliği: Eşik değerleri (threshold) sabit kodlamak yerine, cihazın ivmeölçer hassasiyetine göre (örneğin Sensor.accuracy değerini kontrol ederek) çalışma zamanında güncelleyin.

Aşağıdaki tablo, farklı hareket türleri için önerilen örnekleme hızlarını ve filtreleme gereksinimlerini özetlemektedir:

Hareket Tipi Örnekleme Hızı (Hz) Filtreleme İhtiyacı
Adım Sayar 20 - 50 Hz Düşük Geçiren (Low-pass)
Düşme Algılama 100+ Hz Yüksek Geçiren (High-pass)
Ekran Döndürme 10 Hz Hareketli Ortalama
İpucu: Sensör verilerini işlerken dart:async içindeki StreamTransformer yapısını kullanmak, ana iş parçacığını (UI Thread) yormadan veri akışını yönetmenizi sağlar. Bu, özellikle düşük seviyeli cihazlarda "jank" (takılma) sorunlarını engellemek için hayati önem taşır.

Sonuç

Flutter ile ivmeölçer hareket algılama sistemi geliştirmek, doğru filtreleme teknikleri ve verimli kaynak yönetimi ile oldukça güçlü bir özellik haline gelebilir. Bu rehberde öğrendiğiniz düşük geçiren filtreleme, eşik değer belirleme ve stream yönetimi adımları, profesyonel seviyede bir hareket algılama altyapısının temelini oluşturur. Bir sonraki adım olarak, bu verileri bir yapay zeka modeliyle (örneğin TensorFlow Lite ile) birleştirerek, basit sallama hareketlerinin ötesinde, kullanıcının yürüme veya koşma gibi aktivitelerini sınıflandırmayı deneyebilirsiniz.

Bu yazıya tepkinizi paylaşın:
Selin Yılmaz

Yaratıcı problem çözme teknikleri üzerine odaklanan bir içerik editörüyüm. Hayatı pratikleştiren tüyolarla okuyucuya zaman kazandırmayı hedefleyen yazılar kurguluyorum.

Yorumlar (0)

Yorum Yaz