blob: 2ac3e627671a082b2c8eb569229fe4032babe843 [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
9DistanceSpline::DistanceSpline(const Spline &spline, int num_alpha)
10 : spline_(spline) {
11 distances_.push_back(0.0);
12 const double dalpha = 1.0 / static_cast<double>(num_alpha - 1);
13
14 double last_alpha = 0.0;
15 for (int i = 1; i < num_alpha; ++i) {
16 const double alpha = dalpha * i;
17 distances_.push_back(
18 distances_.back() +
19 GaussianQuadrature5(
20 [this](double alpha) { return this->spline_.DPoint(alpha).norm(); },
21 last_alpha, alpha));
22 last_alpha = alpha;
23 }
24}
25
26::Eigen::Matrix<double, 2, 1> DistanceSpline::DDXY(double distance) const {
27 const double alpha = DistanceToAlpha(distance);
28 const ::Eigen::Matrix<double, 2, 1> dspline_point = spline_.DPoint(alpha);
29 const ::Eigen::Matrix<double, 2, 1> ddspline_point = spline_.DDPoint(alpha);
30
31 const double squared_norm = dspline_point.squaredNorm();
32
33 return ddspline_point / squared_norm -
34 dspline_point * (dspline_point(0) * ddspline_point(0) +
35 dspline_point(1) * ddspline_point(1)) /
36 ::std::pow(squared_norm, 2);
37}
38
39double DistanceSpline::DDTheta(double distance) const {
40 const double alpha = DistanceToAlpha(distance);
41
42 // TODO(austin): We are re-computing DPoint here even worse
43 const ::Eigen::Matrix<double, 2, 1> dspline_point = spline_.DPoint(alpha);
44 const ::Eigen::Matrix<double, 2, 1> ddspline_point = spline_.DDPoint(alpha);
45
46 const double dtheta = spline_.DTheta(alpha);
47 const double ddtheta = spline_.DDTheta(alpha);
48
49 const double squared_norm = dspline_point.squaredNorm();
50
51 return ddtheta / squared_norm -
52 dtheta * (dspline_point(0) * ddspline_point(0) +
53 dspline_point(1) * ddspline_point(1)) /
54 ::std::pow(squared_norm, 2);
55}
56
57double DistanceSpline::DistanceToAlpha(double distance) const {
58 if (distance <= 0.0) {
59 return 0.0;
60 }
61 if (distance >= length()) {
62 return 1.0;
63 }
64
65 // Find the distance right below our number using a binary search.
66 size_t after = ::std::distance(
67 distances_.begin(),
68 ::std::lower_bound(distances_.begin(), distances_.end(), distance));
69 size_t before = after - 1;
70 const double distance_step_size =
71 (1.0 / static_cast<double>(distances_.size() - 1));
72
73 return (distance - distances_[before]) /
74 (distances_[after] - distances_[before]) * distance_step_size +
75 static_cast<double>(before) * distance_step_size;
76}
77
78} // namespace drivetrain
79} // namespace control_loops
80} // namespace frc971