performTUG method
Performs the Timed Up and Go (TUG) test.
Handles the detection of stand up, turns, and sit down events using sensor data. Returns a TugResult with the calculated duration and segment times. Handles cancellation and errors gracefully.
Implementation
Future<TugResult> performTUG() async {
try {
// Start probe
await probe.start();
var standUpIndex = -1;
var firstTurnIndex = Turning(startIndex: -1, endIndex: -1);
var secondTurnIndex = Turning(startIndex: -1, endIndex: -1);
var sitDownIndex = -1;
while (standUpIndex == -1) {
if (kDebugMode) {
print('[TugTestStep] Waiting for stand up detection...');
}
if (completer.isCanceled) {
return TugResult(
identifier: identifier,
time: Duration.zero,
segmentTimes: [],
)..results['error'] = 'Cancelled';
}
await Future.delayed(const Duration(seconds: 1));
standUpIndex = processor.detectStandUp(
accData: probe.accelerometerData,
accActualRate: probe.currentAccSamplingRate().toDouble(),
);
}
if (kDebugMode) {
print(
'[TugTestStep] Stand up detected at index $standUpIndex, starting test...',
);
}
while (firstTurnIndex.startIndex == -1 && firstTurnIndex.endIndex == -1) {
if (kDebugMode) {
print('[TugTestStep] Waiting for turn detection...');
}
if (completer.isCanceled) {
return TugResult(
identifier: identifier,
time: Duration.zero,
segmentTimes: [],
)..results['error'] = 'Cancelled';
}
await Future.delayed(const Duration(seconds: 1));
firstTurnIndex = processor.detectTurn(
gyroData: probe.gyroscopeData,
gyroActualRate: probe.currentGyroSamplingRate().toDouble(),
startTime: probe.accelerometerData[standUpIndex].timestamp,
angleThreshold: (maxAngle / 2) - 15.0,
);
}
if (kDebugMode) {
print(
'[TugTestStep] Turn detected with start index ${firstTurnIndex.startIndex}, end index ${firstTurnIndex.endIndex}, waiting for second turn...',
);
}
while (secondTurnIndex.startIndex == -1 &&
secondTurnIndex.endIndex == -1) {
if (kDebugMode) {
print('[TugTestStep] Waiting for second turn detection...');
}
if (completer.isCanceled) {
return TugResult(
identifier: identifier,
time: Duration.zero,
segmentTimes: [],
)..results['error'] = 'Cancelled';
}
await Future.delayed(const Duration(seconds: 1));
secondTurnIndex = processor.detectTurn(
gyroData: probe.gyroscopeData,
gyroActualRate: probe.currentGyroSamplingRate().toDouble(),
startTime: probe.gyroscopeData[firstTurnIndex.endIndex].timestamp,
angleThreshold: (maxAngle / 2) - 15.0,
);
}
if (kDebugMode) {
print(
'[TugTestStep] Second turn detected with start index ${secondTurnIndex.startIndex}, end index ${secondTurnIndex.endIndex}, waiting for sit down...',
);
}
while (sitDownIndex == -1) {
if (kDebugMode) {
print('[TugTestStep] Waiting for sit down detection...');
}
if (completer.isCanceled) {
return TugResult(
identifier: identifier,
time: Duration.zero,
segmentTimes: [],
)..results['error'] = 'Cancelled';
}
await Future.delayed(const Duration(seconds: 1));
sitDownIndex = processor.detectSitDown(
accData: probe.accelerometerData,
accActualRate: probe.currentAccSamplingRate().toDouble(),
startTime: probe.gyroscopeData[secondTurnIndex.startIndex].timestamp,
minimumTime: probe.gyroscopeData[secondTurnIndex.endIndex].timestamp,
);
}
if (kDebugMode) {
print(
'[TugTestStep] Sit down detected with index $sitDownIndex, stopping test...',
);
}
// Stop probe
await probe.stop();
var duration = probe.accelerometerData[sitDownIndex].timestamp.difference(
probe.accelerometerData[standUpIndex].timestamp,
);
var segmentTimes = [
probe.gyroscopeData[firstTurnIndex.startIndex].timestamp.difference(
probe.accelerometerData[standUpIndex].timestamp,
),
probe.gyroscopeData[firstTurnIndex.endIndex].timestamp.difference(
probe.gyroscopeData[firstTurnIndex.startIndex].timestamp,
),
probe.gyroscopeData[secondTurnIndex.startIndex].timestamp.difference(
probe.gyroscopeData[firstTurnIndex.endIndex].timestamp,
),
probe.gyroscopeData[secondTurnIndex.endIndex].timestamp.difference(
probe.gyroscopeData[secondTurnIndex.startIndex].timestamp,
),
probe.accelerometerData[sitDownIndex].timestamp.difference(
probe.gyroscopeData[secondTurnIndex.endIndex].timestamp,
),
];
if (kDebugMode) {
print('Detected duration: $duration');
}
final results = [
TugResult.fromResults(time: duration, segmentTimes: segmentTimes),
];
// Create WTResult
if (results.isNotEmpty) {
final result = results.first;
return TugResult(
identifier: identifier,
time: result.time,
segmentTimes: result.segmentTimes,
);
} else {
return TugResult(
identifier: identifier,
time: Duration.zero,
segmentTimes: [],
)..results['error'] = 'No valid results found';
}
} catch (e) {
if (kDebugMode) {
print('Error in TUGStep.execute: $e');
}
return TugResult(
identifier: identifier,
time: Duration.zero,
segmentTimes: [],
)..results['error'] = e.toString();
}
}