blob: 2ceaac6aa2ddafa452669f5e2ac1adc7732dd43f [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;
Austin Schuhd749d932020-12-30 21:38:40 -080048 void PopulateStatus(drivetrain::Status::Builder *status) const;
James Kuszmaul1057ce82019-02-09 17:58:24 -080049
50 // Accessor for the current goal state, pretty much only present for debugging
51 // purposes.
Alex Perrycc3ee4c2019-02-09 21:20:41 -080052 ::Eigen::Matrix<double, 5, 1> CurrentGoalState() const {
Austin Schuhd749d932020-12-30 21:38:40 -080053 return current_trajectory_ ? current_trajectory_->GoalState(current_xva_(0),
54 current_xva_(1))
55 : ::Eigen::Matrix<double, 5, 1>::Zero();
James Kuszmaul1057ce82019-02-09 17:58:24 -080056 }
57
58 bool IsAtEnd() const {
Alex Perrycc3ee4c2019-02-09 21:20:41 -080059 return current_trajectory_
Austin Schuhd749d932020-12-30 21:38:40 -080060 ? current_trajectory_->is_at_end(current_xva_.block<2, 1>(0, 0))
61 : true;
James Kuszmaul1057ce82019-02-09 17:58:24 -080062 }
Alex Perrycc3ee4c2019-02-09 21:20:41 -080063
Alex Perrycb7da4b2019-08-28 19:35:56 -070064 // Returns true if the splinedrivetrain is enabled.
65 bool enable() const { return enable_; }
66
Alex Perrycc3ee4c2019-02-09 21:20:41 -080067 enum class PlanState : int8_t {
68 kNoPlan = 0,
69 kBuildingTrajectory = 1,
70 kPlanningTrajectory = 2,
71 kPlannedTrajectory = 3,
72 };
73
Alex Perry731b4602019-02-02 22:13:01 -080074 private:
Alex Perrycc3ee4c2019-02-09 21:20:41 -080075 void ComputeTrajectory();
Alex Perrye32eabc2019-02-08 19:51:19 -080076 void ScaleCapU(Eigen::Matrix<double, 2, 1> *U);
77
Alex Perry731b4602019-02-02 22:13:01 -080078 const DrivetrainConfig<double> dt_config_;
79
Alex Perrycc3ee4c2019-02-09 21:20:41 -080080 int32_t current_spline_handle_ = 0; // Current spline told to excecute.
81 int32_t current_spline_idx_ = 0; // Current executing spline.
Alex Perry4b502a92019-04-06 22:00:38 -070082 bool has_started_execution_ = false;
Alex Perrye32eabc2019-02-08 19:51:19 -080083
Alex Perrycc3ee4c2019-02-09 21:20:41 -080084 ::std::unique_ptr<DistanceSpline> current_distance_spline_;
85 ::std::unique_ptr<Trajectory> current_trajectory_;
James Kuszmaul29e417d2019-04-13 10:03:35 -070086 bool current_drive_spline_backwards_ = false;
Alex Perrycc3ee4c2019-02-09 21:20:41 -080087
88 // State required to compute the next iteration's output.
89 ::Eigen::Matrix<double, 3, 1> current_xva_, next_xva_;
90 ::Eigen::Matrix<double, 2, 1> next_U_;
91
92 // Information used for status message.
93 ::Eigen::Matrix<double, 2, 1> uncapped_U_;
94 bool enable_ = false;
95 bool output_was_capped_ = false;
96
Austin Schuh872723c2019-12-25 14:38:09 -080097 std::atomic<PlanningState> plan_state_ = {PlanningState::NO_PLAN};
Alex Perrycc3ee4c2019-02-09 21:20:41 -080098
99 ::std::thread worker_thread_;
100 // mutex_ is held by the worker thread while it is doing work or by the main
101 // thread when it is sending work to the worker thread.
102 ::aos::Mutex mutex_;
103 // new_goal_ is used to signal to the worker thread that ther is work to do.
104 ::aos::Condition new_goal_;
105 // The following variables are guarded by mutex_.
106 bool run_ = true;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700107
108 // These two structures mirror the flatbuffer Multispline.
109 // TODO(austin): copy the goal flatbuffer directly instead of recreating it
110 // like this...
111 struct MultiSpline {
112 int32_t spline_count;
113 std::array<float, 36> spline_x;
114 std::array<float, 36> spline_y;
115 std::array<ConstraintT, 6> constraints;
116 };
117
118 struct SplineGoal {
119 int32_t spline_idx = 0;
120
121 bool drive_spline_backwards;
122
123 MultiSpline spline;
124 };
125
126 SplineGoal goal_;
Alex Perrycc3ee4c2019-02-09 21:20:41 -0800127 ::std::unique_ptr<DistanceSpline> past_distance_spline_;
128 ::std::unique_ptr<DistanceSpline> future_distance_spline_;
129 ::std::unique_ptr<Trajectory> past_trajectory_;
130 ::std::unique_ptr<Trajectory> future_trajectory_;
James Kuszmaul29e417d2019-04-13 10:03:35 -0700131 bool future_drive_spline_backwards_ = false;
Alex Perrycc3ee4c2019-02-09 21:20:41 -0800132 int32_t future_spline_idx_ = 0; // Current spline being computed.
Austin Schuh6bcc2302019-03-23 22:28:06 -0700133 ::std::atomic<int32_t> planning_spline_idx_{-1};
Alex Perry731b4602019-02-02 22:13:01 -0800134};
135
136} // namespace drivetrain
137} // namespace control_loops
138} // namespace frc971
139
140#endif // FRC971_CONTROL_LOOPS_DRIVETRAIN_SPLINEDRIVETRAIN_H_