blob: 0170151ca0cd00d23baee0cdcc7425b15a767cce [file] [log] [blame]
Alex Perry731b4602019-02-02 22:13:01 -08001#ifndef FRC971_CONTROL_LOOPS_DRIVETRAIN_SPLINEDRIVETRAIN_H_
2#define FRC971_CONTROL_LOOPS_DRIVETRAIN_SPLINEDRIVETRAIN_H_
3
Alex Perrycc3ee4c2019-02-09 21:20:41 -08004#include <atomic>
5#include <thread>
6
Alex Perrya71badb2019-02-06 19:40:41 -08007#include "Eigen/Dense"
8
Alex Perrycc3ee4c2019-02-09 21:20:41 -08009#include "aos/condition.h"
10#include "aos/mutex/mutex.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070011#include "frc971/control_loops/control_loops_generated.h"
Alex Perry731b4602019-02-02 22:13:01 -080012#include "frc971/control_loops/drivetrain/distance_spline.h"
Alex Perry731b4602019-02-02 22:13:01 -080013#include "frc971/control_loops/drivetrain/drivetrain_config.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070014#include "frc971/control_loops/drivetrain/drivetrain_goal_generated.h"
15#include "frc971/control_loops/drivetrain/drivetrain_output_generated.h"
16#include "frc971/control_loops/drivetrain/drivetrain_status_generated.h"
Alex Perry731b4602019-02-02 22:13:01 -080017#include "frc971/control_loops/drivetrain/spline.h"
18#include "frc971/control_loops/drivetrain/trajectory.h"
19
20namespace frc971 {
21namespace control_loops {
22namespace drivetrain {
23
24class SplineDrivetrain {
25 public:
26 SplineDrivetrain(const DrivetrainConfig<double> &dt_config);
27
Alex Perrycb7da4b2019-08-28 19:35:56 -070028 void SetGoal(const ::frc971::control_loops::drivetrain::Goal *goal);
James Kuszmaul75a18c52021-03-10 22:02:07 -080029 // Note that the user maintains ownership of the trajectory flatbuffer for the
30 // entire time; once AddTrajectory() is called, the trajectory pointer must
31 // stay valid until the spline has finished executing and HasTrajectory()
32 // returns false.
33 bool HasTrajectory(const fb::Trajectory *trajectory) const;
34 void AddTrajectory(const fb::Trajectory *trajectory);
Alex Perry731b4602019-02-02 22:13:01 -080035
James Kuszmaulaa2499d2020-06-02 21:31:19 -070036 void Update(bool enabled, const ::Eigen::Matrix<double, 5, 1> &state,
37 const ::Eigen::Matrix<double, 2, 1> &voltage_error);
Alex Perrya71badb2019-02-06 19:40:41 -080038
Alex Perrycb7da4b2019-08-28 19:35:56 -070039 void SetOutput(::frc971::control_loops::drivetrain::OutputT *output);
40
41 flatbuffers::Offset<TrajectoryLogging> MakeTrajectoryLogging(
42 aos::Sender<drivetrain::Status>::Builder *builder) const;
43 flatbuffers::Offset<TrajectoryLogging> MakeTrajectoryLogging(
44 flatbuffers::FlatBufferBuilder *builder) const;
Austin Schuhd749d932020-12-30 21:38:40 -080045 void PopulateStatus(drivetrain::Status::Builder *status) const;
James Kuszmaul1057ce82019-02-09 17:58:24 -080046
47 // Accessor for the current goal state, pretty much only present for debugging
48 // purposes.
Alex Perrycc3ee4c2019-02-09 21:20:41 -080049 ::Eigen::Matrix<double, 5, 1> CurrentGoalState() const {
James Kuszmaul75a18c52021-03-10 22:02:07 -080050 return executing_spline_ ? current_trajectory().GoalState(current_xva_(0),
51 current_xva_(1))
52 : ::Eigen::Matrix<double, 5, 1>::Zero();
James Kuszmaul1057ce82019-02-09 17:58:24 -080053 }
54
55 bool IsAtEnd() const {
James Kuszmaul75a18c52021-03-10 22:02:07 -080056 return executing_spline_
57 ? current_trajectory().is_at_end(current_xva_.block<2, 1>(0, 0))
Austin Schuhd749d932020-12-30 21:38:40 -080058 : true;
James Kuszmaul1057ce82019-02-09 17:58:24 -080059 }
Alex Perrycc3ee4c2019-02-09 21:20:41 -080060
Alex Perrycb7da4b2019-08-28 19:35:56 -070061 // Returns true if the splinedrivetrain is enabled.
62 bool enable() const { return enable_; }
63
Alex Perry731b4602019-02-02 22:13:01 -080064 private:
Alex Perrye32eabc2019-02-08 19:51:19 -080065 void ScaleCapU(Eigen::Matrix<double, 2, 1> *U);
66
James Kuszmaul75a18c52021-03-10 22:02:07 -080067 // This is called to update the internal state for managing all the splines.
68 // Calling it redundantly does not cause any issues. It checks the value of
69 // commanded_spline_ to determine whether we are being commanded to run a
70 // spline, and if there is any trajectory in the list of trajectories matching
71 // the command, we begin/continue executing that spline. If commanded_spline_
72 // is empty or has changed, we stop executing the previous trajectory and
73 // remove it from trajectories_. Then, when the drivetrain code checks
74 // HasTrajectory() for the old trajectory, it will return false and the
75 // drivetrain can free up the fetcher to get the next trajectory.
76 void UpdateSplineHandles();
77
78 // Deletes the currently executing trajectory.
79 void DeleteCurrentSpline();
80
81 const FinishedTrajectory &current_trajectory() const {
82 CHECK(current_trajectory_index_);
83 CHECK_LE(0u, *current_trajectory_index_);
84 CHECK_LT(*current_trajectory_index_, trajectories_.size());
85 return *trajectories_[*current_trajectory_index_];
86 }
87
Alex Perry731b4602019-02-02 22:13:01 -080088 const DrivetrainConfig<double> dt_config_;
89
James Kuszmaul75a18c52021-03-10 22:02:07 -080090 bool executing_spline_ = false;
Alex Perrye32eabc2019-02-08 19:51:19 -080091
James Kuszmaul75a18c52021-03-10 22:02:07 -080092 // TODO(james): Sort out construction to avoid so much dynamic memory
93 // allocation...
94 std::vector<std::unique_ptr<FinishedTrajectory>> trajectories_;
95 std::optional<size_t> current_trajectory_index_;
96
97 std::optional<int> commanded_spline_;
Alex Perrycc3ee4c2019-02-09 21:20:41 -080098
99 // State required to compute the next iteration's output.
100 ::Eigen::Matrix<double, 3, 1> current_xva_, next_xva_;
101 ::Eigen::Matrix<double, 2, 1> next_U_;
102
103 // Information used for status message.
104 ::Eigen::Matrix<double, 2, 1> uncapped_U_;
105 bool enable_ = false;
106 bool output_was_capped_ = false;
Alex Perry731b4602019-02-02 22:13:01 -0800107};
108
109} // namespace drivetrain
110} // namespace control_loops
111} // namespace frc971
112
113#endif // FRC971_CONTROL_LOOPS_DRIVETRAIN_SPLINEDRIVETRAIN_H_