Walk Wright
Het vermogen om te lopen kan verminderd zijn na een herseninfarct. Om het lopen te verbeteren, kan gebruik gemaakt worden van continue sensorische revalidatie via Real-Time Feedworward. Het volgt de beweging van de voeten door een sensor aan beide voeten te bevestigen.
De applicatie leest realtime de sensorgegevens en slaat ze op. Deze gegevens kunnen later in een algoritme geplaatst worden om het lopen te verbeteren. De gebruikte sensoren zijn de MetaMotionNR van MBientlab. Om met deze sensoren te communiceren levert MBientlab de MetaWear SDK. De gegevens worden opgeslagen met behulp van CoreData
en realtime sensorgegevens worden weergegeven met behulp van SwiftUI
.
Idee
Theo Theunissen van Moving Reality benaderde on gedurende de mobile application development cursus en vroeg ons of we intresse hadden om een iOS applicatie te ontwikkelen die deze sensoren konden uitlezen. Hij had problemen bij het gebruik van de SDK en vroeg ons om een wrapper om deze SDK te schrijven.
De SDK is een minimale wrapper om de MetaWear C++ library. Doordat de SDK een directe vertaling was van deze library ontstond er een probleem in het geheugen beheer van Swift. Omdat de sensoren een continue stroom van data sturen werd besloten de wrapper met RxSwift
te bouwen.
Uitdaging
De uitdaging in de SDK zat hem in de callbacks. De SDK implementeerde een bridge
functie om de sensor data op te halen binnen de callback. Echter toen de callback uitgevoerd werd was de referentie niet meer beschikbaar, Automatic Reference Counting had deze namelijk al uit het geheugen verwijderd.
mbl_mw_datasignal_subscribe(la, bridge(obj: self)) { (context, data) in
guard let context = context else { return }
let accSensor: AccelerometerSensor = bridge(ptr: context)
//...
}
Om dit probleem op te lossen hebben wij gekozen voor een static Dictionary
waarin alle sensoren werden toegevoegd. In de callback functie kon vervolgens de juiste sensor opgehaald worden door middel van het MAC address en de sensor type.
mbl_mw_datasignal_subscribe(la, bridge(obj: self)) { (context, data) in
//...
let sensor: AccelerometerSensor? = MetaWearDevice.getSensor(mac: accSensor.device.mac!, type: .accelerometer)
sensor?.subject?.onNext(cartesianFloat)
}