| 305 | |
| 306 | |
| 307 | int tiny_precompute_and_set_cache(TinyCache *cache, |
| 308 | tinyMatrix Adyn, tinyMatrix Bdyn, tinyMatrix fdyn, tinyMatrix Q, tinyMatrix R, |
| 309 | int nx, int nu, tinytype rho, int verbose) { |
| 310 | |
| 311 | if (!cache) { |
| 312 | std::cout << "Error in tiny_precompute_and_set_cache: cache is nullptr" << std::endl; |
| 313 | return 1; |
| 314 | } |
| 315 | |
| 316 | // Update by adding rho * identity matrix to Q, R |
| 317 | tinyMatrix Q1 = Q + rho * tinyMatrix::Identity(nx, nx); |
| 318 | tinyMatrix R1 = R + rho * tinyMatrix::Identity(nu, nu); |
| 319 | |
| 320 | // Printing |
| 321 | if (verbose) { |
| 322 | std::cout << "A = " << Adyn.format(TinyApiFmt) << std::endl; |
| 323 | std::cout << "B = " << Bdyn.format(TinyApiFmt) << std::endl; |
| 324 | std::cout << "Q = " << Q1.format(TinyApiFmt) << std::endl; |
| 325 | std::cout << "R = " << R1.format(TinyApiFmt) << std::endl; |
| 326 | std::cout << "rho = " << rho << std::endl; |
| 327 | } |
| 328 | |
| 329 | // Riccati recursion to get Kinf, Pinf |
| 330 | tinyMatrix Ktp1 = tinyMatrix::Zero(nu, nx); |
| 331 | tinyMatrix Ptp1 = rho * tinyMatrix::Ones(nx, 1).array().matrix().asDiagonal(); |
| 332 | tinyMatrix Kinf = tinyMatrix::Zero(nu, nx); |
| 333 | tinyMatrix Pinf = tinyMatrix::Zero(nx, nx); |
| 334 | |
| 335 | for (int i = 0; i < 1000; i++) |
| 336 | { |
| 337 | Kinf = (R1 + Bdyn.transpose() * Ptp1 * Bdyn).inverse() * Bdyn.transpose() * Ptp1 * Adyn; |
| 338 | Pinf = Q1 + Adyn.transpose() * Ptp1 * (Adyn - Bdyn * Kinf); |
| 339 | // if Kinf converges, break |
| 340 | if ((Kinf - Ktp1).cwiseAbs().maxCoeff() < 1e-5) |
| 341 | { |
| 342 | if (verbose) { |
| 343 | std::cout << "Kinf converged after " << i + 1 << " iterations" << std::endl; |
| 344 | } |
| 345 | break; |
| 346 | } |
| 347 | Ktp1 = Kinf; |
| 348 | Ptp1 = Pinf; |
| 349 | } |
| 350 | |
| 351 | // Compute cached matrices |
| 352 | tinyMatrix Quu_inv = (R1 + Bdyn.transpose() * Pinf * Bdyn).inverse(); |
| 353 | tinyMatrix AmBKt = (Adyn - Bdyn * Kinf).transpose(); |
| 354 | |
| 355 | // Precomputation for affine term |
| 356 | tinyVector APf = AmBKt*Pinf*fdyn; |
| 357 | tinyVector BPf = Bdyn.transpose()*Pinf*fdyn; |
| 358 | |
| 359 | if (verbose) { |
| 360 | std::cout << "Kinf = " << Kinf.format(TinyApiFmt) << std::endl; |
| 361 | std::cout << "Pinf = " << Pinf.format(TinyApiFmt) << std::endl; |
| 362 | std::cout << "Quu_inv = " << Quu_inv.format(TinyApiFmt) << std::endl; |
| 363 | std::cout << "AmBKt = " << AmBKt.format(TinyApiFmt) << std::endl; |
| 364 | std::cout << "APf = " << APf.format(TinyApiFmt) << std::endl; |
no test coverage detected