A sparse MPC solver for walking motion generation (old version).
|
00001 00008 /**************************************** 00009 * INCLUDES 00010 ****************************************/ 00011 #include "qp_as.h" 00012 #include "state_handling.h" 00013 00014 00015 /**************************************** 00016 * FUNCTIONS 00017 ****************************************/ 00018 //============================================== 00019 // bound 00028 void bound::set(const int var_num_, const double lb_, const double ub_, const bool active) 00029 { 00030 var_num = var_num_; 00031 lb = lb_; 00032 ub = ub_; 00033 isActive = active; 00034 } 00035 00036 00037 00038 //============================================== 00039 // qp_as 00040 00050 qp_as::qp_as( 00051 const int N_, 00052 const double Alpha, 00053 const double Beta, 00054 const double Gamma, 00055 const double regularization, 00056 const double tol_) : 00057 qp_solver (N_, Alpha, Beta, Gamma, regularization, tol_), 00058 chol (N_) 00059 { 00060 iHg = new double[2*N]; 00061 00062 // there are no inequality constraints in the initial working set (no hot-starting for the moment) 00063 W = new int[2*N]; 00064 W_sign = new int[2*N]; 00065 00066 Bounds.resize(2*N); 00067 } 00068 00069 00071 qp_as::~qp_as() 00072 { 00073 if (W != NULL) 00074 delete W; 00075 00076 if (iHg != NULL) 00077 delete iHg; 00078 00079 if (W_sign != NULL) 00080 delete W_sign; 00081 } 00082 00083 00095 void qp_as::set_parameters( 00096 const double* T_, 00097 const double* h_, 00098 const double h_initial_, 00099 const double* angle, 00100 const double* zref_x, 00101 const double* zref_y, 00102 const double* lb, 00103 const double* ub) 00104 { 00105 nW = 0; 00106 00107 h_initial = h_initial_; 00108 set_state_parameters (T_, h_, h_initial_, angle); 00109 form_iHg (zref_x, zref_y); 00110 form_bounds(lb, ub); 00111 } 00112 00113 00114 00121 void qp_as::form_iHg(const double *zref_x, const double *zref_y) 00122 { 00123 double p0, p1; 00124 double cosA, sinA; 00125 00126 for (int i = 0; i < N; i++) 00127 { 00128 cosA = spar[i].cos; 00129 sinA = spar[i].sin; 00130 00131 // zref 00132 p0 = zref_x[i]; 00133 p1 = zref_y[i]; 00134 00135 // inv (2*H) * R' * Cp' * zref 00136 iHg[i*2] = -i2Q[0] * (cosA*p0 + sinA*p1)*gain_beta; 00137 iHg[i*2 + 1] = -i2Q[0] * (-sinA*p0 + cosA*p1)*gain_beta; 00138 } 00139 } 00140 00141 00142 00149 void qp_as::form_bounds(const double *lb, const double *ub) 00150 { 00151 for (int i=0; i < N; i++) 00152 { 00153 Bounds[i*2].set(SMPC_NUM_STATE_VAR*i, lb[i*2], ub[i*2], false); 00154 Bounds[i*2+1].set(SMPC_NUM_STATE_VAR*i+3, lb[i*2+1], ub[i*2+1], false); 00155 } 00156 } 00157 00158 00159 00165 int qp_as::check_blocking_bounds() 00166 { 00167 alpha = 1; 00168 00169 /* Index to include in the working set, -1 if no constraint have to be included. */ 00170 int activated_var_num = -1; 00171 00172 00173 for (int i = 0; i < 2*N; i++) 00174 { 00175 // Check only inactive constraints for violation. 00176 // The constraints in the working set will not be violated regardless of 00177 // the depth of descent 00178 if (!Bounds[i].isActive) 00179 { 00180 int ind = Bounds[i].var_num; 00181 int sign = 1; 00182 double t = 1; 00183 00184 if ( dX[ind] < -tol ) 00185 { 00186 t = (Bounds[i].lb - X[ind])/dX[ind]; 00187 sign = -1; 00188 } 00189 else if ( dX[ind] > tol ) 00190 { 00191 t = (Bounds[i].ub - X[ind])/dX[ind]; 00192 } 00193 00194 if (t < alpha) 00195 { 00196 alpha = t; 00197 activated_var_num = i; 00198 W_sign[nW] = sign; 00199 } 00200 } 00201 } 00202 if (activated_var_num != -1) 00203 { 00204 W[nW] = activated_var_num; 00205 nW++; 00206 Bounds[activated_var_num].isActive = true; 00207 } 00208 00209 return (activated_var_num); 00210 } 00211 00212 00226 int qp_as::choose_excl_constr (const double *lambda) 00227 { 00228 double min_lambda = -tol; 00229 int ind_exclude = -1; 00230 00231 // find the constraint with the smallest lambda 00232 for (int i = 0; i < nW; i++) 00233 { 00234 if (lambda[i] * W_sign[i] < min_lambda) 00235 { 00236 min_lambda = lambda[i] * W_sign[i]; 00237 ind_exclude = i; 00238 } 00239 } 00240 00241 if (ind_exclude != -1) 00242 { 00243 Bounds[W[ind_exclude]].isActive = false; 00244 for (int i = ind_exclude; i < nW-1; i++) 00245 { 00246 W[i] = W[i + 1]; 00247 W_sign[i] = W_sign[i + 1]; 00248 } 00249 nW--; 00250 } 00251 00252 return (ind_exclude); 00253 } 00254 00255 00261 int qp_as::solve () 00262 { 00263 // obtain dX 00264 chol.solve(*this, iHg, X, dX); 00265 00266 for (;;) 00267 { 00268 int activated_var_num = check_blocking_bounds(); 00269 00270 // Move in the feasible descent direction 00271 for (int i = 0; i < N*SMPC_NUM_VAR ; i++) 00272 { 00273 X[i] += alpha * dX[i]; 00274 } 00275 00276 // no new inequality constraints 00277 if (activated_var_num == -1) 00278 { 00279 int ind_exclude = choose_excl_constr (chol.get_lambda(*this)); 00280 if (ind_exclude != -1) 00281 { 00282 chol.down_resolve (*this, iHg, nW, W, ind_exclude, X, dX); 00283 } 00284 else 00285 { 00286 break; 00287 } 00288 } 00289 else 00290 { 00291 // add row to the L matrix and find new dX 00292 chol.up_resolve (*this, iHg, nW, W, X, dX); 00293 } 00294 } 00295 00296 return (nW); 00297 }