A sparse MPC solver for walking motion generation.
qp_as.cpp
Go to the documentation of this file.
1 
8 /****************************************
9  * INCLUDES
10  ****************************************/
11 #include "qp.h"
12 #include "qp_as.h"
13 #include "state_handling.h"
14 
15 #include <cmath> //cos,sin
16 
17 
18 using namespace AS;
19 
20 /****************************************
21  * FUNCTIONS
22  ****************************************/
23 
37  const int N_,
38  const double gain_position,
39  const double gain_velocity,
40  const double gain_acceleration,
41  const double gain_jerk,
42  const double tol_,
43  const bool obj_computation_on_,
44  const unsigned int max_added_constraints_num_,
45  const bool constraint_removal_on_) :
46  problem_parameters (N_, gain_position, gain_velocity, gain_acceleration, gain_jerk),
47  chol (N_)
48 {
49  dX = new double[SMPC_NUM_VAR*N]();
50 
51  constraints.resize(2*N);
52 
53  tol = tol_,
54  obj_computation_on = obj_computation_on_;
55  constraint_removal_on = constraint_removal_on_;
56 
57  max_added_constraints_num = max_added_constraints_num_;
59  {
61  }
62 }
63 
64 
67 {
68  if (dX != NULL)
69  delete dX;
70 }
71 
72 
85  const double* T_,
86  const double* h_,
87  const double h_initial_,
88  const double* angle,
89  const double* zref_x_,
90  const double* zref_y_,
91  const double* lb,
92  const double* ub)
93 {
94  set_state_parameters (T_, h_, h_initial_);
95 
96  zref_x = zref_x_;
97  zref_y = zref_y_;
98 
99  active_set.clear();
100 
103 
104 
105  // form inv(2*H) *g and initialize constraints
106  // inv(2*H) * g = inv (2*(beta/2)) * beta * Cp' * zref = zref
107  for (int i = 0, cind = 0; i < N; ++i)
108  {
109  double cosR = cos(angle[i]);
110  double sinR = sin(angle[i]);
111  double RTzref_x = (cosR*zref_x[i] + sinR*zref_y[i]);
112  double RTzref_y = (-sinR*zref_x[i] + cosR*zref_y[i]);
113 
114  constraints[cind].set(
115  cind, cosR, sinR,
116  lb[cind] - RTzref_x,
117  ub[cind] - RTzref_x,
118  false);
119  ++cind;
120 
121  constraints[cind].set(
122  cind, -sinR, cosR,
123  lb[cind] - RTzref_y,
124  ub[cind] - RTzref_y,
125  false);
126  ++cind;
127  }
128 }
129 
130 
131 
142  const double *x_coord,
143  const double *y_coord,
144  const double *init_state,
145  const bool tilde_state,
146  double* X_)
147 {
148  X = X_;
149  form_init_fp_tilde<problem_parameters>(*this, x_coord, y_coord, init_state, tilde_state, X);
150 }
151 
152 
153 
160 {
161  alpha = 1;
162 
163  /* Index to include in the working set, -1 if no constraint have to be included. */
164  int activated_var_num = -1;
165  int sign = 0;
166 
167 
168  for (unsigned int i = 0; i < constraints.size(); ++i)
169  {
170  // Check only inactive constraints for violation.
171  // The constraints in the working set will not be violated regardless of
172  // the depth of descent
173  if (!constraints[i].isActive)
174  {
175  const constraint c = constraints[i];
176 
177  const double constr = X[c.ind]*c.coef_x + X[c.ind+3]*c.coef_y;
178  const double d_constr = dX[c.ind]*c.coef_x + dX[c.ind+3]*c.coef_y;
179 
180  if ( d_constr < -tol )
181  {
182  const double t = (c.lb - constr)/d_constr;
183  if (t < alpha)
184  {
185  alpha = t;
186  activated_var_num = i;
187  sign = -1;
188  }
189  }
190  else if ( d_constr > tol )
191  {
192  const double t = (c.ub - constr)/d_constr;
193  if (t < alpha)
194  {
195  alpha = t;
196  activated_var_num = i;
197  sign = 1;
198  }
199  }
200  }
201  }
202  if (activated_var_num != -1)
203  {
204  constraints[activated_var_num].sign = sign;
205  constraints[activated_var_num].isActive = true;
206  active_set.push_back(constraints[activated_var_num]);
207  }
208 
209  return (activated_var_num);
210 }
211 
212 
213 
226 int qp_as::choose_excl_constr (const double *lambda)
227 {
228  double min_lambda = -tol;
229  int ind_exclude = -1;
230 
231  // find the constraint with the smallest lambda
232  for (unsigned int i = 0; i < active_set.size(); ++i)
233  {
234  if (lambda[i] * active_set[i].sign < min_lambda)
235  {
236  min_lambda = lambda[i] * active_set[i].sign;
237  ind_exclude = i;
238  }
239  }
240 
241  if (ind_exclude != -1)
242  {
243  constraints[active_set[ind_exclude].cind].isActive = false;
244  active_set.erase(active_set.begin()+ind_exclude);
245  }
246 
247  return (ind_exclude);
248 }
249 
250 
258 void qp_as::solve (vector<double> &obj_log)
259 {
260  for (int i = 0; i < N; ++i)
261  {
262  const int ind = i*SMPC_NUM_STATE_VAR;
263  X[ind] -= zref_x[i];
264  X[ind+3] -= zref_y[i];
265  }
266  if (obj_computation_on)
267  {
268  obj_log.clear();
269  obj_log.push_back(compute_obj());
270  }
271 
272  // obtain dX
273  chol.solve(*this, X, dX);
274 
275  for (;;)
276  {
277  int activated_var_num = check_blocking_constraints();
278 
279  // Move in the feasible descent direction
280  for (int i = 0; i < N*SMPC_NUM_VAR; i += SMPC_NUM_VAR)
281  {
282  X[i] += alpha * dX[i];
283  X[i+1] += alpha * dX[i+1];
284  X[i+2] += alpha * dX[i+2];
285  X[i+3] += alpha * dX[i+3];
286  X[i+4] += alpha * dX[i+4];
287  X[i+5] += alpha * dX[i+5];
288  X[i+6] += alpha * dX[i+6];
289  X[i+7] += alpha * dX[i+7];
290  }
291 
292  if (obj_computation_on)
293  {
294  obj_log.push_back(compute_obj());
295  }
296 
297  if (activated_var_num != -1)
298  {
301  {
302  break;
303  }
304 
305  // add row to the L matrix and find new dX
306  chol.up_resolve (*this, active_set, X, dX);
307  }
308  else if (constraint_removal_on)
309  {
310  // no new inequality constraints
311  int ind_exclude = choose_excl_constr (chol.get_lambda(*this));
312  if (ind_exclude == -1)
313  {
314  break;
315  }
316 
317  chol.down_resolve (*this, active_set, ind_exclude, X, dX);
319  }
320  else
321  {
322  break;
323  }
324  }
325 
326  for (int i = 0; i < N; ++i)
327  {
328  const int ind = i*SMPC_NUM_STATE_VAR;
329  X[ind] += zref_x[i];
330  X[ind+3] += zref_y[i];
331  }
332 
333  active_set_size = active_set.size();
334 }
335 
336 
337 
344 {
345  int i,j;
346  double obj_pos = 0;
347  double obj_vel = 0;
348  double obj_acc = 0;
349  double obj_jerk = 0;
350 
351  // phi_X = X'*H*X + g'*X
352  for(i = 0, j = 0;
353  i < N*SMPC_NUM_STATE_VAR;
354  i += SMPC_NUM_STATE_VAR, j += 2)
355  {
356  const double X_copy[6] = {X[i], X[i+1], X[i+2], X[i+3], X[i+4], X[i+5]};
357 
358  // X'*H*X
359  obj_pos += X_copy[0]*X_copy[0] + X_copy[3]*X_copy[3];
360  obj_vel += X_copy[1]*X_copy[1] + X_copy[4]*X_copy[4];
361  obj_acc += X_copy[2]*X_copy[2] + X_copy[5]*X_copy[5];
362  }
363  for (; i < N*SMPC_NUM_VAR; i += SMPC_NUM_CONTROL_VAR)
364  {
365  // X'*H*X
366  obj_jerk += X[i] * X[i] + X[i+1] * X[i+1];
367  }
368 
369  return (0.5*(obj_pos/i2Q[0] + obj_vel/i2Q[1] + obj_acc/i2Q[2] + obj_jerk/i2P));
370 }
371 
const double * zref_y
Definition: qp_as.h:102
bool constraint_removal_on
Definition: qp_as.h:84
#define SMPC_NUM_STATE_VAR
Number of state variables.
Definition: smpc_solver.h:24
void set_state_parameters(const double *, const double *, const double)
Initializes quadratic problem.
double lb
Lower bound.
Definition: as_constraint.h:72
void up_resolve(const AS::problem_parameters &, const vector< AS::constraint > &, const double *, double *)
A wrapper around private functions, which update Cholesky factor and resolve the system.
bool obj_computation_on
Definition: qp_as.h:107
vector< AS::constraint > active_set
A set of active constraints.
Definition: qp_as.h:111
double coef_y
Coefficients.
Definition: as_constraint.h:67
#define SMPC_NUM_VAR
Total number of variables.
Definition: smpc_solver.h:28
double coef_x
Coefficients.
Definition: as_constraint.h:66
const double * zref_x
Definition: qp_as.h:101
unsigned int max_added_constraints_num
Definition: qp_as.h:85
double * X
Definition: qp_as.h:76
int choose_excl_constr(const double *)
Selects a constraint for removal from active set.
Definition: qp_as.cpp:226
unsigned int active_set_size
Definition: qp_as.h:82
double compute_obj()
Compute value of the objective function.
Definition: qp_as.cpp:343
A set of problem parameters.
void form_init_fp(const double *, const double *, const double *, const bool, double *)
Generates an initial feasible point.
Definition: qp_as.cpp:141
double * dX
Definition: qp_as.h:119
#define SMPC_NUM_CONTROL_VAR
Number of control variables.
Definition: smpc_solver.h:26
Defines constraints associated with states of the system.
Definition: as_constraint.h:26
unsigned int removed_constraints_num
Definition: qp_as.h:81
~qp_as()
Definition: qp_as.cpp:66
qp_as(const int N_, const double, const double, const double, const double, const double, const bool, const unsigned int, const bool)
Constructor: initialization of the constant parameters.
Definition: qp_as.cpp:36
void solve(const AS::problem_parameters &, const double *, double *)
Determines feasible descent direction.
int ind
Index of the first element of a state in the vector of states.
Definition: as_constraint.h:61
unsigned int added_constraints_num
Definition: qp_as.h:80
double alpha
Definition: qp_as.h:122
void solve(vector< double > &)
Solve QP problem.
Definition: qp_as.cpp:258
double * get_lambda(const AS::problem_parameters &)
int check_blocking_constraints()
Checks for blocking constraints.
Definition: qp_as.cpp:159
AS::chol_solve chol
An instance of AS::chol_solve class.
Definition: qp_as.h:98
vector< AS::constraint > constraints
Vector of constraints.
Definition: qp_as.h:114
void down_resolve(const AS::problem_parameters &, const vector< AS::constraint > &, const int, const double *, double *)
A wrapper around private functions, which downdate Cholesky factor and resolve the system.
void set_parameters(const double *, const double *, const double, const double *, const double *, const double *, const double *, const double *)
Initializes quadratic problem.
Definition: qp_as.cpp:84
double tol
tolerance
Definition: qp_as.h:105
double ub
Upper bound.
Definition: as_constraint.h:75