LQR

The linear quadratic regulator (LQR) calculates the optimal state-feedback gain matrix K such that the feedback law u = -Kx minimizes the quadratic cost function:

J = \int_{0}^{\infty} (x^T Q x + u^T R u + 2x^T N u) dt

This function accepts system matrices A and B, or an LTI system object, along with weight matrices Q, R, and optionally N. It returns the optimal gain matrix K.

Excel Usage

=LQR(A, B, Q, R, N)
  • A (list[list], required): The state dynamics matrix A (NxN).
  • B (list[list], required): The input matrix B (NxM).
  • Q (list[list], required): The state weighting matrix Q (NxN). Should be positive semi-definite.
  • R (list[list], required): The input weighting matrix R (MxM). Should be positive definite.
  • N (list[list], optional, default: null): Optional cross-weighting matrix N (NxM).

Returns (list[list]): The optimal state-feedback gain matrix K.

Example 1: Double integrator LQR

Inputs:

A B Q R
0 1 0 1 0 1
0 0 1 0 1

Excel formula:

=LQR({0,1;0,0}, {0;1}, {1,0;0,1}, {1})

Expected output:

Result
1 1.73205
Example 2: LQR with explicit zero cross-weight matrix

Inputs:

A B Q R N
0 1 0 2 0 0.8 0
-1 -0.5 1 0 1 0

Excel formula:

=LQR({0,1;-1,-0.5}, {0;1}, {2,0;0,1}, {0.8}, {0;0})

Expected output:

Result
0.870829 1.30046
Example 3: Single-state continuous regulator

Inputs:

A B Q R
-1 1 1 0.5

Excel formula:

=LQR({-1}, {1}, {1}, {0.5})

Expected output:

0.732051

Example 4: Coupled-state continuous regulator

Inputs:

A B Q R
0 1 0 4 0 1
-2 -1 1 0 2

Excel formula:

=LQR({0,1;-2,-1}, {0;1}, {4,0;0,2}, {1})

Expected output:

Result
0.828427 1.15797

Python Code

Show Code
import control as ct
import numpy as np

def lqr(A, B, Q, R, N=None):
    """
    Linear quadratic regulator design for continuous-time systems.

    See: https://python-control.readthedocs.io/en/latest/generated/control.lqr.html

    This example function is provided as-is without any representation of accuracy.

    Args:
        A (list[list]): The state dynamics matrix A (NxN).
        B (list[list]): The input matrix B (NxM).
        Q (list[list]): The state weighting matrix Q (NxN). Should be positive semi-definite.
        R (list[list]): The input weighting matrix R (MxM). Should be positive definite.
        N (list[list], optional): Optional cross-weighting matrix N (NxM). Default is None.

    Returns:
        list[list]: The optimal state-feedback gain matrix K.
    """
    try:
        def to_np(x):
            if x is None:
                return None
            if not isinstance(x, list):
                return np.array([[float(x)]])
            if len(x) > 0 and not isinstance(x[0], list):
                x = [x]
            return np.array([[float(v) if v is not None and str(v) != "" else 0.0 for v in row] for row in x])

        a_np = to_np(A)
        b_np = to_np(B)
        q_np = to_np(Q)
        r_np = to_np(R)
        n_np = to_np(N)

        if n_np is None:
            K, S, E = ct.lqr(a_np, b_np, q_np, r_np)
        else:
            K, S, E = ct.lqr(a_np, b_np, q_np, r_np, n_np)

        return K.tolist()
    except Exception as e:
        return f"Error: {str(e)}"

Online Calculator

The state dynamics matrix A (NxN).
The input matrix B (NxM).
The state weighting matrix Q (NxN). Should be positive semi-definite.
The input weighting matrix R (MxM). Should be positive definite.
Optional cross-weighting matrix N (NxM).