blob: 145060d8e3bf79c7354d2efd80fe0eeaef4a2220 [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 Perrycc3ee4c2019-02-09 21:20:41 -080028 ~SplineDrivetrain() {
29 {
30 ::aos::MutexLocker locker(&mutex_);
31 run_ = false;
32 new_goal_.Signal();
33 }
34 worker_thread_.join();
35 }
36
Alex Perrycb7da4b2019-08-28 19:35:56 -070037 void SetGoal(const ::frc971::control_loops::drivetrain::Goal *goal);
Alex Perry731b4602019-02-02 22:13:01 -080038
James Kuszmaulaa2499d2020-06-02 21:31:19 -070039 void Update(bool enabled, const ::Eigen::Matrix<double, 5, 1> &state,
40 const ::Eigen::Matrix<double, 2, 1> &voltage_error);
Alex Perrya71badb2019-02-06 19:40:41 -080041
Alex Perrycb7da4b2019-08-28 19:35:56 -070042 void SetOutput(::frc971::control_loops::drivetrain::OutputT *output);
43
44 flatbuffers::Offset<TrajectoryLogging> MakeTrajectoryLogging(
45 aos::Sender<drivetrain::Status>::Builder *builder) const;
46 flatbuffers::Offset<TrajectoryLogging> MakeTrajectoryLogging(
47 flatbuffers::FlatBufferBuilder *builder) const;
Alex Perry731b4602019-02-02 22:13:01 -080048 void PopulateStatus(
Alex Perrycb7da4b2019-08-28 19:35:56 -070049 drivetrain::Status::Builder *status) const;
James Kuszmaul1057ce82019-02-09 17:58:24 -080050
51 // Accessor for the current goal state, pretty much only present for debugging
52 // purposes.
Alex Perrycc3ee4c2019-02-09 21:20:41 -080053 ::Eigen::Matrix<double, 5, 1> CurrentGoalState() const {
54 return current_trajectory_
55 ? current_trajectory_->GoalState(current_xva_(0),
56 current_xva_(1))
57 : ::Eigen::Matrix<double, 5, 1>::Zero();
James Kuszmaul1057ce82019-02-09 17:58:24 -080058 }
59
60 bool IsAtEnd() const {
Alex Perrycc3ee4c2019-02-09 21:20:41 -080061 return current_trajectory_
62 ? current_trajectory_->is_at_end(current_xva_.block<2, 1>(0, 0)) :
63 true;
James Kuszmaul1057ce82019-02-09 17:58:24 -080064 }
Alex Perrycc3ee4c2019-02-09 21:20:41 -080065
Alex Perrycb7da4b2019-08-28 19:35:56 -070066 // Returns true if the splinedrivetrain is enabled.
67 bool enable() const { return enable_; }
68
Alex Perrycc3ee4c2019-02-09 21:20:41 -080069 enum class PlanState : int8_t {
70 kNoPlan = 0,
71 kBuildingTrajectory = 1,
72 kPlanningTrajectory = 2,
73 kPlannedTrajectory = 3,
74 };
75
Alex Perry731b4602019-02-02 22:13:01 -080076 private:
Alex Perrycc3ee4c2019-02-09 21:20:41 -080077 void ComputeTrajectory();
Alex Perrye32eabc2019-02-08 19:51:19 -080078 void ScaleCapU(Eigen::Matrix<double, 2, 1> *U);
79
Alex Perry731b4602019-02-02 22:13:01 -080080 const DrivetrainConfig<double> dt_config_;
81
Alex Perrycc3ee4c2019-02-09 21:20:41 -080082 int32_t current_spline_handle_ = 0; // Current spline told to excecute.
83 int32_t current_spline_idx_ = 0; // Current executing spline.
Alex Perry4b502a92019-04-06 22:00:38 -070084 bool has_started_execution_ = false;
Alex Perrye32eabc2019-02-08 19:51:19 -080085
Alex Perrycc3ee4c2019-02-09 21:20:41 -080086 ::std::unique_ptr<DistanceSpline> current_distance_spline_;
87 ::std::unique_ptr<Trajectory> current_trajectory_;
James Kuszmaul29e417d2019-04-13 10:03:35 -070088 bool current_drive_spline_backwards_ = false;
Alex Perrycc3ee4c2019-02-09 21:20:41 -080089
90 // State required to compute the next iteration's output.
91 ::Eigen::Matrix<double, 3, 1> current_xva_, next_xva_;
92 ::Eigen::Matrix<double, 2, 1> next_U_;
93
94 // Information used for status message.
95 ::Eigen::Matrix<double, 2, 1> uncapped_U_;
96 bool enable_ = false;
97 bool output_was_capped_ = false;
98
Austin Schuh872723c2019-12-25 14:38:09 -080099 std::atomic<PlanningState> plan_state_ = {PlanningState::NO_PLAN};
Alex Perrycc3ee4c2019-02-09 21:20:41 -0800100
101 ::std::thread worker_thread_;
102 // mutex_ is held by the worker thread while it is doing work or by the main
103 // thread when it is sending work to the worker thread.
104 ::aos::Mutex mutex_;
105 // new_goal_ is used to signal to the worker thread that ther is work to do.
106 ::aos::Condition new_goal_;
107 // The following variables are guarded by mutex_.
108 bool run_ = true;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700109
110 // These two structures mirror the flatbuffer Multispline.
111 // TODO(austin): copy the goal flatbuffer directly instead of recreating it
112 // like this...
113 struct MultiSpline {
114 int32_t spline_count;
115 std::array<float, 36> spline_x;
116 std::array<float, 36> spline_y;
117 std::array<ConstraintT, 6> constraints;
118 };
119
120 struct SplineGoal {
121 int32_t spline_idx = 0;
122
123 bool drive_spline_backwards;
124
125 MultiSpline spline;
126 };
127
128 SplineGoal goal_;
Alex Perrycc3ee4c2019-02-09 21:20:41 -0800129 ::std::unique_ptr<DistanceSpline> past_distance_spline_;
130 ::std::unique_ptr<DistanceSpline> future_distance_spline_;
131 ::std::unique_ptr<Trajectory> past_trajectory_;
132 ::std::unique_ptr<Trajectory> future_trajectory_;
James Kuszmaul29e417d2019-04-13 10:03:35 -0700133 bool future_drive_spline_backwards_ = false;
Alex Perrycc3ee4c2019-02-09 21:20:41 -0800134 int32_t future_spline_idx_ = 0; // Current spline being computed.
Austin Schuh6bcc2302019-03-23 22:28:06 -0700135 ::std::atomic<int32_t> planning_spline_idx_{-1};
Alex Perry731b4602019-02-02 22:13:01 -0800136};
137
138} // namespace drivetrain
139} // namespace control_loops
140} // namespace frc971
141
142#endif // FRC971_CONTROL_LOOPS_DRIVETRAIN_SPLINEDRIVETRAIN_H_