blob: 1ca1ec68777860edb06b051cf66172967e313e70 [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 Silverman258b9172015-09-19 14:32:57 -04005#ifdef AOS_BAZEL
6#include "third_party/cddlib/lib-src/setoper.h"
7#include "third_party/cddlib/lib-src/cdd.h"
8#else
Brian Silverman8f1018b2013-11-17 21:35:15 -08009#include "libcdd-094g-prefix/include/setoper.h"
10#include "libcdd-094g-prefix/include/cdd.h"
Brian Silverman258b9172015-09-19 14:32:57 -040011#endif
Austin Schuha6c257a2013-10-27 15:36:40 -070012
13namespace aos {
14namespace controls {
15
16// A n dimension polytope.
17template <int number_of_dimensions>
18class HPolytope {
19 public:
20 // Constructs a polytope given the H and k matricies.
21 HPolytope(Eigen::Matrix<double, Eigen::Dynamic, number_of_dimensions> H,
22 Eigen::Matrix<double, Eigen::Dynamic, 1> k)
23 : H_(H),
24 k_(k) {
25 }
26
Brian Silverman6da04272014-05-18 18:47:48 -070027 // This is an initialization function shared across all instantiations of this
28 // template.
29 // This must be called at least once before calling any of the methods. It is
30 // not thread-safe.
Austin Schuha6c257a2013-10-27 15:36:40 -070031 static void Init() {
32 dd_set_global_constants();
33 }
34
35 // Returns a reference to H.
36 const Eigen::Matrix<double, Eigen::Dynamic,
37 number_of_dimensions> &H() const {
38 return H_;
39 }
40
41 // Returns a reference to k.
42 const Eigen::Matrix<double, Eigen::Dynamic,
43 1> &k() const {
44 return k_;
45 }
46
47 // Returns the number of dimensions in the polytope.
48 int ndim() const { return number_of_dimensions; }
49
50 // Returns the number of constraints currently in the polytope.
51 int num_constraints() const { return k_.rows(); }
52
53 // Returns true if the point is inside the polytope.
Brian Silverman6dd2c532014-03-29 23:34:39 -070054 bool IsInside(Eigen::Matrix<double, number_of_dimensions, 1> point) const;
Austin Schuha6c257a2013-10-27 15:36:40 -070055
56 // Returns the list of vertices inside the polytope.
Brian Silverman6dd2c532014-03-29 23:34:39 -070057 Eigen::Matrix<double, number_of_dimensions, Eigen::Dynamic> Vertices() const;
Austin Schuha6c257a2013-10-27 15:36:40 -070058
59 private:
60 Eigen::Matrix<double, Eigen::Dynamic, number_of_dimensions> H_;
61 Eigen::Matrix<double, Eigen::Dynamic, 1> k_;
62};
63
64template <int number_of_dimensions>
65bool HPolytope<number_of_dimensions>::IsInside(
Brian Silverman6dd2c532014-03-29 23:34:39 -070066 Eigen::Matrix<double, number_of_dimensions, 1> point) const {
Austin Schuha6c257a2013-10-27 15:36:40 -070067 auto ev = H_ * point;
68 for (int i = 0; i < num_constraints(); ++i) {
69 if (ev(i, 0) > k_(i, 0)) {
70 return false;
71 }
72 }
73 return true;
74}
75
76template <int number_of_dimensions>
77Eigen::Matrix<double, number_of_dimensions, Eigen::Dynamic>
Brian Silverman6dd2c532014-03-29 23:34:39 -070078 HPolytope<number_of_dimensions>::Vertices() const {
Austin Schuha6c257a2013-10-27 15:36:40 -070079 dd_MatrixPtr matrix = dd_CreateMatrix(num_constraints(), ndim() + 1);
80
81 // Copy the data over. TODO(aschuh): Is there a better way? I hate copying...
82 for (int i = 0; i < num_constraints(); ++i) {
83 dd_set_d(matrix->matrix[i][0], k_(i, 0));
84 for (int j = 0; j < ndim(); ++j) {
85 dd_set_d(matrix->matrix[i][j + 1], -H_(i, j));
86 }
87 }
88
89 matrix->representation = dd_Inequality;
90 matrix->numbtype = dd_Real;
91
92 dd_ErrorType error;
93 dd_PolyhedraPtr polyhedra = dd_DDMatrix2Poly(matrix, &error);
94 if (error != dd_NoError || polyhedra == NULL) {
95 dd_WriteErrorMessages(stderr, error);
96 dd_FreeMatrix(matrix);
97 Eigen::Matrix<double, number_of_dimensions, Eigen::Dynamic> ans(0, 0);
98 return ans;
99 }
100
101 dd_MatrixPtr vertex_matrix = dd_CopyGenerators(polyhedra);
102
103 int num_vertices = 0;
104 int num_rays = 0;
105 for (int i = 0; i < vertex_matrix->rowsize; ++i) {
106 if (dd_get_d(vertex_matrix->matrix[i][0]) == 0) {
107 num_rays += 1;
108 } else {
109 num_vertices += 1;
110 }
111 }
112
113 Eigen::Matrix<double, number_of_dimensions, Eigen::Dynamic> vertices(
114 number_of_dimensions, num_vertices);
115
116 int vertex_index = 0;
117 for (int i = 0; i < vertex_matrix->rowsize; ++i) {
118 if (dd_get_d(vertex_matrix->matrix[i][0]) != 0) {
119 for (int j = 0; j < number_of_dimensions; ++j) {
120 vertices(j, vertex_index) = dd_get_d(vertex_matrix->matrix[i][j + 1]);
121 }
122 ++vertex_index;
123 }
124 }
125 dd_FreeMatrix(vertex_matrix);
126 dd_FreePolyhedra(polyhedra);
127 dd_FreeMatrix(matrix);
128
129 return vertices;
130}
131
132} // namespace controls
133} // namespace aos
134
Briana6553ed2014-04-02 21:26:46 -0700135#endif // AOS_COMMON_CONTROLS_POLYTOPE_H_