Сравнение PD и PID-регуляторов с антивиндапом
Сравнение PD и PID-регуляторов с антивиндапом в задаче управления дистанцией в колонне.
Управление движением колонн является одной из ключевых задач в области интеллектуальных транспортных систем. Основная цель – обеспечить синхронное движение группы транспортных средств с заданной дистанцией между соседними автомобилями, минимизируя рывки, исключая обгоны внутри колонны и гарантируя безопасность. Для достижения этой цели каждый ведомый автомобиль оснащается регулятором, который на основе информации о положении и скорости впереди идущего транспортного средства вычисляет требуемое ускорение. Однако реальные условия – ограничения по ускорению и скорости, задержки в каналах связи, шумы измерений – существенно усложняют задачу. В данной работе представлены две модели системы управления колонной, реализованные в среде имитационного моделирования Engee: базовая модель на основе классического ПД-регулятора и улучшенная модель, использующая ПИД-регулятор. В этом примере проводится сравнительный анализ их эффективности по таким критериям, как точность поддержания дистанции, наличие обгона и устойчивость к возмущениям.
Простая модель (PD‑регулятор)
В базовой версии используется классический ПД-регулятор:
,
где ( ) – ошибка дистанции,
( D ) – заданная дистанция,
( ) – ошибка скорости.
Данная модель демонстрирует вариант параллельного построения, при котором ведомые стремятся занять заданные позиции относительно лидера. В процессе симуляции наблюдается, что пары «Ведомый‑1 и Ведомый‑3», а также «Ведомый‑2 и Ведомый‑4» выстраиваются синхронно — каждая пара оказывается на одинаковом удалении от лидера. Благодаря различным начальным позициям можно наглядно увидеть, как ведомые по‑разному разгоняются, чтобы достичь требуемой дистанции.
Однако в текущей реализации присутствуют следующие ограничения:
-
При наличии постоянных внешних возмущений (например, уклона дороги или бокового ветра) в системе возникает установившаяся ошибка по дистанции – ведомые не могут точно поддерживать заданное расстояние.
-
Зона нечувствительности обрезает малые сигналы управления. В сочетании с отсутствием интегральной составляющей в регуляторе это приводит к долговременному дрейфу позиции, а в итоге – к обгону ведомыми лидера. Таким образом, чисто ПД‑регулятор не обеспечивает устойчивого сопровождения дистанции на длительных интервалах времени.
Структура ведомого включает вычисление ошибок, усиление сигналов, сумматор, блок ограничения ускорения и двойной интегратор (скорость → позиция).

Все ведомые имеют идентичную архитектуру и подключены параллельно: информация от лидера поступает непосредственно на каждый ведомый, что приводит к формированию пар «Ведомый‑1 и Ведомый‑3», «Ведомый‑2 и Ведомый‑4», движущихся синхронно.

function run_model(name)
p, is_loaded = joinpath(@__DIR__, name * ".engee"), name ∉ [m.name for m in engee.get_all_models()]
is_loaded && engee.load(p, force=true)
out = engee.run(engee.open(name), verbose=true)
is_loaded && engee.close(name, force=true)
sleep(0.1); return out
end
initial_positions = [-10.0, -20.0, -30.0, -40.0] # Начальные позиции ведомых относительно лидера
accel_limit_lower = -3.0 # мин. ускорение, м/с²
accel_limit_upper = 3.0 # макс. ускорение, м/с²
speed_limit_lower = 0.0 # мин. скорость, м/с
speed_limit_upper = 15.0 # макс. скорость, м/с
# Параметры ПД-регулятора
D = 10.0 # заданная дистанция, м
Kp = 0.5 # пропорциональный коэффициент
Kd = 2.0 # дифференциальный коэффициент
run_model("Platooning_Basic")
# Извлечение данных с прореживанием
function get_signal(simout, key, step=1)
t = collect(simout[key]).time
val = collect(simout[key]).value
return t[1:step:end], val[1:step:end]
end
t_lx, x_l = get_signal(simout, "Platooning_Basic/Лидер.X_0", 5)
t_lv, v_l = get_signal(simout, "Platooning_Basic/Лидер.V_0", 5)
t1x, x1 = get_signal(simout, "Platooning_Basic/Ведомый-1.x", 5)
t1v, v1 = get_signal(simout, "Platooning_Basic/Ведомый-1.v", 5)
t2x, x2 = get_signal(simout, "Platooning_Basic/Ведомый-2.x", 5)
t2v, v2 = get_signal(simout, "Platooning_Basic/Ведомый-2.v", 5)
t3x, x3 = get_signal(simout, "Platooning_Basic/Ведомый-3.x", 5)
t3v, v3 = get_signal(simout, "Platooning_Basic/Ведомый-3.v", 5)
t4x, x4 = get_signal(simout, "Platooning_Basic/Ведомый-4.x", 5)
t4v, v4 = get_signal(simout, "Platooning_Basic/Ведомый-4.v", 5)
# График скоростей
plot(title="Скорости", xlabel="Время (с)", ylabel="Скорость (м/с)")
plot!(t_lv, v_l, label="Лидер")
plot!(t1v, v1, label="Ведомый-1")
plot!(t2v, v2, label="Ведомый-2")
plot!(t3v, v3, label="Ведомый-3")
display(plot!(t4v, v4, label="Ведомый-4"))
# График позиций
plot(title="Позиции", xlabel="Время (с)", ylabel="Позиция (м)")
plot!(t_lx, x_l, label="Лидер")
plot!(t1x, x1, label="Ведомый-1")
plot!(t2x, x2, label="Ведомый-2")
plot!(t3x, x3, label="Ведомый-3")
plot!(t4x, x4, label="Ведомый-4")
Как мы видим ведомые опережают друг друга, чего быть не должно.
Улучшенная модель (ПИД‑регулятор с anti‑windup)
Для устранения указанных проблем была разработана усложнённая версия, в которой реализован ПИД-регулятор с дополнительными механизмами:
Внесённые улучшения:
- Добавлен интегральный канал – обеспечивает нулевую установившуюся ошибку при постоянных возмущениях.
- Ограничение интегратора (anti‑windup) – выход интегратора ошибки насыщается в пределах ([-0.3; 0.3]), что предотвращает его неограниченное накопление при длительном нахождении сигнала управления в зоне нечувствительности или в насыщении по ускорению/скорости. Anti-windup (анти-виндаун) — это набор методов и техник, направленных на предотвращение или смягчение эффекта «виндауна» (windup) в системах управления, особенно в PID-контроллерах, когда управляющий сигнал превышает возможности актуатора (например, достигает предела мощности или скорости). Этот эффект может привести к накоплению ошибок, нестабильности системы и ухудшению её производительности.
.png)
- Используется ограничение ускорения.
- Перенастройка коэффициентов – для улучшения переходных процессов увеличен дифференциальный коэффициент (K_d = 2.0), а для замедления накопления интеграла выбран относительно небольшой интегральный коэффициент (K_i = 0.05). Пропорциональный коэффициент оставлен прежним (K_p = 0.5).
.png)
В статье демонстрируется эволюция модели: от простого ПД-регулятора к полноценному ПИД-регулятору с защитой от виндапа. Показано, что именно добавление интегральной составляющей и механизма anti‑windup позволяет полностью устранить эффект обгона лидера, при должной настройке можно ликвидировать обгон впереди идущего, обеспечить устойчивое удержание дистанции и реалистичное поведение колонны на длительных интервалах моделирования.
Результаты работы могут быть полезны при проектировании систем адаптивного круиз-контроля (ACC) и управления беспилотными колоннами.
.png)
leader_speed_max = 10.0 # макс. скорость лидера, м/с
leader_accel_max = 3.0 # ускорение лидера, м/с²
D = 10.0 # заданная дистанция, м
Kp, Kd, Ki = 0.5, 2.0, 0.05 # коэффициенты ПИД-регулятора
accel_limit_lower, accel_limit_upper = -2.0, 2.0 # предел ускорения, м/с²
speed_limit_lower, speed_limit_upper = 0.0, 15.0 # предел скорости, м/с
int_err_lower, int_err_upper = -0.3, 0.3 # анти-виндап интегратора
# Шумы измерений
noise_mean = 0.0
noise_variance_position = 0.01
noise_variance_speed = 5
noise_sample_time = 0.01
delay_time = 0.3 # транспортная задержка, с
initial_positions = [-20.0, -40.0, -60.0] # Начальные позиции ведомых (от лидера)
run_model("Platooning_AntiWindup")
t_lx, x_l = get_signal(simout, "Platooning_AntiWindup/Лидер.X_0")
t_lv, v_l = get_signal(simout, "Platooning_AntiWindup/Лидер.V_0")
t1x, x1 = get_signal(simout, "Platooning_AntiWindup/Ведомый-1.x")
t1v, v1 = get_signal(simout, "Platooning_AntiWindup/Ведомый-1.v")
t2x, x2 = get_signal(simout, "Platooning_AntiWindup/Ведомый-2.x")
t2v, v2 = get_signal(simout, "Platooning_AntiWindup/Ведомый-2.v")
t3x, x3 = get_signal(simout, "Platooning_AntiWindup/Ведомый-3.x")
t3v, v3 = get_signal(simout, "Platooning_AntiWindup/Ведомый-3.v")
t = t_lx # Общая временная шкала (используем время лидера)
n = length(t);
Данный график демонстрирует динамику относительного положения ведомых относительно лидера во времени, где отрицательные значения соответствуют отставанию, нулевая линия – позиции лидера, а отсутствие пересечения этой линии подтверждает отсутствие обгона.
t = t_lx
plot(t, [x1 .- x_l, x2 .- x_l, x3 .- x_l],
label=["Вед-1" "Вед-2" "Вед-3"],
xlabel="Время (с)", ylabel="Относительная позиция (м)")
hline!([0], linestyle=:dash, label="Позиция лидера")
Анимация фазового портрета иллюстрирует эволюцию траекторий всех автомобилей в координатах «позиция – скорость», где отсутствие пересечения траекторий ведомых с траекторией лидера подтверждает безопасный режим движения без обгонов.
@gif for i in 1:n fps = 5
plot(title="Фазовый портрет колонны",
xlabel="Позиция, м", ylabel="Скорость, м/с",
legend=:bottomright, xlims=(minimum(x_l)-10, maximum(x_l)+5), ylims=(-1, 16))
# Точки текущего положения
scatter!([x_l[i]], [v_l[i]], label="Лидер", markersize=8, color=:black)
scatter!([x1[i]], [v1[i]], label="Ведомый‑1", markersize=6, color=:red)
scatter!([x2[i]], [v2[i]], label="Ведомый‑2", markersize=6, color=:green)
scatter!([x3[i]], [v3[i]], label="Ведомый‑3", markersize=6, color=:blue)
# Линии траекторий за последние 5 секунд
dt = 5.0
idx = findall(t .>= t[i] - dt)
plot!(x_l[idx], v_l[idx], color=:black, alpha=0.5, linewidth=1, label="")
plot!(x1[idx], v1[idx], color=:red, alpha=0.5, linewidth=1, label="")
plot!(x2[idx], v2[idx], color=:green, alpha=0.5, linewidth=1, label="")
plot!(x3[idx], v3[idx], color=:blue, alpha=0.5, linewidth=1, label="")
annotate!(x_l[i], v_l[i]+0.6, text("t = $(round(t[i], digits=1)) с", 8, :black))
end
Данная анимация отображает движение колонны в системе отсчёта, связанной с лидером, где каждый ведомый автомобиль показан в виде точки на дороге с подписанной текущей скоростью, а отрицательные значения по оси абсцисс соответствуют отставанию, что наглядно демонстрирует сохранение безопасной дистанции и отсутствие обгонов.
y_coord = 1.0
colors = [:black, :red, :green, :blue]
labels = ["Лидер", "Ведомый-1", "Ведомый-2", "Ведомый-3"]
x_min = -80
x_max = 10
@gif for i in 1:n fps = 3
# Позиции относительно лидера
pos_leader = x_l[i] - x_l[i] # 0
pos1 = x1[i] - x_l[i]
pos2 = x2[i] - x_l[i]
pos3 = x3[i] - x_l[i]
positions = [pos_leader, pos1, pos2, pos3]
speeds = [v_l[i], v1[i], v2[i], v3[i]]
current_time = round(t[i], digits=1)
# Базовый график
scatter(positions, fill(y_coord, 4),
markersize = 12,
markercolor = colors,
xlim = (x_min, x_max),
ylim = (0.5, 1.5),
xlabel = "Расстояние от лидера (м)",
ylabel = "",
yticks = ([y_coord], ["Дорога"]),
legend = false,
title = "Время: $(current_time) с, Скорость лидера: $(round(v_l[i], digits=1)) м/с"
)
for (j, (pos, sp)) in enumerate(zip(positions, speeds))
if j == 1
continue
else
annotate!(pos + 2, y_coord + 0.05, text("$(round(sp, digits=1)) м/с", 8, colors[j]))
end
end
for x in range(-100, 50, step=5)
if x_min < x < x_max
plot!([x, x], [0.6, 1.4], linewidth=0.5, color=:gray, alpha=0.4, label="")
end
end
end
Из аналитики данных видно, что все ведомые движутся в фазовой области, не пересекая траекторию лидера.
Интегральная составляющая успешно компенсирует влияние шумов и неточностей, а механизм anti‑windup предотвращает перерегулирование при длительных насыщениях. В результате колонна сохраняет устойчивость на всём протяжении моделирования.
Вывод
В работе проведено сравнение двух подходов к управлению дистанцией в колонне: классического ПД-регулятора и ПИД-регулятора с защитой от виндапа. Моделирование в среде Engee показало, что:
- ПД-регулятор прост в реализации, но страдает от установившейся ошибки, чувствителен к зоне нечувствительности и шумам, что приводит к недопустимому эффекту обгона лидера ведомыми.
- ПИД-регулятор с антивиндапом полностью устраняет указанные недостатки. Добавление интегрального канала обеспечивает нулевую ошибку в установившемся режиме, а ограничение интегратора – устойчивость при насыщениях. Улучшенная модель демонстрирует корректное поведение колонны на длительных интервалах времени, устойчивость к шумам и задержкам, что делает её пригодной для практического применения в системах адаптивного круиз-контроля (ACC) и управления беспилотными колоннами.
Таким образом, эволюция от ПД к ПИД-регулятору с антивиндапом является необходимой для обеспечения надёжного и безопасного движения в составе колонны.

