Метрики качества управления¶
Модуль tensoraerospace.benchmark.function содержит 17 функций для расчёта показателей качества переходных процессов в системах автоматического управления. Метрики охватывают все классические аспекты анализа: временные характеристики, установившийся режим, затухание колебаний и интегральные критерии качества.
from tensoraerospace.benchmark.function import (
overshoot,
settling_time,
rise_time,
peak_time,
maximum_deviation,
static_error,
steady_state_value,
damping_degree,
oscillation_count,
integral_absolute_error,
integral_squared_error,
integral_time_absolute_error,
performance_index,
find_step_function,
get_lower_upper_bound,
find_longest_repeating_series,
)
Быстрый старт¶
Полный рабочий пример: создание ступенчатого отклика с PID-регулятором на модели Boeing 747, вычисление всех метрик.
import gymnasium as gym
import numpy as np
from tensoraerospace.agent.pid import PID
from tensoraerospace.utils import generate_time_period
from tensoraerospace.signals.standard import unit_step
from tensoraerospace.benchmark.function import (
find_step_function,
overshoot,
settling_time,
rise_time,
peak_time,
maximum_deviation,
static_error,
steady_state_value,
damping_degree,
oscillation_count,
integral_absolute_error,
integral_squared_error,
integral_time_absolute_error,
performance_index,
get_lower_upper_bound,
)
# --- Параметры моделирования ---
dt = 0.01
tn = 40 # секунд
tp = generate_time_period(tn=tn, dt=dt)
N = len(tp)
# Ступенчатый сигнал задания: 5 градусов, начало на 1 секунде
reference = unit_step(degree=5, tp=tp, time_step=1.0, output_rad=True).reshape(1, -1)
# Создание среды Boeing 747
env = gym.make(
"LinearLongitudinalB747-v0",
number_time_steps=N,
initial_state=[[0], [0], [0], [0]],
reference_signal=reference,
tracking_states=["theta"],
state_space=["u", "w", "q", "theta"],
control_space=["delta_e"],
output_space=["u", "w", "q", "theta"],
use_reward=False,
dt=dt,
)
# PID-регулятор
pid = PID(env, kp=-10.0, ki=-5.0, kd=-1.5, dt=dt)
# --- Симуляция ---
obs, info = env.reset()
control_log = []
output_log = []
for t in range(N - 1):
setpoint = reference[0, t]
measurement = float(obs[0])
u = pid.select_action(setpoint, measurement)
action = np.array([[float(u)]], dtype=np.float32)
obs, reward, terminated, truncated, info = env.step(action)
control_log.append(setpoint)
output_log.append(measurement)
if terminated or truncated:
break
control_signal = np.array(control_log)
system_signal = np.array(output_log)
# Выделение участка ступенчатого отклика
control_signal, system_signal = find_step_function(control_signal, system_signal)
# --- Расчёт всех метрик ---
print(f"Перерегулирование: {overshoot(control_signal, system_signal):.2f} %")
print(f"Время регулирования (5%): {settling_time(control_signal, system_signal, threshold=0.05)}")
print(f"Время нарастания (10%-90%): {rise_time(control_signal, system_signal)}")
print(f"Время достижения пика: {peak_time(system_signal)}")
print(f"Максимальное отклонение: {maximum_deviation(control_signal, system_signal):.6f}")
print(f"Статическая ошибка: {static_error(control_signal, system_signal):.6f}")
print(f"Установившееся значение (выход): {steady_state_value(system_signal):.6f}")
print(f"Степень затухания: {damping_degree(system_signal):.4f}")
print(f"Число колебаний: {oscillation_count(system_signal)}")
print(f"IAE: {integral_absolute_error(control_signal, system_signal):.4f}")
print(f"ISE: {integral_squared_error(control_signal, system_signal):.4f}")
print(f"ITAE: {integral_time_absolute_error(control_signal, system_signal, dt=dt):.4f}")
print(f"Комплексный индекс качества: {performance_index(control_signal, system_signal, dt=dt):.4f}")
Временные метрики¶
Характеризуют скорость и характер переходного процесса до достижения установившегося режима.
Перерегулирование (Overshoot)¶
Показывает, насколько максимум отклика системы превышает установившееся значение (в процентах).
Формула:
где:
- \(M = \max(y(t))\) --- максимальное значение выходного сигнала,
- \(y_{\text{уст}}\) --- установившееся значение (среднее последних 10% управляющего сигнала).
Интерпретация: чем меньше перерегулирование, тем плавнее переходный процесс. Значение \(\sigma = 0\) означает апериодический (без колебаний) отклик.
API:
| Параметр | Тип | Описание |
|---|---|---|
control_signal |
np.ndarray |
Управляющий (задающий) сигнал |
system_signal |
np.ndarray |
Выходной сигнал системы |
| Возврат | float |
Перерегулирование в процентах |
Пример:
from tensoraerospace.benchmark.function import overshoot
sigma = overshoot(control_signal, system_signal)
print(f"Перерегулирование: {sigma:.2f} %")
Время регулирования (Settling Time)¶
Время (в отсчётах), за которое выходной сигнал входит в коридор допустимого отклонения от установившегося значения и остаётся в нём.
Алгоритм:
- Вычисляется установившееся значение: \(y_{\text{уст}} = \text{mean}(r[\,0.9N\!:\!N\,])\).
- Определяются границы коридора: \(y_{\text{уст}} \cdot (1 \pm \varepsilon)\), где \(\varepsilon\) --- порог (по умолчанию 5%).
- Находятся все индексы, в которых сигнал лежит внутри коридора.
- Среди них выбирается начало самой длинной непрерывной серии --- это и есть время регулирования.
API:
def settling_time(
control_signal: np.ndarray,
system_signal: np.ndarray,
threshold: float = 0.05
) -> Optional[int]
| Параметр | Тип | Описание |
|---|---|---|
control_signal |
np.ndarray |
Управляющий сигнал |
system_signal |
np.ndarray |
Выходной сигнал системы |
threshold |
float |
Допустимое относительное отклонение (по умолчанию 0.05 = 5%) |
| Возврат | Optional[int] |
Индекс начала установившегося режима. Если система не вошла в коридор --- возвращается длина массива |
Пример:
from tensoraerospace.benchmark.function import settling_time
# Время регулирования с допуском ±5%
ts_5 = settling_time(control_signal, system_signal, threshold=0.05)
# Время регулирования с допуском ±2%
ts_2 = settling_time(control_signal, system_signal, threshold=0.02)
print(f"Время регулирования (5%): {ts_5} отсчётов")
print(f"Время регулирования (2%): {ts_2} отсчётов")
Время нарастания (Rise Time)¶
Время (в отсчётах), за которое выходной сигнал нарастает от нижнего порога до верхнего порога установившегося значения.
Формула:
где \(t_{0.1}\) --- момент первого достижения 10% от \(y_{\text{уст}}\), \(t_{0.9}\) --- момент первого достижения 90% от \(y_{\text{уст}}\).
API:
def rise_time(
control_signal: np.ndarray,
system_signal: np.ndarray,
low_threshold: float = 0.1,
high_threshold: float = 0.9,
) -> Optional[float]
| Параметр | Тип | Описание |
|---|---|---|
control_signal |
np.ndarray |
Управляющий сигнал |
system_signal |
np.ndarray |
Выходной сигнал системы |
low_threshold |
float |
Нижний порог (доля от \(y_{\text{уст}}\), по умолчанию 0.1) |
high_threshold |
float |
Верхний порог (доля от \(y_{\text{уст}}\), по умолчанию 0.9) |
| Возврат | Optional[float] |
Время нарастания в отсчётах. None --- если пороги не были достигнуты |
Пример:
from tensoraerospace.benchmark.function import rise_time
tr = rise_time(control_signal, system_signal)
print(f"Время нарастания (10%->90%): {tr} отсчётов")
# Пользовательские пороги: 20% -> 80%
tr_custom = rise_time(control_signal, system_signal, low_threshold=0.2, high_threshold=0.8)
print(f"Время нарастания (20%->80%): {tr_custom} отсчётов")
Время достижения пика (Peak Time)¶
Индекс (в отсчётах), при котором выходной сигнал достигает первого пика.
API:
| Параметр | Тип | Описание |
|---|---|---|
system_signal |
np.ndarray |
Выходной сигнал системы |
| Возврат | Optional[int] |
Индекс первого пика. Если пиков не обнаружено --- индекс максимального значения |
Алгоритм: использует scipy.signal.find_peaks для обнаружения пиков. При отсутствии пиков возвращается np.argmax(system_signal).
Пример:
from tensoraerospace.benchmark.function import peak_time
tp_idx = peak_time(system_signal)
print(f"Время достижения пика: индекс {tp_idx}, значение {system_signal[tp_idx]:.6f}")
Максимальное отклонение (Maximum Deviation)¶
Максимальное абсолютное отклонение выходного сигнала от установившегося значения задания.
Формула:
API:
| Параметр | Тип | Описание |
|---|---|---|
control_signal |
np.ndarray |
Управляющий сигнал |
system_signal |
np.ndarray |
Выходной сигнал системы |
| Возврат | float |
Максимальное абсолютное отклонение |
Пример:
from tensoraerospace.benchmark.function import maximum_deviation
delta_max = maximum_deviation(control_signal, system_signal)
print(f"Максимальное отклонение: {delta_max:.6f}")
Установившиеся метрики¶
Характеризуют точность системы в установившемся режиме --- после завершения переходного процесса.
Статическая ошибка (Static Error)¶
Разница между целевым значением задания и фактическим выходом системы в установившемся состоянии.
Формула:
где:
- \(r_{\text{уст}} = \text{mean}(r[\,0.9N\!:\!N\,])\) --- среднее последних 10% управляющего сигнала,
- \(y_{\text{уст}} = \text{mean}(y[\,0.9N\!:\!N\,])\) --- среднее последних 10% выходного сигнала.
Интерпретация: значение, близкое к нулю, указывает на высокую статическую точность системы.
API:
| Параметр | Тип | Описание |
|---|---|---|
control_signal |
np.ndarray |
Управляющий сигнал |
system_signal |
np.ndarray |
Выходной сигнал системы |
| Возврат | float |
Статическая ошибка |
Пример:
from tensoraerospace.benchmark.function import static_error
e_ss = static_error(control_signal, system_signal)
print(f"Статическая ошибка: {e_ss:.6f}")
Установившееся значение (Steady-State Value)¶
Оценка установившегося значения сигнала по среднему последних \(p\%\) отсчётов.
Формула:
где \(T_{\text{tail}}\) --- множество индексов, соответствующих последним percentage * 100 % отсчётов (по умолчанию 10%).
API:
| Параметр | Тип | Описание |
|---|---|---|
control_signal |
np.ndarray |
Сигнал, для которого оценивается установившееся значение |
percentage |
float |
Доля хвоста сигнала, используемая для усреднения (по умолчанию 0.1 = 10%) |
| Возврат | float |
Оценка установившегося значения |
Пример:
from tensoraerospace.benchmark.function import steady_state_value
# Установившееся значение выходного сигнала (по последним 10%)
y_ss = steady_state_value(system_signal)
# По последним 20% для более стабильной оценки
y_ss_20 = steady_state_value(system_signal, percentage=0.2)
print(f"Установившееся значение: {y_ss:.6f}")
Затухание и колебания¶
Метрики, характеризующие колебательный процесс и степень его затухания.
Степень затухания (Damping Degree)¶
Оценивает относительное уменьшение амплитуды между последовательными пиками колебаний.
Формула:
где \(A_n\) --- амплитуда \(n\)-го пика, \(A_{n-1}\) --- амплитуда предыдущего. Итоговое значение --- среднее по всем парам соседних пиков.
Интерпретация:
- \(D \to 1\) --- быстрое затухание, система хорошо демпфирована.
- \(D \to 0\) --- слабое затухание, колебания медленно убывают.
- \(D < 0\) --- колебания нарастают (неустойчивая система!).
API:
| Параметр | Тип | Описание |
|---|---|---|
system_signal |
np.ndarray |
Выходной сигнал системы |
| Возврат | float |
Средняя степень затухания. Возвращает 0.0, если менее двух пиков |
Пример:
from tensoraerospace.benchmark.function import damping_degree
d = damping_degree(system_signal)
print(f"Степень затухания: {d:.4f}")
Число колебаний (Oscillation Count)¶
Оценивает количество полных колебательных циклов (пар «пик -- впадина») в переходном процессе.
Алгоритм:
- Обнаруживает пики сигнала (
find_peaks(y, height=threshold)). - Обнаруживает впадины (
find_peaks(-y, height=threshold)). - Суммарное число экстремумов делится на 2 --- получается число полных колебаний.
API:
| Параметр | Тип | Описание |
|---|---|---|
system_signal |
np.ndarray |
Выходной сигнал системы |
threshold |
float |
Минимальная амплитуда пика для учёта (по умолчанию 0.01) |
| Возврат | int |
Число полных колебаний |
Пример:
from tensoraerospace.benchmark.function import oscillation_count
n_osc = oscillation_count(system_signal)
print(f"Число колебаний: {n_osc}")
# Учитывать только крупные колебания
n_osc_large = oscillation_count(system_signal, threshold=0.1)
print(f"Число крупных колебаний: {n_osc_large}")
Интегральные критерии качества¶
Интегральные критерии оценивают накопленную ошибку за весь переходный процесс. Они чувствительны к форме и продолжительности ошибки и широко применяются при оптимизации регуляторов.
IAE --- интегральная абсолютная ошибка (Integral Absolute Error)¶
Суммарная абсолютная ошибка за всё время моделирования.
Формула:
Свойства:
- Одинаково штрафует любые ошибки вне зависимости от их знака.
- Менее чувствителен к большим кратковременным выбросам, чем ISE.
API:
| Параметр | Тип | Описание |
|---|---|---|
control_signal |
np.ndarray |
Управляющий (задающий) сигнал |
system_signal |
np.ndarray |
Выходной сигнал системы |
| Возврат | float |
Значение IAE |
Пример:
from tensoraerospace.benchmark.function import integral_absolute_error
iae = integral_absolute_error(control_signal, system_signal)
print(f"IAE: {iae:.4f}")
ISE --- интегральная квадратичная ошибка (Integral Squared Error)¶
Суммарная квадратичная ошибка за всё время моделирования.
Формула:
Свойства:
- Сильно штрафует большие ошибки (квадратичная зависимость).
- Предпочитает системы с малым перерегулированием, даже если затухание медленное.
- Широко используется как целевая функция при оптимизации параметров регуляторов.
API:
| Параметр | Тип | Описание |
|---|---|---|
control_signal |
np.ndarray |
Управляющий сигнал |
system_signal |
np.ndarray |
Выходной сигнал системы |
| Возврат | float |
Значение ISE |
Пример:
from tensoraerospace.benchmark.function import integral_squared_error
ise = integral_squared_error(control_signal, system_signal)
print(f"ISE: {ise:.4f}")
ITAE --- интегральная времявзвешенная абсолютная ошибка (Integral Time Absolute Error)¶
Абсолютная ошибка, взвешенная по времени: ошибки на поздних этапах переходного процесса наказываются сильнее.
Формула:
Свойства:
- Штрафует затянувшиеся переходные процессы.
- Нечувствителен к начальным большим ошибкам (когда \(t\) мало).
- Считается лучшим критерием для настройки регуляторов, обеспечивающих быстрое затухание.
API:
def integral_time_absolute_error(
control_signal: np.ndarray,
system_signal: np.ndarray,
dt: float = 1.0
) -> float
| Параметр | Тип | Описание |
|---|---|---|
control_signal |
np.ndarray |
Управляющий сигнал |
system_signal |
np.ndarray |
Выходной сигнал системы |
dt |
float |
Шаг дискретизации по времени (по умолчанию 1.0) |
| Возврат | float |
Значение ITAE |
Пример:
from tensoraerospace.benchmark.function import integral_time_absolute_error
itae = integral_time_absolute_error(control_signal, system_signal, dt=0.01)
print(f"ITAE: {itae:.4f}")
Комплексный индекс качества (Performance Index)¶
Составной показатель качества переходного процесса, объединяющий несколько критериев с фиксированными весами. Чем меньше --- тем лучше.
Формула:
где \(\sigma\) --- перерегулирование (в процентах).
Свойства:
- Позволяет одним числом сравнить качество различных регуляторов.
- Веса можно адаптировать в зависимости от задачи (в текущей реализации фиксированы).
API:
def performance_index(
control_signal: np.ndarray,
system_signal: np.ndarray,
dt: float = 1.0
) -> float
| Параметр | Тип | Описание |
|---|---|---|
control_signal |
np.ndarray |
Управляющий сигнал |
system_signal |
np.ndarray |
Выходной сигнал системы |
dt |
float |
Шаг дискретизации по времени (по умолчанию 1.0) |
| Возврат | float |
Значение комплексного индекса (меньше = лучше) |
Пример:
from tensoraerospace.benchmark.function import performance_index
J = performance_index(control_signal, system_signal, dt=0.01)
print(f"Комплексный индекс качества: {J:.4f}")
Вспомогательные функции¶
Служебные функции, используемые другими метриками или полезные при подготовке данных.
find_step_function¶
Выделяет участок ступенчатого отклика из записанных сигналов. Обрезает начальную часть, в которой управляющий сигнал равен нулю (или заданному значению signal_val), и возвращает только участок от момента появления ступеньки.
API:
def find_step_function(
control_signal: np.ndarray,
system_signal: np.ndarray,
signal_val: float = 0
) -> Tuple[np.ndarray, np.ndarray]
| Параметр | Тип | Описание |
|---|---|---|
control_signal |
np.ndarray |
Управляющий сигнал |
system_signal |
np.ndarray |
Выходной сигнал системы |
signal_val |
float |
Пороговое значение, от которого начинается ступенька (по умолчанию 0) |
| Возврат | Tuple[np.ndarray, np.ndarray] |
Обрезанные массивы (control_signal, system_signal) |
Raises: ValueError --- если длины входных массивов не совпадают.
Пример:
from tensoraerospace.benchmark.function import find_step_function
# Обрезать начальный участок до ступенчатого воздействия
ctrl, sys = find_step_function(control_signal, system_signal)
# С пользовательским порогом
ctrl, sys = find_step_function(control_signal, system_signal, signal_val=0.01)
get_lower_upper_bound¶
Возвращает массивы нижней и верхней границ коридора допуска вокруг конечного значения управляющего сигнала. Полезно для визуализации зоны допуска при анализе времени регулирования.
Формула:
где \(r_{\text{final}}\) --- последнее значение управляющего сигнала.
API:
def get_lower_upper_bound(
control_signal: np.ndarray,
epsilon: float = 0.05
) -> Tuple[np.ndarray, np.ndarray]
| Параметр | Тип | Описание |
|---|---|---|
control_signal |
np.ndarray |
Управляющий сигнал |
epsilon |
float |
Относительная величина допуска (по умолчанию 0.05 = 5%) |
| Возврат | Tuple[np.ndarray, np.ndarray] |
(lower, upper) --- массивы той же формы, что и control_signal |
Пример:
from tensoraerospace.benchmark.function import get_lower_upper_bound
lower, upper = get_lower_upper_bound(control_signal, epsilon=0.05)
# Использование для визуализации
import matplotlib.pyplot as plt
t = np.arange(len(control_signal))
plt.fill_between(t, lower, upper, alpha=0.2, color="green", label="Коридор ±5%")
plt.plot(t, system_signal, label="Выход системы")
plt.plot(t, control_signal, "--", label="Задание")
plt.legend()
plt.show()
find_longest_repeating_series¶
Находит самую длинную серию последовательных целых чисел в массиве. Используется внутри settling_time для определения начала устойчивого нахождения сигнала в коридоре допуска.
API:
| Параметр | Тип | Описание |
|---|---|---|
numbers |
list |
Список целых чисел |
| Возврат | tuple |
Кортеж (start, end) --- начало и конец самой длинной непрерывной серии. Для пустого списка (0, 0) |
Пример:
from tensoraerospace.benchmark.function import find_longest_repeating_series
# Индексы, в которых сигнал был в коридоре
indices = [2, 3, 4, 10, 11, 12, 13, 14, 20]
start, end = find_longest_repeating_series(indices)
print(f"Самая длинная серия: от {start} до {end}, длина = {end - start + 1}")
# Вывод: Самая длинная серия: от 10 до 14, длина = 5
Пример визуализации¶
Полный пример: моделирование ступенчатого отклика, расчёт метрик и построение аннотированного графика.
import gymnasium as gym
import numpy as np
import matplotlib.pyplot as plt
from tensoraerospace.agent.pid import PID
from tensoraerospace.utils import generate_time_period
from tensoraerospace.signals.standard import unit_step
from tensoraerospace.benchmark.function import (
find_step_function,
overshoot,
settling_time,
rise_time,
peak_time,
maximum_deviation,
static_error,
steady_state_value,
get_lower_upper_bound,
)
# --- 1. Моделирование ---
dt = 0.01
tn = 40
tp = generate_time_period(tn=tn, dt=dt)
N = len(tp)
reference = unit_step(degree=5, tp=tp, time_step=1.0, output_rad=True).reshape(1, -1)
env = gym.make(
"LinearLongitudinalB747-v0",
number_time_steps=N,
initial_state=[[0], [0], [0], [0]],
reference_signal=reference,
tracking_states=["theta"],
state_space=["u", "w", "q", "theta"],
control_space=["delta_e"],
output_space=["u", "w", "q", "theta"],
use_reward=False,
dt=dt,
)
pid = PID(env, kp=-10.0, ki=-5.0, kd=-1.5, dt=dt)
obs, info = env.reset()
control_log, output_log = [], []
for t in range(N - 1):
setpoint = reference[0, t]
measurement = float(obs[0])
u = pid.select_action(setpoint, measurement)
obs, reward, terminated, truncated, info = env.step(
np.array([[float(u)]], dtype=np.float32)
)
control_log.append(setpoint)
output_log.append(measurement)
if terminated or truncated:
break
ctrl = np.array(control_log)
sys_out = np.array(output_log)
# Выделение ступенчатого отклика
ctrl, sys_out = find_step_function(ctrl, sys_out)
# --- 2. Расчёт метрик ---
sigma = overshoot(ctrl, sys_out)
ts = settling_time(ctrl, sys_out, threshold=0.05)
tr = rise_time(ctrl, sys_out)
tp_idx = peak_time(sys_out)
e_ss = static_error(ctrl, sys_out)
y_ss = steady_state_value(sys_out)
lower, upper = get_lower_upper_bound(ctrl, epsilon=0.05)
# --- 3. Построение графика ---
time_axis = np.arange(len(ctrl)) * dt
fig, ax = plt.subplots(figsize=(14, 7))
# Сигналы
ax.plot(time_axis, ctrl, "k--", linewidth=1.5, label="Задание $r(t)$")
ax.plot(time_axis, sys_out, "b-", linewidth=1.5, label="Выход $y(t)$")
# Коридор допуска ±5%
ax.fill_between(time_axis, lower, upper, alpha=0.15, color="green", label="Коридор ±5%")
# Установившееся значение
ax.axhline(y=y_ss, color="gray", linestyle=":", linewidth=1, label=f"$y_{{уст}}$ = {y_ss:.4f}")
# Статическая ошибка
r_final = np.mean(ctrl[int(0.9 * len(ctrl)):])
ax.annotate(
f"$e_{{уст}}$ = {e_ss:.4f}",
xy=(time_axis[-1], y_ss),
xytext=(time_axis[-1] * 0.85, (y_ss + r_final) / 2),
fontsize=10, color="red",
arrowprops=dict(arrowstyle="->", color="red"),
)
# Пик и перерегулирование
if tp_idx is not None and tp_idx < len(time_axis):
ax.plot(time_axis[tp_idx], sys_out[tp_idx], "rv", markersize=10)
ax.annotate(
f"Пик: {sys_out[tp_idx]:.4f}\n$\\sigma$ = {sigma:.1f}%",
xy=(time_axis[tp_idx], sys_out[tp_idx]),
xytext=(time_axis[tp_idx] + 0.5, sys_out[tp_idx] + 0.002),
fontsize=9,
arrowprops=dict(arrowstyle="->", color="red"),
)
# Время регулирования
if ts is not None and ts < len(time_axis):
ax.axvline(x=time_axis[ts], color="orange", linestyle="--", linewidth=1,
label=f"Время регулирования = {time_axis[ts]:.2f} с")
# Время нарастания
if tr is not None:
y_final_est = np.mean(ctrl[int(0.9 * len(ctrl)):])
low_val = y_final_est * 0.1
high_val = y_final_est * 0.9
low_indices = np.where(sys_out >= low_val)[0]
high_indices = np.where(sys_out >= high_val)[0]
if len(low_indices) > 0 and len(high_indices) > 0:
t_low = time_axis[low_indices[0]]
t_high = time_axis[high_indices[0]]
ax.axvspan(t_low, t_high, alpha=0.1, color="purple", label=f"Время нарастания = {tr} отсч.")
ax.set_xlabel("Время, с", fontsize=12)
ax.set_ylabel("Амплитуда", fontsize=12)
ax.set_title("Ступенчатый отклик с аннотациями метрик качества", fontsize=14)
ax.legend(loc="lower right", fontsize=9)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
Таблица интерпретации метрик¶
Ориентировочные значения для оценки качества переходного процесса. Конкретные нормативы зависят от задачи и требований к системе управления.
| Метрика | Обозначение | Хорошо | Удовлетворительно | Плохо | Единицы |
|---|---|---|---|---|---|
| Перерегулирование | \(\sigma\) | < 5% | 5--20% | > 20% | % |
| Время регулирования (5%) | \(t_s\) | Малое (быстрый отклик) | Среднее | Большое (медленная стабилизация) | отсчёты / с |
| Время нарастания | \(t_r\) | Малое | Среднее | Большое | отсчёты / с |
| Время пика | \(t_p\) | Малое | --- | Большое | отсчёты / с |
| Максимальное отклонение | \(\Delta_{\max}\) | Близко к 0 | Умеренное | Большое | ед. сигнала |
| Статическая ошибка | \(e_{\text{уст}}\) | \(\approx 0\) | < 2% от \(r\) | > 5% от \(r\) | ед. сигнала |
| Установившееся значение | \(y_{\text{уст}}\) | \(\approx r_{\text{уст}}\) | --- | Значительно отличается | ед. сигнала |
| Степень затухания | \(D\) | \(\to 1\) | 0.3--0.7 | < 0.3 или < 0 | безразм. |
| Число колебаний | \(N_{\text{osc}}\) | 0--2 | 3--5 | > 5 | шт. |
| IAE | IAE | Малое | Среднее | Большое | ед. сигнала |
| ISE | ISE | Малое | Среднее | Большое | (ед. сигнала)\(^2\) |
| ITAE | ITAE | Малое | Среднее | Большое | ед. сигнала \(\cdot\) с |
| Комплексный индекс | \(J\) | Минимальный | --- | Большой | безразм. |
Рекомендации по выбору критерия¶
- IAE --- универсальный критерий, подходит для большинства задач. Даёт сбалансированную настройку.
- ISE --- если критичны большие отклонения. Обеспечивает малое перерегулирование, но может давать медленный отклик.
- ITAE --- если важно быстрое затухание колебаний. Наказывает «хвосты» переходного процесса.
- Performance Index (\(J\)) --- комплексная оценка для сравнения нескольких алгоритмов на одной задаче.
Типичные компромиссы¶
| Требование | Что улучшается | Что ухудшается |
|---|---|---|
| Уменьшить перерегулирование | Плавность отклика, \(\sigma \downarrow\) | Время регулирования \(t_s \uparrow\) |
| Уменьшить время регулирования | Быстрота \(t_s \downarrow\) | Перерегулирование \(\sigma \uparrow\), число колебаний \(\uparrow\) |
| Уменьшить статическую ошибку | Точность \(e_{\text{уст}} \to 0\) | Увеличение интегральной составляющей может привести к колебаниям |
| Увеличить степень затухания | Устойчивость, \(D \uparrow\) | Медленный отклик, большое \(t_s\) |