blob: a873722b8d3b19ee9d975d757a8e6012997be4af [file] [log] [blame]
Austin Schuha6c257a2013-10-27 15:36:40 -07001#ifndef _AOS_CONTROLS_POLYTOPE_H_
2#define _AOS_CONTROLS_POLYTOPE_H_
3
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
22 static void Init() {
23 dd_set_global_constants();
24 }
25
26 // Returns a reference to H.
27 const Eigen::Matrix<double, Eigen::Dynamic,
28 number_of_dimensions> &H() const {
29 return H_;
30 }
31
32 // Returns a reference to k.
33 const Eigen::Matrix<double, Eigen::Dynamic,
34 1> &k() const {
35 return k_;
36 }
37
38 // Returns the number of dimensions in the polytope.
39 int ndim() const { return number_of_dimensions; }
40
41 // Returns the number of constraints currently in the polytope.
42 int num_constraints() const { return k_.rows(); }
43
44 // Returns true if the point is inside the polytope.
45 bool IsInside(Eigen::Matrix<double, number_of_dimensions, 1> point);
46
47 // Returns the list of vertices inside the polytope.
48 Eigen::Matrix<double, number_of_dimensions, Eigen::Dynamic> Vertices();
49
50 private:
51 Eigen::Matrix<double, Eigen::Dynamic, number_of_dimensions> H_;
52 Eigen::Matrix<double, Eigen::Dynamic, 1> k_;
53};
54
55template <int number_of_dimensions>
56bool HPolytope<number_of_dimensions>::IsInside(
57 Eigen::Matrix<double, number_of_dimensions, 1> point) {
58 auto ev = H_ * point;
59 for (int i = 0; i < num_constraints(); ++i) {
60 if (ev(i, 0) > k_(i, 0)) {
61 return false;
62 }
63 }
64 return true;
65}
66
67template <int number_of_dimensions>
68Eigen::Matrix<double, number_of_dimensions, Eigen::Dynamic>
69 HPolytope<number_of_dimensions>::Vertices() {
70 dd_MatrixPtr matrix = dd_CreateMatrix(num_constraints(), ndim() + 1);
71
72 // Copy the data over. TODO(aschuh): Is there a better way? I hate copying...
73 for (int i = 0; i < num_constraints(); ++i) {
74 dd_set_d(matrix->matrix[i][0], k_(i, 0));
75 for (int j = 0; j < ndim(); ++j) {
76 dd_set_d(matrix->matrix[i][j + 1], -H_(i, j));
77 }
78 }
79
80 matrix->representation = dd_Inequality;
81 matrix->numbtype = dd_Real;
82
83 dd_ErrorType error;
84 dd_PolyhedraPtr polyhedra = dd_DDMatrix2Poly(matrix, &error);
85 if (error != dd_NoError || polyhedra == NULL) {
86 dd_WriteErrorMessages(stderr, error);
87 dd_FreeMatrix(matrix);
88 Eigen::Matrix<double, number_of_dimensions, Eigen::Dynamic> ans(0, 0);
89 return ans;
90 }
91
92 dd_MatrixPtr vertex_matrix = dd_CopyGenerators(polyhedra);
93
94 int num_vertices = 0;
95 int num_rays = 0;
96 for (int i = 0; i < vertex_matrix->rowsize; ++i) {
97 if (dd_get_d(vertex_matrix->matrix[i][0]) == 0) {
98 num_rays += 1;
99 } else {
100 num_vertices += 1;
101 }
102 }
103
104 Eigen::Matrix<double, number_of_dimensions, Eigen::Dynamic> vertices(
105 number_of_dimensions, num_vertices);
106
107 int vertex_index = 0;
108 for (int i = 0; i < vertex_matrix->rowsize; ++i) {
109 if (dd_get_d(vertex_matrix->matrix[i][0]) != 0) {
110 for (int j = 0; j < number_of_dimensions; ++j) {
111 vertices(j, vertex_index) = dd_get_d(vertex_matrix->matrix[i][j + 1]);
112 }
113 ++vertex_index;
114 }
115 }
116 dd_FreeMatrix(vertex_matrix);
117 dd_FreePolyhedra(polyhedra);
118 dd_FreeMatrix(matrix);
119
120 return vertices;
121}
122
123} // namespace controls
124} // namespace aos
125
126#endif // _AOS_CONTROLS_POLYTOPE_H_