blob: b28334cd44d695ff57d46e6e4640e700dba217fa [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
Alex Perrye32eabc2019-02-08 19:51:19 -080039 void Update(bool enabled, const ::Eigen::Matrix<double, 5, 1> &state);
Alex Perrya71badb2019-02-06 19:40:41 -080040
Alex Perrycb7da4b2019-08-28 19:35:56 -070041 void SetOutput(::frc971::control_loops::drivetrain::OutputT *output);
42
43 flatbuffers::Offset<TrajectoryLogging> MakeTrajectoryLogging(
44 aos::Sender<drivetrain::Status>::Builder *builder) const;
45 flatbuffers::Offset<TrajectoryLogging> MakeTrajectoryLogging(
46 flatbuffers::FlatBufferBuilder *builder) const;
Alex Perry731b4602019-02-02 22:13:01 -080047 void PopulateStatus(
Alex Perrycb7da4b2019-08-28 19:35:56 -070048 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 {
53 return current_trajectory_
54 ? current_trajectory_->GoalState(current_xva_(0),
55 current_xva_(1))
56 : ::Eigen::Matrix<double, 5, 1>::Zero();
James Kuszmaul1057ce82019-02-09 17:58:24 -080057 }
58
59 bool IsAtEnd() const {
Alex Perrycc3ee4c2019-02-09 21:20:41 -080060 return current_trajectory_
61 ? current_trajectory_->is_at_end(current_xva_.block<2, 1>(0, 0)) :
62 true;
James Kuszmaul1057ce82019-02-09 17:58:24 -080063 }
Alex Perrycc3ee4c2019-02-09 21:20:41 -080064
Alex Perrycb7da4b2019-08-28 19:35:56 -070065 // Returns true if the splinedrivetrain is enabled.
66 bool enable() const { return enable_; }
67
Alex Perrycc3ee4c2019-02-09 21:20:41 -080068 enum class PlanState : int8_t {
69 kNoPlan = 0,
70 kBuildingTrajectory = 1,
71 kPlanningTrajectory = 2,
72 kPlannedTrajectory = 3,
73 };
74
Alex Perry731b4602019-02-02 22:13:01 -080075 private:
Alex Perrycc3ee4c2019-02-09 21:20:41 -080076 void ComputeTrajectory();
Alex Perrye32eabc2019-02-08 19:51:19 -080077 void ScaleCapU(Eigen::Matrix<double, 2, 1> *U);
78
Alex Perry731b4602019-02-02 22:13:01 -080079 const DrivetrainConfig<double> dt_config_;
80
Alex Perrycc3ee4c2019-02-09 21:20:41 -080081 int32_t current_spline_handle_ = 0; // Current spline told to excecute.
82 int32_t current_spline_idx_ = 0; // Current executing spline.
Alex Perry4b502a92019-04-06 22:00:38 -070083 bool has_started_execution_ = false;
Alex Perrye32eabc2019-02-08 19:51:19 -080084
Alex Perrycc3ee4c2019-02-09 21:20:41 -080085 ::std::unique_ptr<DistanceSpline> current_distance_spline_;
86 ::std::unique_ptr<Trajectory> current_trajectory_;
James Kuszmaul29e417d2019-04-13 10:03:35 -070087 bool current_drive_spline_backwards_ = false;
Alex Perrycc3ee4c2019-02-09 21:20:41 -080088
89 // State required to compute the next iteration's output.
90 ::Eigen::Matrix<double, 3, 1> current_xva_, next_xva_;
91 ::Eigen::Matrix<double, 2, 1> next_U_;
92
93 // Information used for status message.
94 ::Eigen::Matrix<double, 2, 1> uncapped_U_;
95 bool enable_ = false;
96 bool output_was_capped_ = false;
97
Austin Schuh872723c2019-12-25 14:38:09 -080098 std::atomic<PlanningState> plan_state_ = {PlanningState::NO_PLAN};
Alex Perrycc3ee4c2019-02-09 21:20:41 -080099
100 ::std::thread worker_thread_;
101 // mutex_ is held by the worker thread while it is doing work or by the main
102 // thread when it is sending work to the worker thread.
103 ::aos::Mutex mutex_;
104 // new_goal_ is used to signal to the worker thread that ther is work to do.
105 ::aos::Condition new_goal_;
106 // The following variables are guarded by mutex_.
107 bool run_ = true;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700108
109 // These two structures mirror the flatbuffer Multispline.
110 // TODO(austin): copy the goal flatbuffer directly instead of recreating it
111 // like this...
112 struct MultiSpline {
113 int32_t spline_count;
114 std::array<float, 36> spline_x;
115 std::array<float, 36> spline_y;
116 std::array<ConstraintT, 6> constraints;
117 };
118
119 struct SplineGoal {
120 int32_t spline_idx = 0;
121
122 bool drive_spline_backwards;
123
124 MultiSpline spline;
125 };
126
127 SplineGoal goal_;
Alex Perrycc3ee4c2019-02-09 21:20:41 -0800128 ::std::unique_ptr<DistanceSpline> past_distance_spline_;
129 ::std::unique_ptr<DistanceSpline> future_distance_spline_;
130 ::std::unique_ptr<Trajectory> past_trajectory_;
131 ::std::unique_ptr<Trajectory> future_trajectory_;
James Kuszmaul29e417d2019-04-13 10:03:35 -0700132 bool future_drive_spline_backwards_ = false;
Alex Perrycc3ee4c2019-02-09 21:20:41 -0800133 int32_t future_spline_idx_ = 0; // Current spline being computed.
Austin Schuh6bcc2302019-03-23 22:28:06 -0700134 ::std::atomic<int32_t> planning_spline_idx_{-1};
Alex Perrye32eabc2019-02-08 19:51:19 -0800135
136 // TODO(alex): pull this out of dt_config.
137 const ::Eigen::DiagonalMatrix<double, 5> Q =
138 (::Eigen::DiagonalMatrix<double, 5>().diagonal()
James Kuszmaulc73bb222019-04-07 12:15:35 -0700139 << 1.0 / ::std::pow(0.12, 2),
140 1.0 / ::std::pow(0.12, 2), 1.0 / ::std::pow(0.1, 2),
Austin Schuh11043182019-03-23 22:29:12 -0700141 1.0 / ::std::pow(1.5, 2), 1.0 / ::std::pow(1.5, 2))
Alex Perrye32eabc2019-02-08 19:51:19 -0800142 .finished()
143 .asDiagonal();
144 const ::Eigen::DiagonalMatrix<double, 2> R =
145 (::Eigen::DiagonalMatrix<double, 2>().diagonal()
146 << 1.0 / ::std::pow(12.0, 2),
147 1.0 / ::std::pow(12.0, 2))
148 .finished()
149 .asDiagonal();
Alex Perry731b4602019-02-02 22:13:01 -0800150};
151
152} // namespace drivetrain
153} // namespace control_loops
154} // namespace frc971
155
156#endif // FRC971_CONTROL_LOOPS_DRIVETRAIN_SPLINEDRIVETRAIN_H_