modm API documentation
moving_average.hpp
1 /*
2  * Copyright (c) 2009-2010, Martin Rosekeit
3  * Copyright (c) 2009-2011, Fabian Greif
4  * Copyright (c) 2010, Georgi Grinshpun
5  * Copyright (c) 2012, Niklas Hauser
6  * Copyright (c) 2012, Sascha Schade
7  * Copyright (c) 2015, Thorsten Lajewski
8  * Copyright (c) 2017, Daniel Krebs
9  * Copyright (c) 2018, Christopher Durand
10  *
11  * This file is part of the modm project.
12  *
13  * This Source Code Form is subject to the terms of the Mozilla Public
14  * License, v. 2.0. If a copy of the MPL was not distributed with this
15  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
16  */
17 // ----------------------------------------------------------------------------
18 
19 #ifndef MODM_MOVING_AVERAGE_HPP
20 #define MODM_MOVING_AVERAGE_HPP
21 
22 #include <cstddef>
23 #include <cstdint>
24 #include <type_traits>
25 
26 namespace modm
27 {
28  namespace filter{
29  /**
30  * \brief Moving average filter
31  *
32  * Calculates the average of N newest values, i.a. the sum of the last N
33  * values have been passed to update(...), divided by N. If less than N
34  * values have been passed to the filter, the division factor is still N,
35  * so missing values are assumed to be zero.
36  *
37  * For integer types this implementation stores the current sum of all values in the buffer
38  * and updates this value with every call of update() by subtracting
39  * the overwritten buffer index and adding the new one.
40  *
41  * Due to numerical instabillity for floating value types, inside the update function
42  * the sum has to be recalculated making it less efficient.
43  *
44  * The internal sum is always up to date and the getValue()
45  * method consists of only one division.
46  *
47  * \warning Input range is limited by the following equation
48  * \code N * input::maxValue < T::maxValue \endcode
49  * The sum off the last N input values must not be greater than
50  * the maximum value of T, otherwise an overflow will occur.
51  *
52  * \tparam T Input type
53  * \tparam N Number of samples (maximum is 65356 or 2**16)
54  *
55  * \ingroup modm_math_filter
56  */
57  template<typename T, std::size_t N>
59  {
60  private:
61  using Index = std::conditional_t<
62  (N >= 256),
63  uint_fast16_t,
64  uint_fast8_t
65  >;
66 
67  public:
68  MovingAverage(const T& initialValue = 0);
69 
70  /// Append new value
71  void
72  update(const T& input);
73 
74  /// Get filtered value
75  const T
76  getValue() const;
77 
78  private:
79  Index index;
80  T buffer[N];
81  T sum;
82  };
83  }
84 }
85 
86 // ----------------------------------------------------------------------------
87 template<typename T, std::size_t N>
89  index(0), sum(N * initialValue)
90 {
91  for (Index i = 0; i < N; ++i) {
92  buffer[i] = initialValue;
93  }
94 }
95 
96 // ----------------------------------------------------------------------------
97 // TODO implementierung für float anpassen
98 template<typename T, std::size_t N>
99 void
101 {
102  sum -= buffer[index];
103  sum += input;
104 
105  buffer[index] = input;
106 
107  index++;
108  if (index >= N) {
109  index = 0;
110  }
111 }
112 
113 // -----------------------------------------------------------------------------
114 
115 
116 template<typename T, std::size_t N>
117 const T
119 {
120  return (sum / static_cast<T>(N));
121 }
122 
123 
124 #include "moving_average_float_impl.hpp"
125 #endif // MODM_MOVING_AVERAGE_HPP
const T getValue() const
Get filtered value.
Definition: moving_average.hpp:118
void update(const T &input)
Append new value.
Definition: moving_average.hpp:100
Moving average filter.
Definition: moving_average.hpp:58