Skip to content

Commit 76d51e6

Browse files
author
camilo
committed
fix to pid and smoother
1 parent f464cbb commit 76d51e6

File tree

10 files changed

+145
-78
lines changed

10 files changed

+145
-78
lines changed

doc/qssmoother.dox

Lines changed: 70 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
* easy signal processing.
1010
*
1111
* Below is the list of filters supported by @ref qssmoother :
12-
*
12+
*
1313
* @section qssmoother_lpf1 First Order Low Pass Filter
14-
*
15-
* \ref qlibs::smootherLPF1 is first-order low-pass filter that passes signals
16-
* with a frequency lower than a chosen cutoff frequency and reduces signals
17-
* with frequencies higher than the cutoff. This results in a smoother signal
14+
*
15+
* \ref qlibs::smootherLPF1 is first-order low-pass filter that passes signals
16+
* with a frequency lower than a chosen cutoff frequency and reduces signals
17+
* with frequencies higher than the cutoff. This results in a smoother signal
1818
* by removing short-term fluctuations and highlighting longer-term trends.
1919
* The discrete-time equation of this filter is defined as follows, where \f$w\f$
2020
* is the cut-off frequency given in \f$rad/seg\f$
@@ -43,7 +43,7 @@
4343
* @endcode
4444
*
4545
* @section qssmoother_lpf2 Second Order Low Pass Filter
46-
*
46+
*
4747
* \ref qlibs::smootherLPF2 is a filter with similar properties to the 1st order low pass filter. The main
4848
* difference is that the stop band roll-off will be twice the 1st order filters
4949
* at 40dB/decade (12dB/octave) as the operating frequency increases above the
@@ -74,10 +74,10 @@
7474
* // error, smooth filter cant be configured
7575
* }
7676
* @endcode
77-
*
7877
*
79-
* @section qssmoother_mwm1 Moving Window Median Filter O(n)
80-
*
78+
*
79+
* @section qssmoother_mwm1 Moving Window Median Filter O(n)
80+
*
8181
* \ref qlibs::smootherMWM1 is a low-pass filter that calculates the moving median of the input signal over
8282
* time using the sliding window method. A window of a specified length is moved
8383
* sample by sample and the median of the data in the window is computed.
@@ -92,11 +92,11 @@
9292
*
9393
* <center> \f$ \frac{1}{N}\sum_{i=0}^{N-1}y(t-i)=\frac{1}{N}[ y(t) + y(t-1) + ... + y(t-N-1) ] \f$ </center>
9494
*
95-
* This filter has a time complexity of \f$O(n)\f$
95+
* This filter has a time complexity of \f$O(n)\f$
9696
*
9797
* @subsection qssmoother_ex3 Example: setting up a moving window median filter:
9898
* @code{.c}
99-
* smootherMWM1 filter;
99+
* smootherMWM1 filter;
100100
* real_t m_window[ 20 ] = { 0.0f };
101101
* bool ret;
102102
*
@@ -107,8 +107,8 @@
107107
* @endcode
108108
*
109109
*
110-
* @section qssmoother_mwm2 Moving Window Median Filter O(1)
111-
*
110+
* @section qssmoother_mwm2 Moving Window Median Filter O(1)
111+
*
112112
* \ref qlibs::smootherMWM2 is a filter that operates on the same principle as the previous filter. The main
113113
* difference is the treatment of the sliding window, which is implemented as a
114114
* TDL (Tapped Delay Line) using a circular queue.
@@ -126,7 +126,7 @@
126126
*
127127
* @subsection qssmoother_ex4 Example: Setting up a moving window median filter:
128128
* @code{.c}
129-
* smootherMWM2 filter;
129+
* smootherMWM2 filter;
130130
* real_t m_window[ 150 ] = { 0.0f };
131131
* bool ret;
132132
*
@@ -137,8 +137,8 @@
137137
* @endcode
138138
*
139139
*
140-
* @section qssmoother_mor1 Moving Outlier Removal Filter O(n)
141-
*
140+
* @section qssmoother_mor1 Moving Outlier Removal Filter O(n)
141+
*
142142
* The \ref qlibs::smootherMOR1 filter detects and removes outliers in the input signal by computing the
143143
* median of a moving window for each sample. If a new incoming sample deviates
144144
* from the median by a specified margin \f$\alpha\f$, it is replaced by the
@@ -152,11 +152,11 @@
152152
* \f$ \text{else}=x(k) \f$
153153
* </center>
154154
*
155-
* This filter has a time complexity of \f$O(n)\f$
155+
* This filter has a time complexity of \f$O(n)\f$
156156
*
157157
* @subsection qssmoother_ex5 Example: setting up an outlier removal filter:
158158
* @code{.c}
159-
* smootherMOR1 smoother;
159+
* smootherMOR1 smoother;
160160
* real_t alpha = 0.8f;
161161
* real_t m_window[ 10 ] = { 0.0f };
162162
* bool ret;
@@ -168,14 +168,14 @@
168168
* @endcode
169169
*
170170
*
171-
* @section qssmoother_mor2 Moving Outlier Removal Filter O(1)
172-
*
173-
* The \ref qlibs::smootherMOR2 is similar to the previous filter, but with a constant time complexity of  \f$O(1)\f$
171+
* @section qssmoother_mor2 Moving Outlier Removal Filter O(1)
172+
*
173+
* The \ref qlibs::smootherMOR2 is similar to the previous filter, but with a constant time complexity of  \f$O(1)\f$
174174
* by using a \ref qlibs::tdl data structure.
175175
*
176176
* @subsection qssmoother_ex6 Example: setting up an outlier removal filter:
177177
* @code{.c}
178-
* smootherMOR2 smoother;
178+
* smootherMOR2 smoother;
179179
* real_t alpha = 0.8f;
180180
* real_t m_window[ 100 ] = { 0.0f };
181181
* bool ret;
@@ -191,7 +191,7 @@
191191
*
192192
* \ref qlibs::smootherGMWF is a filter that uses a kernel for smoothing, which defines the shape of the function
193193
* that is used to take the average of the neighboring points. A Gaussian kernel
194-
* has the shape of a Gaussian curve with a normal distribution.
194+
* has the shape of a Gaussian curve with a normal distribution.
195195
*
196196
* The coefficients of the kernel are computed from the following equation:
197197
*
@@ -210,7 +210,7 @@
210210
* const real_t sigma = 0.5f;
211211
* const real_t centerOffset = SMOOTHER_WINDOW_SIZE/2.0f;
212212
*
213-
* smootherGMWF filter;
213+
* smootherGMWF filter;
214214
* real_t window[ SMOOTHER_WINDOW_SIZE ] = { 0.0f };
215215
* real_t kernel[ SMOOTHER_WINDOW_SIZE ] = { 0.0f };
216216
* bool ret;
@@ -222,7 +222,7 @@
222222
* @endcode
223223
*
224224
*
225-
* @section qssmoother_expw Exponential Weighting filter
225+
* @section qssmoother_expw Exponential Weighting filter
226226
*
227227
* The \ref qlibs::smootherEXPW filter uses a weighting factor that is computed and applied to the input
228228
* signal in a recursive manner. The weighting factor decreases exponentially as
@@ -244,7 +244,7 @@
244244
*
245245
* @subsection qssmoother_ex8 Example: setting up an exponential weighting filter:
246246
* @code{.c}
247-
* smootherEXPW filter;
247+
* smootherEXPW filter;
248248
* real_t lambda = 0.8f;
249249
* bool ret;
250250
*
@@ -255,16 +255,16 @@
255255
* @endcode
256256
*
257257
*
258-
* @section qssmoother_klmn Scalar Kalman filter
258+
* @section qssmoother_klmn Scalar Kalman filter
259259
*
260260
* The \ref qlibs::smootherKLMN (Kalman Filter) is an efficient optimal estimator that provides a recursive
261261
* computational methodology for getting the state of a signal from measurements
262262
* that are typically noisy, while providing an estimate of the uncertainty of
263263
* the estimate. Here, the scalar or one-dimensional version is provided
264264
* and only three design parameters are required, the initial covariance \f$P(0)\f$,
265265
* the signal noise covariance \f$Q\f$ and the measurement uncertainty \f$r\f$.
266-
*
267-
* The recursive equations used by this scalar version are:
266+
*
267+
* The recursive equations used by this scalar version are:
268268
*
269269
* predict
270270
*
@@ -283,11 +283,11 @@
283283
* <center> \f$ P(k) = ( 1 - K(k)H )P(k-1) \f$ </center>
284284
*
285285
* Where
286-
*
286+
*
287287
* \f$A\f$ is the state transition model, \f$H\f$ the observation model, \f$x(k)\f$
288288
* the filter output (state estimation), \f$P(k)\f$ the covariance of the predicted
289289
* state, \f$u(k)\f$ the signal measurement and \f$K(k)\f$ the kalman gain.
290-
*
290+
*
291291
* @subsection qssmoother_ex9 Example: setting up a scalar Kalman filter:
292292
* @code{.c}
293293
* smootherKLMN filter;
@@ -303,13 +303,13 @@
303303
* @section qssmoother_desf Double Exponential Smoothing
304304
*
305305
* The \ref qlibs::smootherDESF is a time series forecasting filter used to analyze and predict trends in
306-
* data. It is an extension of simple exponential smoothing that incorporates
306+
* data. It is an extension of simple exponential smoothing that incorporates
307307
* trend information into the forecast.
308-
*
308+
*
309309
* The double exponential smoothing filter calculates two smoothing coefficients,
310310
* one for the level of the series and one for the trend. These coefficients are
311-
* used to give more weight to recent observations and dampen the effect of
312-
* older observations. The level and trend are then updated using the following
311+
* used to give more weight to recent observations and dampen the effect of
312+
* older observations. The level and trend are then updated using the following
313313
* equations:
314314
*
315315
* Level:
@@ -318,55 +318,66 @@
318318
* Trend:
319319
* <center> \f$ T(t) = \beta [ L(t-1) + T(t-1) ] + ( 1 - \beta ) T(t-1) \f$ </center>
320320
*
321-
* where \f$\alpha\f$ and \f$\beta\f$ are the smoothing coefficients for the
321+
* where \f$\alpha\f$ and \f$\beta\f$ are the smoothing coefficients for the
322322
* level and trend, respectively.
323-
*
323+
*
324324
* The double exponential smoothing filter can be used to generate forecasts by
325325
* extrapolating the level and trend components into the future. The forecast for
326326
* time \f$t+k\f$ is given by:
327-
*
327+
*
328328
* <center> \f$ F(t+k) = L(t) + kT(t) \f$ </center>
329-
*
329+
*
330330
* Where \f$k\f$ is the number of time periods into the future.
331331
*
332-
* Overall, double exponential smoothing is a simple but effective technique
332+
* Overall, double exponential smoothing is a simple but effective technique
333333
* for forecasting time series data with trends. It can be easily implemented 3
334-
* and provides accurate forecasts for short-term predictions. However, it may
335-
* not perform well for longer-term forecasts or for data with complex seasonal
334+
* and provides accurate forecasts for short-term predictions. However, it may
335+
* not perform well for longer-term forecasts or for data with complex seasonal
336336
* patterns.
337337
*
338+
* @subsection qssmoother_ex10 Example: setting up the Double Exponential Smoothing:
339+
* @code{.c}
340+
* smootherDESF filter;
341+
* bool ret;
342+
*
343+
* ret = filter.setup( 0.08f, 0.085f, 10.0f );
344+
* if ( !ret ) {
345+
* // error, smooth filter cant be configured
346+
* }
347+
* @endcode
348+
*
338349
* @section qssmoother_alnf Adaptive Linear Filter
339350
*
340351
* The \ref qlibs::smootherALNF is a digital filter that adjusts its parameters based on the
341352
* characteristics of the input signal and the desired output signal.
342-
*
353+
*
343354
* The adaptive linear filter works by using an algorithm to iteratively adjust
344355
* the filter coefficients in response to changes in the input signal \f$x(t)\f$.
345356
* The algorithm seeks to minimize the difference between the filter output and
346-
* the desired output, known as the error signal \f$ e(t)\f$. This is done by
347-
* adjusting the filter coefficients \f$w_i(t)\f$ in the direction that reduces
348-
* the error signal. For this, the Least Mean Squares (LMS) algorithm is being
349-
* used. The LMS algorithm updates the filter coefficients by multiplying the
350-
* error signal by the input signal and a small step size parameter, and then
357+
* the desired output, known as the error signal \f$ e(t)\f$. This is done by
358+
* adjusting the filter coefficients \f$w_i(t)\f$ in the direction that reduces
359+
* the error signal. For this, the Least Mean Squares (LMS) algorithm is being
360+
* used. The LMS algorithm updates the filter coefficients by multiplying the
361+
* error signal by the input signal and a small step size parameter, and then
351362
* adding this product to the existing filter coefficients.
352-
*
353-
* It is particularly useful in situations where the characteristics of the
363+
*
364+
* It is particularly useful in situations where the characteristics of the
354365
* input signal are unknown or change over time, as it can adapt to these changes
355366
* and continue to provide accurate filtering or modeling.
356367
*
357-
* One potential drawback of the adaptive linear filter is that it can be
358-
* computationally intensive, especially if the input signal is large or the
359-
* filter has many coefficients. Additionally, the performance of the filter
360-
* can be sensitive to the choice of step size parameter, which must be
368+
* One potential drawback of the adaptive linear filter is that it can be
369+
* computationally intensive, especially if the input signal is large or the
370+
* filter has many coefficients. Additionally, the performance of the filter
371+
* can be sensitive to the choice of step size parameter, which must be
361372
* carefully chosen to balance convergence speed with stability.
362373
*
363374
* The adaptation rule for every filter coefficient is given by
364375
* <center> \f$ \Delta w(t) = \alpha e(t) x(t) + \mu \Delta w(t-1) \f$ </center>
365376
*
366377
* <center> \f$ w(t) = w(t-1) x(t) + \Delta w(t) \f$ </center>
367378
*
368-
* The equation also includes a momentum term that adds a fraction of the
369-
* previous coefficient update to the current coefficient update. This can help
379+
* The equation also includes a momentum term that adds a fraction of the
380+
* previous coefficient update to the current coefficient update. This can help
370381
* to reduce oscillations in the filter output and improve convergence speed.
371382
*
372383
* @section qssmoother_ex10 Example of signal smoothing
@@ -392,7 +403,7 @@
392403
* constexpr uint32_t SMOOTHER_SAMPLE_TIME = 100;
393404
* constexpr real_t GAUSS_SIGMA = 0.5f;
394405
* constexpr real_t GAUSS_CENTER = SMOOTHER_WINDOW_SIZE/2.0f;
395-
*
406+
*
396407
* void xTaskSignalProcessing( void *arg )
397408
* {
398409
* smootherGMWF *filter = static_cast<smootherGMWF *>( arg );
@@ -405,14 +416,14 @@
405416
* vTaskDelay( SMOOTHER_SAMPLE_TIME / portTICK_RATE_MS ) ;
406417
* }
407418
* }
408-
*
419+
*
409420
* int main( int argc, char *argv[] )
410421
* {
411422
* smootherGMWF filter;
412423
* real_t window[ SMOOTHER_WINDOW_SIZE ] = { 0.0f };
413424
* real_t kernel[ SMOOTHER_WINDOW_SIZE ] = { 0.0f };
414425
* bool ret;
415-
*
426+
*
416427
* BSP_SystemInit( );
417428
* ret = filter.setup( GAUSS_SIGMA, GAUSS_CENTER, window, kernel );
418429
* if ( !ret ) {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <qlibs.h>
2+
3+
smootherGMWF filter;
4+
constexpr real_t SMOOTHER_SAMPLE_TIME = 20; /*mS*/
5+
int inputPin = A0; // select the input pin for the potentiometer that will drive the system
6+
7+
void setup() {
8+
Serial.begin(9600);
9+
/*setup the gaussian filter*/
10+
constexpr size_t SMOOTHER_WINDOW_SIZE = 30;
11+
constexpr real_t GAUSS_SIGMA = 20.0f;
12+
constexpr real_t GAUSS_CENTER = 0.0f;
13+
real_t window[ SMOOTHER_WINDOW_SIZE ] = { 0.0f };
14+
real_t kernel[ SMOOTHER_WINDOW_SIZE ] = { 0.0f };
15+
filter.setup( GAUSS_SIGMA, GAUSS_CENTER, window, kernel );
16+
}
17+
18+
void loop() {
19+
real_t noise = static_cast<float>( random(-1000, 1000) )/10000.00;
20+
real_t noised_signal = noise + map( analogRead( inputPin ), 0, 1023, 0.0f, 100.0f );
21+
real_t filterd_signal = filter.smooth( noised_signal );
22+
Serial.print( noised_signal );
23+
Serial.print( "," );
24+
Serial.println( filterd_signal );
25+
delay( SMOOTHER_SAMPLE_TIME);
26+
}

library.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"maintainer": true
1717
}
1818
],
19-
"version": "1.1.9",
19+
"version": "1.2.0",
2020
"license": "MIT",
2121
"frameworks": "arduino",
2222
"platforms": "*"

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=qlibs
2-
version=1.1.9
2+
version=1.2.0
33
license=MIT
44
author=J. Camilo Gomez C. <[email protected]>
55
maintainer=J. Camilo Gomez C. <[email protected]>

src/include/fis.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ namespace qlibs {
379379
*/
380380
using rules = int8_t;
381381
/*! @cond */
382-
#define FIS_RULES_MIN_VALUE INT8_MIN
382+
constexpr fis::rules FIS_RULES_MIN_VALUE = INT8_MIN;
383383
/*! @endcond */
384384
#else
385385
/**
@@ -403,7 +403,7 @@ namespace qlibs {
403403
*/
404404
using rules = int16_t;
405405
/*! @cond */
406-
#define FIS_RULES_MIN_VALUE INT16_MIN
406+
constexpr fis::rules FIS_RULES_MIN_VALUE = INT16_MIN;
407407
/*! @endcond */
408408
#endif
409409

0 commit comments

Comments
 (0)