Reference Tracking and Optimal Control · Lesson

English translation

Topics covered

Examine why reference error remains even with a stable controller, and compare tracking performance with control-input cost.

Stability and reference tracking have different conditions

u=−Kx is a regulator that drives the state to the origin. For a reference r, use u=−Kx+Nru=-Kx+Nr and calculate N from the nominal model's steady-state equation.

Assess stability using A−BKA-BK, and calculate the tracked output including the reference path.

Interpreting LQR cost

Define the cost of state deviations and input use as J=∫(x⊤Qx+u⊤Ru)dtJ=\int(x^\top Qx+u^\top Ru)\,dt. Increasing Q assigns a higher cost to that state deviation.

This does not mean that all metrics improve simultaneously. States with different units require normalization by reference magnitudes or interpretation of the weights' units.

This model is a 2nd-order system with normalized states and input. Under R>0R>0 and suitable controllability conditions, solve the CARE to obtain K=R−1B⊤PK=R^{-1}B^\top P. If the input saturates, the optimality of this linear, unconstrained design no longer applies directly.

Checking the same design in MATLAB

Reference gain adjusts the input amplitude to achieve the desired steady-state output. LQR state-feedback gain is determined by the costs assigned to state error and control input.

Same poles, different reference tracking

Keep the control poles fixed and change only the reference gain to examine differences in the steady-state value.

import numpy as np
from scipy.signal import place_poles,StateSpace,lsim
from scipy.linalg import solve_continuous_are
import matplotlib.pyplot as plt
A=np.array([[0.,1.],[-2.,-3.]])
B=np.array([[0.],[1.]]);C=np.array([[1.,0.]])
K=place_poles(A,B,[-2.,-4.]).gain_matrix
N=float((-1/(C@np.linalg.solve(A-B@K,B))).item())
print('K:',K,'N:',N);assert np.isclose(N,8)
t=np.linspace(0,5,1001)
for gain in [1.,N]:
    _,y,_=lsim(StateSpace(A-B@K,B*gain,C,0),np.ones(len(t)),t)
    plt.plot(t,y,label=f'N={gain:g}')
plt.xlabel('Time [s]');plt.ylabel('Position');plt.legend();plt.grid()
P=solve_continuous_are(A,B,np.diag([4.,1.]),np.array([[1.]]))
klqr=B.T@P
print('LQR gain:',klqr,'closed-loop poles:',np.linalg.eigvals(A-B@klqr))
K: [[6. 3.]] N: 7.999999999999995
LQR gain: [[0.82842712 0.41421356]] closed-loop poles: [-1.41421356 -2.        ]
실행 결과

Official documentation and data