Skip to content

Commit cfe2110

Browse files
FintasticManJF002
authored andcommitted
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.
1 parent 3085bb3 commit cfe2110

File tree

5 files changed

+137
-0
lines changed

5 files changed

+137
-0
lines changed

src/CMakeLists.txt

+5
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,8 @@ list(APPEND SOURCE_FILES
493493

494494
buttonhandler/ButtonHandler.cpp
495495
touchhandler/TouchHandler.cpp
496+
497+
utility/Math.cpp
496498
)
497499

498500
list(APPEND RECOVERY_SOURCE_FILES
@@ -558,6 +560,8 @@ list(APPEND RECOVERY_SOURCE_FILES
558560
components/fs/FS.cpp
559561
buttonhandler/ButtonHandler.cpp
560562
touchhandler/TouchHandler.cpp
563+
564+
utility/Math.cpp
561565
)
562566

563567
list(APPEND RECOVERYLOADER_SOURCE_FILES
@@ -677,6 +681,7 @@ set(INCLUDE_FILES
677681
components/motor/MotorController.h
678682
buttonhandler/ButtonHandler.h
679683
touchhandler/TouchHandler.h
684+
utility/Math.h
680685
)
681686

682687
include_directories(

src/components/motion/MotionController.cpp

+57
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,39 @@
22

33
#include <task.h>
44

5+
#include "utility/Math.h"
6+
57
using namespace Pinetime::Controllers;
68

9+
namespace {
10+
constexpr inline int32_t Clamp(int32_t val, int32_t min, int32_t max) {
11+
return val < min ? min : (val > max ? max : val);
12+
}
13+
14+
// only returns meaningful values if inputs are acceleration due to gravity
15+
int16_t DegreesRolled(int16_t y, int16_t z, int16_t prevY, int16_t prevZ) {
16+
int16_t prevYAngle = Pinetime::Utility::Asin(Clamp(prevY * 32, -32767, 32767));
17+
int16_t yAngle = Pinetime::Utility::Asin(Clamp(y * 32, -32767, 32767));
18+
19+
if (z < 0 && prevZ < 0) {
20+
return yAngle - prevYAngle;
21+
}
22+
if (prevZ < 0) {
23+
if (y < 0) {
24+
return -prevYAngle - yAngle - 180;
25+
}
26+
return -prevYAngle - yAngle + 180;
27+
}
28+
if (z < 0) {
29+
if (y < 0) {
30+
return prevYAngle + yAngle + 180;
31+
}
32+
return prevYAngle + yAngle - 180;
33+
}
34+
return prevYAngle - yAngle;
35+
}
36+
}
37+
738
void MotionController::Update(int16_t x, int16_t y, int16_t z, uint32_t nbSteps) {
839
if (this->nbSteps != nbSteps && service != nullptr) {
940
service->OnNewStepCountValue(nbSteps);
@@ -23,13 +54,39 @@ void MotionController::Update(int16_t x, int16_t y, int16_t z, uint32_t nbSteps)
2354
zHistory++;
2455
zHistory[0] = z;
2556

57+
stats = GetAccelStats();
58+
2659
int32_t deltaSteps = nbSteps - this->nbSteps;
2760
if (deltaSteps > 0) {
2861
currentTripSteps += deltaSteps;
2962
}
3063
this->nbSteps = nbSteps;
3164
}
3265

66+
MotionController::AccelStats MotionController::GetAccelStats() const {
67+
AccelStats stats;
68+
69+
for (uint8_t i = 0; i < AccelStats::numHistory; i++) {
70+
stats.yMean += yHistory[histSize - i];
71+
stats.zMean += zHistory[histSize - i];
72+
stats.prevYMean += yHistory[1 + i];
73+
stats.prevZMean += zHistory[1 + i];
74+
}
75+
stats.yMean /= AccelStats::numHistory;
76+
stats.zMean /= AccelStats::numHistory;
77+
stats.prevYMean /= AccelStats::numHistory;
78+
stats.prevZMean /= AccelStats::numHistory;
79+
80+
for (uint8_t i = 0; i < AccelStats::numHistory; i++) {
81+
stats.yVariance += (yHistory[histSize - i] - stats.yMean) * (yHistory[histSize - i] - stats.yMean);
82+
stats.zVariance += (zHistory[histSize - i] - stats.zMean) * (zHistory[histSize - i] - stats.zMean);
83+
}
84+
stats.yVariance /= AccelStats::numHistory;
85+
stats.zVariance /= AccelStats::numHistory;
86+
87+
return stats;
88+
}
89+
3390
bool MotionController::ShouldRaiseWake(bool isSleeping) {
3491
if ((x + 335) <= 670 && zHistory[0] < 0) {
3592
if (!isSleeping) {

src/components/motion/MotionController.h

+16
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,22 @@ namespace Pinetime {
6868
TickType_t lastTime = 0;
6969
TickType_t time = 0;
7070

71+
struct AccelStats {
72+
static constexpr uint8_t numHistory = 2;
73+
74+
int16_t yMean = 0;
75+
int16_t zMean = 0;
76+
int16_t prevYMean = 0;
77+
int16_t prevZMean = 0;
78+
79+
uint32_t yVariance = 0;
80+
uint32_t zVariance = 0;
81+
};
82+
83+
AccelStats GetAccelStats() const;
84+
85+
AccelStats stats = {};
86+
7187
int16_t lastX = 0;
7288
int16_t x = 0;
7389
int16_t lastYForRaiseWake = 0;

src/utility/Math.cpp

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include "utility/Math.h"
2+
3+
#include <lvgl/src/lv_misc/lv_math.h>
4+
5+
using namespace Pinetime::Utility;
6+
7+
#ifndef PINETIME_IS_RECOVERY
8+
9+
int16_t Pinetime::Utility::Asin(int16_t arg) {
10+
int16_t a = arg < 0 ? -arg : arg;
11+
12+
int16_t angle = 45;
13+
int16_t low = 0;
14+
int16_t high = 90;
15+
while (low <= high) {
16+
int16_t sinAngle = _lv_trigo_sin(angle);
17+
int16_t sinAngleSub = _lv_trigo_sin(angle - 1);
18+
int16_t sinAngleAdd = _lv_trigo_sin(angle + 1);
19+
20+
if (a >= sinAngleSub && a <= sinAngleAdd) {
21+
if (a <= (sinAngleSub + sinAngle) / 2) {
22+
angle--;
23+
} else if (a > (sinAngle + sinAngleAdd) / 2) {
24+
angle++;
25+
}
26+
break;
27+
}
28+
29+
if (a < sinAngle) {
30+
high = angle - 1;
31+
}
32+
33+
else {
34+
low = angle + 1;
35+
}
36+
37+
angle = (low + high) / 2;
38+
}
39+
40+
return arg < 0 ? -angle : angle;
41+
}
42+
43+
#else
44+
45+
int16_t Pinetime::Utility::Asin(int16_t /*arg*/) {
46+
return 0;
47+
}
48+
49+
#endif

src/utility/Math.h

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
5+
namespace Pinetime {
6+
namespace Utility {
7+
// returns the arcsin of `arg`. asin(-32767) = -90, asin(32767) = 90
8+
int16_t Asin(int16_t arg);
9+
}
10+
}

0 commit comments

Comments
 (0)