-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLengthCalculator.cpp
98 lines (88 loc) · 4.19 KB
/
LengthCalculator.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/***************************************************************************
* Copyright (C) 2016 *
* by Fioratto Raffaele, Cardinale Claudio *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* As a special exception, if other files instantiate templates or use *
* macros or inline functions from this file, or you compile this file *
* and link it with other works to produce a work based on this file, *
* this file does not by itself cause the resulting work to be covered *
* by the GNU General Public License. However the source code for this *
* file must still be made available in accordance with the GNU General *
* Public License. This exception does not invalidate any other reasons *
* why a work based on this file might be covered by the GNU General *
* Public License. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, see <http://www.gnu.org/licenses/> *
***************************************************************************/
#include "LengthCalculator.h"
#include <math.h>
#include <Arduino.h>
LengthCalculator::LengthCalculator() :
lastLength(-1.0), decrementingY(false), previousY(10000), minY(10000),
zeroTime(0), previousTime(0) {
}
/**
* return the last leght calculated
* it wants acceleromenter value of y and time in ms
**/
float LengthCalculator::getLength(int accY, long long now) {
//low pass filter
float absAccY = ALPHA_ANGLE * fabs(accY) + (1 - ALPHA_ANGLE) * previousY;
//is decrementing
if (absAccY < previousY) {
/**
* is decrementing from this call ->
* we have done a quarter of period and we are able to caclulate length
**/
if (!decrementingY) {
int period = calculatePeriod();
float theta = calculateTheta();
//Serial.println(period);
//Serial.println(theta/3.14*180);
calculateLength(period, theta);
}
minY = absAccY;
decrementingY = true;
zeroTime = now;
} else {
decrementingY = false;
}
previousY = absAccY;
previousTime = now;
return lastLength;
}
/* PRIVATE METHODS */
//calculate length of the pendulum and set in the private property
void LengthCalculator::calculateLength(int period, float theta) {
//period is in ms
//this is the inverse of the pendulum serie approximated to the second term
float tmpLength = G * pow(period / 1000.0, 2.0)/(4 * pow(M_PI, 2) * pow((1 + pow(theta, 2) / 16), 2));
//thresholds to exclude small changes
if (tmpLength >= LENGTH_THRESHOLD && theta > ANGLE_THRESHOLD) {
//low pass filter
lastLength = tmpLength * ALPHA_LENGTH + (1 - ALPHA_LENGTH) * lastLength;
}
}
//calculate the max theta of the current period
float LengthCalculator::calculateTheta() {
//0 is the vertical position
//the purpose of min is avoid NaN result of asin
//we don't need information about the side of the ependulum, for that reason we use abs
return M_PI / 2 - asin(fmin((float) 1.0, fabs(minY / (SCALE * G))));
}
//calculate the current period (not yet finished)
int LengthCalculator::calculatePeriod() {
//we have measured a quarter of a period
return (previousTime - zeroTime) * 4;
}