blob: 370533f201544404216aca5afe327f2bde12e5f4 [file] [log] [blame]
Philipp Schrader29d54f22016-04-02 22:14:48 +00001#ifndef FRC971_ZEROING_AVERAGER_H_
2#define FRC971_ZEROING_AVERAGER_H_
3
4#include <algorithm>
5#include <array>
Tyler Chatowbf0609c2021-07-31 16:13:27 -07006#include <cstdint>
Philipp Schrader29d54f22016-04-02 22:14:48 +00007
James Kuszmauld3f9eb22020-01-12 15:02:07 -08008#include "Eigen/Dense"
9#include "glog/logging.h"
10
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080011namespace frc971::zeroing {
Philipp Schrader29d54f22016-04-02 22:14:48 +000012
13// Averages a set of given numbers. Numbers are given one at a time. Once full
14// the average may be requested.
James Kuszmauld3f9eb22020-01-12 15:02:07 -080015// TODO(james): Look at deduplicating this with some of the work in the
16// MoveDetector.
17template <typename Scalar, size_t num_samples, int rows_per_sample = 1>
Philipp Schrader29d54f22016-04-02 22:14:48 +000018class Averager {
19 public:
James Kuszmauld3f9eb22020-01-12 15:02:07 -080020 typedef Eigen::Matrix<Scalar, rows_per_sample, 1> Vector;
James Kuszmaulb1e29372020-02-11 16:55:36 -080021 Averager() {
22 for (Vector &datum : data_) {
23 datum.setZero();
24 }
25 }
Philipp Schrader29d54f22016-04-02 22:14:48 +000026 // Adds one data point to the set of data points to be averaged.
James Kuszmauld3f9eb22020-01-12 15:02:07 -080027 // If more than "num_samples" samples are added, they will start overwriting
Philipp Schrader29d54f22016-04-02 22:14:48 +000028 // the oldest ones.
James Kuszmauld3f9eb22020-01-12 15:02:07 -080029 void AddData(Scalar data) {
30 CHECK_EQ(1, rows_per_sample);
31 AddData(Vector(data));
32 }
33 void AddData(const Vector &data) {
Philipp Schrader29d54f22016-04-02 22:14:48 +000034 data_[data_point_index_] = data;
James Kuszmauld3f9eb22020-01-12 15:02:07 -080035 num_data_points_ = std::min(num_samples, num_data_points_ + 1);
36 data_point_index_ = (data_point_index_ + 1) % num_samples;
Philipp Schrader29d54f22016-04-02 22:14:48 +000037 }
38
39 // Returns the average of the data points.
James Kuszmauld3f9eb22020-01-12 15:02:07 -080040 Vector GetAverage() const {
Philipp Schrader29d54f22016-04-02 22:14:48 +000041 if (num_data_points_ == 0) {
James Kuszmauld3f9eb22020-01-12 15:02:07 -080042 return Vector::Zero();
Philipp Schrader29d54f22016-04-02 22:14:48 +000043 }
44
James Kuszmauld3f9eb22020-01-12 15:02:07 -080045 Vector average;
46 average.setZero();
47 for (const Vector &data : data_) {
Philipp Schrader29d54f22016-04-02 22:14:48 +000048 average += data;
49 }
50 return average / num_data_points_;
51 }
52
James Kuszmauld3f9eb22020-01-12 15:02:07 -080053 // Return the difference between the min and max values in the data buffer.
54 Scalar GetRange() const {
55 if (num_data_points_ == 0) {
56 return 0.0;
57 }
58 Vector min_value;
59 min_value.setConstant(std::numeric_limits<Scalar>::max());
60 Vector max_value;
61 max_value.setConstant(std::numeric_limits<Scalar>::lowest());
62 // The array will always fill up starting at zero, so we can iterate from
63 // zero safely.
64 for (size_t ii = 0; ii < num_data_points_; ++ii) {
65 const Vector &value = data_[ii];
66 min_value = min_value.cwiseMin(value);
67 max_value = max_value.cwiseMax(value);
68 }
69 return (max_value - min_value).maxCoeff();
70 }
Philipp Schrader29d54f22016-04-02 22:14:48 +000071
James Kuszmauld3f9eb22020-01-12 15:02:07 -080072 void Reset() {
73 num_data_points_ = 0;
74 data_point_index_ = 0;
75 }
76
77 // Returns true when we've gathered num_samples data points.
78 bool full() const { return num_data_points_ >= num_samples; };
79
80 size_t size() const { return num_samples; }
Philipp Schrader29d54f22016-04-02 22:14:48 +000081
82 private:
83 // Data points to be averaged.
James Kuszmauld3f9eb22020-01-12 15:02:07 -080084 std::array<Vector, num_samples> data_;
Philipp Schrader29d54f22016-04-02 22:14:48 +000085 // Which data point in "data_" will be filled in next.
86 size_t data_point_index_ = 0;
87 // Number of data points added via AddData().
88 size_t num_data_points_ = 0;
89};
90
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080091} // namespace frc971::zeroing
Philipp Schrader29d54f22016-04-02 22:14:48 +000092
93#endif // FRC971_ZEROING_AVERAGER_H_