A sparse MPC solver for walking motion generation (old version).
|
00001 00008 /**************************************** 00009 * INCLUDES 00010 ****************************************/ 00011 00012 #include "matrix_ecL_ip.h" 00013 00014 #include <cmath> // sqrt 00015 00016 00017 /**************************************** 00018 * FUNCTIONS 00019 ****************************************/ 00020 00021 //============================================== 00022 // constructors / destructors 00023 00024 00025 matrix_ecL_ip::matrix_ecL_ip (const int N) 00026 { 00027 ecL = new double[MATRIX_SIZE_6x6*N + MATRIX_SIZE_6x6*(N-1)](); 00028 00029 M = new double[MATRIX_SIZE_6x6]; 00030 MAT = new double[MATRIX_SIZE_6x6]; 00031 } 00032 00033 00034 matrix_ecL_ip::~matrix_ecL_ip() 00035 { 00036 if (ecL != NULL) 00037 delete ecL; 00038 00039 if (M != NULL) 00040 delete M; 00041 if (MAT != NULL) 00042 delete MAT; 00043 } 00044 00045 //============================================== 00046 00047 00048 00061 void matrix_ecL_ip::form_M ( 00062 const double sinA, 00063 const double cosA, 00064 const double *i2Q, 00065 const double* i2hess) 00066 { 00067 /* 00068 * Numbers mark identical elements of M 00069 * 1 5 00070 * 2 00071 * 3 00072 * 5 4 00073 * 2 00074 * 3 00075 */ 00076 // diagonal elements 00077 M[0] = i2hess[0]*cosA*cosA + i2hess[1]*sinA*sinA; 00078 /*M[28] =*/ M[7] = i2Q[1]; 00079 /*M[35] =*/ M[14] = i2Q[2]; 00080 M[21] = i2hess[0]*sinA*sinA + i2hess[1]*cosA*cosA; 00081 00082 // symmetric nondiagonal elements 00083 /*M[18] =*/ M[3] = (i2hess[0] - i2hess[1])*cosA*sinA; 00084 } 00085 00086 00087 00097 void matrix_ecL_ip::chol_dec (double *mx) 00098 { 00099 double *curel; 00100 00101 for (int i = 0; i < MATRIX_SIDE_6x6; i++) // row 00102 { 00103 // non-diagonal elements 00104 for (int j = 0; j < i; j++) // column 00105 { 00106 curel = &mx[j*MATRIX_SIDE_6x6 + i]; 00107 for (int k = 0; k < j; k++) // column 00108 { 00109 *curel -= mx[k*MATRIX_SIDE_6x6 + i] * mx[k*MATRIX_SIDE_6x6 + j]; 00110 } 00111 00112 *curel /= mx[j*MATRIX_SIDE_6x6 + j]; 00113 } 00114 00115 // diagonal element 00116 curel = &mx[i*MATRIX_SIDE_6x6 + i]; 00117 for (int k = 0; k < i; k++) // column 00118 { 00119 *curel -= mx[k*MATRIX_SIDE_6x6 + i] * mx[k*MATRIX_SIDE_6x6 + i]; 00120 } 00121 *curel = sqrt(*curel); 00122 } 00123 } 00124 00125 00126 00137 void matrix_ecL_ip::form_MBiPB (const double *B, const double i2P, double *result) 00138 { 00139 // diagonal elements 00140 result[0] = i2P * B[0]*B[0] + M[0]; 00141 /*result[28] =*/ result[7] = i2P * B[1]*B[1] + M[7]; 00142 /*result[35] =*/ result[14] = i2P * B[2]*B[2] + M[14]; 00143 result[21] = i2P * B[0]*B[0] + M[21]; 00144 00145 // symmetric elements (no need to initialize all of them) 00146 /*result[22] =*/ result[1] = i2P * B[0]*B[1]; 00147 /*result[23] =*/ result[2] = i2P * B[0]*B[2]; 00148 /*result[29] =*/ result[8] = i2P * B[1]*B[2]; 00149 result[3] = M[3]; 00150 } 00151 00152 00153 00160 void matrix_ecL_ip::form_MAT (const double A3, const double A6) 00161 { 00162 // 1st column 00163 MAT[0] = M[0]; 00164 MAT[1] = A3 * M[7]; 00165 MAT[2] = A6 * M[14]; 00166 MAT[3] = M[3]; 00167 00168 // 2nd column 00169 MAT[7] = M[7]; 00170 MAT[8] = A3 * M[14]; 00171 00172 // 3rd column 00173 MAT[14] = M[14]; 00174 00175 // 4th column 00176 MAT[21] = M[21]; 00177 MAT[22] = MAT[1]; 00178 MAT[23] = MAT[2]; 00179 00180 // 5th column 00181 MAT[28] = MAT[7]; 00182 MAT[29] = MAT[8]; 00183 00184 // 6th column 00185 MAT[35] = MAT[14]; 00186 } 00187 00188 00189 00197 void matrix_ecL_ip::form_L_non_diag(const double *ecLp, double *ecLc) 00198 { 00199 /* 00200 * L(k,k) * L(k+1,k)' = -M*A' 00201 * 00202 * x x x x x 00203 * xx xx x xx 00204 * xxx * xxxx = xxx 00205 * xxxx xxxx x x 00206 * xxxxx xxxxx xx 00207 * xxxxxx xxxxxx xxx 00208 */ 00209 00210 00211 // copy (MAT)' to ecLc 00212 ecLc[0] = -MAT[0]; 00213 ecLc[27] = ecLc[6] = -MAT[1]; 00214 ecLc[33] = ecLc[12] = -MAT[2]; 00215 00216 ecLc[3] = ecLc[18] = -MAT[3]; 00217 00218 ecLc[28] = ecLc[7] = -MAT[7]; 00219 ecLc[34] = ecLc[13] = -MAT[8]; 00220 00221 ecLc[35] = ecLc[14] = -MAT[14]; 00222 00223 ecLc[21] = -MAT[21]; 00224 00225 // reset elements 00226 ecLc[9] = ecLc[15] = ecLc[19] = ecLc[20] = ecLc[24] = ecLc[25] = 00227 ecLc[26] = ecLc[30] = ecLc[31] = ecLc[32] = 0; 00228 00229 00230 for (int i = 0; i < MATRIX_SIDE_6x6; i++) // row of L(k+1,k) 00231 { 00232 for (int j = 0; j < MATRIX_SIDE_6x6; j++) // element in the row of L(k+1,k) 00233 { 00234 double *curel = &ecLc[j*MATRIX_SIDE_6x6 + i]; 00235 for (int k = 0; k < j; k++) // elements in a row of L(k,k) 00236 { 00237 *curel -= ecLc[k*MATRIX_SIDE_6x6 + i] * ecLp[k*MATRIX_SIDE_6x6 + j]; 00238 } 00239 00240 *curel /= ecLp[j*MATRIX_SIDE_6x6 + j]; 00241 } 00242 } 00243 } 00244 00245 00254 void matrix_ecL_ip::form_L_diag(double *ecLc) 00255 { 00256 // finish initialization of MBiPB 00257 ecLc[28] = ecLc[7]; 00258 ecLc[35] = ecLc[14]; 00259 // symmetric elements (no need to initialize all of them) 00260 ecLc[22] = ecLc[1]; 00261 ecLc[23] = ecLc[2]; 00262 ecLc[29] = ecLc[8]; 00263 // reset elements 00264 ecLc[4] = ecLc[5] = ecLc[9] = ecLc[10] = ecLc[11] = 00265 ecLc[15] = ecLc[16] = ecLc[17] = 0; 00266 00267 00268 // chol (L(k+1,k+1)) 00269 chol_dec (ecLc); 00270 } 00271 00272 00273 00284 void matrix_ecL_ip::form_AMATMBiPB(const double A3, const double A6, double *result) 00285 { 00286 // 1st,4th column 00287 result[0] += MAT[0] + A3*MAT[1] + A6*MAT[2]; 00288 result[1] += MAT[1] + A3*MAT[2]; 00289 result[2] += MAT[2]; 00290 result[3] += MAT[3]; 00291 00292 // 2nd column 00293 // symmetric elements are not initialized 00294 result[7] += MAT[7] + A3*MAT[8]; 00295 result[8] += MAT[8]; 00296 00297 // 6th column 00298 result[14] += MAT[14]; 00299 result[35] = result[14]; 00300 00301 // 4th column 00302 result[21] += MAT[21] + A3*MAT[1] + A6*MAT[2]; 00303 result[22] = result[1]; 00304 result[23] = result[2]; 00305 00306 // 5th column 00307 result[28] = result[7]; 00308 result[29] = result[8]; 00309 00310 // 6th column 00311 result[35] = result[14]; 00312 00313 // reset elements 00314 result[4] = result[5] = result[9] = result[10] = result[11] = 00315 result[15] = result[16] = result[17] = 0; 00316 } 00317 00318 00319 00330 void matrix_ecL_ip::form_L_diag (const double *ecLp, double *ecLc) 00331 { 00332 /* - L(k+1,k) * L(k+1,k)' + A*M*A' + MBiPB 00333 * xxxxxx x x 00334 * xxxxx xx x 00335 * xxxx xxxx 00336 * xxxxxx * xxxx 00337 * xx xxxxx 00338 * x xxxxxx 00339 */ 00340 // - L(k+1,k) * L(k+1,k)' 00341 for (int i = 0; i < MATRIX_SIDE_6x6; i++) // row 00342 { 00343 for (int j = 0; j <= i; j++) // column 00344 { 00345 double *curel = &ecLc[i + MATRIX_SIDE_6x6*j]; 00346 for (int k = 0; k < MATRIX_SIDE_6x6; k++) // elements in a row 00347 { 00348 *curel -= ecLp[i + MATRIX_SIDE_6x6*k] * ecLp[j + MATRIX_SIDE_6x6*k]; 00349 } 00350 } 00351 } 00352 00353 // chol (L(k+1,k+1)) 00354 chol_dec (ecLc); 00355 } 00356 00357 00358 00365 void matrix_ecL_ip::form (const problem_parameters& ppar, const double *i2hess) 00366 { 00367 int i; 00368 state_parameters stp; 00369 00370 stp = ppar.spar[0]; 00371 00372 // the first matrix on diagonal 00373 form_M (stp.sin, stp.cos, ppar.i2Q, i2hess); 00374 form_MBiPB (stp.B, ppar.i2P, ecL); 00375 form_L_diag (ecL); 00376 00377 // offsets 00378 double *ecL_cur = &ecL[MATRIX_SIZE_6x6]; 00379 double *ecL_prev = &ecL[0]; 00380 for (i = 1; i < ppar.N; i++) 00381 { 00382 stp = ppar.spar[i]; 00383 00384 // form all matrices 00385 form_MAT (stp.A3, stp.A6); 00386 form_L_non_diag (ecL_prev, ecL_cur); 00387 00388 // update offsets 00389 ecL_cur = &ecL_cur[MATRIX_SIZE_6x6]; 00390 ecL_prev = &ecL_prev[MATRIX_SIZE_6x6]; 00391 00392 00393 i2hess = &i2hess[2]; 00394 form_M (stp.sin, stp.cos, ppar.i2Q, i2hess); 00395 form_MBiPB (stp.B, ppar.i2P, ecL_cur); 00396 form_AMATMBiPB(stp.A3, stp.A6, ecL_cur); 00397 form_L_diag(ecL_prev, ecL_cur); 00398 00399 // update offsets 00400 ecL_cur = &ecL_cur[MATRIX_SIZE_6x6]; 00401 ecL_prev = &ecL_prev[MATRIX_SIZE_6x6]; 00402 } 00403 } 00404 00405 00406 00414 void matrix_ecL_ip::solve_forward(const int N, double *x) 00415 { 00416 int i,j,k; 00417 double *xc = x; // 6 current elements of x 00418 double *xp; // 6 elements of x computed on the previous iteration 00419 double *ecL_cur = &ecL[0]; // lower triangular matrix lying on the 00420 // diagonal of L 00421 double *ecL_prev; // upper triangular matrix lying to the left from 00422 // ecL_cur at the same level of L 00423 00424 00425 // compute the first 6 elements using forward substitution 00426 for (j = 0; j < MATRIX_SIDE_6x6; j++) // row 00427 { 00428 for (k = 0; k < j; k++) // column 00429 { 00430 xc[j] -= xc[k]*ecL_cur[j+k*MATRIX_SIDE_6x6]; 00431 } 00432 xc[j] /= ecL_cur[j+j*MATRIX_SIDE_6x6]; 00433 } 00434 00435 00436 for (i = 1; i < N; i++) 00437 { 00438 // switch to the next level of L / next 6 elements 00439 xp = xc; 00440 xc = &xc[SMPC_NUM_STATE_VAR]; 00441 00442 ecL_prev = &ecL_cur[MATRIX_SIZE_6x6]; 00443 ecL_cur = &ecL_prev[MATRIX_SIZE_6x6]; 00444 00445 00446 // update the right part of the equation 00447 for (j = 0; j < MATRIX_SIDE_6x6; j++) // column 00448 { 00449 for (k = 0; k < MATRIX_SIDE_6x6; k++) // row 00450 { 00451 xc[k] -= xp[j]*ecL_prev[j*MATRIX_SIDE_6x6 + k]; 00452 } 00453 } 00454 00455 // forward substitution 00456 for (j = 0; j < MATRIX_SIDE_6x6; j++) // row 00457 { 00458 for (k = 0; k < j; k++) // column 00459 { 00460 xc[j] -= xc[k]*ecL_cur[j+k*MATRIX_SIDE_6x6]; 00461 } 00462 xc[j] /= ecL_cur[j+j*MATRIX_SIDE_6x6]; 00463 } 00464 } 00465 } 00466 00467 00474 void matrix_ecL_ip::solve_backward (const int N, double *x) 00475 { 00476 int i,j,k; 00477 double *xc = & x[(N-1)*SMPC_NUM_STATE_VAR]; // current 6 elements of result 00478 double *xp; // 6 elements computed on the previous iteration 00479 00480 // elements of these matrices accessed as if they were transposed 00481 // lower triangular matrix lying on the diagonal of L 00482 double *ecL_cur = &ecL[2 * (N - 1) * MATRIX_SIZE_6x6]; 00483 // upper triangular matrix lying to the right from ecL_cur at the same level of L' 00484 double *ecL_prev; 00485 00486 00487 // compute the last 6 elements using backward substitution 00488 for (j = MATRIX_SIDE_6x6-1; j >= 0; j--) // row 00489 { 00490 for (k = MATRIX_SIDE_6x6-1; k > j; k--) // column 00491 { 00492 xc[j] -= xc[k]*ecL_cur[k+j*MATRIX_SIDE_6x6]; 00493 } 00494 xc[j] /= ecL_cur[j+j*MATRIX_SIDE_6x6]; 00495 } 00496 00497 00498 for (i = N-2; i >= 0 ; i--) 00499 { 00500 xp = xc; 00501 xc = & x[i*SMPC_NUM_STATE_VAR]; 00502 00503 ecL_cur = &ecL[2 * i * MATRIX_SIZE_6x6]; 00504 ecL_prev = &ecL_cur[MATRIX_SIZE_6x6]; 00505 00506 00507 // update the right part of the equation 00508 for (j = 0; j < MATRIX_SIDE_6x6; j++) // row 00509 { 00510 for (k = 0; k < MATRIX_SIDE_6x6; k++) // column 00511 { 00512 xc[j] -= xp[k]*ecL_prev[j*MATRIX_SIDE_6x6 + k]; 00513 } 00514 } 00515 00516 // backward substitution 00517 for (j = MATRIX_SIDE_6x6-1; j >= 0; j--) // row 00518 { 00519 for (k = MATRIX_SIDE_6x6-1; k > j; k--) // column 00520 { 00521 xc[j] -= xc[k]*ecL_cur[k+j*MATRIX_SIDE_6x6]; 00522 } 00523 xc[j] /= ecL_cur[j+j*MATRIX_SIDE_6x6]; 00524 } 00525 } 00526 }