blob: 8ef26e7c2912e8f26658f4de5c26d859bda8b729 [file] [log] [blame]
James Kuszmaulfb0e0ae2014-03-25 07:04:47 -07001#include "frc971/control_loops/coerce_goal.h"
2
3#include "Eigen/Dense"
4
5#include "aos/controls/polytope.h"
6
7namespace frc971 {
8namespace control_loops {
9
10Eigen::Matrix<double, 2, 1> CoerceGoal(aos::controls::HPolytope<2> &region,
11 const Eigen::Matrix<double, 1, 2> &K,
12 double w,
13 const Eigen::Matrix<double, 2, 1> &R) {
14 if (region.IsInside(R)) {
15 return R;
16 }
17 Eigen::Matrix<double, 2, 1> parallel_vector;
18 Eigen::Matrix<double, 2, 1> perpendicular_vector;
19 perpendicular_vector = K.transpose().normalized();
20 parallel_vector << perpendicular_vector(1, 0), -perpendicular_vector(0, 0);
21
22 aos::controls::HPolytope<1> t_poly(
23 region.H() * parallel_vector,
24 region.k() - region.H() * perpendicular_vector * w);
25
26 Eigen::Matrix<double, 1, Eigen::Dynamic> vertices = t_poly.Vertices();
27 if (vertices.innerSize() > 0) {
28 double min_distance_sqr = 0;
29 Eigen::Matrix<double, 2, 1> closest_point;
30 for (int i = 0; i < vertices.innerSize(); i++) {
31 Eigen::Matrix<double, 2, 1> point;
32 point = parallel_vector * vertices(0, i) + perpendicular_vector * w;
33 const double length = (R - point).squaredNorm();
34 if (i == 0 || length < min_distance_sqr) {
35 closest_point = point;
36 min_distance_sqr = length;
37 }
38 }
39 return closest_point;
40 } else {
41 Eigen::Matrix<double, 2, Eigen::Dynamic> region_vertices =
42 region.Vertices();
43 double min_distance = INFINITY;
44 int closest_i = 0;
45 for (int i = 0; i < region_vertices.outerSize(); i++) {
46 const double length = ::std::abs(
47 (perpendicular_vector.transpose() * (region_vertices.col(i)))(0, 0));
48 if (i == 0 || length < min_distance) {
49 closest_i = i;
50 min_distance = length;
51 }
52 }
53 return region_vertices.col(closest_i);
54 }
55}
56
57} // namespace control_loops
58} // namespace frc971