Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

経路追従制御用の DDPG エージェントの学習

この例では、経路追従制御 (PFC) 用の深層決定論的方策勾配 (DDPG) エージェントの学習を Simulink® で実行する方法を説明します。DDPG エージェントの詳細については、深層決定論的方策勾配 (DDPG) エージェントを参照してください。

Simulink モデル

この例では、自車については単純な自転車モデル、先行車両については単純な縦方向のモデルを強化学習の環境として使用します。この学習の目的は、縦方向の加速と減速を制御して先行車両との安全な距離を維持しつつ、自車を設定速度で走行させること、およびフロント ステアリング角度を制御して車線のセンターラインに沿って自車を走行させ続けることです。PFC の詳細については、Path Following Control System (Model Predictive Control Toolbox)を参照してください。自車の車両運動は、次のパラメーターで指定します。

m = 1600;   % total vehicle mass (kg)
Iz = 2875;  % yaw moment of inertia (mNs^2)
lf = 1.4;   % long. distance from center of gravity to front tires (m)
lr = 1.6;   % long. distance from center of gravity to rear tires (m)
Cf = 19000; % cornering stiffness of front tires (N/rad)
Cr = 33000; % cornering stiffness of rear tires (N/rad)
tau = 0.5;  % longitudinal time constant

2 台の車両の初期位置と初期速度を指定します。

x0_lead = 50;   % initial position for lead car (m)
v0_lead = 24;   % initial velocity for lead car (m/s)
x0_ego = 10;    % initial position for ego car (m)
v0_ego = 18;    % initial velocity for ego car (m/s)

停止時の既定の間隔 (m)、時間ギャップ (s)、および運転手が設定した速度 (m/s) を指定します。

D_default = 10;
t_gap = 1.4;
v_set = 28;

車両運動の物理的な制約をシミュレートするため、加速度を [–3,2] (m/s^2) の範囲に制限し、ステアリング角度を [–0.2618,0.2618] (rad) の範囲 (-15 ~ 15 度) に制限します。

amin_ego = -3;
amax_ego = 2;
umin_ego = -0.2618; % +15 deg
umax_ego = 0.2618; % -15 deg

道路の曲率は定数 0.001 (m-1) で定義されます。横方向の偏差の初期値を 0.2 m とし、相対ヨー角の初期値を -0.1 rad とします。

rho = 0.001;
e1_initial = 0.2;
e2_initial = -0.1;

サンプル時間 Ts とシミュレーション期間 Tf を秒単位で定義します。

Ts = 0.1;
Tf = 60;

モデルを開きます。

mdl = "rlPFCMdl";
open_system(mdl)
agentblk = mdl + "/RL Agent";

このモデルの場合、次のようにします。

  • アクション信号は、加速度のアクションとステアリング角度のアクションで構成される。加速度のアクション信号は、-3 ~ 2 (m/s^2) の値を取る。ステアリングのアクション信号は、-15 度 (-0.2618 rad) ~ 15 度 (0.2618 rad) の値を取る。

  • 自車の基準速度 Vref を次のように定義する。相対距離が安全距離未満の場合、自車は先行車両の速度と運転手が設定した速度の最小値に追従する。この方法により、自車は先行車両からある程度の距離を維持する。相対距離が安全距離より大きい場合、自車は運転手が設定した速度に追従する。この例では、安全距離は自車の縦方向の速度 V の線形関数、つまり、tgap*V+Ddefault として定義される。安全距離によって、自車の追従速度が決まる。

  • 環境からの観測値には、縦方向の測定値、つまり、速度誤差 eV=Vref-Vego、その積分 e、および自車の縦方向の速度 V が含まれる。また、この観測値には、横方向の測定値、つまり、横方向の偏差 e1、相対ヨー角 e2、これらの微分 e˙1 および e˙2、これらの積分 e1 および e2 が含まれる。

  • シミュレーションは、横方向の偏差が |e1|>1 となるか、縦方向の速度が Vego<0.5 となるか、先行車両と自車との相対距離が Drel<0 となったときに終了する。

  • 各タイム ステップ t で与えられる報酬 rt は次のとおりとする。

rt=-(100e12+500ut-12+10eV2+100at-12)×1e-3-10Ft+2Ht+Mt

ここで、ut-1 は前のタイム ステップ t-1 からのステアリングの入力、at-1 は前のタイム ステップからの加速度の入力です。この 3 つの論理値は次のようになります。

  • Ft=1 (シミュレーションが終了した場合)、Ft=0 (それ以外の場合)

  • Ht=1 (横方向の誤差が e12<0.01 の場合)、Ht=0 (それ以外の場合)

  • Mt=1 (速度の誤差が eV2<1 の場合)、Mt=0 (それ以外の場合)

報酬に含まれるこの 3 つの論理項は、横方向の誤差と速度の誤差の両方を小さくするようエージェントに促す一方、シミュレーションが早期に終了した場合はエージェントにペナルティを課します。

環境インターフェイスの作成

Simulink モデル用の環境インターフェイスを作成します。

観測値の仕様を作成します。

obsInfo = rlNumericSpec([9 1], ...
    LowerLimit=-inf*ones(9,1), ...
    UpperLimit=inf*ones(9,1));
obsInfo.Name = "observations";

アクションの仕様を作成します。

actInfo = rlNumericSpec([2 1], ...
    LowerLimit=[-3;-0.2618], ...
    UpperLimit=[2;0.2618]);
actInfo.Name = "accel;steer";

環境インターフェイスを作成します。

env = rlSimulinkEnv(mdl,agentblk,obsInfo,actInfo);

初期条件を定義するには、無名関数ハンドルを使用して環境リセット関数を指定します。例の終わりに定義されているリセット関数 localResetFcn は、先行車両の初期位置、横方向の偏差、相対ヨー角をランダム化します。

env.ResetFcn = @(in)localResetFcn(in);

再現性をもたせるために、乱数発生器のシードを固定します。

rng(0)

DDPG エージェントの作成

DDPG エージェントは、パラメーター化された Q 値関数近似器を使用して方策の価値を推定します。Q 値関数クリティックは、現在の観測値とアクションを入力として取り、単一のスカラーを出力として返します (状態からのアクションが与えられた割引累積長期報酬の推定値は、現在の観測値に対応し、その後の方策に従います)。

パラメーター化された Q 値関数をクリティック内でモデル化するには、2 つの入力層 (そのうち 1 つは obsInfo で指定された観測チャネル用で、もう 1 つは actInfo で指定されたアクション チャネル用) と 1 つの出力層 (これはスカラー値を返します) をもつニューラル ネットワークを使用します。prod(obsInfo.Dimension) および prod(actInfo.Dimension) は、行ベクトル、列ベクトル、行列のいずれによって構成されているかにかかわらず、それぞれ観測値と行動空間の次元の数を返すことに注意してください。

各ネットワーク パスを layer オブジェクトの配列として定義し、各パスの入力層と出力層に名前を割り当てます。これらの名前を使用すると、パスを接続してから、ネットワークの入力層と出力層に適切な環境チャネルを明示的に関連付けることができます。

% Number of neurons
L = 100;

% Main path
mainPath = [
    featureInputLayer(prod(obsInfo.Dimension),Name="obsInLyr")
    fullyConnectedLayer(L)
    reluLayer
    fullyConnectedLayer(L)
    additionLayer(2,Name="add")
    reluLayer
    fullyConnectedLayer(L)
    reluLayer
    fullyConnectedLayer(1,Name="QValLyr")
    ];

% Action path
actionPath = [
    featureInputLayer(prod(actInfo.Dimension),Name="actInLyr")
    fullyConnectedLayer(L,Name="actOutLyr")
    ];

dlnetwork オブジェクトを組み立てます。

criticNet = dlnetwork();
criticNet = addLayers(criticNet,mainPath);
criticNet = addLayers(criticNet,actionPath);    
criticNet = connectLayers(criticNet,"actOutLyr","add/in2");

dlnetwork オブジェクトを初期化し、重みの数を表示します。

criticNet = initialize(criticNet);
summary(criticNet)
   Initialized: true

   Number of learnables: 21.6k

   Inputs:
      1   'obsInLyr'   9 features
      2   'actInLyr'   2 features

クリティック ネットワークの構成を表示します。

plot(criticNet)

指定したニューラル ネットワーク、および環境のアクション仕様と観測仕様を使用して、クリティックを作成します。追加の引数として、観測チャネルとアクション チャネルに接続するネットワーク層の名前も渡します。詳細については、rlQValueFunctionを参照してください。

critic = rlQValueFunction(criticNet,obsInfo,actInfo,...
    ObservationInputNames="obsInLyr",ActionInputNames="actInLyr");

DDPG エージェントは、連続行動空間において、パラメーター化された決定論的方策を使用します。この方策は、連続決定論的アクターによって学習されます。このアクターは、現在の観測値を入力として取り、観測値の決定論的関数であるアクションを出力として返します。

パラメーター化された方策をアクター内でモデル化するには、1 つの入力層 (これは、obsInfo で指定された、環境観測チャネルのコンテンツを受け取ります) と 1 つの出力層 (これは、actInfo で指定された、環境アクション チャネルへのアクションを返します) をもつニューラル ネットワークを使用します。

ネットワークを layer オブジェクトの配列として定義します。

actorNet = [
    featureInputLayer(prod(obsInfo.Dimension))
    fullyConnectedLayer(L)
    reluLayer
    fullyConnectedLayer(L)
    reluLayer
    fullyConnectedLayer(L)
    reluLayer
    fullyConnectedLayer(2)
    tanhLayer
    scalingLayer(Scale=[2.5;0.2618],Bias=[-0.5;0])
    ];

dlnetwork オブジェクトに変換し、ネットワークを初期化し、重みの数を表示します。

actorNet = dlnetwork(actorNet);
actorNet = initialize(actorNet);
summary(actorNet)
   Initialized: true

   Number of learnables: 21.4k

   Inputs:
      1   'input'   9 features

クリティックと同様にアクターを作成します。詳細については、rlContinuousDeterministicActorを参照してください。

actor = rlContinuousDeterministicActor(actorNet,obsInfo,actInfo);

rlOptimizerOptionsを使用して、クリティックとアクターの学習オプションを指定します。

criticOptions = rlOptimizerOptions( ...
    LearnRate=1e-3, ...
    GradientThreshold=1, ...
    L2RegularizationFactor=1e-4);
actorOptions = rlOptimizerOptions( ...
    LearnRate=1e-4, ...
    GradientThreshold=1, ...
    L2RegularizationFactor=1e-4);

rlDDPGAgentOptionsを使用して、DDPG エージェントのオプション (アクターとクリティックのオプションなど) を指定します。

agentOptions = rlDDPGAgentOptions(...
    SampleTime=Ts,...
    ActorOptimizerOptions=actorOptions,...
    CriticOptimizerOptions=criticOptions,...
    ExperienceBufferLength=1e6);
agentOptions.NoiseOptions.Variance = [0.6;0.1];
agentOptions.NoiseOptions.VarianceDecayRate = 1e-5;

アクター、クリティック、およびエージェントのオプションを使用して、DDPG エージェントを作成します。詳細については、rlDDPGAgentを参照してください。

agent = rlDDPGAgent(actor,critic,agentOptions);

エージェントの学習

エージェントに学習させるには、まず、学習オプションを指定します。この例では、次のオプションを使用します。

  • 最大 10000 個のエピソードについて、各エピソードの学習を実行 (各エピソードは最大 maxsteps タイム ステップ持続)。

  • Episode Manager のダイアログ ボックスに学習の進行状況を表示 (Verbose オプションと Plots オプションを設定)。

  • 1700 を超える累積エピソード報酬をエージェントが受け取ったときに学習を停止。

詳細については、rlTrainingOptionsを参照してください。

maxepisodes = 1e4;
maxsteps = ceil(Tf/Ts);
trainingOpts = rlTrainingOptions(...
    MaxEpisodes=maxepisodes,...
    MaxStepsPerEpisode=maxsteps,...
    Verbose=false,...
    Plots="training-progress",...
    StopTrainingCriteria="EpisodeCount",...
    StopTrainingValue=1450);

関数 train を使用して、エージェントに学習させます。学習は計算量が多いプロセスのため、完了するのに数分かかります。この例の実行時間を節約するために、doTrainingfalse に設定して事前学習済みのエージェントを読み込みます。エージェントに学習させるには、doTrainingtrue に設定します。

doTraining = false;

if doTraining    
    % Train the agent.
    trainingStats = train(agent,env,trainingOpts);
else
    % Load a pretrained agent for the example.
    load("SimulinkPFCDDPG.mat","agent")       
end

DDPG エージェントのシミュレーション

学習済みエージェントの性能を検証するには、以下のコマンドのコメントを解除して Simulink 環境内でこのエージェントをシミュレートします。エージェントのシミュレーションの詳細については、rlSimulationOptions および sim を参照してください。

% simOptions = rlSimulationOptions(MaxSteps=maxsteps);
% experience = sim(env,agent,simOptions);

確定的な初期条件を使用して学習済みエージェントのデモを実行するには、このモデルを Simulink でシミュレートします。

e1_initial = -0.4;
e2_initial = 0.1;
x0_lead = 80;
sim(mdl)

以下のプロットは、先行車両が自車の 70 (m) 先にあるときのシミュレーション結果を示します。

  • 最初の 35 秒間は、相対距離が安全距離より大きいため (右下のプロット)、自車は設定速度に追従します (右上のプロット)。加速して設定速度に到達するために、加速度はほとんどが非負です (左上のプロット)。

  • 35 ~ 42 秒では、相対距離が安全距離より概ね小さいため (右下のプロット)、自車は先行車両の速度と設定速度のうち最小値に追従します。先行車両の速度が設定速度より小さいため (右上のプロット)、先行車両の速度に追従するように、加速度はゼロ以外になります (左上のプロット)。

  • 42 ~ 58 秒では、自車は設定速度に追従し (右上のプロット)、加速度は 0 のままです (左上のプロット)。

  • 58 ~ 60 秒では、相対距離が安全距離より小さくなるため (右下のプロット)、自車は減速して先行車両の速度に追従します。

  • 左下のプロットは、横方向の偏差を示します。このプロットに示されているように、1 秒以内に横方向の偏差が大きく減少しています。横方向の偏差は 0.05 m 未満を維持しています。

Simulink モデルを閉じます。

bdclose(mdl)

リセット関数

function in = localResetFcn(in)
    
    % random value for initial position of lead car
    in = setVariable(in,"x0_lead",40+randi(60,1,1));
    
    % random value for lateral deviation
    in = setVariable(in,"e1_initial", 0.5*(-1+2*rand));
    
    % random value for relative yaw angle
    in = setVariable(in,"e2_initial", 0.1*(-1+2*rand));

end

参考

関数

オブジェクト

ブロック

関連する例

詳細