blob: dd0e31634bb25112789c2db5116d5d426b791ec4 [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
24 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>
32InterpolationTable<YValue>::InterpolationTable(const ::std::vector<Point> &table)
33 : table_(table) {
34 ::std::sort(table_.begin(), table_.end(),
35 [](const Point &a, const Point &b) {
36 return a.first < b.first;
37 });
38 }
39
40template <typename YValue>
41YValue InterpolationTable<YValue>::Get(double x) const {
42 // Points to to the smallest item such that it->first >= dist, or end() if no
43 // such item exists.
44 auto it = ::std::lower_bound(table_.begin(), table_.end(), x,
45 [](const Point &a,
46 double dist) { return a.first < dist; });
47 if (it == table_.begin()) {
48 return it->second;
49 } else if (it == table_.end()) {
50 return table_.back().second;
51 } else {
52 auto x_a2 = it;
53 auto x_a1 = it - 1;
54 double x1 = x_a1->first;
55 double x2 = x_a2->first;
56 double coefficient = (x - x1) / (x2 - x1);
57 return YValue::BlendY(coefficient, x_a1->second, x_a2->second);
58 }
59}
60
61template <typename YValue>
62bool InterpolationTable<YValue>::GetInRange(double x, YValue* result) const {
63 // Points to to the smallest item such that it->first >= dist, or end() if no
64 // such item exists.
65 auto it = ::std::lower_bound(table_.begin(), table_.end(), x,
66 [](const Point &a,
67 double dist) { return a.first < dist; });
68 if (it == table_.begin()) {
69 return false;
70 } else if (it == table_.end()) {
71 return false;
72 } else {
73 auto x_a2 = it;
74 auto x_a1 = it - 1;
75 double x1 = x_a1->first;
76 double x2 = x_a2->first;
77 double coefficient = (x - x1) / (x2 - x1);
78 *result = YValue::BlendY(coefficient, x_a1->second, x_a2->second);
79 return true;
80 }
81}
82
Philipp Schradere8ad6382017-04-09 21:51:21 +000083} // namespace shooter_interpolation
84} // namespace frc971
85
86#endif // FRC971_SHOOTER_INTERPOLATION_INTERPOLATION_H_