blob: 21f2f8cb06ec047d477456237e59513980d29ba6 [file] [log] [blame]
Austin Schuhe9ae4562023-04-25 22:18:18 -07001#include "frc971/solvers/convex.h"
2
3#include "gtest/gtest.h"
4
Stephan Pleinesf63bde82024-01-13 15:59:33 -08005namespace frc971::solvers::testing {
Austin Schuhe9ae4562023-04-25 22:18:18 -07006
7const Eigen::IOFormat kHeavyFormat(Eigen::StreamPrecision, 0, ", ",
8 ",\n "
9 " ",
10 "[", "]", "[", "]");
11
12class SimpleQP : public ConvexProblem<2, 4, 1> {
13 public:
14 // QP of the for 0.5 * X^t Q_ X + p.T * X
15 SimpleQP(Eigen::Matrix<double, 2, 2> Q, Eigen::Matrix<double, 2, 1> p,
16 double x0_max, double x0_min, double x1_max, double x1_min)
17 : Q_(Q), p_(p) {
18 C_ << 1, 0, -1, 0, 0, 1, 0, -1;
19 c_ << x0_max, -x0_min, x1_max, -x1_min;
20 }
21
22 double f0(Eigen::Ref<const Eigen::Matrix<double, 2, 1>> X) const override {
23 return 0.5 * (X.transpose() * Q_ * X)(0, 0);
24 }
25
26 Eigen::Matrix<double, 2, 1> df0(
27 Eigen::Ref<const Eigen::Matrix<double, 2, 1>> X) const override {
28 return Q_ * X + p_;
29 }
30
31 Eigen::Matrix<double, 2, 2> ddf0(
32 Eigen::Ref<const Eigen::Matrix<double, 2, 1>> /*X*/) const override {
33 return Q_;
34 }
35
36 // Returns the constraints f(X) < 0, and their derivitive.
37 Eigen::Matrix<double, 4, 1> f(
38 Eigen::Ref<const Eigen::Matrix<double, 2, 1>> X) const override {
39 return C_ * X - c_;
40 }
41 Eigen::Matrix<double, 4, 2> df(
42 Eigen::Ref<const Eigen::Matrix<double, 2, 1>> /*X*/) const override {
43 return C_;
44 }
45
46 // Returns the equality constraints of the form A x = b
47 Eigen::Matrix<double, 1, 2> A() const override {
48 return Eigen::Matrix<double, 1, 2>(1, -1);
49 }
50 Eigen::Matrix<double, 1, 1> b() const override {
51 return Eigen::Matrix<double, 1, 1>(0);
52 }
53
54 private:
55 Eigen::Matrix<double, 2, 2> Q_;
56 Eigen::Matrix<double, 2, 1> p_;
57
58 Eigen::Matrix<double, 4, 2> C_;
59 Eigen::Matrix<double, 4, 1> c_;
60};
61
62// Test a constrained quadratic problem where the constraints aren't active.
63TEST(SolverTest, SimpleQP) {
64 Eigen::Matrix<double, 2, 2> Q = Eigen::DiagonalMatrix<double, 2>(1.0, 1.0);
65 Eigen::Matrix<double, 2, 1> p(-4, -6);
66
67 SimpleQP qp(Q, p, 6, -1, 6, -1);
68 Solver<2, 4, 1> s;
69 Eigen::Vector2d result = s.Solve(qp, Eigen::Matrix<double, 2, 1>(0, 0));
70 LOG(INFO) << "Result is " << std::setprecision(12)
71 << result.transpose().format(kHeavyFormat);
72 EXPECT_NEAR((result - Eigen::Vector2d(5.0, 5.0)).norm(), 0.0, 1e-6);
73}
74
75// Test a constrained quadratic problem where the constraints are active.
76TEST(SolverTest, Constrained) {
77 Eigen::Matrix<double, 2, 2> Q = Eigen::DiagonalMatrix<double, 2>(1.0, 2.0);
78 Eigen::Matrix<double, 2, 1> p(-5, -10);
79
80 SimpleQP qp(Q, p, 4, -1, 5, -1);
81 Solver<2, 4, 1> s;
82 Eigen::Vector2d result = s.Solve(qp, Eigen::Matrix<double, 2, 1>(3, 4));
83 LOG(INFO) << "Result is " << std::setprecision(12)
84 << result.transpose().format(kHeavyFormat);
85 EXPECT_NEAR((result - Eigen::Vector2d(4.0, 4.0)).norm(), 0.0, 1e-6);
86}
87
88// Test a constrained quadratic problem where the constraints are active and the
89// initial value is the solution.
90TEST(SolverTest, ConstrainedFromSolution) {
91 Eigen::Matrix<double, 2, 2> Q = Eigen::DiagonalMatrix<double, 2>(1.0, 2.0);
92 Eigen::Matrix<double, 2, 1> p(-5, -10);
93
94 SimpleQP qp(Q, p, 4, -1, 5, -1);
95 Solver<2, 4, 1> s;
96 Eigen::Vector2d result = s.Solve(qp, Eigen::Matrix<double, 2, 1>(4, 4));
97 LOG(INFO) << "Result is " << std::setprecision(12)
98 << result.transpose().format(kHeavyFormat);
99 EXPECT_NEAR((result - Eigen::Vector2d(4.0, 4.0)).norm(), 0.0, 1e-6);
100}
101
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800102} // namespace frc971::solvers::testing