blob: e37346ea18b1fe42db115847d77dfdaeec0ce336 [file] [log] [blame]
Briana6553ed2014-04-02 21:26:46 -07001#ifndef AOS_COMMON_CONTROLS_POLYTOPE_H_
2#define AOS_COMMON_CONTROLS_POLYTOPE_H_
Austin Schuha6c257a2013-10-27 15:36:40 -07003
4#include "Eigen/Dense"
Brian Silverman8f1018b2013-11-17 21:35:15 -08005#include "libcdd-094g-prefix/include/setoper.h"
6#include "libcdd-094g-prefix/include/cdd.h"
Austin Schuha6c257a2013-10-27 15:36:40 -07007
8namespace aos {
9namespace controls {
10
11// A n dimension polytope.
12template <int number_of_dimensions>
13class HPolytope {
14 public:
15 // Constructs a polytope given the H and k matricies.
16 HPolytope(Eigen::Matrix<double, Eigen::Dynamic, number_of_dimensions> H,
17 Eigen::Matrix<double, Eigen::Dynamic, 1> k)
18 : H_(H),
19 k_(k) {
20 }
21
Brian Silverman6da04272014-05-18 18:47:48 -070022 // This is an initialization function shared across all instantiations of this
23 // template.
24 // This must be called at least once before calling any of the methods. It is
25 // not thread-safe.
Austin Schuha6c257a2013-10-27 15:36:40 -070026 static void Init() {
27 dd_set_global_constants();
28 }
29
30 // Returns a reference to H.
31 const Eigen::Matrix<double, Eigen::Dynamic,
32 number_of_dimensions> &H() const {
33 return H_;
34 }
35
36 // Returns a reference to k.
37 const Eigen::Matrix<double, Eigen::Dynamic,
38 1> &k() const {
39 return k_;
40 }
41
42 // Returns the number of dimensions in the polytope.
43 int ndim() const { return number_of_dimensions; }
44
45 // Returns the number of constraints currently in the polytope.
46 int num_constraints() const { return k_.rows(); }
47
48 // Returns true if the point is inside the polytope.
Brian Silverman6dd2c532014-03-29 23:34:39 -070049 bool IsInside(Eigen::Matrix<double, number_of_dimensions, 1> point) const;
Austin Schuha6c257a2013-10-27 15:36:40 -070050
51 // Returns the list of vertices inside the polytope.
Brian Silverman6dd2c532014-03-29 23:34:39 -070052 Eigen::Matrix<double, number_of_dimensions, Eigen::Dynamic> Vertices() const;
Austin Schuha6c257a2013-10-27 15:36:40 -070053
54 private:
55 Eigen::Matrix<double, Eigen::Dynamic, number_of_dimensions> H_;
56 Eigen::Matrix<double, Eigen::Dynamic, 1> k_;
57};
58
59template <int number_of_dimensions>
60bool HPolytope<number_of_dimensions>::IsInside(
Brian Silverman6dd2c532014-03-29 23:34:39 -070061 Eigen::Matrix<double, number_of_dimensions, 1> point) const {
Austin Schuha6c257a2013-10-27 15:36:40 -070062 auto ev = H_ * point;
63 for (int i = 0; i < num_constraints(); ++i) {
64 if (ev(i, 0) > k_(i, 0)) {
65 return false;
66 }
67 }
68 return true;
69}
70
71template <int number_of_dimensions>
72Eigen::Matrix<double, number_of_dimensions, Eigen::Dynamic>
Brian Silverman6dd2c532014-03-29 23:34:39 -070073 HPolytope<number_of_dimensions>::Vertices() const {
Austin Schuha6c257a2013-10-27 15:36:40 -070074 dd_MatrixPtr matrix = dd_CreateMatrix(num_constraints(), ndim() + 1);
75
76 // Copy the data over. TODO(aschuh): Is there a better way? I hate copying...
77 for (int i = 0; i < num_constraints(); ++i) {
78 dd_set_d(matrix->matrix[i][0], k_(i, 0));
79 for (int j = 0; j < ndim(); ++j) {
80 dd_set_d(matrix->matrix[i][j + 1], -H_(i, j));
81 }
82 }
83
84 matrix->representation = dd_Inequality;
85 matrix->numbtype = dd_Real;
86
87 dd_ErrorType error;
88 dd_PolyhedraPtr polyhedra = dd_DDMatrix2Poly(matrix, &error);
89 if (error != dd_NoError || polyhedra == NULL) {
90 dd_WriteErrorMessages(stderr, error);
91 dd_FreeMatrix(matrix);
92 Eigen::Matrix<double, number_of_dimensions, Eigen::Dynamic> ans(0, 0);
93 return ans;
94 }
95
96 dd_MatrixPtr vertex_matrix = dd_CopyGenerators(polyhedra);
97
98 int num_vertices = 0;
99 int num_rays = 0;
100 for (int i = 0; i < vertex_matrix->rowsize; ++i) {
101 if (dd_get_d(vertex_matrix->matrix[i][0]) == 0) {
102 num_rays += 1;
103 } else {
104 num_vertices += 1;
105 }
106 }
107
108 Eigen::Matrix<double, number_of_dimensions, Eigen::Dynamic> vertices(
109 number_of_dimensions, num_vertices);
110
111 int vertex_index = 0;
112 for (int i = 0; i < vertex_matrix->rowsize; ++i) {
113 if (dd_get_d(vertex_matrix->matrix[i][0]) != 0) {
114 for (int j = 0; j < number_of_dimensions; ++j) {
115 vertices(j, vertex_index) = dd_get_d(vertex_matrix->matrix[i][j + 1]);
116 }
117 ++vertex_index;
118 }
119 }
120 dd_FreeMatrix(vertex_matrix);
121 dd_FreePolyhedra(polyhedra);
122 dd_FreeMatrix(matrix);
123
124 return vertices;
125}
126
127} // namespace controls
128} // namespace aos
129
Briana6553ed2014-04-02 21:26:46 -0700130#endif // AOS_COMMON_CONTROLS_POLYTOPE_H_