Merge remote-tracking branch 'origin/master' into mmosca-mavlinkrc
[inav.git] / src / main / common / lulu.c
blob8ab7803ed1bb956b1fef3c533980f74134279836
1 #include "lulu.h"
3 #include <stdbool.h>
4 #include <stdint.h>
5 #include <string.h>
6 #include <math.h>
8 #include "platform.h"
10 #include "common/filter.h"
11 #include "common/maths.h"
12 #include "common/utils.h"
14 #ifdef __ARM_ACLE
15 #include <arm_acle.h>
16 #endif /* __ARM_ACLE */
17 #include <fenv.h>
19 void luluFilterInit(luluFilter_t *filter, int N)
21 filter->N = constrain(N, 1, 15);
22 filter->windowSize = filter->N * 2 + 1;
23 filter->windowBufIndex = 0;
25 memset(filter->luluInterim, 0, sizeof(float) * (filter->windowSize));
26 memset(filter->luluInterimB, 0, sizeof(float) * (filter->windowSize));
29 FAST_CODE float fixRoad(float *series, float *seriesB, int index, int filterN, int windowSize)
31 float curVal = 0;
32 float curValB = 0;
33 for (int N = 1; N <= filterN; N++)
35 int indexNeg = (index + windowSize - 2 * N) % windowSize;
36 int curIndex = (indexNeg + 1) % windowSize;
37 float prevVal = series[indexNeg];
38 float prevValB = seriesB[indexNeg];
39 int indexPos = (curIndex + N) % windowSize;
41 for (int i = windowSize - 2 * N; i < windowSize - N; i++)
43 if (indexPos >= windowSize)
45 indexPos = 0;
47 if (curIndex >= windowSize)
49 curIndex = 0;
51 // curIndex = (2 - 1) % 3 = 1
52 curVal = series[curIndex];
53 curValB = seriesB[curIndex];
54 float nextVal = series[indexPos];
55 float nextValB = seriesB[indexPos];
56 // onbump (s, 1, 1, 3)
57 // if(onBump(series, curIndex, N, windowSize))
58 if (prevVal < curVal && curVal > nextVal)
60 float maxValue = MAX(prevVal, nextVal);
62 series[curIndex] = maxValue;
63 int k = curIndex;
64 for (int j = 1; j < N; j++)
66 if (++k >= windowSize)
68 k = 0;
70 series[k] = maxValue;
74 if (prevValB < curValB && curValB > nextValB)
76 float maxValue = MAX(prevValB, nextValB);
78 curVal = maxValue;
79 seriesB[curIndex] = maxValue;
80 int k = curIndex;
81 for (int j = 1; j < N; j++)
83 if (++k >= windowSize)
85 k = 0;
87 seriesB[k] = maxValue;
90 prevVal = curVal;
91 prevValB = curValB;
92 curIndex++;
93 indexPos++;
96 curIndex = (indexNeg + 1) % windowSize;
97 prevVal = series[indexNeg];
98 prevValB = seriesB[indexNeg];
99 indexPos = (curIndex + N) % windowSize;
100 for (int i = windowSize - 2 * N; i < windowSize - N; i++)
102 if (indexPos >= windowSize)
104 indexPos = 0;
106 if (curIndex >= windowSize)
108 curIndex = 0;
110 // curIndex = (2 - 1) % 3 = 1
111 curVal = series[curIndex];
112 curValB = seriesB[curIndex];
113 float nextVal = series[indexPos];
114 float nextValB = seriesB[indexPos];
116 if (prevVal > curVal && curVal < nextVal)
118 float minValue = MIN(prevVal, nextVal);
120 curVal = minValue;
121 series[curIndex] = minValue;
122 int k = curIndex;
123 for (int j = 1; j < N; j++)
125 if (++k >= windowSize)
127 k = 0;
129 series[k] = minValue;
133 if (prevValB > curValB && curValB < nextValB)
135 float minValue = MIN(prevValB, nextValB);
136 curValB = minValue;
137 seriesB[curIndex] = minValue;
138 int k = curIndex;
139 for (int j = 1; j < N; j++)
141 if (++k >= windowSize)
143 k = 0;
145 seriesB[k] = minValue;
148 prevVal = curVal;
149 prevValB = curValB;
150 curIndex++;
151 indexPos++;
154 return (curVal - curValB) / 2;
157 FAST_CODE float luluFilterPartialApply(luluFilter_t *filter, float input)
159 // This is the value N of the LULU filter.
160 int filterN = filter->N;
161 // This is the total window size for the rolling buffer
162 int filterWindow = filter->windowSize;
164 int windowIndex = filter->windowBufIndex;
165 float inputVal = input;
166 int newIndex = (windowIndex + 1) % filterWindow;
167 filter->windowBufIndex = newIndex;
168 filter->luluInterim[windowIndex] = inputVal;
169 filter->luluInterimB[windowIndex] = -inputVal;
170 return fixRoad(filter->luluInterim, filter->luluInterimB, windowIndex, filterN, filterWindow);
173 FAST_CODE float luluFilterApply(luluFilter_t *filter, float input)
175 // This is the UL filter
176 float resultA = luluFilterPartialApply(filter, input);
177 // We use the median interpretation of this filter to remove bias in the output
178 return resultA;