Community Engee

Модель САУ ЛА по лучу в среде Engee

作者
avatar-goltsevgoltsev
Notebook
In [ ]:
# подключение библиотек
import Pkg
Pkg.add("ControlSystems") ## библитека для анализа САУ
Pkg.add("Plots") ## библитека для построения графиков
using ControlSystems
using Plots
using LinearAlgebra # библиотека для операций с векторами и матрицами (используется в методе градиентного спуска)
# Ограничения верхнего уровня (для расчета оптимальных коэффициентов передаточной функции)
lu = fill(300.0, 3)
# Ограничения нижнего уровня (для расчета оптимальных коэффициентов передаточной функции)
lb = fill(0.3, 3)
# Начальная точка с которой начинаем итерации по методу градиентного спуска
x0 = [0.5, 0.5, 0.5]
   Resolving package versions...
  No Changes to `~/.project/Project.toml`
  No Changes to `~/.project/Manifest.toml`
   Resolving package versions...
  No Changes to `~/.project/Project.toml`
  No Changes to `~/.project/Manifest.toml`
Out[0]:
3-element Vector{Float64}:
 0.5
 0.5
 0.5

Зададим функцию которую будем минимизировать

In [ ]:
# Функция целей
function myfun(x::Vector{T}) where {T}
    return (150850000*x[1]) / (150850000*x[2] - 168000*x[1] + 67882500*x[3] + 49005000)
end
Out[0]:
myfun (generic function with 1 method)

Задам функцию содержащую ограничения для оптимизируемых коэффициентов

In [ ]:
# Функция ограничения неравенства
function mycon(x::Vector{T}) where {T}
    c1 = 2.15 - (150850000*x[1])^-1 * (150850000*x[2] - 168000*x[1] + 67882500*x[3] + 49005000) *
              (73687500*x[3] - 150000*x[1] - 168000*x[2] + 2009250) * inv(588909 - 150000*x[2])
    
    c2 = 2.15 - (150850000*x[2] - 168000*x[1] + 67882500*x[3] + 49005000)^-1 *
              (73687500*x[3] - 150000*x[1] - 168000*x[2] + 2009250) * (588909 - 150000*x[2]) * inv(9534)
    
    c3 = 2.15 - (73687500*x[3] - 150000*x[1] - 168000*x[2] + 2009250)^-1 *
              (588909 - 150000*x[2]) * 9534 * inv(75)
    
    return [c1, c2, c3]
end
Out[0]:
mycon (generic function with 1 method)

Задам функцию для расчета градиента исследуемой функции

In [ ]:
# Градиент функции цели (оцениваем численно)
function grad_f(x::Vector{T}, eps=1e-6)::Vector{T} where {T}
    n = length(x) # расчет длины вектора х
    gradient = zeros(T, n) # вектор для хранения значений градиента
    for i in 1:n
        dx = copy(x); dx[i] += eps # перебор значений х
        df = myfun(dx) - myfun(x) # расчет разности значений функции в ближайщих точках х
        gradient[i] = df / eps # расчет значений градиента
    end
    return gradient
end
Out[0]:
grad_f (generic function with 2 methods)

Функция содержащая метод градиентного спуска

In [ ]:
# Алгоритм градиентного спуска
function minimize_gradient_descent(f, x0, max_iter=100, learning_rate=0.1, tol=1e-8)
    x = x0 # начальное значение х
    current_val = f(x0) # начальное значение функции
    prev_val = Inf  # начальное значение критерия осанова
    iter_count = 0 ## начальное значение счетчика
    while true  ## бесконечный цикл
        current_val = f(x) # текущее значение функции
        
        if abs(current_val - prev_val) < tol || iter_count >= max_iter ## критерий остановки итераций
            break
        end
        
        g = grad_f(x)  # расчет градиента функции в точке
        step = -learning_rate .* g # расчет длины шага
        
        # Проверяем границы (ограничения)
        proposed_x = clamp.(x .+ step, lb, lu) # прверка того попадает ли новая точка в интервал 
        # между заданными ограничениями
        x .= proposed_x   # обновление значения х
        prev_val = current_val  # обновление значения функции
        iter_count += 1  # увеличение счетчика итераций
    end
    return x, current_val
end
Out[0]:
minimize_gradient_descent (generic function with 4 methods)

Вызов функции минимизации и отображение найденных значений

In [ ]:
# Запускаем процесс минимизации
x_optimal, fval = minimize_gradient_descent(myfun, x0)
println("Оптимизированный вектор х:", x_optimal)
println("Значение целевой функции:", fval)
Оптимизированный вектор х:[0.3, 1.5408350000878919, 0.9683759127849241]
Значение целевой функции:0.1303707770360182

Задаю значения коэффициентов которые найдены с помощью метода градиентного спуска.

In [ ]:
Kwz = x_optimal[1]
Kny = x_optimal[2]
Knyi = x_optimal[3]
Out[0]:
0.9683759127849241

Инициализация констант которые будут использоваться для расчета передаточной функции САУ

In [ ]:
c1 = 1.12;
c2 = 86;
c3 = 131;
c4 = 1;
c5 = 0;
c6 = 21.8;
c9 = 0.12;
g = 9.81;
a0 = c2+c1*c4;
a1 = (c1+c4+c5)
b1 = 50
b3 = 6
K = b3/b1
T = 1/b1
K1 = 1
K2 = 1
Out[0]:
1

Передаточная функция САУ

In [ ]:
a5 = 75
a4 = 9534
a3 = (588909 - 150000*Kny)
a2 = (73687500*Kwz - 150000*Knyi - 168000*Kny + 2009250)
a1 = (150850000*Kny - 168000*Knyi + 67882500*Kwz + 49005000)
a0 = 150850000*Knyi
W2 = tf([-150000*Knyi, -168000*Knyi, 150850000*Knyi],[a5, a4, a3, a2, a1, a0])
Out[0]:
TransferFunction{Continuous, ControlSystemsBase.SisoRational{Float64}}
                       -145256.38691773862s^2 - 162687.15334786725s + 1.460795064436058e8
-----------------------------------------------------------------------------------------------------------------
75.0s^5 + 9534.0s^4 + 357783.7499868162s^3 + 2.3711383333067495e7s^2 + 3.016420226099106e8s + 1.460795064436058e8

Continuous-time transfer function model
In [ ]:
y, t = step(W2,0:0.1:10) # расчет переходного процесса
t = collect(0:0.1:10)
plot(t,y',title="Переходный процесс") ## построение графика переходного процесса
Out[0]:
In [ ]:
y2, t = impulse(W2,0:0.1:10) # расчет точек импульсной характеристики
t = collect(0:0.1:10)
plot(t,y2',title="Импульсная характеристика")  # построение графика импульсной характеристики
Out[0]:
In [ ]:
bodeplot(W2) # построение графика частотной характеристики
Out[0]:
In [ ]:
nyquistplot(W2) # годограф найквиста
Out[0]:
In [ ]:
pzmap(W2)  # диаграмма нулей и полюсов
Out[0]:
In [ ]:
marginplot(W2)  # диаграмма запасов устойчивости
Out[0]:

Пересчитаю значение запаса устойчивости в логарифмический масштаб

In [ ]:
L = 20*log10(48)
print("Запас устойчивости: ")
print(L)
print(" Дб")
Запас устойчивости:33.624824747511745  Дб