Tetrapod Project
miqp_biped.cpp
Go to the documentation of this file.
2 
3 #include "ros/console.h"
4 #include<iostream>
5 #include<cassert>
6 #include<fstream>
7 
8 namespace miqp{
9 namespace biped{
10 
11 using drake::solvers::MatrixXDecisionVariable;
12 
13 DecVars add_decision_variables(drake::solvers::MathematicalProgram &prog, Terrain &terrain, int n_steps)
14 {
15  DecVars decision_variables;
16 
17  int n_stones = terrain.getSteppingStones().rows();
18 
19  decision_variables.position_left = prog.NewContinuousVariables(n_steps + 1, 3);
20 
21  decision_variables.position_right = prog.NewContinuousVariables(n_steps + 1, 3);
22 
23  decision_variables.stone_left = prog.NewBinaryVariables(n_steps + 1, n_stones, "b");
24 
25  decision_variables.stone_right = prog.NewBinaryVariables(n_steps + 1, n_stones, "b");
26 
27  drake::solvers::MatrixDecisionVariable<1,1> first_left_M = prog.NewBinaryVariables(1, 1, "b");
28 
29  decision_variables.first_left = first_left_M(0,0); //there must be a better solution to this?
30 
31  return decision_variables;
32 }
33 
34 void set_initial_and_goal_position(drake::solvers::MathematicalProgram &prog, Terrain &terrain, DecVars &decision_variables)
35 {
36  MatrixXDecisionVariable &position_left = decision_variables.position_left;
37 
38  MatrixXDecisionVariable &position_right = decision_variables.position_right;
39 
40  Eigen::Vector3d foot_offset(0, 0.2, 0);
41 
42  Eigen::Vector3d center(terrain.getStoneByName("initial").getCenter());
43 
44  Eigen::Vector3d initial_position_left = center;
45 
46  Eigen::Vector3d initial_position_right = center - foot_offset;
47 
48  center = terrain.getStoneByName("goal").getCenter();
49 
50  Eigen::Vector3d goal_position_left = center;
51 
52  Eigen::Vector3d goal_position_right = center - foot_offset;
53 
54  //Enforce Initial positions of the feet
55  assert(position_left.cols() == initial_position_left.rows() && initial_position_left.cols() == 1);
56 
57  prog.AddLinearConstraint(position_left.row(0).transpose() == initial_position_left);
58 
59  assert(position_right.cols() == initial_position_right.rows() && initial_position_right.cols() == 1);
60 
61  prog.AddLinearConstraint(position_right.row(0).transpose() == initial_position_right);
62 
63  //Enforce Goal positions of the feet
64  assert(position_left.cols() == goal_position_left.rows() && goal_position_left.cols() == 1);
65 
66  prog.AddLinearConstraint(position_left.row(position_left.rows() - 1).transpose() == goal_position_left);
67 
68  assert(position_right.cols() == goal_position_right.rows() && goal_position_right.cols() == 1);
69 
70  prog.AddLinearConstraint(position_right.row(position_right.rows() - 1).transpose() == goal_position_right);
71 }
72 
73 void relative_position_limits(drake::solvers::MathematicalProgram &prog, int n_steps, double step_span, double step_height, DecVars &decision_variables)
74 {
75  MatrixXDecisionVariable &position_left = decision_variables.position_left;
76 
77  MatrixXDecisionVariable &position_right = decision_variables.position_right;
78 
79  //Get absolute value constraint by adding two linear inequality constraints
80  //Constraints for step[i] against step[i]
81  for (int t = 0; t < n_steps; ++t)
82  {
83  prog.AddLinearConstraint(position_left.block(t + 1, 0, 1, 2).transpose() - position_right.block(t, 0, 1, 2).transpose() <= Eigen::Vector2d::Constant(step_span/2));
84 
85  prog.AddLinearConstraint(position_right.block(t + 1, 0, 1, 2).transpose() - position_left.block(t, 0, 1, 2).transpose() <= Eigen::Vector2d::Constant(step_span/2));
86 
87  prog.AddLinearConstraint(position_left(t + 1, 2) - position_right(t, 2) <= step_height);
88 
89  prog.AddLinearConstraint(position_right(t + 1, 2) - position_left(t, 2) <= step_height);
90  }
91 }
92 
93 void step_sequence(drake::solvers::MathematicalProgram &prog, int n_steps, double step_span, DecVars &decision_variables)
94 {
95  MatrixXDecisionVariable &position_left = decision_variables.position_left;
96 
97  MatrixXDecisionVariable &position_right = decision_variables.position_right;
98 
99  drake::solvers::DecisionVariable &first_left = decision_variables.first_left;
100 
101  drake::symbolic::Expression first_right = 1 - first_left;
102 
103  Eigen::Vector2d step_limit = Eigen::Vector2d::Constant(step_span);
104 
105  Eigen::Matrix<drake::symbolic::Expression, 3, 1> step_left, step_right;
106 
107  Eigen::Matrix<drake::symbolic::Expression, 3, 1> limit_left, limit_right;
108 
109  for (int t = 0; t < n_steps; ++t)
110  {
111  step_left = position_left.row(t + 1).transpose() - position_left.row(t).transpose();
112 
113  step_right = position_right.row(t + 1).transpose() - position_right.row(t).transpose();
114 
115  if (t % 2 == 0)
116  {
117  limit_left << step_span*first_left, step_span*first_left;
118 
119  limit_right << step_span*first_right, step_span*first_right;
120  } else
121  {
122  limit_left << step_span*first_right, step_span*first_right;
123 
124  limit_right << step_span*first_left, step_span*first_left;
125  }
126 
127  prog.AddLinearConstraint(step_left <= limit_left);
128 
129  prog.AddLinearConstraint(step_left >= -limit_left);
130 
131  prog.AddLinearConstraint(step_right <= limit_right);
132 
133  prog.AddLinearConstraint(step_right >= -limit_right);
134  }
135 }
136 
137 void one_stone_per_foot(drake::solvers::MathematicalProgram &prog, int n_steps, DecVars &decision_variables)
138 {
139  MatrixXDecisionVariable stone_left = decision_variables.stone_left;
140 
141  MatrixXDecisionVariable stone_right = decision_variables.stone_right;
142 
143  Eigen::VectorXi one_vec = Eigen::VectorXi::Ones(stone_left.rows());
144 
145  prog.AddLinearConstraint(stone_left*Eigen::VectorXd::Ones(stone_left.cols()) == Eigen::VectorXd::Ones(stone_left.rows()));
146 
147  prog.AddLinearConstraint(stone_right*Eigen::VectorXd::Ones(stone_right.cols()) == Eigen::VectorXd::Ones(stone_right.rows()));
148 }
149 
150 Eigen::Vector4d get_big_M(Terrain terrain)
151 {
152  SteppingStone initial = terrain.getStoneByName("initial");
153 
154  SteppingStone goal = terrain.getStoneByName("goal");
155 
156  SteppingStone lateral = terrain.getStoneByName("lateral");
157 
158  Eigen::Vector2d M(goal.getCenter()(0) - initial.getCenter()(0), lateral.getTopRight()(1) - initial.getCenter()(1));
159 
160  Eigen::Vector4d res;
161 
162  res << M, M;
163 
164  return res;
165 }
166 
167 void foot_in_stepping_stone(drake::solvers::MathematicalProgram &prog, Terrain &terrain, int n_steps, DecVars &decision_variables)
168 {
169  MatrixXDecisionVariable &position_left = decision_variables.position_left;
170 
171  MatrixXDecisionVariable &position_right = decision_variables.position_right;
172 
173  MatrixXDecisionVariable &stone_left = decision_variables.stone_left;
174 
175  MatrixXDecisionVariable &stone_right = decision_variables.stone_right;
176 
177  Eigen::Vector4d M = get_big_M(terrain);
178 
179  int n_stones = terrain.getSteppingStones().rows();
180 
181  Eigen::MatrixXd A_ineq, b_ineq, A_eq, b_eq;
182 
183  drake::solvers::DecisionVariable d_l, d_r;
184 
185  for (int t = 0; t < n_steps; ++t)
186  {
187  for (int i = 0; i < n_stones; ++i)
188  {
189  A_ineq = terrain.getSteppingStones()(i).getAIneq();
190 
191  b_ineq = terrain.getSteppingStones()(i).getBIneq();
192 
193  A_eq = terrain.getSteppingStones()(i).getAEq();
194 
195  b_eq = terrain.getSteppingStones()(i).getBEq();
196 
197  d_l = stone_left(t,i);
198 
199  d_r = stone_right(t,i);
200 
201  prog.AddLinearConstraint(A_ineq*position_left.row(t).transpose() <= b_ineq + (1 - d_l)*M);
202 
203  prog.AddLinearConstraint(A_ineq*position_right.row(t).transpose() <= b_ineq + (1 - d_r)*M);
204 
205  prog.AddLinearConstraint(A_eq*position_left.row(t).transpose() <= b_eq + (1 - d_l)*M);
206 
207  prog.AddLinearConstraint(A_eq*position_left.row(t).transpose() >= b_eq - (1 - d_l)*M);
208 
209  prog.AddLinearConstraint(A_eq*position_right.row(t).transpose() <= b_eq + (1 - d_r)*M);
210 
211  prog.AddLinearConstraint(A_eq*position_right.row(t).transpose() >= b_eq - (1 - d_r)*M);
212 
213  }
214  }
215 
216 }
217 
218 void minimize_step_length(drake::solvers::MathematicalProgram &prog, int n_steps, DecVars &decision_variables)
219 {
220  MatrixXDecisionVariable &position_left = decision_variables.position_left;
221 
222  MatrixXDecisionVariable &position_right = decision_variables.position_right;
223 
224  Eigen::Matrix<drake::symbolic::Expression, 3, 1> dist_l;
225 
226  Eigen::Matrix<drake::symbolic::Expression, 3, 1> dist_r;
227 
228  drake::symbolic::Expression res;
229 
230  for (int t = 0; t < n_steps; ++t)
231  {
232  dist_l = position_left.row(t + 1).transpose() - position_left.row(t).transpose();
233 
234  dist_r = position_right.row(t + 1).transpose() - position_right.row(t).transpose();
235 
236  res = (dist_l.transpose()*dist_l + dist_r.transpose()*dist_r).eval()(0);
237 
238  prog.AddQuadraticCost(res);
239  }
240 }
241 
242 void writeMatToFile(Eigen::MatrixXd &mat, std::string filename)
243 {
244  std::ofstream file(filename);
245 
246  if (file.is_open())
247  {
248  file.clear();
249 
250  file << mat;
251 
252  ROS_INFO("writeMatToFile: Successfully wrote to file");
253  } else
254  {
255  ROS_ERROR("could not open file");
256 
257  throw "could not open file " + filename;
258  }
259 
260  file.close();
261 }
262 
263 void writeDecVarsToFile(DecVars_res &decision_variables, std::string base_name)
264 {
265  std::string fend = ".csv";
266 
267  writeMatToFile(decision_variables.position_left, base_name + "_position_left" + fend);
268 
269  writeMatToFile(decision_variables.position_right, base_name + "_position_right" + fend);
270 
271  writeMatToFile(decision_variables.stone_left, base_name + "_stone_left" + fend);
272 
273  writeMatToFile(decision_variables.stone_right, base_name + "_stone_right" + fend);
274 }
275 
276 }
277 }
const Eigen::Vector3d & getCenter() const
const Eigen::Vector3d & getTopRight() const
const SteppingStone & getStoneByName(std::string name) const
Definition: terrain.cpp:95
const Eigen::Array< SteppingStone, Eigen::Dynamic, 1 > & getSteppingStones() const
Definition: terrain.h:23
Eigen::Vector3d Vector3d
Definition: kinematics.h:49
void foot_in_stepping_stone(drake::solvers::MathematicalProgram &prog, Terrain &terrain, int n_steps, DecVars &decision_variables)
Definition: miqp_biped.cpp:167
void relative_position_limits(drake::solvers::MathematicalProgram &prog, int n_steps, double step_span, DecVars &decision_variables)
void set_initial_and_goal_position(drake::solvers::MathematicalProgram &prog, Terrain &terrain, DecVars &decision_variables)
Definition: miqp_biped.cpp:34
void writeMatToFile(Eigen::MatrixXd &mat, std::string filename)
Definition: miqp_biped.cpp:242
DecVars add_decision_variables(drake::solvers::MathematicalProgram &prog, Terrain &terrain, int n_steps)
Definition: miqp_biped.cpp:13
Eigen::Vector4d get_big_M(Terrain terrain)
Definition: miqp_biped.cpp:150
void minimize_step_length(drake::solvers::MathematicalProgram &prog, int n_steps, DecVars &decision_variables)
Definition: miqp_biped.cpp:218
void step_sequence(drake::solvers::MathematicalProgram &prog, int n_steps, double step_span, DecVars &decision_variables)
Definition: miqp_biped.cpp:93
void writeDecVarsToFile(DecVars_res &decision_variables, std::string base_name="footstep_planner")
Definition: miqp_biped.cpp:263
void one_stone_per_foot(drake::solvers::MathematicalProgram &prog, int n_steps, DecVars &decision_variables)
Definition: miqp_biped.cpp:137
int step_span
Definition: visualize.py:14
Eigen::MatrixXd position_left
Definition: miqp_biped.h:38
Eigen::MatrixXd position_right
Definition: miqp_biped.h:40
Eigen::MatrixXd stone_right
Definition: miqp_biped.h:44
Eigen::MatrixXd stone_left
Definition: miqp_biped.h:42
drake::solvers::DecisionVariable first_left
Definition: miqp_biped.h:33
MatrixXDecisionVariable stone_right
Definition: miqp_biped.h:31
MatrixXDecisionVariable position_left
Definition: miqp_biped.h:25
MatrixXDecisionVariable stone_left
Definition: miqp_biped.h:29
MatrixXDecisionVariable position_right
Definition: miqp_biped.h:27