blob: 23a1b06d70103dab3dc9796e2668a13e674940bf [file] [log] [blame]
#ifndef FRC971_ZEROING_AVERAGER_H_
#define FRC971_ZEROING_AVERAGER_H_
#include <algorithm>
#include <array>
#include <stdint.h>
#include "Eigen/Dense"
#include "glog/logging.h"
namespace frc971 {
namespace zeroing {
// Averages a set of given numbers. Numbers are given one at a time. Once full
// the average may be requested.
// TODO(james): Look at deduplicating this with some of the work in the
// MoveDetector.
template <typename Scalar, size_t num_samples, int rows_per_sample = 1>
class Averager {
public:
typedef Eigen::Matrix<Scalar, rows_per_sample, 1> Vector;
Averager() {
for (Vector &datum : data_) {
datum.setZero();
}
}
// Adds one data point to the set of data points to be averaged.
// If more than "num_samples" samples are added, they will start overwriting
// the oldest ones.
void AddData(Scalar data) {
CHECK_EQ(1, rows_per_sample);
AddData(Vector(data));
}
void AddData(const Vector &data) {
data_[data_point_index_] = data;
num_data_points_ = std::min(num_samples, num_data_points_ + 1);
data_point_index_ = (data_point_index_ + 1) % num_samples;
}
// Returns the average of the data points.
Vector GetAverage() const {
if (num_data_points_ == 0) {
return Vector::Zero();
}
Vector average;
average.setZero();
for (const Vector &data : data_) {
average += data;
}
return average / num_data_points_;
}
// Return the difference between the min and max values in the data buffer.
Scalar GetRange() const {
if (num_data_points_ == 0) {
return 0.0;
}
Vector min_value;
min_value.setConstant(std::numeric_limits<Scalar>::max());
Vector max_value;
max_value.setConstant(std::numeric_limits<Scalar>::lowest());
// The array will always fill up starting at zero, so we can iterate from
// zero safely.
for (size_t ii = 0; ii < num_data_points_; ++ii) {
const Vector &value = data_[ii];
min_value = min_value.cwiseMin(value);
max_value = max_value.cwiseMax(value);
}
return (max_value - min_value).maxCoeff();
}
void Reset() {
num_data_points_ = 0;
data_point_index_ = 0;
}
// Returns true when we've gathered num_samples data points.
bool full() const { return num_data_points_ >= num_samples; };
size_t size() const { return num_samples; }
private:
// Data points to be averaged.
std::array<Vector, num_samples> data_;
// Which data point in "data_" will be filled in next.
size_t data_point_index_ = 0;
// Number of data points added via AddData().
size_t num_data_points_ = 0;
};
} // namespace zeroing
} // namespace frc971
#endif // FRC971_ZEROING_AVERAGER_H_