detectSitDown method
int
detectSitDown({
- required List<
SensorEvent> accData, - required double accActualRate,
- required DateTime startTime,
- required DateTime minimumTime,
Detects the sit-down event in TUG test using accelerometer data.
Similar to stand-up detection but searches after a given start time and ensures proper timing constraints (minimum 2 seconds after detection). The algorithm:
- Removes gravity from y-axis acceleration
- Applies low-pass filtering
- Detects peaks in processed data after start time
- Validates timing by waiting 2 seconds after detection
Returns the index of the detected sit-down event, or -1 if none found.
Implementation
int detectSitDown({
required List<SensorEvent> accData,
required double accActualRate,
required DateTime startTime,
required DateTime minimumTime,
}) {
if (accData.isEmpty) return -1;
int smoothingWindow = 10;
double threshold = 0.6; // Acceleration threshold for sit-down detection
// Process accelerometer data - remove gravity from y-axis
var processedAccData = lowPassFilter(
accData.map((e) => e.y - 9.8).toList(),
4.0, // Low-pass filter cutoff frequency
);
// Apply smoothing using moving average window (same as stand-up detection)
List<double> smoothedAcc = List<double>.filled(
processedAccData.length,
0.0,
);
for (int i = 0; i < processedAccData.length; i++) {
double sum = 0.0;
int count = 0;
// Calculate moving average within window bounds
for (
int j = (i - smoothingWindow ~/ 2).clamp(
0,
processedAccData.length - 1,
);
j <= (i + smoothingWindow ~/ 2).clamp(0, processedAccData.length - 1);
j++
) {
sum += processedAccData[j];
count++;
}
smoothedAcc[i] = sum / count;
}
// Find starting index based on start time
var startIndex = accData.indexWhere((a) => a.timestamp.isAfter(startTime));
var sitIndex = -1;
// Search for sit-down event after start time with timing validation
for (int i = startIndex; i < processedAccData.length - 1; i++) {
bool isPeak =
processedAccData[i] > processedAccData[i - 1] &&
processedAccData[i] > processedAccData[i + 1];
if (isPeak && processedAccData[i] > threshold) {
sitIndex = i; // Record potential sit-down event
}
if (sitIndex != -1 &&
i - sitIndex > 2 * accActualRate &&
accData[i].timestamp.isAfter(minimumTime)) {
// Ensure at least 2 seconds after sit down for validation
return sitIndex;
}
}
return -1;
}