blob: 5c404a0f7cffd3edca41750c71846533786200ad [file] [log] [blame]
Austin Schuh941b46d2018-12-19 18:06:05 +11001#ifndef FRC971_CONTROL_LOOPS_DRIVETRAIN_DISTANCE_SPLINE_H_
2#define FRC971_CONTROL_LOOPS_DRIVETRAIN_DISTANCE_SPLINE_H_
3
4#include <vector>
5
6#include "Eigen/Dense"
Austin Schuhf7c65202022-11-04 21:28:20 -07007#include "absl/types/span.h"
Philipp Schrader790cb542023-07-05 21:06:52 -07008
Austin Schuhf7c65202022-11-04 21:28:20 -07009#include "aos/containers/sized_array.h"
Austin Schuh941b46d2018-12-19 18:06:05 +110010#include "frc971/control_loops/drivetrain/spline.h"
James Kuszmaul75a18c52021-03-10 22:02:07 -080011#include "frc971/control_loops/drivetrain/trajectory_generated.h"
Austin Schuh941b46d2018-12-19 18:06:05 +110012#include "frc971/control_loops/fixed_quadrature.h"
13
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080014namespace frc971::control_loops::drivetrain {
Austin Schuh941b46d2018-12-19 18:06:05 +110015
James Kuszmaul75a18c52021-03-10 22:02:07 -080016std::vector<Spline> FlatbufferToSplines(const MultiSpline *fb);
17
Austin Schuh941b46d2018-12-19 18:06:05 +110018// Class to hold a spline as a function of distance.
Austin Schuhf7c65202022-11-04 21:28:20 -070019class DistanceSplineBase {
Austin Schuh941b46d2018-12-19 18:06:05 +110020 public:
21 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
22
Austin Schuhf7c65202022-11-04 21:28:20 -070023 virtual ~DistanceSplineBase() {}
James Kuszmaul75a18c52021-03-10 22:02:07 -080024
25 flatbuffers::Offset<fb::DistanceSpline> Serialize(
26 flatbuffers::FlatBufferBuilder *fbb,
27 flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Constraint>>>
28 constraints) const;
Austin Schuh941b46d2018-12-19 18:06:05 +110029
30 // Returns a point on the spline as a function of distance.
31 ::Eigen::Matrix<double, 2, 1> XY(double distance) const {
Austin Schuh280996e2019-01-19 17:43:37 -080032 const AlphaAndIndex a = DistanceToAlpha(distance);
Austin Schuhf7c65202022-11-04 21:28:20 -070033 return splines()[a.index].Point(a.alpha);
Austin Schuh941b46d2018-12-19 18:06:05 +110034 }
35
36 // Returns the velocity as a function of distance.
37 ::Eigen::Matrix<double, 2, 1> DXY(double distance) const {
Austin Schuh280996e2019-01-19 17:43:37 -080038 const AlphaAndIndex a = DistanceToAlpha(distance);
Austin Schuhf7c65202022-11-04 21:28:20 -070039 return splines()[a.index].DPoint(a.alpha).normalized();
Austin Schuh941b46d2018-12-19 18:06:05 +110040 }
41
42 // Returns the acceleration as a function of distance.
43 ::Eigen::Matrix<double, 2, 1> DDXY(double distance) const;
44
45 // Returns the heading as a function of distance.
46 double Theta(double distance) const {
Austin Schuh280996e2019-01-19 17:43:37 -080047 const AlphaAndIndex a = DistanceToAlpha(distance);
Austin Schuhf7c65202022-11-04 21:28:20 -070048 return splines()[a.index].Theta(a.alpha);
Austin Schuh941b46d2018-12-19 18:06:05 +110049 }
50
51 // Returns the angular velocity as a function of distance.
James Kuszmaulaa2499d2020-06-02 21:31:19 -070052 // This is also equivalent to the curvature at the given point.
Austin Schuh941b46d2018-12-19 18:06:05 +110053 double DTheta(double distance) const {
54 // TODO(austin): We are re-computing DPoint here!
Austin Schuh280996e2019-01-19 17:43:37 -080055 const AlphaAndIndex a = DistanceToAlpha(distance);
Austin Schuhf7c65202022-11-04 21:28:20 -070056 const Spline &spline = splines()[a.index];
Austin Schuh280996e2019-01-19 17:43:37 -080057 return spline.DTheta(a.alpha) / spline.DPoint(a.alpha).norm();
Austin Schuh941b46d2018-12-19 18:06:05 +110058 }
59
James Kuszmaulaa2499d2020-06-02 21:31:19 -070060 // Returns the derivative of heading with respect to time at a given
61 // distance along the spline, if we are travelling at the provided velocity.
Austin Schuhec7f06d2019-01-04 07:47:15 +110062 double DThetaDt(double distance, double velocity) const {
63 return DTheta(distance) * velocity;
64 }
65
Austin Schuh941b46d2018-12-19 18:06:05 +110066 // Returns the angular acceleration as a function of distance.
67 double DDTheta(double distance) const;
68
69 // Returns the length of the path in meters.
Austin Schuhf7c65202022-11-04 21:28:20 -070070 double length() const { return distances().back(); }
Austin Schuh941b46d2018-12-19 18:06:05 +110071
Austin Schuhf7c65202022-11-04 21:28:20 -070072 virtual const absl::Span<const float> distances() const = 0;
73 virtual const absl::Span<const Spline> splines() const = 0;
James Kuszmaul75a18c52021-03-10 22:02:07 -080074
Austin Schuh941b46d2018-12-19 18:06:05 +110075 private:
Austin Schuh280996e2019-01-19 17:43:37 -080076 struct AlphaAndIndex {
77 size_t index;
78 double alpha;
79 };
80
Austin Schuh941b46d2018-12-19 18:06:05 +110081 // Computes alpha for a distance
Austin Schuh280996e2019-01-19 17:43:37 -080082 AlphaAndIndex DistanceToAlpha(double distance) const;
Austin Schuhf7c65202022-11-04 21:28:20 -070083};
Austin Schuh280996e2019-01-19 17:43:37 -080084
Austin Schuhf7c65202022-11-04 21:28:20 -070085// Class which computes a DistanceSpline and stores it.
86class DistanceSpline final : public DistanceSplineBase {
87 public:
88 DistanceSpline(const Spline &spline, int num_alpha = 0);
89 DistanceSpline(::std::vector<Spline> &&splines, int num_alpha = 0);
90 DistanceSpline(const MultiSpline *fb, int num_alpha = 0);
91
92 const absl::Span<const float> distances() const override {
93 return distances_;
94 }
95 const absl::Span<const Spline> splines() const override { return splines_; }
96
97 private:
James Kuszmaul75a18c52021-03-10 22:02:07 -080098 ::std::vector<float> BuildDistances(size_t num_alpha);
Austin Schuh941b46d2018-12-19 18:06:05 +110099
100 // The spline we are converting to a distance.
Austin Schuh280996e2019-01-19 17:43:37 -0800101 const ::std::vector<Spline> splines_;
Austin Schuh941b46d2018-12-19 18:06:05 +1100102 // An interpolation table of distances evenly distributed in alpha.
James Kuszmaul75a18c52021-03-10 22:02:07 -0800103 const ::std::vector<float> distances_;
Austin Schuh941b46d2018-12-19 18:06:05 +1100104};
105
Austin Schuhf7c65202022-11-04 21:28:20 -0700106// Class exposing a finished DistanceSpline flatbuffer as a DistanceSpline.
107//
108// The lifetime of the provided fb::DistanceSpline needs to out-live this class.
109class FinishedDistanceSpline final : public DistanceSplineBase {
110 public:
111 static constexpr size_t kMaxSplines = 6;
112 FinishedDistanceSpline(const fb::DistanceSpline &fb);
113
114 const absl::Span<const float> distances() const override {
115 return distances_;
116 }
117 const absl::Span<const Spline> splines() const override { return splines_; }
118
119 private:
120 ::std::vector<float> BuildDistances(size_t num_alpha);
121
122 // The spline we are converting to a distance.
123 aos::SizedArray<Spline, kMaxSplines> splines_;
124 // An interpolation table of distances evenly distributed in alpha.
James Kuszmauldc534432023-02-05 14:51:11 -0800125 absl::Span<const float> distances_;
Austin Schuhf7c65202022-11-04 21:28:20 -0700126};
127
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -0800128} // namespace frc971::control_loops::drivetrain
Austin Schuh941b46d2018-12-19 18:06:05 +1100129
130#endif // FRC971_CONTROL_LOOPS_DRIVETRAIN_DISTANCE_SPLINE_H_