Main Content

制約の適用を使用したアダプティブ クルーズ コントロール用の RL エージェントの学習

この例では、Constraint Enforcement ブロックでガイド付き探索を使用してアダプティブ クルーズ コントロール (ACC) 用の強化学習 (RL) エージェントに学習させる方法を示します。

概要

この例における目標は、前後方向の加速度とブレーキを制御することで、先行車との安全距離を維持しながら自車を設定速度で走行させることです。この例では、Train DDPG Agent for Adaptive Cruise Control (Reinforcement Learning Toolbox)の例と同じ車両モデルおよびパラメーターを使用します。

乱数シードを設定し、モデルのパラメーターを構成します。

% Set random seed.
rng('default')

% Parameters
x0_lead = 50;   % Initial position for lead car (m)
v0_lead = 25;   % Initial velocity for lead car (m/s)
x0_ego = 10;    % Initial position for ego car (m)
v0_ego = 20;    % Initial velocity for ego car (m/s)
D_default = 10; % Default spacing (m)
t_gap = 1.4;    % Time gap (s)
v_set = 30;     % Driver-set velocity (m/s)
amin_ego = -3;  % Minimum acceleration for driver comfort (m/s^2)
amax_ego = 2;   % Maximum acceleration for driver comfort (m/s^2)
Ts = 0.1;       % Sample time (s)     
Tf = 60;        % Duration (s)

制約式の学習

ACC アプリケーションの安全信号は、自車の速度 v と自車と先行車の間の相対距離 d です。この例では、これらの信号に対する制約は 10v30.5 および d5 です。これらの制約は、x における自車の実際の加速度、自車の速度、相対距離、および先行車の速度の状態に依存します。

アクション u は自車の加速度コマンドです。安全信号をアクションと状態から記述した方程式は次のようになります。

[vk+1dk+1]=[f1(xk)f2(xk)]+[g1(xk)g2(xk)]uk

Constraint Enforcement ブロックは、形式 fx+gxuc の制約を受け入れます。この例では、この制約関数の係数は次のようになります。

fx=[-f1(xk)-f2(xk)f1(xk)],gx=[-g1(xk)-g2(xk)g1(xk)],c=[-10-530.5]

不明な関数 fi および gi を学習させるには、最初に環境から学習データを収集しなければなりません。そのため、まず rlLearnConstraintACC モデルを使用して RL 環境を作成します。

mdl = 'rlLearnConstraintACC';
open_system(mdl)

このモデルでは、RL Agent ブロックはアクションを生成しません。代わりに、ランダムな外部アクションを環境に渡すように構成されています。データ収集モデルで非アクティブな RL Agent ブロックを使用するのは、データ収集で使用する環境モデル、アクション信号と観測信号の構成、およびモデルのリセット関数をその後のエージェントの学習で使用するものと確実に一致させるためです。

ランダムな外部アクション信号は [10, 6] の範囲で一様分布します。つまり、自車の最大制動力は -10 m/s^2、最大加速力は 6 m/s^2 です。

学習用の環境からの観測には、車両間の相対距離、先行車の速度、自車の速度、および自車の加速度の 4 つがあります。それらの値についての連続観測空間を定義します。

obsInfo = rlNumericSpec([4 1]);

エージェントによるアクションの出力は加速度コマンドです。加速度の範囲を指定して対応する連続行動空間を作成します。

actInfo = rlNumericSpec([1 1],'LowerLimit',-3,'UpperLimit',2);

このモデルの RL 環境を作成します。各学習エピソードまたはシミュレーションの開始時に先行車の位置をランダムに設定するリセット関数を指定します。

agentblk = [mdl '/RL Agent'];
env = rlSimulinkEnv(mdl,agentblk,obsInfo,actInfo);
env.ResetFcn = @(in)localResetFcn(in);

次に、補助関数 createDDPGAgentBACC を使用して、連続行動と連続観測をサポートする DDPG 強化学習エージェントを作成します。この関数は、アクション仕様と観測仕様に基づいてクリティック表現とアクター表現を作成し、その表現を使用して DDPG エージェントを作成します。

agent = createDDPGAgentACC(Ts,obsInfo,actInfo);

データの収集には補助関数 collectDataACC を使用します。この関数は、環境とエージェントをシミュレートし、結果の入出力データを収集します。結果の学習データには 9 つの列があります。

  • 車両間の相対距離

  • 先行車の速度

  • 自車の速度

  • 自車の実際の加速度

  • 自車の加速度コマンド

  • 次のタイム ステップにおける車両間の相対距離

  • 次のタイム ステップにおける先行車の速度

  • 次のタイム ステップにおける自車の速度

  • 次のタイム ステップにおける自車の実際の加速度

この例では、事前に収集した学習データを読み込みます。自分でデータを収集する場合は、collectDatatrue に設定します。

collectData = false;
if collectData
    count = 1000;
    data = collectDataACC(env,agent,count);
else
    load trainingDataACC data
end

この例では、自車と先行車のダイナミクスは線形です。したがって、安全信号の制約についての最小二乗解、つまり v=RvId=RdI を求めることができます。ここで I[xk;uk] です。

% Extract state and input data.
I = data(1:1000,[4,3,1,2,5]);
% Extract data for the relative distance in the next time step.
d = data(1:1000,6);
% Compute the relation from the state and input to relative distance.
Rd = I\d;
% Extract data for actual ego car velocity.
v = data(1:1000,8);
% Compute the relation from the state and input to ego car velocity.
Rv = I\v;

補助関数 validateConstraintACC を使用して学習済みの制約を検証します。この関数は、学習済みの制約を使用して入力学習データを処理します。その後、ネットワークの出力を学習の出力と比較し、平方根平均二乗誤差 (RMSE) を計算します。

validateConstraintACC(data,Rd,Rv)
Test Data RMSE for Relative Distance  = 8.118162e-04
Test Data RMSE for Ego Velocity = 1.721814e-15

RMSE の値が小さく、制約の学習が正しく完了したことを示しています。

制約の適用を使用したエージェントの学習

制約の適用を使用したエージェントの学習には rlACCwithConstraint モデルを使用します。このモデルでは、エージェントからの加速度コマンドを環境への適用前に制約します。

mdl = 'rlACCwithConstraint';
open_system(mdl)

制約の実装を表示するには、Constraint サブシステムを開きます。ここで、線形制約の関係から figi の値がモデルで生成されます。モデルでは、これらの値が制約範囲と一緒に Constraint Enforcement ブロックに送られます。

このモデルを使用して RL 環境を作成します。アクション仕様は制約学習環境と同じです。学習用の環境からの観測は、速度誤差の積分、速度誤差、および自車の速度の 3 つです。

Environment サブシステムでは、重大な制約に違反した場合に isDone 信号を生成します。これは、自車の速度が負になったとき (後退したとき)、または相対距離がゼロ未満になったとき (自車が先行車に衝突したとき) のいずれかに該当します。RL Agent ブロックでは、この信号を使用して学習エピソードを完了前に終了します。

obsInfo = rlNumericSpec([3 1]);
agentblk = [mdl '/RL Agent'];
env = rlSimulinkEnv(mdl,agentblk,obsInfo,actInfo);
env.ResetFcn = @(in)localResetFcn(in);

観測仕様が学習と異なるため、DDPG エージェントも新たに作成しなければなりません。

agent = createDDPGAgentACC(Ts,obsInfo,actInfo);

エージェントの学習のオプションを指定します。エージェントに最大 5000 エピソードまで学習させます。エピソード報酬が 260 を超えたら学習を停止します。

maxepisodes = 5000;
maxsteps = ceil(Tf/Ts);
trainingOpts = rlTrainingOptions(...
    'MaxEpisodes',maxepisodes,...
    'MaxStepsPerEpisode',maxsteps,...
    'Verbose',false,...
    'Plots','training-progress',...
    'StopTrainingCriteria','EpisodeReward',...
    'StopTrainingValue',260);

エージェントに学習させます。学習は時間がかかるプロセスであるため、この例では事前学習済みのエージェントを読み込みます。代わりに自分でエージェントに学習させる場合は、trainAgenttrue に設定します。

trainAgent = false;
if trainAgent
    trainingStats = train(agent,env,trainingOpts);
else
    load rlAgentConstraintACC agent
end

次の図に学習結果を示します。

[合計ステップ数][エピソード番号][エピソード ステップ] の積に等しいことから、各学習エピソードが完了前に終了せずに最後まで実行されています。したがって、Constraint Enforcement ブロックにより、自車が重大な制約に違反しないようになります。

学習済みのエージェントを実行し、シミュレーション結果を確認します。

x0_lead = 80;
sim(mdl);

制約なしのエージェントの学習

エージェントの学習に制約の適用を使用する利点を確認するために、制約なしでエージェントに学習させ、学習結果を制約の適用を使用した場合と比較できます。

制約なしのエージェントの学習には rlACCwithoutConstraint モデルを使用します。このモデルでは、エージェントからのアクションを環境にそのまま適用します。エージェントで使用するアクション仕様と観測仕様は同じです。

mdl = 'rlACCwithoutConstraint';
open_system(mdl)

このモデルを使用して RL 環境を作成します。

agentblk = [mdl '/RL Agent'];
env = rlSimulinkEnv(mdl,agentblk,obsInfo,actInfo);
env.ResetFcn = @(in)localResetFcn(in);

学習させる新しい DDPG エージェントを作成します。このエージェントの構成は前の学習で使用したエージェントと同じにします。

agent = createDDPGAgentACC(Ts,obsInfo,actInfo);

制約の適用を使用した場合と同じ学習オプションを使用してエージェントに学習させます。この例では、前の学習と同じように、事前学習済みのエージェントを読み込みます。自分でエージェントに学習させる場合は、trainAgent を true に設定します。

trainAgent = false;
if trainAgent
    trainingStats2 = train(agent,env,trainingOpts);
else
    load rlAgentACC agent
end

次の図に学習結果を示します。

[合計ステップ数][エピソード番号][エピソード ステップ] の積よりも小さいことから、制約違反によって完了前に終了したエピソードが学習に含まれています。

学習済みのエージェントを実行し、シミュレーション結果をプロットします。

x0_lead = 80;
sim(mdl)

bdclose('rlLearnConstraintACC')
bdclose('rlACCwithConstraint')
bdclose('rlACCwithoutConstraint')

ローカル リセット関数

function in = localResetFcn(in)
% Reset the initial position of the lead car.
in = setVariable(in,'x0_lead',40+randi(60,1,1));
end

参考

ブロック

関連するトピック