Skip to content

Instantly share code, notes, and snippets.

@simplecohesion
Last active February 10, 2020 14:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simplecohesion/6b36be51687334ba7e45d40ac3077759 to your computer and use it in GitHub Desktop.
Save simplecohesion/6b36be51687334ba7e45d40ac3077759 to your computer and use it in GitHub Desktop.
MetaWear Quaternion Streaming
extension MetaWear{
func configureSensorFusion() -> Task<()> {
guard isConnectedAndSetup else {
return Task<()>.init(error: MetaWearError.operationFailed(message: "device not connected"))
}
let completionSource = TaskCompletionSource<()>()
self.apiAccessQueue.async {
mbl_mw_metawearboard_tear_down(self.board)
mbl_mw_sensor_fusion_set_mode(self.board, MBL_MW_SENSOR_FUSION_MODE_IMU_PLUS)
mbl_mw_sensor_fusion_write_config(self.board)
completionSource.trySet(result: ())
}
return completionSource.task
}
func createQuaternionTimerSignal(samplePeriod: UInt32) -> Task<OpaquePointer> {
guard isConnectedAndSetup else {
return Task<OpaquePointer>.init(error: MetaWearError.operationFailed(message: "device not connected"))
}
let completionSource = TaskCompletionSource<OpaquePointer>()
self.apiAccessQueue.async {
mbl_mw_dataprocessor_time_create(self.quaternionSignal, MBL_MW_TIME_ABSOLUTE, samplePeriod, bridgeRetained(obj: completionSource)) { (context, dataPtr) in
let _completionSource: TaskCompletionSource<OpaquePointer> = bridgeTransfer(ptr: context!)
guard let dataPtr = dataPtr else {
_completionSource.trySet(error: MetaWearError.operationFailed(message: "No data pointer"))
return
}
_completionSource.trySet(result: dataPtr)
}
}
return completionSource.task
}
func startStreamingQuaternion(timerSignal: OpaquePointer, sensorDataBridge: SensorDataBridge) -> Task<()> {
guard isConnectedAndSetup else {
return Task<()>.init(error: MetaWearError.operationFailed(message: "device not connected"))
}
let completionSource = TaskCompletionSource<()>()
sensorDataBridge.completionSource = completionSource
self.apiAccessQueue.async {
mbl_mw_datasignal_subscribe(sensorDataBridge.quaternionTimeSignal, bridge(obj: sensorDataBridge)) { (context, dataPtr) in
let _sensorDataBridge: SensorDataBridge = bridge(ptr: context!)
guard let dataPtr = dataPtr else {
if !(_sensorDataBridge.completionSource?.task.completed ?? false) {
_sensorDataBridge.completionSource?.trySet(error: MetaWearError.operationFailed(message: "could not subscribe to quaternion streaming"))
}
return
}
//return completed task only when first data has streamed
if !(_sensorDataBridge.completionSource?.task.completed ?? false) {
_sensorDataBridge.completionSource?.trySet(result: ())
}
let mblQuaternion = dataPtr.pointee.copy().valueAs() as MblMwQuaternion
_sensorDataBridge.metawearHandler?.quaternionData(quaternion: mblQuaternion, metawear: _sensorDataBridge.metawear)
}
mbl_mw_sensor_fusion_enable_data(self.board, MBL_MW_SENSOR_FUSION_DATA_QUATERNION)
mbl_mw_sensor_fusion_start(self.board)
}
return completionSource.task
}
func stopStreamingQuaternion(sensorDataBridge: SensorDataBridge) -> Task<()> {
guard isConnectedAndSetup else {
return Task<()>.init(error: MetaWearError.operationFailed(message: "device not connected"))
}
let source = TaskCompletionSource<()>()
apiAccessQueue.async {
mbl_mw_datasignal_unsubscribe(sensorDataBridge.quaternionTimeSignal)
mbl_mw_dataprocessor_remove(sensorDataBridge.quaternionTimeSignal)
sensorDataBridge.quaternionTimeSignal = nil
mbl_mw_sensor_fusion_stop(self.board)
mbl_mw_sensor_fusion_clear_enabled_mask(self.board)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
source.trySet(result: ())
}
}
return source.task
}
}
protocol MetaWearDelegate: class {
func quaternionData(quaternion: MblMwQuaternion, metawear: MetaWear)
}
struct SensorDataBridge {
weak var metawearHandler: MetaWearDelegate?
var metawear: MetaWear
var quaternionTimeSignal: OpaquePointer?
var completionSource: TaskCompletionSource<()>?
init (_ metawearHandler: MetaWearDelegate, _ metawear: MetaWear) {
self.metawearHandler = metawearHandler
self.metawear = metawear
}
}
var metaWear: MetaWear
var sensorDataBridge: SensorDataBridge
metaWear.configureSensorFusion().continueOnSuccessWithTask {
return metaWear.createQuaternionTimerSignal(samplePeriod: UInt32(100))
}.continueOnSuccessWithTask { timerPointer in
return metaWear.startStreamingQuaternion(timerSignal: timerPointer, sensorDataBridge: sensorDataBridge)
}.continueOnError { error in
//handle error
}
@mehdico
Copy link

mehdico commented Feb 10, 2020

hi @simplecohesion,
I got some errors in MetaWear+QuaternionStreaming.swift file.
can you help me, please?

- Value of type 'MetaWear' has no member 'quaternionSignal' (mbl_mw_dataprocessor_time_create(self.quaternionSignal, MBL_M...)

- Cannot assign to property: 'sensorDataBridge' is a 'let' constant (sensorDataBridge.completionSource = completionSource)

- Cannot invoke 'bridge' with an argument list of type '(obj: SensorDataBridge)' (mbl_mw_datasignal_subscribe(sensorDataBridge.quaternionTime...)

- Cannot assign to property: 'sensorDataBridge' is a 'let' constant (sensorDataBridge.quaternionTimeSignal = nil)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment