blob: bce532f994e799d98760b159a8472774fd6cb40b [file] [log] [blame]
Philipp Schradere8ad6382017-04-09 21:51:21 +00001#ifndef FRC971_SHOOTER_INTERPOLATION_INTERPOLATION_H_
2#define FRC971_SHOOTER_INTERPOLATION_INTERPOLATION_H_
3
Parker Schuh94d56792017-04-13 20:32:50 -07004#include <algorithm>
Philipp Schradere8ad6382017-04-09 21:51:21 +00005#include <utility>
6#include <vector>
7
8namespace frc971 {
9namespace shooter_interpolation {
10
Parker Schuh94d56792017-04-13 20:32:50 -070011double Blend(double coefficient, double a1, double a2);
Philipp Schradere8ad6382017-04-09 21:51:21 +000012
Parker Schuh94d56792017-04-13 20:32:50 -070013template <typename YValue>
Philipp Schradere8ad6382017-04-09 21:51:21 +000014class InterpolationTable {
15 public:
Parker Schuh94d56792017-04-13 20:32:50 -070016 using Point = ::std::pair<double, YValue>;
Philipp Schrader9a833362017-04-09 22:56:16 +000017 InterpolationTable() = default;
Parker Schuh94d56792017-04-13 20:32:50 -070018 InterpolationTable(const ::std::vector<Point> &table);
Philipp Schradere8ad6382017-04-09 21:51:21 +000019
20 // Uses the interpolation table to calculate the optimal shooter angle and
21 // power for a shot
Parker Schuh94d56792017-04-13 20:32:50 -070022 YValue Get(double x) const;
23
Philipp Schrader790cb542023-07-05 21:06:52 -070024 bool GetInRange(double x, YValue *type) const;
Philipp Schradere8ad6382017-04-09 21:51:21 +000025
26 private:
27 // Contains the list of angle entries in the interpolation table
Parker Schuh94d56792017-04-13 20:32:50 -070028 ::std::vector<Point> table_;
Philipp Schradere8ad6382017-04-09 21:51:21 +000029};
30
Parker Schuh94d56792017-04-13 20:32:50 -070031template <typename YValue>
Philipp Schrader790cb542023-07-05 21:06:52 -070032InterpolationTable<YValue>::InterpolationTable(
33 const ::std::vector<Point> &table)
34 : table_(table) {
35 ::std::sort(table_.begin(), table_.end(),
36 [](const Point &a, const Point &b) { return a.first < b.first; });
37}
Parker Schuh94d56792017-04-13 20:32:50 -070038
39template <typename YValue>
40YValue InterpolationTable<YValue>::Get(double x) const {
41 // Points to to the smallest item such that it->first >= dist, or end() if no
42 // such item exists.
Philipp Schrader790cb542023-07-05 21:06:52 -070043 auto it = ::std::lower_bound(
44 table_.begin(), table_.end(), x,
45 [](const Point &a, double dist) { return a.first < dist; });
Parker Schuh94d56792017-04-13 20:32:50 -070046 if (it == table_.begin()) {
47 return it->second;
48 } else if (it == table_.end()) {
49 return table_.back().second;
50 } else {
51 auto x_a2 = it;
52 auto x_a1 = it - 1;
53 double x1 = x_a1->first;
54 double x2 = x_a2->first;
55 double coefficient = (x - x1) / (x2 - x1);
56 return YValue::BlendY(coefficient, x_a1->second, x_a2->second);
57 }
58}
59
60template <typename YValue>
Philipp Schrader790cb542023-07-05 21:06:52 -070061bool InterpolationTable<YValue>::GetInRange(double x, YValue *result) const {
Parker Schuh94d56792017-04-13 20:32:50 -070062 // Points to to the smallest item such that it->first >= dist, or end() if no
63 // such item exists.
Philipp Schrader790cb542023-07-05 21:06:52 -070064 auto it = ::std::lower_bound(
65 table_.begin(), table_.end(), x,
66 [](const Point &a, double dist) { return a.first < dist; });
Parker Schuh94d56792017-04-13 20:32:50 -070067 if (it == table_.begin()) {
68 return false;
69 } else if (it == table_.end()) {
70 return false;
71 } else {
72 auto x_a2 = it;
73 auto x_a1 = it - 1;
74 double x1 = x_a1->first;
75 double x2 = x_a2->first;
76 double coefficient = (x - x1) / (x2 - x1);
77 *result = YValue::BlendY(coefficient, x_a1->second, x_a2->second);
78 return true;
79 }
80}
81
Philipp Schradere8ad6382017-04-09 21:51:21 +000082} // namespace shooter_interpolation
83} // namespace frc971
84
85#endif // FRC971_SHOOTER_INTERPOLATION_INTERPOLATION_H_