startHeadTracking method
Future<HeadTrackingResponse>
startHeadTracking({
- VitureImuFrequency imuFrequency = VitureImuFrequency.freq120Hz,
- bool setDarwinOpenExclusive = false,
Implementation
Future<HeadTrackingResponse> startHeadTracking({
VitureImuFrequency imuFrequency = VitureImuFrequency.freq120Hz,
bool setDarwinOpenExclusive = false,
}) async {
const imuMode = VitureImuMode.pose;
if (_isHeadTrackingActive || _isStarting) {
return HeadTrackingResponse(
status: true,
message: "Successfully started head tracking.",
code: bindings.VITURE_GLASSES_SUCCESS,
);
}
if (_isReleasing) {
throw StateError(
'Cannot start head tracking while release is in progress.',
);
}
_isStarting = true;
_imuMode = imuMode;
try {
_sensorController ??= StreamController<VitureSensorData>.broadcast();
final result = await _opQueue.then((_) async {
await connect(setDarwinOpenExclusive: setDarwinOpenExclusive);
final api = _api;
final provider = _provider;
if (api == null || provider == null || provider == ffi.nullptr) {
return HeadTrackingResponse(
status: false,
message: "Unable to find the glasses.",
code: bindings.VITURE_GLASSES_ERROR_DEVICE_REJECTED,
);
}
_deviceType = api.xr_device_provider_get_device_type(provider);
if (_deviceType != VitureDeviceType.carina) {
if (imuMode == VitureImuMode.raw) {
_rawCallable =
ffi.NativeCallable<
bindings.VitureImuRawCallbackFunction
>.listener((
ffi.Pointer<ffi.Float> dataPtr,
int timestamp,
int vsync,
) {
if (!_isHeadTrackingActive || dataPtr == ffi.nullptr) return;
final controller = _sensorController;
if (controller == null || controller.isClosed) return;
try {
controller.add(
VitureSensorData.raw(
gyroX: dataPtr[0],
gyroY: dataPtr[1],
gyroZ: dataPtr[2],
accelX: dataPtr[3],
accelY: dataPtr[4],
accelZ: dataPtr[5],
magX: dataPtr[6],
magY: dataPtr[7],
magZ: dataPtr[8],
temperature: dataPtr[9],
timestamp: timestamp,
vsync: vsync,
),
);
} catch (_) {}
});
api.xr_device_provider_register_imu_raw_callback(
provider,
_rawCallable!.nativeFunction,
);
} else {
_poseCallable =
ffi.NativeCallable<
bindings.VitureImuPoseCallbackFunction
>.listener((ffi.Pointer<ffi.Float> dataPtr, int timestamp) {
if (!_isHeadTrackingActive || dataPtr == ffi.nullptr) return;
final controller = _sensorController;
if (controller == null || controller.isClosed) return;
try {
controller.add(
VitureSensorData.pose(
roll: dataPtr[0],
pitch: dataPtr[1],
yaw: dataPtr[2],
quatW: dataPtr[3],
quatX: dataPtr[4],
quatY: dataPtr[5],
quatZ: dataPtr[6],
timestamp: timestamp,
),
);
} catch (_) {}
});
api.xr_device_provider_register_imu_pose_callback(
provider,
_poseCallable!.nativeFunction,
);
}
final openResult = api.xr_device_provider_open_imu(
provider,
imuMode.value,
imuFrequency.value,
);
if (openResult < 0) {
await _forceCleanupHeadTracking();
return HeadTrackingResponse(
status: false,
message: "Unable to find the glasses.",
code: bindings.VITURE_GLASSES_ERROR_DEVICE_REJECTED,
);
}
} else {
_posePtr = calloc<ffi.Float>(7);
_statusPtr = calloc<ffi.Int>();
_carinaTimer = Timer.periodic(const Duration(milliseconds: 2), (_) {
if (!_isHeadTrackingActive) return;
final api = _api;
final provider = _provider;
final posePtr = _posePtr;
final statusPtr = _statusPtr;
if (api == null ||
provider == null ||
posePtr == null ||
statusPtr == null) {
return;
}
try {
api.xr_device_provider_get_gl_pose_carina(
provider,
posePtr,
0.0,
statusPtr,
);
if (statusPtr.value == 0) {
final controller = _sensorController;
if (controller == null || controller.isClosed) return;
controller.add(
VitureSensorData.pose(
roll: posePtr[0],
pitch: posePtr[1],
yaw: posePtr[2],
quatW: posePtr[3],
quatX: posePtr[4],
quatY: posePtr[5],
quatZ: posePtr[6],
timestamp: DateTime.now().millisecondsSinceEpoch,
),
);
}
} catch (_) {}
});
}
return HeadTrackingResponse(
status: true,
message: "Successfully started head tracking.",
code: bindings.VITURE_GLASSES_SUCCESS,
);
});
_opQueue = _opQueue.then((_) {}, onError: (_) {});
if (result.status) {
_isHeadTrackingActive = true;
}
return result;
} catch (e) {
await _forceCleanupHeadTracking();
return HeadTrackingResponse(
status: false,
message: "Unable to find the glasses.",
code: bindings.VITURE_GLASSES_ERROR_DEVICE_REJECTED,
);
} finally {
_isStarting = false;
}
}