diff options
| author | Finlay Davidson <finlay.davidson@coderclass.nl> | 2023-06-25 15:59:34 +0200 |
|---|---|---|
| committer | JF <JF002@users.noreply.github.com> | 2023-08-17 21:21:22 +0200 |
| commit | cfe21103ea197f98555d5002d389d0c24e7b5544 (patch) | |
| tree | 31c2a1eb02de94ef6e954d2d9dd03b9331341d00 /src/components | |
| parent | 3085bb39901cd71c4e2fe006ad0c0967a66f7a80 (diff) | |
motioncontroller: Add functions for analysis
These are functions for converting acceleration due to gravity to angles
in degrees, and some statistical analysis including the mean and
variance.
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/motion/MotionController.cpp | 57 | ||||
| -rw-r--r-- | src/components/motion/MotionController.h | 16 |
2 files changed, 73 insertions, 0 deletions
diff --git a/src/components/motion/MotionController.cpp b/src/components/motion/MotionController.cpp index b2643a7c..69e418ce 100644 --- a/src/components/motion/MotionController.cpp +++ b/src/components/motion/MotionController.cpp @@ -2,8 +2,39 @@ #include <task.h> +#include "utility/Math.h" + using namespace Pinetime::Controllers; +namespace { + constexpr inline int32_t Clamp(int32_t val, int32_t min, int32_t max) { + return val < min ? min : (val > max ? max : val); + } + + // only returns meaningful values if inputs are acceleration due to gravity + int16_t DegreesRolled(int16_t y, int16_t z, int16_t prevY, int16_t prevZ) { + int16_t prevYAngle = Pinetime::Utility::Asin(Clamp(prevY * 32, -32767, 32767)); + int16_t yAngle = Pinetime::Utility::Asin(Clamp(y * 32, -32767, 32767)); + + if (z < 0 && prevZ < 0) { + return yAngle - prevYAngle; + } + if (prevZ < 0) { + if (y < 0) { + return -prevYAngle - yAngle - 180; + } + return -prevYAngle - yAngle + 180; + } + if (z < 0) { + if (y < 0) { + return prevYAngle + yAngle + 180; + } + return prevYAngle + yAngle - 180; + } + return prevYAngle - yAngle; + } +} + void MotionController::Update(int16_t x, int16_t y, int16_t z, uint32_t nbSteps) { if (this->nbSteps != nbSteps && service != nullptr) { service->OnNewStepCountValue(nbSteps); @@ -23,6 +54,8 @@ void MotionController::Update(int16_t x, int16_t y, int16_t z, uint32_t nbSteps) zHistory++; zHistory[0] = z; + stats = GetAccelStats(); + int32_t deltaSteps = nbSteps - this->nbSteps; if (deltaSteps > 0) { currentTripSteps += deltaSteps; @@ -30,6 +63,30 @@ void MotionController::Update(int16_t x, int16_t y, int16_t z, uint32_t nbSteps) this->nbSteps = nbSteps; } +MotionController::AccelStats MotionController::GetAccelStats() const { + AccelStats stats; + + for (uint8_t i = 0; i < AccelStats::numHistory; i++) { + stats.yMean += yHistory[histSize - i]; + stats.zMean += zHistory[histSize - i]; + stats.prevYMean += yHistory[1 + i]; + stats.prevZMean += zHistory[1 + i]; + } + stats.yMean /= AccelStats::numHistory; + stats.zMean /= AccelStats::numHistory; + stats.prevYMean /= AccelStats::numHistory; + stats.prevZMean /= AccelStats::numHistory; + + for (uint8_t i = 0; i < AccelStats::numHistory; i++) { + stats.yVariance += (yHistory[histSize - i] - stats.yMean) * (yHistory[histSize - i] - stats.yMean); + stats.zVariance += (zHistory[histSize - i] - stats.zMean) * (zHistory[histSize - i] - stats.zMean); + } + stats.yVariance /= AccelStats::numHistory; + stats.zVariance /= AccelStats::numHistory; + + return stats; +} + bool MotionController::ShouldRaiseWake(bool isSleeping) { if ((x + 335) <= 670 && zHistory[0] < 0) { if (!isSleeping) { diff --git a/src/components/motion/MotionController.h b/src/components/motion/MotionController.h index c967530b..de86d44c 100644 --- a/src/components/motion/MotionController.h +++ b/src/components/motion/MotionController.h @@ -68,6 +68,22 @@ namespace Pinetime { TickType_t lastTime = 0; TickType_t time = 0; + struct AccelStats { + static constexpr uint8_t numHistory = 2; + + int16_t yMean = 0; + int16_t zMean = 0; + int16_t prevYMean = 0; + int16_t prevZMean = 0; + + uint32_t yVariance = 0; + uint32_t zVariance = 0; + }; + + AccelStats GetAccelStats() const; + + AccelStats stats = {}; + int16_t lastX = 0; int16_t x = 0; int16_t lastYForRaiseWake = 0; |
