raisewake: Improve raise to wake algorithm

This new algorithm calculates the number of degrees that the wrist has
rolled, and checks if that is above a threshold.

First it checks if the wrist is still enough for the acceleration values
to be considered mostly from gravity. It does this by calculating the
mean over the past 2 SystemTask loops, and checking that the variance
from that mean is below a threshold.
Then it calculates the angle the wrist is being held at, and calculates
the difference from the angle some time ago. If this difference is above
the threshold, it wakes the watch.
This commit is contained in:
Finlay Davidson 2023-05-20 01:27:00 +02:00 committed by JF
parent cfe21103ea
commit 2b1eae7f59
3 changed files with 16 additions and 21 deletions

View file

@ -87,26 +87,22 @@ MotionController::AccelStats MotionController::GetAccelStats() const {
return stats; return stats;
} }
bool MotionController::ShouldRaiseWake(bool isSleeping) { bool MotionController::ShouldRaiseWake() const {
if ((x + 335) <= 670 && zHistory[0] < 0) { constexpr uint32_t varianceThresh = 56 * 56;
if (!isSleeping) { constexpr int16_t xThresh = 384;
if (yHistory[0] <= 0) { constexpr int16_t yThresh = -64;
return false; constexpr int16_t rollDegreesThresh = -45;
}
lastYForRaiseWake = 0; if (x < -xThresh || x > xThresh) {
return false; return false;
} }
if (yHistory[0] >= 0) { // if the variance is below the threshold, the accelerometer values can be considered to be from acceleration due to gravity
lastYForRaiseWake = 0; if (stats.yVariance > varianceThresh || (stats.yMean < -724 && stats.zVariance > varianceThresh) || stats.yMean > yThresh) {
return false; return false;
} }
if (yHistory[0] + 230 < lastYForRaiseWake) {
lastYForRaiseWake = yHistory[0]; return DegreesRolled(stats.yMean, stats.zMean, stats.prevYMean, stats.prevZMean) < rollDegreesThresh;
return true;
}
}
return false;
} }
bool MotionController::ShouldShakeWake(uint16_t thresh) { bool MotionController::ShouldShakeWake(uint16_t thresh) {

View file

@ -45,7 +45,7 @@ namespace Pinetime {
} }
bool ShouldShakeWake(uint16_t thresh); bool ShouldShakeWake(uint16_t thresh);
bool ShouldRaiseWake(bool isSleeping); bool ShouldRaiseWake() const;
int32_t CurrentShakeSpeed() const { int32_t CurrentShakeSpeed() const {
return accumulatedSpeed; return accumulatedSpeed;
@ -86,7 +86,6 @@ namespace Pinetime {
int16_t lastX = 0; int16_t lastX = 0;
int16_t x = 0; int16_t x = 0;
int16_t lastYForRaiseWake = 0;
static constexpr uint8_t histSize = 8; static constexpr uint8_t histSize = 8;
Utility::CircularBuffer<int16_t, histSize> yHistory = {}; Utility::CircularBuffer<int16_t, histSize> yHistory = {};
Utility::CircularBuffer<int16_t, histSize> zHistory = {}; Utility::CircularBuffer<int16_t, histSize> zHistory = {};

View file

@ -430,7 +430,7 @@ void SystemTask::UpdateMotion() {
if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep) { if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep) {
if ((settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) && if ((settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) &&
motionController.ShouldRaiseWake(state == SystemTaskState::Sleeping)) || motionController.ShouldRaiseWake()) ||
(settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake) && (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake) &&
motionController.ShouldShakeWake(settingsController.GetShakeThreshold()))) { motionController.ShouldShakeWake(settingsController.GetShakeThreshold()))) {
GoToRunning(); GoToRunning();