blob: 85e9242627b099de9bf7315c974f7644e2b5dbae [file] [log] [blame]
Austin Schuh1d731362022-02-22 13:57:55 -08001#ifndef Y2022_CONTROL_LOOPS_SUPERSTRUCTURE_CATAPULT_CATAPULT_H_
2#define Y2022_CONTROL_LOOPS_SUPERSTRUCTURE_CATAPULT_CATAPULT_H_
3
4#include "Eigen/Dense"
5#include "frc971/control_loops/state_feedback_loop.h"
6#include "glog/logging.h"
7#include "osqp++.h"
8
9namespace y2022 {
10namespace control_loops {
11namespace superstructure {
12namespace catapult {
13
14// MPC problem for a specified horizon. This contains all the state for the
15// solver, setters to modify the current and target state, and a way to fetch
16// the solution.
17class MPCProblem {
18 public:
19 MPCProblem(size_t horizon,
20 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> P,
21 Eigen::Matrix<double, Eigen::Dynamic, 1> accel_q,
22 Eigen::Matrix<double, 2, 2> Af,
23 Eigen::Matrix<double, Eigen::Dynamic, 2> final_q);
24
25 MPCProblem(MPCProblem const &) = delete;
26 void operator=(MPCProblem const &x) = delete;
27
28 // Sets the current and final state. This keeps the problem in tact and
29 // doesn't recreate it, so it will be fast.
30 void SetState(Eigen::Matrix<double, 2, 1> X_initial,
31 Eigen::Matrix<double, 2, 1> X_final);
32
33 // Solves our problem.
34 bool Solve();
35
36 double solve_time() const { return solve_time_; }
37
38 // Returns the solution that the solver found when Solve was last called.
39 double U(size_t i) const { return solver_.primal_solution()(i); }
40
41 // Returns the number of U's to be solved.
42 size_t horizon() const { return horizon_; }
43
44 // Warm starts the optimizer with the provided solution to make it solve
45 // faster.
46 void WarmStart(const MPCProblem &p);
47
48 private:
49 // The number of u's to solve for.
50 const size_t horizon_;
51
52 // The problem statement variables needed by SetState to update q.
53 const Eigen::Matrix<double, Eigen::Dynamic, 1> accel_q_;
54 const Eigen::Matrix<double, 2, 2> Af_;
55 const Eigen::Matrix<double, Eigen::Dynamic, 2> final_q_;
56
57 Eigen::Matrix<double, 2, 1> X_initial_;
58 Eigen::Matrix<double, 2, 1> X_final_;
59
60 // Solver state.
61 osqp::OsqpInstance instance_;
62 osqp::OsqpSolver solver_;
63 osqp::OsqpSettings settings_;
64
65 double solve_time_ = 0;
66};
67
68// Decently efficient problem generator for multiple horizons given a max
69// horizon to solve for.
70//
71// The math is documented in mpc.tex
72class CatapultProblemGenerator {
73 public:
74 // Builds a problem generator for the specified max horizon and caches a lot
75 // of the state.
76 CatapultProblemGenerator(size_t horizon);
77
78 // Returns the maximum horizon.
79 size_t horizon() const { return horizon_; }
80
81 // Makes a problem for the specificed horizon.
82 std::unique_ptr<MPCProblem> MakeProblem(size_t horizon);
83
84 // Returns the P and Q matrices for the problem statement.
85 // cost = 0.5 X.T P X + q.T X
86 const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> P(size_t horizon);
87 const Eigen::Matrix<double, Eigen::Dynamic, 1> q(
88 size_t horizon, Eigen::Matrix<double, 2, 1> X_initial,
89 Eigen::Matrix<double, 2, 1> X_final);
90
91 private:
92 const Eigen::Matrix<double, Eigen::Dynamic, 1> accel_q(size_t horizon);
93
94 const Eigen::Matrix<double, 2, 2> Af(size_t horizon);
95 const Eigen::Matrix<double, 2, Eigen::Dynamic> Bf(size_t horizon);
96 const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> Pi(
97 size_t horizon);
98
99 // These functions are used in the constructor to build up the matrices below.
100 Eigen::Matrix<double, Eigen::Dynamic, 2> MakeAs();
101 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> MakeBs();
102 Eigen::Matrix<double, Eigen::Dynamic, 1> Makem();
103 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> MakeM();
104 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> MakeW();
105 Eigen::Matrix<double, Eigen::Dynamic, 1> Makew();
106 Eigen::DiagonalMatrix<double, Eigen::Dynamic> MakePi();
107 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> MakeP();
108
109 const StateFeedbackPlant<2, 1, 1> plant_;
110 const size_t horizon_;
111
112 const Eigen::DiagonalMatrix<double, 2> Q_final_;
113
114 const Eigen::Matrix<double, Eigen::Dynamic, 2> As_;
115 const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> Bs_;
116 const Eigen::Matrix<double, Eigen::Dynamic, 1> m_;
117 const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> M_;
118
119 const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> W_;
120 const Eigen::Matrix<double, Eigen::Dynamic, 1> w_;
121 const Eigen::DiagonalMatrix<double, Eigen::Dynamic> Pi_;
122
123 const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> WM_;
124 const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> Wmpw_;
125};
126
127} // namespace catapult
128} // namespace superstructure
129} // namespace control_loops
130} // namespace y2022
131
132#endif // Y2022_CONTROL_LOOPS_SUPERSTRUCTURE_CATAPULT_CATAPULT_H_