A sparse MPC solver for walking motion generation (old version).
|
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 }