Linear Quadratic Regulator (LQR) 설명 및 구현

Background

Optimization Problem

Optimality Condition

LQR for Discrete Time & Finite Horizon

Problem Setting

Lagrangian Function 및 Hamiltonian Matrix

Optimal Control Derivation

Optimal Control Derivation via Dynamic Programming

위에서는 optimization problem 접근 방식으로 control을 구하였다. 이와 다른 방식으로, Reinforcement Learning (그 중에서 value iteration 방식)과 같이 각 state 마다 value function을 정의하여 control을 구할 수도 있다. 이러한 value function을 cost-to-go 함수라 말한다. 이 방식을 통해 유도한 결과 또한 위와 동일한 결과를 얻을 수 있다. 이번 포스트에서는 유도를 생략하고 다음 기회에 해볼 예정이다.

Code Implemetation

LQR과 같은 optimal controller들은 계산량이 많아 파이썬에서 구현하면 real-time control이 어려워진다. 이를 위해 LQR의 핵심 파트 ($P_i$ matrix를 구하는 계산) 만 c++로 작성 및 동적 라이브러리 파일을 compile한 뒤, 파이썬으로 모듈화 하였다. c++ 코드는 아래와 같다.

void get_action(int X_DIM, int U_DIM, double* init_x, int time_horizon, double* A_data, double* B_data,
                    double* R_data, double* Q_data, double* Qf_data, double* return_var){
    // ######## declare variables ########
    mat A_mat(A_data, X_DIM, X_DIM);
    mat B_mat(B_data, X_DIM, U_DIM);
    mat R_mat(R_data, U_DIM, U_DIM);
    mat Q_mat(Q_data, X_DIM, X_DIM);
    mat Qf_mat(Qf_data, X_DIM, X_DIM);

    mat* P_mat_list = new mat[time_horizon];
    mat S_mat = Qf_mat;
    // ###################################

    for(int t_idx=time_horizon-1; t_idx>=0; t_idx--){
        P_mat_list[t_idx] = (R_mat + B_mat.transpose().matmul(S_mat.matmul(B_mat))).inverse_matmul(B_mat.transpose().matmul(S_mat.matmul(A_mat)));
        S_mat = Q_mat + A_mat.transpose().matmul(S_mat.matmul(A_mat - B_mat.matmul(P_mat_list[t_idx])));
    }

    for(int i=0;i<time_horizon;i++){
        memcpy(&return_var[i*X_DIM*U_DIM], P_mat_list[i].data, sizeof(double)*X_DIM*U_DIM);
    }

    delete[] P_mat_list;
    return;
    }

컴파일 과정, 모듈화 과정, 파이썬 코드는 모두 여기에 소개되어 있다.

Result

Conclusion

optimal control의 가장 기본이 되는 방법인 LQR을 다뤄보았다. 다음번엔, non linear dynamics에서 적용가능한 iterative LQR (iLQR)에 대해 다룰 예정이다.