blob: f07f5eed17b977526a9dd6caa02bcae1f6fa7b87 [file] [log] [blame]
Austin Schuh941b46d2018-12-19 18:06:05 +11001#include "frc971/control_loops/drivetrain/distance_spline.h"
2
3#include "frc971/control_loops/drivetrain/spline.h"
4
5namespace frc971 {
6namespace control_loops {
7namespace drivetrain {
8
Austin Schuh280996e2019-01-19 17:43:37 -08009::std::vector<double> DistanceSpline::BuildDistances(size_t num_alpha) {
10 num_alpha = num_alpha == 0 ? 100 * splines_.size() : num_alpha;
11 ::std::vector<double> distances;
12 distances.push_back(0.0);
Austin Schuh941b46d2018-12-19 18:06:05 +110013
Austin Schuh280996e2019-01-19 17:43:37 -080014 const double dalpha =
15 static_cast<double>(splines_.size()) / static_cast<double>(num_alpha - 1);
Austin Schuh941b46d2018-12-19 18:06:05 +110016 double last_alpha = 0.0;
Austin Schuh280996e2019-01-19 17:43:37 -080017 for (size_t i = 1; i < num_alpha; ++i) {
Austin Schuh941b46d2018-12-19 18:06:05 +110018 const double alpha = dalpha * i;
Austin Schuh280996e2019-01-19 17:43:37 -080019 distances.push_back(distances.back() +
20 GaussianQuadrature5(
21 [this](double alpha) {
22 const size_t spline_index = ::std::min(
23 static_cast<size_t>(::std::floor(alpha)),
24 splines_.size() - 1);
25 return this->splines_[spline_index]
26 .DPoint(alpha - spline_index)
27 .norm();
28 },
29 last_alpha, alpha));
Austin Schuh941b46d2018-12-19 18:06:05 +110030 last_alpha = alpha;
31 }
Austin Schuh280996e2019-01-19 17:43:37 -080032 return distances;
Austin Schuh941b46d2018-12-19 18:06:05 +110033}
34
Austin Schuh280996e2019-01-19 17:43:37 -080035DistanceSpline::DistanceSpline(::std::vector<Spline> &&splines, int num_alpha)
36 : splines_(::std::move(splines)), distances_(BuildDistances(num_alpha)) {}
37
38DistanceSpline::DistanceSpline(const Spline &spline, int num_alpha)
39 : splines_({spline}), distances_(BuildDistances(num_alpha)) {}
40
Austin Schuh941b46d2018-12-19 18:06:05 +110041::Eigen::Matrix<double, 2, 1> DistanceSpline::DDXY(double distance) const {
Austin Schuh280996e2019-01-19 17:43:37 -080042 const AlphaAndIndex a = DistanceToAlpha(distance);
43 const ::Eigen::Matrix<double, 2, 1> dspline_point =
44 splines_[a.index].DPoint(a.alpha);
45 const ::Eigen::Matrix<double, 2, 1> ddspline_point =
46 splines_[a.index].DDPoint(a.alpha);
Austin Schuh941b46d2018-12-19 18:06:05 +110047
48 const double squared_norm = dspline_point.squaredNorm();
49
50 return ddspline_point / squared_norm -
51 dspline_point * (dspline_point(0) * ddspline_point(0) +
52 dspline_point(1) * ddspline_point(1)) /
53 ::std::pow(squared_norm, 2);
54}
55
56double DistanceSpline::DDTheta(double distance) const {
Austin Schuh280996e2019-01-19 17:43:37 -080057 const AlphaAndIndex a = DistanceToAlpha(distance);
Austin Schuh941b46d2018-12-19 18:06:05 +110058
59 // TODO(austin): We are re-computing DPoint here even worse
Austin Schuh280996e2019-01-19 17:43:37 -080060 const ::Eigen::Matrix<double, 2, 1> dspline_point =
61 splines_[a.index].DPoint(a.alpha);
62 const ::Eigen::Matrix<double, 2, 1> ddspline_point =
63 splines_[a.index].DDPoint(a.alpha);
Austin Schuh941b46d2018-12-19 18:06:05 +110064
Austin Schuh280996e2019-01-19 17:43:37 -080065 const double dtheta = splines_[a.index].DTheta(a.alpha);
66 const double ddtheta = splines_[a.index].DDTheta(a.alpha);
Austin Schuh941b46d2018-12-19 18:06:05 +110067
68 const double squared_norm = dspline_point.squaredNorm();
69
70 return ddtheta / squared_norm -
71 dtheta * (dspline_point(0) * ddspline_point(0) +
72 dspline_point(1) * ddspline_point(1)) /
73 ::std::pow(squared_norm, 2);
74}
75
Austin Schuh280996e2019-01-19 17:43:37 -080076DistanceSpline::AlphaAndIndex DistanceSpline::DistanceToAlpha(
77 double distance) const {
Austin Schuh941b46d2018-12-19 18:06:05 +110078 if (distance <= 0.0) {
Austin Schuh280996e2019-01-19 17:43:37 -080079 return {0, 0.0};
Austin Schuh941b46d2018-12-19 18:06:05 +110080 }
81 if (distance >= length()) {
Austin Schuh280996e2019-01-19 17:43:37 -080082 return {splines_.size() - 1, 1.0};
Austin Schuh941b46d2018-12-19 18:06:05 +110083 }
84
85 // Find the distance right below our number using a binary search.
86 size_t after = ::std::distance(
87 distances_.begin(),
88 ::std::lower_bound(distances_.begin(), distances_.end(), distance));
89 size_t before = after - 1;
90 const double distance_step_size =
Austin Schuh280996e2019-01-19 17:43:37 -080091 (splines_.size() / static_cast<double>(distances_.size() - 1));
Austin Schuh941b46d2018-12-19 18:06:05 +110092
Austin Schuh280996e2019-01-19 17:43:37 -080093 const double alpha = (distance - distances_[before]) /
94 (distances_[after] - distances_[before]) *
95 distance_step_size +
96 static_cast<double>(before) * distance_step_size;
97 const size_t index = static_cast<size_t>(::std::floor(alpha));
98
99 return {index, alpha - index};
Austin Schuh941b46d2018-12-19 18:06:05 +1100100}
101
102} // namespace drivetrain
103} // namespace control_loops
104} // namespace frc971