Настройка ПИ-контроллера с помощью Обучения с Подкреплением

Этот пример показов, как настроить ПИ-контроллер с помощью алгоритма TD3 глубокого детерминированного градиента ( обучения с подкреплением) с двумя задержками. Производительность настроенного контроллера сравнивается с эффективностью контроллера, настроенного с помощью приложения Control System Tuner. Для настройки контроллеров в Simulink ® требуется программное обеспечение Simulink Control Design™.

Для относительно простых задач управления с небольшим количеством настраиваемых параметров основанные на модели методы настройки могут получить хорошие результаты с более быстрым процессом настройки по сравнению с безмодельными методами на основе RL. Однако методы RL могут быть более подходящими для сильно нелинейных систем или адаптивной настройки контроллера.

Чтобы облегчить сравнение контроллеров, оба метода настройки используют линейную квадратичную целевую функцию Гауссова (LQG).

Этот пример использует агента обучения с подкреплением (RL), чтобы вычислить усиления для ПИ-контроллера. Для примера, который заменяет ПИ-контроллер на контроллер нейронной сети, смотрите Создать Окружение Simulink и Train Агента.

Модель окружения

Модель окружения для этого примера является моделью бака с водой. Цель этой системы управления состоит в том, чтобы поддерживать уровень воды в баке, чтобы соответствовать ссылке значению.

open_system('watertankLQG')

Модель включает технологический шум с отклонением E(n2(t))=1.

Поддержание уровня воды при минимизации усилий по управлению uконтроллеры в этом примере используют следующий критерий LQG.

J=limTE(1T0T((ref-y)2(t)+0.01u2(t))dt)

Чтобы симулировать контроллер в этой модели, необходимо задать время симуляции Tf и шаг расчета контроллером Ts в секундах.

Ts = 0.1;
Tf = 10;

Для получения дополнительной информации о модели бака с водой смотрите Модель Simulink (Simulink Control Design).

Настройка ПИ-контроллера с помощью Control System Tuner

Чтобы настроить контроллер в Simulink с помощью Control System Tuner, необходимо задать блок контроллера как настроенный блок и определить цели процесса настройки. Для получения дополнительной информации об использовании Control System Tuner, смотрите Настроить Систему Управления Используя Control System Tuner (Simulink Control Design).

В данном примере откройте сохраненный сеанс ControlSystemTunerSession.mat использование Control System Tuner. Этот сеанс задает блок ПИД-регулятор в watertankLQG модель как настроенный блок и содержит цель настройки LQG.

controlSystemTuner("ControlSystemTunerSession")

Чтобы настроить контроллер, на вкладке Tuning, нажмите Tune.

Настроенные пропорциональные и интегральные составляющие составляют приблизительно 9,8 и 1e-6, соответственно.

Kp_CST = 9.80199999804512;
Ki_CST = 1.00019996230706e-06;

Создайте окружение для обучения агента

Чтобы определить модель для обучения агента RL, измените модель бака с водой с помощью следующих шагов.

  1. Удалите ПИД-регулятор.

  2. Вставьте блок агента RL.

  3. Создайте вектор наблюдения [edte]T где e=r-h, h - высота бака, и r - высота ссылки. Подключите сигнал наблюдения к блоку RL Agent.

  4. Определите функцию вознаграждения для агента RL как отрицательное значение стоимости LQG, то есть, Reward=-((ref-h)2(t)+0.01u2(t)). Агент RL максимизирует это вознаграждение, таким образом минимизируя стоимость LQG.

Получившаяся модель rlwatertankPIDTune.slx.

mdl = 'rlwatertankPIDTune';
open_system(mdl)

Создайте объект интерфейса окружения. Для этого используйте localCreatePIDEnv функция, заданная в конце этого примера.

[env,obsInfo,actInfo] = localCreatePIDEnv(mdl);

Извлеките размерности наблюдений и действий для этого окружения.

numObservations = obsInfo.Dimension(1);
numActions = prod(actInfo.Dimension);

Исправьте начальное значение генератора для повторяемости.

rng(0)

Создайте TD3 агента

Учитывая наблюдения, агент TD3 решает, какое действие предпринять, используя представление актера. Чтобы создать актёра, сначала создайте глубокую нейронную сеть с входом наблюдения и выходом действия. Для получения дополнительной информации смотрите rlDeterministicActorRepresentation.

Можно смоделировать ПИ-контроллер как нейронную сеть с одним полносвязным слоем с интегральными наблюдениями ошибок и ошибок.

u=[edte]*[KiKp]T

Здесь:

  • u - выход нейронной сети актёра.

  • Kp и Ki являются абсолютными значениями весов нейронной сети.

  • e=r-h, h - высота бака, и r - высота ссылки.

Оптимизация градиентного спуска может привести веса к отрицательным значениям. Чтобы избежать отрицательных весов, замените нормальные fullyConnectedLayer с fullyConnectedPILayer. Этот слой гарантирует, что веса положительны, реализуя функцию Y=abs(WEIGHTS)*X. Этот слой задан в fullyConnectedPILayer.m.

initialGain = single([1e-3 2]);
actorNetwork = [
    featureInputLayer(numObservations,'Normalization','none','Name','state')
    fullyConnectedPILayer(initialGain, 'Action')];
actorOptions = rlRepresentationOptions('LearnRate',1e-3,'GradientThreshold',1);
actor = rlDeterministicActorRepresentation(actorNetwork,obsInfo,actInfo,...
    'Observation',{'state'},'Action',{'Action'},actorOptions);

Агент TD3 аппроксимирует долгосрочное вознаграждение, заданное наблюдениями и действиями, с помощью двух представлений функции ценности критика. Чтобы создать критиков, сначала создайте глубокую нейронную сеть с двумя входами, наблюдением и действием и одним выходом. Для получения дополнительной информации о создании представления функции ценности глубокой нейронной сети, смотрите, Создают политику и представления функции ценности.

Чтобы создать критиков, используйте localCreateCriticNetwork функция, заданная в конце этого примера. Используйте одну и ту же структуру сети для обеих представлений критика.

criticNetwork = localCreateCriticNetwork(numObservations,numActions);
criticOpts = rlRepresentationOptions('LearnRate',1e-3,'GradientThreshold',1);

critic1 = rlQValueRepresentation(criticNetwork,obsInfo,actInfo,...
    'Observation','state','Action','action',criticOpts);
critic2 = rlQValueRepresentation(criticNetwork,obsInfo,actInfo,...
    'Observation','state','Action','action',criticOpts);
critic = [critic1 critic2];

Сконфигурируйте агента с помощью следующих опций.

  • Установите агента, чтобы использовать шаг расчета контроллера Ts.

  • Установите размер мини-партии в 128 выборки опыта.

  • Установите длину буфера опыта равную 1e6.

  • Установите модель исследования и модель сглаживания целевой политики, чтобы использовать Гауссов шум с отклонением 0,1.

Задайте опции TD3 агента, используя rlTD3AgentOptions.

agentOpts = rlTD3AgentOptions(...
    'SampleTime',Ts,...
    'MiniBatchSize',128, ...
    'ExperienceBufferLength',1e6);
agentOpts.ExplorationModel.StandardDeviation = sqrt(0.1);
agentOpts.TargetPolicySmoothModel.StandardDeviation = sqrt(0.1);

Создайте агента TD3 с помощью заданного представления актера, представления критика и опций агента. Для получения дополнительной информации смотрите rlTD3AgentOptions.

agent = rlTD3Agent(actor,critic,agentOpts);

Обучите агента

Чтобы обучить агента, сначала задайте следующие опции обучения.

  • Запускайте каждое обучение самое большее для 1000 эпизоды с каждым эпизодом, длящимся самое большее 1 00 временные шаги.

  • Отображение процесса обучения в Диспетчере эпизодов (установите Plots опция) и отключить отображение командной строки (установите Verbose опция).

  • Остановите обучение, когда агент получит среднее совокупное вознаграждение, больше -355 в 100 последовательных эпизодах. На данной точке агент может контролировать уровень воды в баке.

Для получения дополнительной информации смотрите rlTrainingOptions.

maxepisodes = 1000;
maxsteps = ceil(Tf/Ts);
trainOpts = rlTrainingOptions(...
    'MaxEpisodes',maxepisodes, ...
    'MaxStepsPerEpisode',maxsteps, ...
    'ScoreAveragingWindowLength',100, ...
    'Verbose',false, ...
    'Plots','training-progress',...
    'StopTrainingCriteria','AverageReward',...
    'StopTrainingValue',-355);

Обучите агента с помощью train функция. Обучение этого агента является интенсивным в вычислительном отношении процессом, который занимает несколько минут. Чтобы сэкономить время при запуске этого примера, загрузите предварительно обученного агента путем установки doTraining на false. Чтобы обучить агента самостоятельно, установите doTraining на true.

doTraining = false;

if doTraining
    % Train the agent.
    trainingStats = train(agent,env,trainOpts);
else
    % Load pretrained agent for the example.
    load('WaterTankPIDtd3.mat','agent')
end

Валидация обученного агента

Проверьте выученного агента относительно модели путем симуляции.

simOpts = rlSimulationOptions('MaxSteps',maxsteps);
experiences = sim(env,agent,simOpts);

Интеграл и пропорциональные составляющие ПИ-контроллера являются абсолютными весами представления актера. Чтобы получить веса, сначала извлеките настраиваемые параметры от актёра.

actor = getActor(agent);
parameters = getLearnableParameters(actor);

Получите коэффициент усиления контроллера.

Ki = abs(parameters{1}(1))
Ki = single
    0.3958
Kp = abs(parameters{1}(2))
Kp = single
    8.0822

Примените усиления, полученные от агента RL, к исходному блоку ПИ-контроллера и запустите симуляцию переходной характеристики.

mdlTest = 'watertankLQG';
open_system(mdlTest);
set_param([mdlTest '/PID Controller'],'P',num2str(Kp))
set_param([mdlTest '/PID Controller'],'I',num2str(Ki))
sim(mdlTest)

Извлеките информацию об переходной характеристике, стоимости LQG и запасе устойчивости для симуляции. Чтобы вычислить запас устойчивости, используйте localStabilityAnalysis функция, заданная в конце этого примера.

rlStep = simout;
rlCost = cost;
rlStabilityMargin = localStabilityAnalysis(mdlTest);

Примените усиления, полученные с помощью Control System Tuner, к исходному блоку ПИ-контроллера и запустите симуляцию переходной характеристики.

set_param([mdlTest '/PID Controller'],'P',num2str(Kp_CST))
set_param([mdlTest '/PID Controller'],'I',num2str(Ki_CST))
sim(mdlTest)
cstStep = simout;
cstCost = cost;
cstStabilityMargin = localStabilityAnalysis(mdlTest);

Сравнение эффективности контроллера

Постройте график переходной характеристики для каждой системы.

figure
plot(cstStep)
hold on
plot(rlStep)
grid on
legend('Control System Tuner','RL','Location','southeast')
title('Step Response')

Figure contains an axes. The axes with title Step Response contains 2 objects of type line. These objects represent Control System Tuner, RL.

Проанализируйте переходную характеристику для обеих симуляций.

rlStepInfo = stepinfo(rlStep.Data,rlStep.Time);
cstStepInfo = stepinfo(cstStep.Data,cstStep.Time);
stepInfoTable = struct2table([cstStepInfo rlStepInfo]);
stepInfoTable = removevars(stepInfoTable,{...
    'SettlingMin','SettlingMax','Undershoot','PeakTime'});
stepInfoTable.Properties.RowNames = {'Control System Tuner','RL'};
stepInfoTable
stepInfoTable=2×4 table
                            RiseTime    SettlingTime    Overshoot     Peak 
                            ________    ____________    _________    ______

    Control System Tuner    0.77322        1.3594        0.33125     9.9023
    RL                      0.97617        1.7408        0.40451     10.077

Анализируйте стабильность для обеих симуляций.

stabilityMarginTable = struct2table([cstStabilityMargin rlStabilityMargin]);
stabilityMarginTable = removevars(stabilityMarginTable,{...
    'GMFrequency','PMFrequency','DelayMargin','DMFrequency'});
stabilityMarginTable.Properties.RowNames = {'Control System Tuner','RL'};
stabilityMarginTable
stabilityMarginTable=2×3 table
                            GainMargin    PhaseMargin    Stable
                            __________    ___________    ______

    Control System Tuner      8.1616        84.122       true  
    RL                        9.9226        84.241       true  

Сравните совокупную стоимость LQG для этих двух контроллеров. Настроенный на RL контроллер дает несколько более оптимальное решение.

rlCumulativeCost  = sum(rlCost.Data)
rlCumulativeCost = -375.9135
cstCumulativeCost = sum(cstCost.Data)
cstCumulativeCost = -376.9373

Оба контроллера дают стабильные отклики, причем контроллер настроен с помощью Control System Tuner, что обеспечивает более быструю реакцию. Однако метод настройки RL создает более высокий запас по амплитуде и более оптимальное решение.

Локальные функции

Функция для создания бака с водой окружения RL.

function [env,obsInfo,actInfo] = localCreatePIDEnv(mdl)

% Define the observation specification obsInfo and action specification actInfo.
obsInfo = rlNumericSpec([2 1]);
obsInfo.Name = 'observations';
obsInfo.Description = 'integrated error and error';

actInfo = rlNumericSpec([1 1]);
actInfo.Name = 'PID output';

% Build the environment interface object.
env = rlSimulinkEnv(mdl,[mdl '/RL Agent'],obsInfo,actInfo);

% Set a cutom reset function that randomizes the reference values for the model.
env.ResetFcn = @(in)localResetFcn(in,mdl);
end

Функция для рандомизации опорного сигнала и начальной высоты резервуара для воды в начале каждого эпизода.

function in = localResetFcn(in,mdl)

% randomize reference signal
blk = sprintf([mdl '/Desired \nWater Level']);
hRef = 10 + 4*(rand-0.5);
in = setBlockParameter(in,blk,'Value',num2str(hRef));

% randomize initial height
hInit = 0;
blk = [mdl '/Water-Tank System/H'];
in = setBlockParameter(in,blk,'InitialCondition',num2str(hInit));

end

Функция для линеаризации и вычисления запасов устойчивости системы бака с водой SISO.

function margin = localStabilityAnalysis(mdl)

io(1) = linio([mdl '/Sum1'],1,'input');
io(2) = linio([mdl '/Water-Tank System'],1,'openoutput');
op = operpoint(mdl);
op.Time = 5;
linsys = linearize(mdl,io,op);

margin = allmargin(linsys);
end

Функция для создания сети критика.

function criticNetwork = localCreateCriticNetwork(numObservations,numActions)
statePath = [
    featureInputLayer(numObservations,'Normalization','none','Name','state')
    fullyConnectedLayer(32,'Name','fc1')];
actionPath = [
    featureInputLayer(numActions,'Normalization','none','Name','action')
    fullyConnectedLayer(32,'Name','fc2')];
commonPath = [
    concatenationLayer(1,2,'Name','concat')
    reluLayer('Name','reluBody1')
    fullyConnectedLayer(32,'Name','fcBody')
    reluLayer('Name','reluBody2')
    fullyConnectedLayer(1,'Name','qvalue')];

criticNetwork = layerGraph();
criticNetwork = addLayers(criticNetwork,statePath);
criticNetwork = addLayers(criticNetwork,actionPath);
criticNetwork = addLayers(criticNetwork,commonPath);

criticNetwork = connectLayers(criticNetwork,'fc1','concat/in1');
criticNetwork = connectLayers(criticNetwork,'fc2','concat/in2');
end

См. также

|

Похожие темы