Apollo 10.0
自动驾驶开放平台
linear_quadratic_regulator.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2017 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
18
19#include <limits>
20
21#include "Eigen/Dense"
22
23#include "cyber/common/log.h"
24
25namespace apollo {
26namespace common {
27namespace math {
28
29using Matrix = Eigen::MatrixXd;
30
31// solver with cross term
32void SolveLQRProblem(const Matrix &A, const Matrix &B, const Matrix &Q,
33 const Matrix &R, const Matrix &M, const double tolerance,
34 const uint max_num_iteration, Matrix *ptr_K,
35 uint *iterate_num, double *result_diff) {
36 if (A.rows() != A.cols() || B.rows() != A.rows() || Q.rows() != Q.cols() ||
37 Q.rows() != A.rows() || R.rows() != R.cols() || R.rows() != B.cols() ||
38 M.rows() != Q.rows() || M.cols() != R.cols()) {
39 AERROR << "LQR solver: one or more matrices have incompatible dimensions.";
40 return;
41 }
42
43 Matrix AT = A.transpose();
44 Matrix BT = B.transpose();
45 Matrix MT = M.transpose();
46
47 // Solves a discrete-time Algebraic Riccati equation (DARE)
48 // Calculate Matrix Difference Riccati Equation, initialize P and Q
49 Matrix P = Q;
50 uint num_iteration = 0;
51 double diff = std::numeric_limits<double>::max();
52 while (num_iteration++ < max_num_iteration && diff > tolerance) {
53 Matrix P_next =
54 AT * P * A -
55 (AT * P * B + M) * (R + BT * P * B).inverse() * (BT * P * A + MT) + Q;
56 // check the difference between P and P_next
57 diff = fabs((P_next - P).maxCoeff());
58 P = P_next;
59 }
60
61 if (num_iteration >= max_num_iteration) {
62 ADEBUG << "LQR solver cannot converge to a solution, "
63 "last consecutive result diff is: "
64 << diff;
65 } else {
66 ADEBUG << "LQR solver converged at iteration: " << num_iteration
67 << ", max consecutive result diff.: " << diff;
68 }
69 *iterate_num = num_iteration;
70 *result_diff = diff;
71 *ptr_K = (R + BT * P * B).inverse() * (BT * P * A + MT);
72}
73
74void SolveLQRProblem(const Matrix &A, const Matrix &B, const Matrix &Q,
75 const Matrix &R, const double tolerance,
76 const uint max_num_iteration, Matrix *ptr_K,
77 uint *iterate_num, double *result_diff) {
78 // create M as zero matrix of the right size:
79 // M.rows() == Q.rows() && M.cols() == R.cols()
80 Matrix M = Matrix::Zero(Q.rows(), R.cols());
81 SolveLQRProblem(A, B, Q, R, M, tolerance, max_num_iteration, ptr_K,
82 iterate_num, result_diff);
83}
84
85} // namespace math
86} // namespace common
87} // namespace apollo
Solver for discrete-time linear quadratic problem.
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
void SolveLQRProblem(const Matrix &A, const Matrix &B, const Matrix &Q, const Matrix &R, const Matrix &M, const double tolerance, const uint max_num_iteration, Matrix *ptr_K, uint *iterate_num, double *result_diff)
class register implement
Definition arena_queue.h:37
repeated Vector rows