A sparse MPC solver for walking motion generation (old version).
solver/matrix_ecL_as.cpp
Go to the documentation of this file.
00001 
00008 /****************************************
00009  * INCLUDES 
00010  ****************************************/
00011 
00012 #include "matrix_ecL_as.h"
00013 
00014 #include <cmath> // sqrt
00015 
00016 
00017 /****************************************
00018  * FUNCTIONS 
00019  ****************************************/
00020 
00021 //==============================================
00022 // constructors / destructors
00023 
00024 matrix_ecL_as::matrix_ecL_as (const int N)
00025 {
00026     ecL = new double[MATRIX_SIZE_3x3*N + MATRIX_SIZE_3x3*(N-1)]();
00027 
00028     iQAT = new double[MATRIX_SIZE_3x3];
00029     ecL_diag = new double*[N];
00030     for (int i = 0; i < N; i++)
00031     {
00032         ecL_diag[i] = &ecL[i * MATRIX_SIZE_3x3 * 2];
00033     }
00034     ecL_ndiag = new double*[N-1];
00035     for (int i = 0; i < N-1; i++)
00036     {
00037         ecL_ndiag[i] = &ecL[i * MATRIX_SIZE_3x3 * 2 + MATRIX_SIZE_3x3];
00038     }
00039 }
00040 
00041 
00042 matrix_ecL_as::~matrix_ecL_as()
00043 {
00044     if (ecL != NULL)
00045         delete ecL;
00046 
00047     if (ecL_diag != NULL)
00048         delete ecL_diag;
00049 
00050     if (ecL_ndiag != NULL)
00051         delete ecL_ndiag;
00052 
00053     if (iQAT != NULL)
00054         delete iQAT;
00055 }
00056 //==============================================
00057 
00058 
00059 
00068 void matrix_ecL_as::chol_dec (double *mx9)
00069 {
00070     // 1st line
00071     mx9[0] = sqrt (mx9[0]);
00072 
00073     // 2nd line
00074     mx9[1] /= mx9[0];
00075     mx9[4] = sqrt(mx9[4] - mx9[1]*mx9[1]); 
00076 
00077     // 3rd line
00078     mx9[2] /= mx9[0]; 
00079     mx9[5] = (mx9[5] - mx9[2]*mx9[1])/mx9[4];
00080     mx9[8] = sqrt(mx9[8] - mx9[5]*mx9[5] - mx9[2]*mx9[2]);
00081 
00082     // These elements must be 0. (but they are never used)
00083 //    mx9[3] = mx9[6] = mx9[7] = 0;
00084 }
00085 
00086 
00087 
00099 void matrix_ecL_as::form_iQBiPB (const double *B, const double *i2Q, const double i2P, double* result)
00100 {
00101     // diagonal elements
00102     result[0] = i2P * B[0]*B[0] + i2Q[0];
00103     result[4] = i2P * B[1]*B[1] + i2Q[1];
00104     result[8] = i2P * B[2]*B[2] + i2Q[2];
00105 
00106     // symmetric elements (no need to initialize all of them)
00107     result[1] = /*result[3] =*/ i2P * B[0]*B[1];
00108     result[2] = /*result[6] =*/ i2P * B[0]*B[2];
00109     result[5] = /*result[7] =*/ i2P * B[1]*B[2];
00110 }
00111 
00112 
00113 
00122 void matrix_ecL_as::form_iQAT (const double A3, const double A6, const double *i2Q)
00123 {
00124     iQAT[0] = i2Q[0];
00125     iQAT[1] = A3 * i2Q[1];
00126     iQAT[2] = A6 * i2Q[2];
00127     iQAT[4] = i2Q[1];
00128     iQAT[5] = A3 * i2Q[2];
00129     iQAT[8] = i2Q[2];
00130 }
00131 
00132 
00143 void matrix_ecL_as::form_AiQATiQBiPB (const problem_parameters &ppar, const state_parameters& stp, double *result)
00144 {
00145     form_iQBiPB (stp.B, ppar.i2Q, ppar.i2P, result);
00146 
00147     // 1st column
00148     result[0] += iQAT[0] + stp.A3*iQAT[1] + stp.A6*iQAT[2];
00149     result[1] +=                  iQAT[1] + stp.A3*iQAT[2];
00150     result[2] +=                                   iQAT[2];
00151 
00152     // 2nd column
00153     // symmetric elements are not initialized
00154 //    result[3] = iQBiPB[3] + A3*iQAT[4] + A6*iQAT[5];
00155     result[4] += iQAT[4] + stp.A3*iQAT[5];
00156     result[5] +=                  iQAT[5];
00157 
00158     // 3rd column
00159 //    result[6] = iQBiPB[6] + A6*iQAT[8];
00160 //    result[7] = iQBiPB[7] + A3*iQAT[8];
00161     result[8] += iQAT[8];
00162 }
00163 
00164 
00165 
00173 void matrix_ecL_as::form_L_non_diag(const double *ecLp, double *ecLc)
00174 {
00175     /* L(k+1,k) * L(k,k)' = - inv(Q) * A'
00176      *
00177      * xxx      xxx     xxx
00178      *  xx  *    xx =    xx
00179      *   x        x       x
00180      *
00181      * all matrices are upper triangular
00182      */
00183 
00184     // main diagonal
00185     ecLc[0] = -iQAT[0] / ecLp[0];
00186     ecLc[4] = -iQAT[4] / ecLp[4];
00187     ecLc[8] = -iQAT[8] / ecLp[8];
00188 
00189     // sub-diagonal 1
00190     ecLc[3] = (-iQAT[1] - ecLc[0]*ecLp[1]) / ecLp[4];
00191     ecLc[7] = (-iQAT[5] - ecLc[4]*ecLp[5]) / ecLp[8];
00192 
00193     // sub-diagonal 2
00194     ecLc[6] = (-iQAT[2] - ecLc[0]*ecLp[2] - ecLc[3]*ecLp[5]) / ecLp[8];
00195 }
00196 
00197 
00198 
00209 void matrix_ecL_as::form_L_diag(const double *ecLp, double *ecLc)
00210 {
00211     // L(k+1,k+1) = (- L(k+1,k) * L(k+1,k)') + (A * inv(Q) * A' + inv(Q) + B * inv(P) * B)
00212     // diagonal elements
00213     ecLc[0] -= ecLp[0]*ecLp[0] + ecLp[3]*ecLp[3] + ecLp[6]*ecLp[6];
00214     ecLc[4] -= ecLp[4]*ecLp[4] + ecLp[7]*ecLp[7];
00215     ecLc[8] -= ecLp[8]*ecLp[8];
00216     // symmetric nondiagonal elements (no need to initialize all of them)
00217     ecLc[1] -= /*ecLc[3] =*/ ecLp[3]*ecLp[4] + ecLp[6]*ecLp[7];
00218     ecLc[2] -= /*ecLc[6] =*/ ecLp[6]*ecLp[8];
00219     ecLc[5] -= /*ecLc[7] =*/ ecLp[7]*ecLp[8];
00220 
00221     // chol (L(k+1,k+1))
00222     chol_dec (ecLc);
00223 }
00224 
00225 
00226 
00232 void matrix_ecL_as::form (const problem_parameters& ppar)
00233 {
00234     int i;
00235     state_parameters stp;
00236 
00237 
00238 
00239     // the first matrix on diagonal
00240     stp = ppar.spar[0];
00241     form_iQBiPB (stp.B, ppar.i2Q, ppar.i2P, ecL_diag[0]);
00242     chol_dec (ecL_diag[0]);
00243 
00244 
00245     // offsets
00246     for (i = 1; i < ppar.N; i++)
00247     {
00248         stp = ppar.spar[i];
00249         form_iQAT (stp.A3, stp.A6, ppar.i2Q);
00250 
00251         // form (b), (d), (f) ... 
00252         form_L_non_diag(ecL_diag[i-1], ecL_ndiag[i-1]);
00253 
00254         // form (c), (e), (g) ...
00255         form_AiQATiQBiPB (ppar, stp, ecL_diag[i]);
00256         form_L_diag(ecL_ndiag[i-1], ecL_diag[i]);
00257     }
00258 }
00259 
00260 
00268 void matrix_ecL_as::solve_forward(const int N, double *x)
00269 {
00270     int i, j;
00271     double *xc = x; // 6 current elements of x
00272     double *xp; // 6 elements of x computed on the previous iteration
00273 
00274 
00275     // compute the first 6 elements using forward substitution
00276     xc[0] /= ecL_diag[0][0];
00277     xc[3] /= ecL_diag[0][0];
00278 
00279     xc[1] -= xc[0] * ecL_diag[0][1];
00280     xc[1] /= ecL_diag[0][4];
00281 
00282     xc[4] -= xc[3] * ecL_diag[0][1];
00283     xc[4] /= ecL_diag[0][4];
00284 
00285     xc[2] -= xc[0] * ecL_diag[0][2] + xc[1] * ecL_diag[0][5];
00286     xc[2] /= ecL_diag[0][8];
00287 
00288     xc[5] -= xc[3] * ecL_diag[0][2] + xc[4] * ecL_diag[0][5];
00289     xc[5] /= ecL_diag[0][8];
00290 
00291 
00292     for (i = 1, j = 0; i < N; i++,j++)
00293     {
00294         // switch to the next level of L / next 6 elements
00295         xp = xc;
00296         xc = &xc[SMPC_NUM_STATE_VAR];
00297 
00298 
00299         // update the right part of the equation and compute elements
00300         xc[0] -= xp[0] * ecL_ndiag[j][0] + xp[1] * ecL_ndiag[j][3] + xp[2] * ecL_ndiag[j][6];
00301         xc[0] /= ecL_diag[i][0];
00302 
00303         xc[3] -= xp[3] * ecL_ndiag[j][0] + xp[4] * ecL_ndiag[j][3] + xp[5] * ecL_ndiag[j][6];
00304         xc[3] /= ecL_diag[i][0];
00305 
00306 
00307         xc[1] -= xp[1] * ecL_ndiag[j][4] + xp[2] * ecL_ndiag[j][7] + xc[0] * ecL_diag[i][1];
00308         xc[1] /= ecL_diag[i][4];
00309 
00310         xc[4] -= xp[4] * ecL_ndiag[j][4] + xp[5] * ecL_ndiag[j][7] + xc[3] * ecL_diag[i][1];
00311         xc[4] /= ecL_diag[i][4];
00312 
00313 
00314         xc[2] -= xp[2] * ecL_ndiag[j][8] + xc[0] * ecL_diag[i][2] + xc[1] * ecL_diag[i][5];
00315         xc[2] /= ecL_diag[i][8];
00316 
00317         xc[5] -= xp[5] * ecL_ndiag[j][8] + xc[3] * ecL_diag[i][2] + xc[4] * ecL_diag[i][5];
00318         xc[5] /= ecL_diag[i][8];
00319     }
00320 }
00321 
00322 
00329 void matrix_ecL_as::solve_backward (const int N, double *x)
00330 {
00331     int i;
00332     double *xc = & x[(N-1)*SMPC_NUM_STATE_VAR]; // current 6 elements of result
00333     double *xp; // 6 elements computed on the previous iteration
00334     
00335 
00336     // compute the last 6 elements using backward substitution
00337     xc[2] /= ecL_diag[N-1][8];
00338     xc[5] /= ecL_diag[N-1][8];
00339 
00340     xc[1] -= xc[2] * ecL_diag[N-1][5];
00341     xc[1] /= ecL_diag[N-1][4];
00342     xc[4] -= xc[5] * ecL_diag[N-1][5];
00343     xc[4] /= ecL_diag[N-1][4];
00344 
00345     xc[0] -= xc[2] * ecL_diag[N-1][2] + xc[1] * ecL_diag[N-1][1];
00346     xc[0] /= ecL_diag[N-1][0];
00347     xc[3] -= xc[5] * ecL_diag[N-1][2] + xc[4] * ecL_diag[N-1][1];
00348     xc[3] /= ecL_diag[N-1][0];
00349 
00350 
00351     for (i = N-2; i >= 0 ; i--)
00352     {
00353         xp = xc;
00354         xc = & x[i*SMPC_NUM_STATE_VAR];
00355 
00356         // update the right part of the equation and compute elements
00357         xc[2] -= xp[0] * ecL_ndiag[i][6] + xp[1] * ecL_ndiag[i][7] + xp[2] * ecL_ndiag[i][8];
00358         xc[2] /= ecL_diag[i][8];
00359 
00360         xc[5] -= xp[3] * ecL_ndiag[i][6] + xp[4] * ecL_ndiag[i][7] + xp[5] * ecL_ndiag[i][8];
00361         xc[5] /= ecL_diag[i][8];
00362 
00363 
00364         xc[1] -= xp[0] * ecL_ndiag[i][3] + xp[1] * ecL_ndiag[i][4] + xc[2] * ecL_diag[i][5];
00365         xc[1] /= ecL_diag[i][4];
00366 
00367         xc[4] -= xp[3] * ecL_ndiag[i][3] + xp[4] * ecL_ndiag[i][4] + xc[5] * ecL_diag[i][5];
00368         xc[4] /= ecL_diag[i][4];
00369 
00370 
00371         xc[0] -= xp[0] * ecL_ndiag[i][0] + xc[2] * ecL_diag[i][2] + xc[1] * ecL_diag[i][1];
00372         xc[0] /= ecL_diag[i][0];
00373 
00374         xc[3] -= xp[3] * ecL_ndiag[i][0] + xc[5] * ecL_diag[i][2] + xc[4] * ecL_diag[i][1];
00375         xc[3] /= ecL_diag[i][0];
00376     }
00377 }