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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
/*
* Copyright (C) 2016 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef IGNITION_COMMON_MOVINGWINDOWFILTER_HH_
#define IGNITION_COMMON_MOVINGWINDOWFILTER_HH_
#include <memory>
#include <vector>
namespace ignition
{
namespace common
{
/// \cond
/// \brief Private data members for MovingWindowFilter class.
/// This must be in the header due to templatization.
template< typename T>
class MovingWindowFilterPrivate
{
// \brief Constructor
public: MovingWindowFilterPrivate();
/// \brief For moving window smoothed value
public: unsigned int valWindowSize = 4;
/// \brief buffer history of raw values
public: std::vector<T> valHistory;
/// \brief iterator pointing to current value in buffer
public: typename std::vector<T>::iterator valIter;
/// \brief keep track of running sum
public: T sum;
/// \brief keep track of number of elements
public: unsigned int samples = 0;
};
/// \endcond
//////////////////////////////////////////////////
template<typename T>
MovingWindowFilterPrivate<T>::MovingWindowFilterPrivate()
{
/// \TODO FIXME hardcoded initial value for now
this->valHistory.resize(this->valWindowSize);
this->valIter = this->valHistory.begin();
this->sum = T();
}
/// \brief Base class for MovingWindowFilter
template< typename T>
class MovingWindowFilter
{
/// \brief Constructor
public: MovingWindowFilter();
/// \brief Destructor
public: virtual ~MovingWindowFilter();
/// \brief Update value of filter
/// \param[in] _val new raw value
public: void Update(T _val);
/// \brief Set window size
/// \param[in] _n new desired window size
public: void SetWindowSize(unsigned int _n);
/// \brief Get the window size.
/// \return The size of the moving window.
public: unsigned int WindowSize() const;
/// \brief Get whether the window has been filled.
/// \return True if the window has been filled.
public: bool WindowFilled() const;
/// \brief Get filtered result
/// \return Latest filtered value
public: T Value();
/// \brief Allow subclasses to initialize their own data pointer.
/// \param[in] _d Reference to data pointer.
protected: explicit MovingWindowFilter<T>(
MovingWindowFilterPrivate<T> &_d);
/// \brief Data pointer.
protected: std::unique_ptr<MovingWindowFilterPrivate<T>> dataPtr;
};
//////////////////////////////////////////////////
template<typename T>
MovingWindowFilter<T>::MovingWindowFilter()
: dataPtr(new MovingWindowFilterPrivate<T>())
{
}
//////////////////////////////////////////////////
template<typename T>
MovingWindowFilter<T>::~MovingWindowFilter()
{
this->dataPtr->valHistory.clear();
}
//////////////////////////////////////////////////
template<typename T>
void MovingWindowFilter<T>::Update(T _val)
{
// update sum and sample size with incoming _val
// keep running sum
this->dataPtr->sum += _val;
// shift pointer, wrap around if end has been reached.
++this->dataPtr->valIter;
if (this->dataPtr->valIter == this->dataPtr->valHistory.end())
{
// reset iterator to beginning of queue
this->dataPtr->valIter = this->dataPtr->valHistory.begin();
}
// increment sample size
++this->dataPtr->samples;
if (this->dataPtr->samples > this->dataPtr->valWindowSize)
{
// subtract old value if buffer already filled
this->dataPtr->sum -= (*this->dataPtr->valIter);
// put new value into queue
(*this->dataPtr->valIter) = _val;
// reduce sample size
--this->dataPtr->samples;
}
else
{
// put new value into queue
(*this->dataPtr->valIter) = _val;
}
}
//////////////////////////////////////////////////
template<typename T>
void MovingWindowFilter<T>::SetWindowSize(unsigned int _n)
{
this->dataPtr->valWindowSize = _n;
this->dataPtr->valHistory.clear();
this->dataPtr->valHistory.resize(this->dataPtr->valWindowSize);
this->dataPtr->valIter = this->dataPtr->valHistory.begin();
this->dataPtr->sum = T();
this->dataPtr->samples = 0;
}
//////////////////////////////////////////////////
template<typename T>
unsigned int MovingWindowFilter<T>::WindowSize() const
{
return this->dataPtr->valWindowSize;
}
//////////////////////////////////////////////////
template<typename T>
bool MovingWindowFilter<T>::WindowFilled() const
{
return this->dataPtr->samples == this->dataPtr->valWindowSize;
}
//////////////////////////////////////////////////
template<typename T>
T MovingWindowFilter<T>::Value()
{
return this->dataPtr->sum / static_cast<double>(this->dataPtr->samples);
}
}
}
#endif
|