blob: 26b141f3d488b4944861ef76095047c52836c2dd [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
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -08008namespace frc971::shooter_interpolation {
Philipp Schradere8ad6382017-04-09 21:51:21 +00009
Parker Schuh94d56792017-04-13 20:32:50 -070010double Blend(double coefficient, double a1, double a2);
Philipp Schradere8ad6382017-04-09 21:51:21 +000011
Parker Schuh94d56792017-04-13 20:32:50 -070012template <typename YValue>
Philipp Schradere8ad6382017-04-09 21:51:21 +000013class InterpolationTable {
14 public:
Parker Schuh94d56792017-04-13 20:32:50 -070015 using Point = ::std::pair<double, YValue>;
Philipp Schrader9a833362017-04-09 22:56:16 +000016 InterpolationTable() = default;
Parker Schuh94d56792017-04-13 20:32:50 -070017 InterpolationTable(const ::std::vector<Point> &table);
Philipp Schradere8ad6382017-04-09 21:51:21 +000018
19 // Uses the interpolation table to calculate the optimal shooter angle and
20 // power for a shot
Parker Schuh94d56792017-04-13 20:32:50 -070021 YValue Get(double x) const;
22
Philipp Schrader790cb542023-07-05 21:06:52 -070023 bool GetInRange(double x, YValue *type) const;
Philipp Schradere8ad6382017-04-09 21:51:21 +000024
25 private:
26 // Contains the list of angle entries in the interpolation table
Parker Schuh94d56792017-04-13 20:32:50 -070027 ::std::vector<Point> table_;
Philipp Schradere8ad6382017-04-09 21:51:21 +000028};
29
Parker Schuh94d56792017-04-13 20:32:50 -070030template <typename YValue>
Philipp Schrader790cb542023-07-05 21:06:52 -070031InterpolationTable<YValue>::InterpolationTable(
32 const ::std::vector<Point> &table)
33 : table_(table) {
34 ::std::sort(table_.begin(), table_.end(),
35 [](const Point &a, const Point &b) { return a.first < b.first; });
36}
Parker Schuh94d56792017-04-13 20:32:50 -070037
38template <typename YValue>
39YValue InterpolationTable<YValue>::Get(double x) const {
40 // Points to to the smallest item such that it->first >= dist, or end() if no
41 // such item exists.
Philipp Schrader790cb542023-07-05 21:06:52 -070042 auto it = ::std::lower_bound(
43 table_.begin(), table_.end(), x,
44 [](const Point &a, double dist) { return a.first < dist; });
Parker Schuh94d56792017-04-13 20:32:50 -070045 if (it == table_.begin()) {
46 return it->second;
47 } else if (it == table_.end()) {
48 return table_.back().second;
49 } else {
50 auto x_a2 = it;
51 auto x_a1 = it - 1;
52 double x1 = x_a1->first;
53 double x2 = x_a2->first;
54 double coefficient = (x - x1) / (x2 - x1);
55 return YValue::BlendY(coefficient, x_a1->second, x_a2->second);
56 }
57}
58
59template <typename YValue>
Philipp Schrader790cb542023-07-05 21:06:52 -070060bool InterpolationTable<YValue>::GetInRange(double x, YValue *result) const {
Parker Schuh94d56792017-04-13 20:32:50 -070061 // Points to to the smallest item such that it->first >= dist, or end() if no
62 // such item exists.
Philipp Schrader790cb542023-07-05 21:06:52 -070063 auto it = ::std::lower_bound(
64 table_.begin(), table_.end(), x,
65 [](const Point &a, double dist) { return a.first < dist; });
Parker Schuh94d56792017-04-13 20:32:50 -070066 if (it == table_.begin()) {
67 return false;
68 } else if (it == table_.end()) {
69 return false;
70 } else {
71 auto x_a2 = it;
72 auto x_a1 = it - 1;
73 double x1 = x_a1->first;
74 double x2 = x_a2->first;
75 double coefficient = (x - x1) / (x2 - x1);
76 *result = YValue::BlendY(coefficient, x_a1->second, x_a2->second);
77 return true;
78 }
79}
80
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080081} // namespace frc971::shooter_interpolation
Philipp Schradere8ad6382017-04-09 21:51:21 +000082
83#endif // FRC971_SHOOTER_INTERPOLATION_INTERPOLATION_H_