Example #1
0
def smp_nonlinear_model(plotting=False):
    """Пример идентификации объекта, описываемого 
    нелинейной моделью, с использованием простейшего 
    адаптивного алгоритма."""

    def obj(x, u):
        return 10 + 2 * np.sin(1 * x) + 4 * u + np.random.uniform(-1, 1)

    m = create_model('a0+a1*sin(a2*x1(t-1))+a3*u1(t-1)')
    idn = identifier.Identifier(m)
    idn.init_data(x=[[0, 9.94, 13.41, 15.44]],
                  a=[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]],
                  u=[[0, 1, 1, 1]])
    smp = alg_old.Adaptive(idn, method='smp')
    n = 20  # количество тактов
    a = np.zeros((n, 4))
    o_ar = np.zeros((n,))
    m_ar = np.zeros((n,))
    u_ar = [i+1 for i in range(n)]
    for i in range(n):
        obj_val = [obj(*idn.model.last_x, *idn.model.get_var_values(t='u')[0])]
        new_a = smp.update(obj_val)
        idn.update_x(obj_val)
        idn.update_u([u_ar[i]])
        idn.update_a(new_a)
        a[i] = new_a
        o_ar[i] = obj_val[0]
        m_ar[i] = idn.model.get_last_model_value()

    print(a)

    if plotting:
        t = np.array([i for i in range(n)])
        real_a = [10, 2, 1, 4]
        draw(t, o_ar, m_ar, a, real_a)
Example #2
0
def lsm_nonlinear_model(plotting=False):
    """Пример с нелинейной моделью, внешним 
    воздействим и алгоритмом на основе МНК."""
    def obj(x, j):
        res = 3 + 0.1 * np.power(x, 1.5) + np.random.uniform(-0.2, 0.2)
        if 10 < j <= 15:
            res += 5
        return res
    m = create_model('a0+a1*(x(t-1)**a2)')
    idn = identifier.Identifier(m)
    idn.init_data(x=[[2.82, 3.43, 3.617]],
                  a=[[1, 1, 1], [1, 1, 1], [1, 1, 1]],
                  u=[])
    lsm = alg_old.Adaptive(idn, m='lsm')
    n = 20
    a = np.zeros((n, 3))
    o_ar = np.zeros((n,))
    m_ar = np.zeros((n,))
    for i in range(n):
        obj_val = [obj(*idn.model.last_x, i)]
        new_a = lsm.update(obj_val, w=0.04, init_weight=0.04)
        idn.update_x(obj_val)
        idn.update_a(new_a)

        a[i] = new_a
        o_ar[i] = obj_val[0]
        m_ar[i] = idn.model.get_last_model_value()

    print(a)

    if plotting:
        real_a = [3, 0.1, 1.5]
        t = np.array([i for i in range(n)])
        draw(t, o_ar, m_ar, a, real_a)
Example #3
0
def lsm_linear_model(plotting=False):
    """Пример идентификации модели с чистым 
    запаздыванием с использованием алгоритма 
    на основе МНК."""
    def obj(x, u):
        return 10 + 0.1 * x + 5 * u + np.random.uniform(-1, 1)
    m = create_model('a_0+a1*x1(t-1)+a_2*u1(t-3)')
    idn = identifier.Identifier(m)
    idn.init_data(x=[[10, 12, 11.2]], a=[[1, 1, 1], [1, 1, 1], [1, 1, 1]], u=[[0, 0, 1, 0, 0]])
    lsm = alg_old.Adaptive(idn, m='lsm')
    n = 20
    a = np.zeros((n, 3))
    o_ar = np.zeros((n,))
    m_ar = np.zeros((n,))
    u_ar = [i + 1 for i in range(n)]
    for i in range(n):
        obj_val = [obj(*idn.model.last_x, *idn.model.get_var_values(t='u')[0])]
        new_a = lsm.update(obj_val, w=0.01, init_weight=0.01)
        idn.update_x(obj_val)
        idn.update_u([u_ar[i]])
        idn.update_a(new_a)

        a[i] = new_a
        o_ar[i] = obj_val[0]
        m_ar[i] = idn.model.get_last_model_value()

    print(a)

    if plotting:
        real_a = [10, 0.1, 5]
        t = np.array([i for i in range(n)])
        draw(t, o_ar, m_ar, a, real_a)
Example #4
0
def smp_linear_model(plotting=False):
    """Пример идентификации для простой модели с 
    импользованием простейшего адаптивного алгоритма."""
    # функция имитирующая объект
    def obj(x):
        return 5 + 0.5 * x + np.random.uniform(-1, 1)

    # создаем модель, имеет два неизвестных коэффициентов a0 и a1
    m = create_model('a0+a1*x(t-1)')

    # создаем идентификатор
    idn = identifier.Identifier(m)
    # проводим инициализацию начальных значений,
    # простейший адаптивный алгоритм не сольно чувствителен
    # к начальным данным, но если все входы/выходы
    # инициализировать нулями, то свободный коэффициент
    # (если есть) вычислиться точнее.
    # Закомментируйте следующую строку и раскомментируйте
    # строку за ней, посмотрите на результат.
    idn.init_data(x=[[0, 0]], a=[[1, 1], [1, 1]])
    # idn.init_data(x=[[0, 5]], a=[[1, 1], [1, 1]])

    # выбор простейшего адаптивного алгоритма
    smp = alg_old.Adaptive(idn, method='smp')

    n = 20  # количество тактов
    a = np.zeros((n, 2))
    o_ar = np.zeros((n, ))
    m_ar = np.zeros((n, ))
    # основной цикл, имитируем 20 тактов
    for i in range(n):
        # измерение выхода объекта
        obj_val = [obj(*idn.model.last_x)]
        # идентификация коэффициентов
        new_a = smp.update(obj_val)
        # обновление данных идентификатора
        idn.update_x(obj_val)
        idn.update_a(new_a)

        a[i] = new_a
        o_ar[i] = obj_val[0]
        m_ar[i] = idn.model.get_last_model_value()

    print(a)

    if plotting:
        t = np.array([i for i in range(n)])
        real_a = [5, .5]
        draw(t, o_ar, m_ar, a, real_a)
Example #5
0
def robust_lsm_linear_model(plotting=False):  # FIXME: проверить.
    """Пример идентификации модели объекта с 
    использованием робастного алгоритма на основе МНК.
    Выброс производится намеренно на 20 такте для 
    демонстрации работы алгоритма."""
    def obj(x, u):
        return 5 + 0.5 * x + 2 * u + np.random.uniform(-0.1, 0.1)
    m = create_model('a0+a1*x(t-1)+a2*u(t-1)')
    idn = identifier.Identifier(m)
    idn.init_data(x=[[0, 4.85, 9.26]],
                  a=[[1, 1, 1], [1, 1, 1], [1, 1, 1]],
                  u=[[0, 1, 1]])
    lsm = alg_old.AdaptiveRobust(idn, m='lsm')

    n = 30
    a = np.zeros((n, 3))
    o_ar = np.zeros((n,))
    m_ar = np.zeros((n,))
    u_ar = [i + 1 for i in range(n)]
    for i in range(n):
        if i == 0:
            obj_val = obj(*idn.model.last_x, *idn.model.last_u)
        else:
            obj_val = obj(o_ar[i-1], *idn.model.last_u)
        if i == 20:
            # имитация выброса, на состоянии объекта он не сказывается.
            # например ошибка чтения с датчика.
            o_ar[i] = obj_val
            obj_val = 10 * obj_val  # TODO: такое поведение из-за того, что выброс сохраняется в памяти
            print(obj_val)
        else:
            o_ar[i] = obj_val

        new_a = lsm.update([obj_val], w=0.01, init_weight=0.01, core='abs_pow', mu=0.5)
        idn.update_x([obj_val])
        idn.update_u([u_ar[i]])
        idn.update_a(new_a)

        a[i] = new_a
        m_ar[i] = idn.model.get_last_model_value()

    print(a)

    if plotting:
        real_a = [5, 0.5, 2]
        t = np.array([i for i in range(n)])
        draw(t, o_ar, m_ar, a, real_a)
Example #6
0
def example_3():
    """Пример использование библиотеки CotPy для адаптивного 
    управления на основе модели без идентификации.
    Модель с инерцией по управлению."""
    def obj(x, u1, u2):
        """Функция имитации объекта."""
        return x + u1 + u2

    def xt(j):
        """Функция генерации уставки."""
        if j < 10:
            return 10
        elif 10 <= j < 15:
            return 100
        elif 15 <= j <= 20:
            return 250
        else:
            return 50

    m = model.create_model("x(t-1)+u(t-1)+u(t-2)")
    m.initialization(x=[[0]], u=[[0, 0]])

    r = Regulator(m)
    r.synthesis()
    r.set_limit(-25, 40)

    n = 30
    u_ar = np.zeros((n, ))
    o_ar = np.zeros((n, ))
    xt_ar = np.zeros((n, ))

    for i in range(n):
        obj_val = [
            obj(*m.get_var_values(t='x')[0],
                *m.get_var_values(t='u')[0])
        ]
        new_u = r.update(obj_val, xt(i + 1))
        m.update_x(obj_val)
        m.update_u(new_u)
        u_ar[i] = new_u[0]
        o_ar[i] = obj_val[0]
        xt_ar[i] = xt(i)

    t = np.array([i for i in range(n)])

    draw_object_movement(t, o_ar, xt_ar, u_ar)
Example #7
0
def example_7():
    """Пример расчета коэффициентов модели по имеющимся 
    данным входов и выходов объекта. 
    Используется стандартный метод наименьших квадратов."""
    # исходные данные входов (u) и выходов (x) объекта
    u = [
        100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
        100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
        100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
        100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
        100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
        70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
        70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
        70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
        70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
        70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
        70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
        70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
        70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
        70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
        70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
        70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
        70, 70
    ]
    x = [
        27.4, 28.1, 30.0, 30.8, 31.1, 31.4, 31.6, 31.9, 32.1, 32.4, 32.8, 33.2,
        33.7, 34.3, 34.8, 35.4, 36.1, 36.8, 37.6, 38.3, 39.0, 39.8, 40.6, 41.4,
        42.1, 42.9, 43.7, 44.4, 45.2, 46.0, 46.7, 47.5, 48.3, 49.1, 49.8, 50.6,
        51.4, 52.3, 53.1, 53.9, 54.7, 55.5, 56.3, 57.2, 58.0, 58.9, 59.8, 60.7,
        61.6, 62.5, 63.4, 64.4, 65.3, 66.3, 67.2, 68.1, 68.9, 69.9, 70.8, 71.7,
        72.6, 73.6, 74.6, 75.8, 76.7, 77.7, 78.7, 79.6, 80.5, 81.4, 82.3, 83.2,
        84.0, 84.7, 85.4, 86.1, 86.6, 87.1, 87.5, 87.9, 88.3, 88.6, 88.8, 89.1,
        89.4, 89.6, 89.8, 89.9, 90.1, 90.3, 90.4, 90.5, 90.6, 90.8, 90.9, 91.0,
        91.1, 91.2, 91.3, 91.4, 91.4, 91.5, 91.6, 91.6, 91.7, 91.8, 91.8, 91.9,
        91.9, 91.9, 92.1, 92.1, 92.2, 92.3, 92.3, 92.4, 92.4, 92.5, 92.5, 92.6,
        92.6, 92.7, 92.7, 92.8, 92.8, 92.9, 92.9, 92.9, 92.9, 93.0, 93.1, 93.1,
        93.1, 93.1, 93.2, 93.2, 93.2, 93.2, 93.2, 93.3, 93.3, 93.3, 93.4, 93.4,
        93.4, 93.5, 93.6, 93.6, 93.6, 93.6, 93.6, 93.7, 93.7, 93.7, 93.8, 93.8,
        93.8, 93.9, 93.9, 94.0, 94.0, 94.1, 94.1, 94.2, 94.3, 94.3, 94.4, 94.4,
        94.4, 94.5, 94.6, 94.6, 94.6, 94.6, 94.7, 94.8, 94.8, 94.8, 94.9, 94.9,
        94.9, 95.0, 95.0, 95.1, 95.1, 95.1, 95.2, 95.3, 95.3, 95.3, 95.4, 95.4,
        95.4, 95.5, 95.5, 95.5, 95.6, 95.6, 95.6, 95.6, 95.6, 95.6, 95.7, 95.7,
        95.7, 95.7, 95.7, 95.6, 95.6, 95.6, 95.6, 95.7, 95.8, 95.8, 95.9, 95.9,
        96.0, 96.1, 96.1, 96.1, 96.2, 96.3, 96.3, 96.4, 96.4, 96.4, 96.4, 96.5,
        96.5, 96.6, 96.6, 96.6, 96.7, 96.7, 96.8, 96.8, 96.8, 96.8, 96.9, 96.9,
        96.9, 97.0, 97.0, 97.0, 97.0, 97.0, 97.0, 97.1, 97.1, 97.1, 97.2, 97.2,
        97.3, 97.3, 97.3, 97.3, 97.4, 97.4, 97.4, 97.5, 97.5, 97.5, 97.5, 97.6,
        97.6, 97.6, 97.6, 97.6, 97.7, 97.7
    ]

    # создаем модель
    expr = "a0+a1*x(t-1)+a2*x(t-2)+a3*u(t-1)+a4*u(t-2)"
    m = model.create_model(expr)
    idn = identifier.Identifier(m)
    print('Модель:', m.sp_expr)
    # подготавливаем идентификатор. В начале объект был выключен (управление равно 0) и имел температуру 27.4.
    idn.init_data(a=np.ones((5, 5)),
                  x=np.full((1, 6), x[0]),
                  u=np.zeros((1, 6)),
                  type_memory='min',
                  memory_size=0)
    # для вычисления коэффициентов используем стандартный МНК
    algorithm = alg_old.LSM(idn, m='lsm')

    print('Количество измерений:', len(u))
    new_a = algorithm.update(u, x)
    print('Коэффициенты:', new_a)
Example #8
0
def example_6(use_lsm=False, with_err=False):
    """
    Пример использования библиотеки CotPy для модели с дополнительными входами.
    :param use_lsm: Если уставновлен True используется адаптивный МНК, 
                    иначе простейший адаптивный алгоритм.
    :param with_err: Добавление аддитивной равномерно 
                     распределенной помехи амплитудой 0.1 к выходу объекта 
    :return: None
    """

    a = np.array([1.68, 1.235, -0.319, 0.04, 0.027, 0.1, 0.05])

    def obj(x1, x2, u1, u2, z1, z2):
        """Имитация объекта"""
        val = a[0] + a[1] * x1 + a[2] * x2 + a[3] * u1 + a[4] * u2 + a[
            5] * z1 + a[6] * z2
        if with_err:
            return val + np.random.uniform(-0.05, 0.05)
        else:
            return val

    def xt():
        """Уставка"""
        return 65

    # создание модели
    expr = "a0+a1*x(t-1)+a2*x(t-2)+a3*u(t-6)+a4*u(t-7)+a5*z1(t-1)+a6*z2(t-1)"
    m = model.create_model(expr)
    idn = identifier.Identifier(m)
    print('Модель:', m.sp_expr)

    # TODO: сделать для случая когда память меньше memory_size = 1
    if use_lsm:
        init_x = [[20, 20, 20.9885, 22.27, 23.39, 24.57, 25.51, 26.06]]
        init_u = [[10, 0, 10, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0]]
        init_z = np.array([[5.765, 5.24, 5.00, 5.77, 5.32, 5.90, 5.13],
                           [2.84, 2.54, 2.76, 2.51, 2.95, 2.52, 2.59]])
        method = 'lsm'
    else:
        init_x = np.full((1, 8), 20.)
        init_u = np.zeros((1, 13))
        init_z = np.array(
            [np.random.uniform(5, 6, 7),
             np.random.uniform(2, 2.5, 7)])
        method = 'smp'

    idn.init_data(a=np.ones((7, 7)),
                  x=init_x,
                  u=init_u,
                  z=init_z,
                  type_memory='min',
                  memory_size=5)
    algorithm = alg_old.Adaptive(idn, m=method)

    r = Regulator(m)
    r.set_limit(0, 100)
    r.synthesis()
    print('Закон управления:', r.expr)
    print('Аргументы:', r.expr_args)

    n = 240
    u_ar = np.zeros((n, ))
    o_ar = np.zeros((n, ))
    a_ar = np.zeros((n, 7))
    xt_ar = np.zeros((n, ))

    er = np.zeros((n, 7))

    for i in range(n):
        x = [
            obj(*np.hstack(idn.model.get_var_values(t='x')),
                *np.hstack(idn.model.get_var_values(t='u')),
                *np.hstack(idn.model.get_var_values(t='z')))
        ]
        if use_lsm:
            # В адаптивном МНК применяется метод последовательной линеаризации (МПЛ) и адаптивный вес
            new_a = algorithm.update(x,
                                     w=0.01,
                                     init_weight=0.01,
                                     uinc=True,
                                     adaptive_weight=False)
        else:
            # Используется простейший адаптивный с памятью
            new_a = algorithm.update(x,
                                     gamma=1,
                                     gt='a',
                                     weight=0.9,
                                     h=0.1,
                                     use_memory=True)

        idn.update_a(new_a)

        # Дополнительные входы являются случайными возмущениями (которые можно только измерять)
        # и, например, принимают случайные в определенных интервалах
        z = [np.random.uniform(5, 6), np.random.uniform(2.5, 3)]
        new_u = r.update(x, xt(), ainputs=z)

        u_ar[i] = new_u[0]
        o_ar[i] = x[0]
        a_ar[i] = new_a
        xt_ar[i] = xt()

        idn.update_x(x)
        idn.update_u(new_u)
        idn.update_z(z)

        er[i] = a - new_a

    print('Last coefficients:', idn.model.last_a)

    t = np.array([i for i in range(n)])
    # График движенияя объекта
    draw_object_movement(t, o_ar, xt_ar, u_ar)

    # График процесса идентификации
    fig, axs = plt.subplots(nrows=4, ncols=1)
    prop_cycle = plt.rcParams['axes.prop_cycle']
    colors = prop_cycle.by_key()['color']

    plot_coefficient(axs[0], t, a_ar[:, 0], a[0], '$t$', '$\\alpha_{0}$',
                     colors[0])

    n_ax = 1
    for i in range(1, len(a) - 1, 2):
        for k in range(2):
            axs[n_ax].plot(t,
                           a_ar[:, i + k],
                           label=f'$\\alpha_{{{str(i+k)}}}$',
                           linestyle='-',
                           color=colors[k + 1])
            axs[n_ax].plot(t, [a[i + k] for _ in range(n)],
                           linestyle='--',
                           color=colors[k + 1])
        axs[n_ax].set_xlabel('$t$')
        axs[n_ax].set_ylabel(
            f'$\\alpha_{{{str(i)}}},\\alpha_{{{str(i + 1)}}}$',
            rotation='horizontal',
            ha='right')
        axs[n_ax].grid(True)
        l = axs[n_ax].legend(labelspacing=0, borderpad=0.3)
        l.set_draggable(True)
        n_ax += 1

    plt.show()
Example #9
0
def example_5(with_err=False):
    """
    Пример использование библиотеки CotPy для адаптивного 
    управления на основе нелинейной модели с чистым 
    запаздыванием в 1 такт.
    :param with_err: Добавление аддитивной равномерно 
                     распределенной помехи амплитудой 0.2 к выходу объекта 
    :return: None
    """

    a = [1.3, 0.52]

    def obj(x, u):
        """Имитация объекта, описываемого нелинейной относительно входов/выходов моделью."""
        val = a[0] + a[1] * x * u
        if with_err:
            return val + np.random.uniform(-0.1, 0.1)
        return val

    def xt(j):
        """Уставка"""
        if j <= 75:
            return 75
        elif 75 < j <= 100:
            return 35
        elif 100 < j <= 120:
            return 25
        else:
            return 60

    expr = "a0+a1*x(t-1)*u(t-2)"
    m = model.create_model(expr)
    idn = identifier.Identifier(m)

    idn.init_data(a=np.ones((2, 2)), x=[[1.3, 1.3]], u=[[0, 0, 0]])
    # В данном случае простейший адаптивный алгоритм отлично справиться
    smp = alg_old.Adaptive(idn, m='smp')

    r = Regulator(m)
    r.set_limit(0, 100)
    r.synthesis()

    n = 240
    u_ar = np.zeros((n, ))
    o_ar = np.zeros((n, ))
    a_ar = np.zeros((n, len(a)))
    xt_ar = np.zeros((n, ))

    for i in range(n):
        x_val = [
            obj(*idn.model.get_var_values(t='x')[0],
                *idn.model.get_var_values(t='u')[0])
        ]

        new_a = smp.update(x_val,
                           gamma=1,
                           gt='a',
                           weight=0.9,
                           h=0.1,
                           deep_tuning=False,
                           aw=False)
        idn.update_a(new_a)

        new_u = r.update(x_val, xt(i + 1))

        u_ar[i] = new_u[0]
        o_ar[i] = x_val[0]
        a_ar[i] = new_a
        xt_ar[i] = xt(i)

        idn.update_x(x_val)
        idn.update_u(new_u)

    print('Last coefficients:', idn.model.last_a)

    t = np.array([i for i in range(n)])

    # График движенияя объекта
    draw_object_movement(t, o_ar, xt_ar, u_ar)

    # График процесса идентификации
    fig, axs = plt.subplots(nrows=2, ncols=1)
    prop_cycle = plt.rcParams['axes.prop_cycle']
    colors = prop_cycle.by_key()['color']

    plot_coefficient(axs[0], t, a_ar[:, 0], a[0], '$t$', '$\\alpha_{0}$',
                     colors[0])
    plot_coefficient(axs[1], t, a_ar[:, 1], a[1], '$t$', '$\\alpha_{1}$',
                     colors[0])
Example #10
0
def example_1(with_err=False):
    """
    Пример использования библиотеки CotPy 
    для синтеза закона адаптивного управления 
    с идентификацией. Используется модель с 
    чистым запаздыванием в 2 такта.
    :param with_err: если True добавляется аддитивная равномерно распределенная помеха 
                     амплитудой 0.2 к измерению выхода объекта
    :return: None
    """

    a = [-10, 0.3, 3]  # реальные коэффициенты

    def obj(x, u):
        """Функция имитации объекта."""
        val = a[0] + a[1] * x + a[2] * u
        if with_err:
            return val + np.random.uniform(-0.1, 0.1)
        else:
            return val

    def xt(j):
        """Функция генерации уставки."""
        if j < 10:
            return 100
        elif 10 <= j <= 15:
            return 150
        else:
            return 50

    # создание модели (с чистым запаздыванием)
    m = model.create_model('a_0+a1*x1(t-1)+a_2*u1(t-3)')

    # создание идентификатора и инициализация начальных значений
    idn = identifier.Identifier(m)
    idn.init_data(x=[[0, -11.33, -9.37]],
                  a=np.ones((3, 3)),
                  u=[[0, 2, 3, 4, 4]])

    # определение алгоритма идентификации
    smp = alg_old.Adaptive(idn, m='smp')

    n = 30
    # массивы для сохранения промежуточных значений
    u_ar = np.zeros((n, ))
    o_ar = np.zeros((n, ))
    a_ar = np.zeros((n, len(a)))
    xt_ar = np.zeros((n, ))

    # создание регулятора, установка ограничений на управление и синтез закона управления
    r = Regulator(m)
    r.set_limit(0, 100)
    r.synthesis()

    # основной цикл
    for i in range(n):
        # измерение выхода объекта
        obj_val = [
            obj(*idn.model.get_var_values(t='x')[0],
                *idn.model.get_var_values(t='u')[0])
        ]

        # Для идентификации используется простейший адаптивный алгоритм
        # с методом последовательной линеаризации (глубокая подстройка)
        new_a = smp.update(obj_val,
                           gamma=0.01,
                           gt='a',
                           weight=0.9,
                           h=0.1,
                           deep_tuning=True)
        idn.update_a(new_a)

        # расчет управляющего воздействия
        new_u = r.update(obj_val, xt(i + 3))

        # сохранение промежуточных результатов для построения графика
        u_ar[i] = new_u[0]
        o_ar[i] = obj_val[0]
        a_ar[i] = new_a
        xt_ar[i] = xt(i)

        # обновление состояния модели
        idn.update_x(obj_val)
        idn.update_u(new_u)

    t = [i for i in range(n)]
    draw_object_movement(t, o_ar, xt_ar, u_ar)

    # График процесса идентификации
    fig, axs = plt.subplots(nrows=3, ncols=1)
    prop_cycle = plt.rcParams['axes.prop_cycle']
    colors = prop_cycle.by_key()['color']

    for i in range(len(a)):
        plot_coefficient(axs[i], t, a_ar[:, i], a[i], '$t$',
                         f'$\\alpha_{{{str(i)}}}$', colors[i])

    plt.show()
Example #11
0
def example_4(use_lsm=False, with_err=False):
    """
    Пример использование библиотеки CotPy для адаптивного 
    управления на основе сложной линейной модели с чистым 
    запаздыванием в 5 тактов.
    Моделируется процесс нагрева и поддержания температуры жидкости.
    :param use_lsm: Использование адаптивного алгоритма МНК. 
                    Есле use_lsm=False используется простейшый адаптивный алгоритм.
    :param with_err: Добавление аддитивной равномерно распределенной помехи.
    :return: None
    """

    # реальные коэффициенты
    a = [1.68, 1.235, -0.319, 0.04, 0.027]

    def obj(x1, x2, u1, u2, j):
        """Имитация объекта"""
        val = a[0] + a[1] * x1 + a[2] * x2 + a[3] * u1 + a[4] * u2
        if with_err:
            return val + np.random.uniform(-0.1, 0.1)
            # return val + np.random.uniform(-0.15, 0.15)
            # return val + np.random.uniform(-0.2, 0.2)
            # return val + np.random.uniform(-1, 1)
            # return val + np.random.uniform(-1.5, 1.5)
            # return val + np.random.uniform(-5, 5)
            # return val + np.random.uniform(-0.5, 0.5)
            # return val - 0.1
            # return val - 0.3
            # return val - 0.5
            # return val + 5
            # return val + 0.1*np.sin(2*np.pi*j/240*100)
        else:
            return val

    def xt(j):
        """Уставка"""
        if j <= 50:
            return 80
        elif 50 < j <= 80:
            return 35
        elif 80 < j <= 100:
            return 25
        elif 100 < j <= 125:
            return 60
        elif 125 < j <= 150:
            return 70
        elif 150 < j <= 175:
            return 20
        elif 175 < j <= 200:
            return 90
        else:
            return 65

    # Создание модели и идентификатора
    expr = "a0+a1*x(t-1)+a2*x(t-2)+a3*u(t-6)+a4*u(t-7)"
    m = model.create_model(expr)
    idn = identifier.Identifier(m)
    print('Модель:', m.sp_expr)
    if m.get_index_fm() is not None:
        print(f'Индекс свободного члена: {m.get_index_fm()}')
    else:
        print('Нет свободного члена')

    # Инициализация начальных значений
    if use_lsm:
        # Для адаптивного алгоритма МНК необходимы "исторические" данные работы объекта.
        # Инициализация управления нулями (при выключенном объекте)
        # приведет к неработоспособности алгоритма.
        init_x = [[20, 20, 20.4, 20.764, 21.246, 21.528]]
        init_u = [[10., 0., 10., 0., 10., 0., 0., 0., 0., 0., 0.]]
        method = 'lsm'
    else:
        # Простейший адаптивный алгоритм не чувствителен к начальным данным.
        init_x = np.full((1, 7), 20.)  # 6
        init_u = np.zeros((1, 12))  # 11
        method = 'smp'

    idn.init_data(a=np.ones((5, 5)),
                  x=init_x,
                  u=init_u,
                  type_memory='min',
                  memory_size=6)  # 5  6
    algorithm = alg_old.Adaptive(idn, m=method)

    # Создание регулятора и синтез закона управления
    r = Regulator(m)
    r.set_limit(0, 100)
    r.synthesis()
    print('Закон управления:', r.expr)
    print('Аргументы:', r.expr_args)

    n = 240  # количество рабочих тактов
    u_ar = np.zeros((n, ))
    o_ar = np.zeros((n, ))
    a_ar = np.zeros((n, len(a)))
    xt_ar = np.zeros((n, ))
    a_er = np.zeros((n, len(a)))  # массив для сохранения ошибки идентификации

    for i in range(n):
        x = [
            obj(*idn.model.get_var_values(t='x')[0],
                *idn.model.get_var_values(t='u')[0], i)
        ]
        # Идентификация коэффициентов
        # Используется глубокая подстройка на основе приращений (deep_tuning=True),
        # а также адаптивный вес при подстройке свободного коэффициента (aw=True)
        if use_lsm:
            # Использование модели в приращениях uinc=True и
            # адаптивного веса при подстройке свободного коэффициента adaptive_weight=False
            new_a = algorithm.update(x,
                                     w=0.01,
                                     init_weight=0.01,
                                     uinc=True,
                                     adaptive_weight=False)
        else:
            # Использование глубокой подстройки (с использованием модели в приращениях) deep_tuning=True,
            # адаптивного веса aw=True,
            # использование памяти use_memory=True
            new_a = algorithm.update(x,
                                     gamma=1,
                                     gt='a',
                                     weight=0.9,
                                     h=0.1,
                                     deep_tuning=True,
                                     aw=False,
                                     use_memory=True)
            # new_a = idn.avr(new_a, avr_type='efi', l=0.98)
            # new_a = idn.avr(new_a, avr_type='std')

        idn.update_a(new_a)

        # Расчет управляющего воздействия ведется с учетом запаздывания в 5 тактов.
        new_u = r.update(x, xt(i + 6))

        u_ar[i] = new_u[0]
        o_ar[i] = x[0]
        a_ar[i] = new_a
        xt_ar[i] = xt(i)
        a_er[i] = np.array(a) - new_a

        idn.update_x(x)
        idn.update_u(new_u)

    print('Last coefficients:', idn.model.last_a)

    t = np.array([i for i in range(n)])

    # График движенияя объекта
    draw_object_movement(t, o_ar, xt_ar, u_ar)

    # График процесса идентификации
    fig, axs = plt.subplots(nrows=3, ncols=1)
    prop_cycle = plt.rcParams['axes.prop_cycle']
    colors = prop_cycle.by_key()['color']

    plot_coefficient(axs[0], t, a_ar[:, 0], a[0], '$t$', '$\\alpha_{0}$',
                     colors[0])

    n_ax = 1
    for i in range(1, 5, 2):
        for k in range(2):
            axs[n_ax].plot(t,
                           a_ar[:, i + k],
                           label=f'$\\alpha_{{{str(i+k)}}}$',
                           linestyle='-',
                           color=colors[k + 1])
            axs[n_ax].plot(t, [a[i + k] for _ in range(n)],
                           linestyle='--',
                           color=colors[k + 1])
        axs[n_ax].set_xlabel('$t$')
        axs[n_ax].set_ylabel(
            f'$\\alpha_{{{str(i)}}},\\alpha_{{{str(i + 1)}}}$',
            rotation='horizontal',
            ha='right')
        axs[n_ax].grid(True)
        l = axs[n_ax].legend(labelspacing=0, borderpad=0.3)
        l.set_draggable(True)
        n_ax += 1

    # График ошибки идентификации
    fig, axs = plt.subplots(nrows=1, ncols=1)
    if a_er is not None:
        for i in range(len(a_er[0])):
            axs.plot(t,
                     a_er[:, i],
                     label=f'$e_{{\\alpha_{i}}}$',
                     linestyle='-',
                     color=colors[i])
        axs.set_xlabel('$t$')
        axs.grid(True)
        axs.legend()

    plt.show()
Example #12
0
def example_2(with_err=False):
    """
    Пример использования библиотеки CotPy для синтеза 
    закона адаптивного управления. 
    Для идентификации используется стандартный алгоритм метода наименьших квадратов. 
    Модель простая с небольшой инерцией.
    :param with_err: если True добавляется аддитивная равномерно распределенная помеха 
                     амплитудой 0.4 к измерению выхода объекта
    :return: None
    """

    a = [-10, 0.3, 0.1, 3]

    def obj(x1, x2, u):
        """Функция имитации объекта."""
        val = a[0] + a[1] * x1 + a[2] * x2 + a[3] * u
        if with_err:
            return val + np.random.uniform(-0.2, 0.2)
        else:
            return val

    def xt(j):
        """Функция генерации уставки."""
        if j < 10:
            return 10
        elif 10 <= j < 15:
            return 100
        elif 15 <= j <= 20:
            return 250
        else:
            return 50

    expr = "a0+a1*x(t-1)+a2*x(t-2)+a3*u(t-1)"
    m = model.create_model(expr)
    idn = identifier.Identifier(m)

    # значения коэффициентов 'a' выставляем равными 1 (можно не
    # передавать вовсе, тогда по умолчанию инициализируется единицами)
    # либо другими предполагаемыми значениями.
    idn.init_data(x=[[0, 0, -10, -10, -11]], u=[[0, 1, 1, 1]])
    lsm = alg_old.Adaptive(idn, m='lsm')

    r = Regulator(m)
    r.set_limit(0, 255)
    r.synthesis()

    n = 30
    u_ar = np.zeros((n, ))
    o_ar = np.zeros((n, ))
    a_ar = np.zeros((n, len(a)))
    xt_ar = np.zeros((n, ))

    for i in range(n):
        x = [
            obj(*idn.model.get_var_values(t='x')[0],
                *idn.model.get_var_values(t='u')[0])
        ]

        new_a = lsm.update(x, w=0.01, init_weight=0.01)
        idn.update_a(new_a)

        new_u = r.update(x, xt(i + 1))

        u_ar[i] = new_u[0]
        o_ar[i] = x[0]
        a_ar[i] = new_a
        xt_ar[i] = xt(i)

        idn.update_x(x)
        idn.update_u(new_u)

    print('Last coefficients:', idn.model.last_a)

    t = np.array([i for i in range(n)])

    draw_object_movement(t, o_ar, xt_ar, u_ar)

    # График процесса идентификации
    fig, axs = plt.subplots(nrows=3, ncols=1)
    prop_cycle = plt.rcParams['axes.prop_cycle']
    colors = prop_cycle.by_key()['color']

    plot_coefficient(axs[0], t, a_ar[:, 0], a[0], '$t$', '$\\alpha_{0}$',
                     colors[0])

    for i in range(1, 3):
        axs[1].plot(t,
                    a_ar[:, i],
                    label=f'$\\alpha_{{{str(i)}}}$',
                    linestyle='-',
                    color=colors[i])
        axs[1].plot(t, [a[i] for _ in range(n)],
                    linestyle='--',
                    color=colors[i])
    axs[1].set_xlabel('$t$')
    axs[1].set_ylabel('$\\alpha_{1},\\alpha_{2}$',
                      rotation='horizontal',
                      ha='right')
    axs[1].grid(True)
    l = axs[1].legend(labelspacing=0, borderpad=0.3)
    l.set_draggable(True)

    plot_coefficient(axs[2], t, a_ar[:, 3], a[3], '$t$', '$\\alpha_{3}$',
                     colors[1])

    plt.show()