Python で見る現代制御


    numpy, scipy.integrate.odeint, matplotlib.pyplot を使うため、まず
    import する。
  
    >>> import numpy
    >>> import matplotlib.pyplot as plt
    >>> from scipy.integrate import odeint

□ 可制御性・可観測性

   システム

     x'(t) = A x(t) + b u(t)
     y(t) = c x(t)

     A = [-2 , -1; -1, -2], b = [1; 1], c = [1, 0]

    の可制御性と,可観測性を調べる.

    >>> A = numpy.array([[-2, -1],[-1, -2]])
    >>> b = numpy.array([1, 1])
    >>> c = numpy.array([1, 0])
    >>> Mc = numpy.column_stack((b, A.dot(b)))
    >>> numpy.linalg.det(Mc)

      Mc の行列式が 0 なので可制御ではない.

    >>> Mo = numpy.row_stack((c, c.dot(A)))
    >>> numpy.linalg.det(Mo)

      Mo の行列式が 0 でないので可観測である.

□ 対角化

   システム

     x'(t) = A x(t) + b u(t)
     y(t) = c x(t)

     A = [-2 , -1; -1, -2], b = [1; 1], c = [1, 0]

    を対角化する.

    >>> A = numpy.array([[-2, -1],[-1, -2]])
    >>> b = numpy.array([1, 1])
    >>> c = numpy.array([1, 0])
    >>> (V, T) = numpy.linalg.eig(A)
    >>> Abar = numpy.linalg.inv(T).dot(A).dot(T)
    >>> bbar = numpy.linalg.inv(T).dot(b)
    >>> cbar = c.dot(T)
    >>> print Abar, bbar, cbar

    この結果,システムが可制御ではないが可観測であることがわかる.

□ 可制御正準形

   システム

     x'(t) = A x(t) + b u(t)
     y(t) = c x(t)

     A = [-1 , 2; -1, -4], b = [1; 1], c = [1, 0]

    を可制御正準形に変換する.

    >>> A = numpy.array([[-1, 2], [-1, -4]])
    >>> b = numpy.array([1, 1])
    >>> c = numpy.array([1, 0])
    >>> p = numpy.poly(A)
    >>> p

      特性多項式が s^2 + 5 s + 6 となることがわかる.

    >>> S = numpy.array([[p[1], 1],[1, 0]])
    >>> T = numpy.column_stack((b, A.dot(b))).dot(S)
    >>> iT = numpy.linalg.inv(T)
    >>> Abar = iT.dot(A).dot(T)
    >>> bbar = iT.dot(b)
    >>> cbar = c.dot(T)
    >>> print Abar, bbar, cbar

□ 安定性判別

   システム

     x'(t) = A x(t) + b u(t)
     y(t) = c x(t)

     A = [-1 , 2; -1, -4], b = [1; 1], c = [1, 0]

    の安定性を判別する.

    >>> A = numpy.array([[-1, 2], [-1, -4]])
    >>> numpy.roots(numpy.poly(A))

    A の特性方程式の根の実部が全て負なので,システムは安定である.

□ 状態フィードバック制御の極配置

   システム

     x'(t) = A x(t) + b u(t)
     y(t) = c x(t)

     A = [-1 , -2; -1, -4], b = [1; 1], c = [1, 0]

    の極を -1+2j, -1-2j に設定する状態フィードバックゲイン f を求める.

    >>> A = numpy.array([[-1, -2], [-1, -4]])
    >>> b = numpy.array([1, 1])
    >>> c = numpy.array([1, 0])
    >>> p1 = numpy.poly(A)
    >>> S = numpy.array([[p[1], 1],[1, 0]])
    >>> T = numpy.column_stack((b, A.dot(b))).dot(S)
    >>> iT = numpy.linalg.inv(T)
    >>> p2 = numpy.poly(numpy.array([-1+2j, -1-2j]))
    >>> f = numpy.array([p2[2] - p1[2], p2[1] - p1[1]]).dot(iT)
    >>> f

    初期値 x(0) = [1; -1] の場合の応答を確かめる.

    >>> global A,b,f
    >>> def F(x, t):
            global A, b, f
            return (A-numpy.outer(b,f)).dot(x)
    >>> x0 = numpy.array([1, -1])
    >>> t = numpy.linspace(0, 5, 1001)
    >>> y = odeint(F, x0, t)
    >>> plt.plot(t, y)
    >>> plt.grid('on')
    >>> plt.show()

□ 直接フィードバック制御における根軌跡

   システム

     x'(t) = A x(t) + b u(t)
     y(t) = c x(t)

     A = [-1, 0, 0; -1, -1, -1; -2, 1, -2], b = [1; 1; 1], c = [0, 0, 1]

    に対して u(t) = -k y(t) という直接フィードバックを行ったときの根軌跡を
    求める.

    >>> A = numpy.array([[-1, 0, 0], [-1, -1, -1], [-2, 1, -2]])
    >>> b = numpy.array([1, 1, 1])
    >>> c = numpy.array([0, 0, 1])
    >>> global A, b, c
    >>> def F(k):
            global A, b, c
            return numpy.roots(numpy.poly(A- k*numpy.outer(b,c)))
    >>> k = numpy.linspace(0, 30, 61)
    >>> nc = numpy.size(k)
    >>> r = F(k[0])
    >>> for i in range(nc)[1:]:
            r = numpy.concatenate((r, F(k[i])))
    >>> plt.plot(numpy.real(r), numpy.imag(r), 'x')
    >>> plt.grid('on')
    >>> plt.show()

□ 同一次元オブザーバの構成

   システム

     x'(t) = A x(t) + b u(t)
     y(t) = c x(t)

     A = [-1 , -2; -1, -4], b = [1; 1], c = [1, 0]

    に対して,-4, -5 に極を持つ同一次元オブザーバ

    z'(t) = A z(t) -k[c z(t) - y(t)] + b u(t) = (A - k c)z(t) + k y(t) + b u(t)
  
    のゲイン k を決定する.

    >>> A = numpy.array([[-1, -2], [-1, -4]])
    >>> b = numpy.array([1, 1])
    >>> c = numpy.array([1, 0])
    >>> p1 = numpy.poly(A)
    >>> S = numpy.array([[p[1], 1],[1, 0]])
    >>> T = numpy.column_stack((c, A.T.dot(c))).dot(S)
    >>> iT = numpy.linalg.inv(T)
    >>> p2 = numpy.poly([-4, -5])
    >>> k = numpy.array([p2[2] - p1[2], p2[1] - p1[1]]).dot(iT)
    >>> k
    
    オブザーバの推定の様子を確かめる.初期値 x(0) = [0; 0], z(0) = [1; 1]
    u(t) = 1 (単位ステップ入力)とする.

    >>> A1 = numpy.column_stack((A, numpy.zeros((2,2))))
    >>> A2 =  numpy.column_stack((numpy.outer(k,c),\
        A-numpy.outer(k,c)))
    >>> AA = numpy.row_stack((A1, A2))
    >>> bb = numpy.concatenate((b, b))
    >>> global AA, bb
    >>> def F(x, t):
            global AA, bb
            return AA.dot(x) + bb
    >>> x0 = numpy.array([0, 0, 1, 1])
    >>> t = numpy.linspace(0, 5, 1001)
    >>> y = odeint(F, x0, t)
    >>> plt.plot(t, y)
    >>> plt.grid('on')
    >>> plt.show()

□ 同一次元オブザーバとフィードバック制御の併合システム

   システム

     x'(t) = A x(t) + b u(t)
     y(t) = c x(t)

     A = [-1 , -2; -1, -4], b = [1; 1], c = [1, 0]

    に対して,-4, -5 に極を持つ同一次元オブザーバ

    z'(t) = A z(t) -k[c z(t) - y(t)] + b u(t) = (A - k c)z(t) + k y(t) + b u(t)
  
    の推定値を用いて,極を -1+2j, -1-2j に配置したフィードバック制御を
    行う.

    >>> A = numpy.array([[-1, -2], [-1, -4]])
    >>> b = numpy.array([1, 1])
    >>> c = numpy.array([1, 0])
    >>> p1 = numpy.poly(A)
    >>> S = numpy.array([[p[1], 1],[1, 0]])
    >>> T = numpy.column_stack((c, A.T.dot(c))).dot(S)
    >>> iT = numpy.linalg.inv(T)
    >>> p2 = numpy.poly([-4, -5])
    >>> k = numpy.array([p2[2] - p1[2], p2[1] - p1[1]]).dot(iT)
    >>> T = numpy.column_stack((b, A.dot(b))).dot(S)
    >>> iT = numpy.linalg.inv(T)
    >>> p2 = numpy.poly([-1+2j, -1-2j])
    >>> f = numpy.array([p2[2] - p1[2], p2[1] - p1[1]]).dot(iT)
    >>> print k, f

    併合システムの応答を確かめる.
    初期値 x(0) = [1; -1], z(0) = [0; 0] とする.

    >>> A1 = numpy.column_stack((A, -numpy.outer(b,f)))
    >>> A2 =  numpy.column_stack((numpy.outer(k,c),\
        A - numpy.outer(k,c) - numpy.outer(b,f)))
    >>> AA = numpy.row_stack((A1, A2))
    >>> global AA
    >>> def F(x, t):
            global AA
            return AA.dot(x)
    >>> x0 = numpy.array([1, -1, 0, 0])
    >>> t = numpy.linspace(0, 5, 1001)
    >>> y = odeint(F, x0, t)
    >>> plt.plot(t, y)
    >>> plt.grid('on')
    >>> plt.show()


Python で数値計算
naniwa@rbt.his.u-fukui.ac.jp