A sparse MPC solver for walking motion generation (old version).
solver/qp_as.cpp
Go to the documentation of this file.
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 }