メインコンテンツ

DDPG エージェントを使用した四足歩行ロボットの移動

この例では、深層決定論的方策勾配 (DDPG) エージェントを使用して四足歩行ロボットに歩行を学習させる方法を示します。この例のロボットは、Simscape™ Multibody™ を使用してモデル化されています。DDPG エージェントの詳細については、深層決定論的方策勾配 (DDPG) エージェントを参照してください。

再現性のための乱数ストリームの固定

サンプル コードには、さまざまな段階で乱数の計算が含まれる場合があります。サンプル コード内のさまざまなセクションの先頭にある乱数ストリームを固定すると、実行するたびにセクション内の乱数シーケンスが維持されるため、結果が再現される可能性が高くなります。詳細については、Results Reproducibilityを参照してください。

シード 0 で乱数ストリームを固定し、メルセンヌ・ツイスター乱数アルゴリズムを使用します。乱数生成に使用されるシード制御の詳細については、rngを参照してください。

previousRngState = rng(0,"twister");

出力 previousRngState は、ストリームの前の状態に関する情報が格納された構造体です。例の最後で、状態を復元します。

この例で提供されているスクリプト initializeRobotParameters を使用して、必要なパラメーターを MATLAB® のベース ワークスペースに読み込みます。

initializeRobotParameters;

四足歩行ロボット モデル

この例の環境は四足歩行ロボットであり、学習の目標は、最小限の制御操作を使用してロボットを直進歩行させることです。

モデルを開きます。

mdl = "rlQuadrupedRobot";
open_system(mdl)

ロボットは Simscape™ Multibody™ を使用してモデル化されており、主な構造コンポーネントは 4 本の脚および胴体で構成されています。脚は、胴体に対して脚を回転させることができる回転ジョイントを介して胴体に接続されています。ジョイントは、RL エージェントによって提供されるトルク信号によって作動します。

観測値

ロボット環境はエージェントに 44 個の観測値を提供し、それぞれは -1 ~ 1 で正規化されます。観測値は次のとおりです。

  • 胴体重心の Y (垂直方向) および Y (横方向) の位置

  • 胴体の向きを表す四元数

  • 重心における胴体の X (前方)、Y (垂直方向)、および Z (横方向) の速度

  • 胴体のロール レート、ピッチ レート、およびヨー レート

  • 各脚の股関節と膝関節の角度位置と角速度

  • 各脚の接地による法線力と摩擦力

  • 前のタイム ステップからのアクション値 (各関節のトルク)

4 本の脚すべてで、股関節と膝関節の角度の初期値は、それぞれ -0.8234 ラジアンと 1.6468 ラジアンに設定されます。関節の中立位置は 0 ラジアンに設定されます。脚は、最大限に伸ばし、地面に対して垂直に揃えたときに、中立位置となります。

アクション

エージェントは、-1 ~ 1 で正規化された 8 つのアクションを生成します。スケーリング係数を乗算することで、これらは回転ジョイントの 8 つのジョイント トルク信号に対応します。ジョイント トルクの範囲はすべて、各ジョイントで +/- 10 N·m です。

報酬

学習が実行されている間、各タイム ステップで以下の報酬がエージェントに提供されます。この報酬関数は、進行方向の正の速度に対して正の報酬を与えることで、エージェントに前進するよう推奨します。また、各タイム ステップで一定の報酬 (25Ts/Tf25 Ts/Tf) を与えることで、早期終了を回避するようエージェントに推奨します。報酬関数のその他の項は、目的の高さと方向からの大きな逸脱や過剰なジョイント トルクの使用といった、望ましくない状態を阻止するペナルティです。

rt=vx+25TsTf-50yˆ2-20θ2-0.02iut-1i2r(t) = vx(t) + 25 * Ts/Tf - - 50 * ĥ(t)^2 - 20 * θ(t)2 - 0.02 * Σ u(t-1)^2

ここで、

  • vxvx(t) は、胴体重心の x 方向の速度。

  • TsTsTfTf は、それぞれ環境のサンプル時間と最終シミュレーション時間。

  • yˆ は、目的の高さ 0.75 m からの胴体重心の高さのスケーリング済み誤差。

  • θ は胴体のピッチ角。

  • ut-1iu(t-1) は、前のタイム ステップからのジョイント i のアクション値。

エピソードの終了

学習中またはシミュレーション中に、次のいずれかの状況が発生すると、エピソードは終了します。

  • 地面からの胴体重心の高さが 0.5 m 未満 (落下)。

  • 胴体の頭または尾が地面の下にある。

  • いずれかの膝関節が地面の下にある。

  • ロール角、ピッチ角、またはヨー角が範囲外 (それぞれ +/– 0.1745 ラジアン、+/– 0.1745 ラジアン、および +/– 0.3491 ラジアン)。

環境オブジェクトの作成

観測値セットのパラメーターを指定します。

numObs = 44;
obsInfo = rlNumericSpec([numObs 1]);
obsInfo.Name = "observations";

アクション セットのパラメーターを指定します。

numAct = 8;
actInfo = rlNumericSpec([numAct 1],LowerLimit=-1,UpperLimit=1);
actInfo.Name = "torque";

強化学習モデルを使用して環境を作成します。

blk = mdl + "/RL Agent";
env = rlSimulinkEnv(mdl,blk,obsInfo,actInfo);

学習が実行されている間、例の最後に記載されている関数 quadrupedResetFcn により、初期ジョイント角度と角速度にランダムな偏差が導入されます。

env.ResetFcn = @quadrupedResetFcn;

DDPG エージェント オブジェクトの作成

DDPG エージェントは、パラメーター化された Q 値関数近似器をクリティックとして使用して方策の価値を推定します。また、連続行動空間において、パラメーター化された決定論的方策も使用します。この方策は、連続決定論的アクターによって学習されます。

深層ニューラル ネットワーク価値関数の作成の詳細については、Create Policies and Value Functionsを参照してください。DDPG エージェント用のニューラル ネットワークの作成例については、Compare DDPG Agent to LQR Controllerを参照してください。

まず、エージェントに学習させるために、次のオプションを指定します。詳細については、rlDDPGAgentOptionsを参照してください。

  • 多様な経験のセットを保存するために、経験バッファーの容量を 1e6 に指定。

  • MaxMiniBatchPerEpoch 値を指定して、学習反復ごとに最大 200 回の勾配ステップ更新を実行。

  • 学習用のミニバッチ サイズを 256 に指定。ミニバッチが小さいほど計算効率は高くなりますが、学習にばらつきが生じる可能性があります。対照的に、バッチ サイズが大きいほど学習は安定しますが、より多くのメモリが必要になります。

  • エージェントのアクターとクリティックのオプティマイザー アルゴリズムの学習率を 1e-3 に指定。学習率が大きいと、大幅な更新が発生し、動作の逸脱につながる可能性がありますが、値が低いと、最適な点に到達するまでに多くの更新が必要になる可能性があります。

  • 計算された勾配をクリップして学習アルゴリズムの安定性を高めるために、勾配しきい値を 1.0 に指定。

  • エージェントの行動空間の探索を改善するために、標準偏差を 0.1、平均アトラクション係数を 1.0 に指定。

  • サンプル時間 Ts=0.025s を指定。

% create the agent options object
agentOptions = rlDDPGAgentOptions();

% specify the options
agentOptions.SampleTime = Ts;
agentOptions.MiniBatchSize = 256;
agentOptions.ExperienceBufferLength = 1e6;
agentOptions.MaxMiniBatchPerEpoch = 200;

% optimizer options
agentOptions.ActorOptimizerOptions.LearnRate = 1e-3;
agentOptions.ActorOptimizerOptions.GradientThreshold = 1;
agentOptions.CriticOptimizerOptions.LearnRate = 1e-3;
agentOptions.CriticOptimizerOptions.GradientThreshold = 1;

% exploration options
agentOptions.NoiseOptions.StandardDeviation = 0.1;
agentOptions.NoiseOptions.MeanAttractionConstant = 1.0; 

エージェントを作成すると、アクター ネットワークとクリティック ネットワークの初期パラメーターがランダムな値で初期化されます。エージェントが常に同じパラメーター値で初期化されるように、乱数ストリームを固定します。

rng(0,"twister");

層ごとに 256 個の隠れユニットをもつエージェントの rlDDPGAgent オブジェクトを作成します。

initOpts = rlAgentInitializationOptions(NumHiddenUnit=256);
agent = rlDDPGAgent(obsInfo,actInfo,initOpts,agentOptions);

学習オプションの指定

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

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

  • [強化学習の学習モニター] ダイアログ ボックスに学習の進行状況を表示 (Plots オプションを設定)。

  • 貪欲方策の評価が 300 を超えたときに学習を停止。

trainOpts = rlTrainingOptions(...
    MaxEpisodes=10000,...
    MaxStepsPerEpisode=floor(Tf/Ts),...
    ScoreAveragingWindowLength=250,...
    Plots="training-progress",...
    StopTrainingCriteria="EvaluationStatistic",...
    StopTrainingValue=300);

並列でエージェントに学習させるには、次の学習オプションを指定します。並列で学習させるには、Parallel Computing Toolbox™ ソフトウェアが必要です。Parallel Computing Toolbox™ ソフトウェアがインストールされていない場合は、UseParallelfalse に設定します。

  • UseParallel オプションを true に設定。

  • 非同期並列ワーカーを使用してエージェントに学習させる。

trainOpts.UseParallel = true;
trainOpts.ParallelizationOptions.Mode = "async";

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

並列学習では、ワーカーは環境を使用してエージェントの方策をシミュレートし、経験をリプレイ メモリに保存します。ワーカーが非同期的に動作する場合、保存された経験の順序は確定的ではない可能性があるため、最終的な学習結果が異なる可能性があります。再現性の可能性を最大限高めるには次のようにします。

  • コードを実行するたびに、同じ数の並列ワーカーで並列プールを初期化する。プール サイズの指定については、クラスターの検出とクラスター プロファイルの使用 (Parallel Computing Toolbox)を参照してください。

  • trainOpts.ParallelizationOptions.Mode"sync" に設定して同期並列学習を使用する。

  • trainOpts.ParallelizationOptions.WorkerRandomSeeds を使用し、各並列ワーカーに乱数シードを割り当てる。既定値 -1 は、各並列ワーカーに一意の乱数シードが割り当てられることを意味します。

エージェントの学習

再現性のために乱数ストリームを固定します。

rng(0,"twister");

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

doTraining = false;
if doTraining    
    % Evaluate the greedy policy performance by taking the cumulative
    % reward mean over 5 simulations every 25 training episodes.
    evaluator = rlEvaluator(NumEpisodes=5, EvaluationFrequency=25);
    % Train the agent.
    result = train(agent, env, trainOpts, Evaluator=evaluator);
else
    % Load pretrained agent parameters for the example.
    load("rlQuadrupedAgentParams.mat","params")
    setLearnableParameters(agent, params);
end

学習済みエージェントのシミュレーション

再現性のために乱数ストリームを固定します。

rng(0,"twister");

学習済みエージェントのパフォーマンスを検証するには、ロボット環境内でこのエージェントをシミュレーションします。エージェントのシミュレーションの詳細については、rlSimulationOptions および sim を参照してください。

simOptions = rlSimulationOptions(MaxSteps=floor(Tf/Ts));
experience = sim(env,agent,simOptions);

previousRngState に保存されている情報を使用して、乱数ストリームを復元します。

rng(previousRngState);

リセット関数

function in = quadrupedResetFcn(in)
% Randomize initial conditions.

l1 = evalin('base','l1');
l2 = evalin('base','l2');

max_foot_disp_x = 0.1;
min_body_height = 0.7;
max_body_height = 0.8;
max_speed_x = 0.05;
max_speed_y = 0.025;

if rand < 0.5
    % Start from random initial conditions

    % Randomize height
    b = min_body_height + (max_body_height - min_body_height) * rand;

    % Randomize x-displacement of foot from hip joint
    a = -max_foot_disp_x + 2 * max_foot_disp_x * rand(1,4);

    % Calculate joint angles
    d2r = pi/180;
    th_FL = d2r * quadrupedInverseKinematics(a(1),-b,l1,l2);
    th_FR = d2r * quadrupedInverseKinematics(a(2),-b,l1,l2);
    th_RL = d2r * quadrupedInverseKinematics(a(3),-b,l1,l2);
    th_RR = d2r * quadrupedInverseKinematics(a(4),-b,l1,l2);

    % Adjust for foot height
    foot_height = ...
        0.05*l2*(1-sin(2*pi-(3*pi/2+sum([th_FL;th_FR;th_RL;th_RR],2))));
    y_body = max(b) + max(foot_height);

    % Randomize body velocities
    vx = 2 * max_speed_x * (rand-0.5);
    vy = 2 * max_speed_y * (rand-0.5);

else
    % Start from fixed initial conditions

    y_body = 0.7588;
    th_FL = [-0.8234 1.6468];
    th_FR = th_FL;
    th_RL = th_FL;
    th_RR = th_FL;
    vx = 0;
    vy = 0;
end

in = setVariable(in,'y_init',y_body);
in = setVariable(in,'init_ang_FL',th_FL);
in = setVariable(in,'init_ang_FR',th_FR);
in = setVariable(in,'init_ang_RL',th_RL);
in = setVariable(in,'init_ang_RR',th_RR);
in = setVariable(in,'vx_init',vx);
in = setVariable(in,'vy_init',vy);
end

参考文献

[1] Heess, Nicolas, Dhruva TB, Srinivasan Sriram, Jay Lemmon, Josh Merel, Greg Wayne, Yuval Tassa, et al. ‘Emergence of Locomotion Behaviours in Rich Environments’. ArXiv:1707.02286 [Cs], 10 July 2017. https://arxiv.org/abs/1707.02286.

参考

関数

オブジェクト

ブロック

トピック