ACKER

Ackermann’s formula is an alternative method for calculating the state feedback gain matrix K such that A - BK reaches desired pole locations.

While mathematically elegant, acker can be numerically unstable for high-order systems (typically N > 10) compared to the place function. It is primarily recommended for SISO systems of lower order.

Excel Usage

=ACKER(A, B, poles)
  • A (list[list], required): The state dynamics matrix A (NxN).
  • B (list[list], required): The input matrix B (Nx1 - MUST be SISO for Ackermann).
  • poles (list[list], required): The desired closed-loop pole locations (1xN or Nx1).

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

Example 1: SISO pole placement with acker

Inputs:

A B poles
0 1 0 -5 -6
-2 -3 1

Excel formula:

=ACKER({0,1;-2,-3}, {0;1}, {-5,-6})

Expected output:

Result
28 8
Example 2: Accept flat pole list input

Inputs:

A B poles
0 1 0 -4,-7
-2 -3 1

Excel formula:

=ACKER({0,1;-2,-3}, {0;1}, -4,-7)

Expected output:

Result
26 8
Example 3: Place moderate stable poles

Inputs:

A B poles
0 1 0 -2 -3
-1 -1 1

Excel formula:

=ACKER({0,1;-1,-1}, {0;1}, {-2,-3})

Expected output:

Result
5 4
Example 4: Place faster closed-loop poles

Inputs:

A B poles
0 1 0 -3 -8
0 0 1

Excel formula:

=ACKER({0,1;0,0}, {0;1}, {-3,-8})

Expected output:

Result
24 11

Python Code

Show Code
import control as ct
import numpy as np

def acker(A, B, poles):
    """
    Pole placement using Ackermann's formula.

    See: https://python-control.readthedocs.io/en/latest/generated/control.acker.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 (Nx1 - MUST be SISO for Ackermann).
        poles (list[list]): The desired closed-loop pole locations (1xN or Nx1).

    Returns:
        list[list]: The 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])

        def parse_poles(x):
            values = []
            if not isinstance(x, list):
                x = [x]
            for item in x:
                if isinstance(item, list):
                    for v in item:
                        if v is not None and str(v) != "":
                            s = str(v)
                            values.append(complex(s.replace('i', 'j')) if 'i' in s or 'j' in s else float(v))
                elif item is not None and str(item) != "":
                    s = str(item)
                    values.append(complex(s.replace('i', 'j')) if 'i' in s or 'j' in s else float(item))
            return values

        a_np = to_np(A)
        b_np = to_np(B)
        p_list = parse_poles(poles)

        if len(p_list) == 0:
            return "Error: poles must contain at least one value"

        K = ct.acker(a_np, b_np, p_list)

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

Online Calculator

The state dynamics matrix A (NxN).
The input matrix B (Nx1 - MUST be SISO for Ackermann).
The desired closed-loop pole locations (1xN or Nx1).