Main Content

モバイル ロボットの強化学習を使用した障害物の回避

この例では、Deep Deterministic Policy Gradient (DDPG) ベースの強化学習を使用して、モバイル ロボットが障害物を回避する手法を開発します。DDPG アルゴリズムの簡単な概要については、Deep Deterministic Policy Gradient (DDPG) Agents (Reinforcement Learning Toolbox)を参照してください。

このシナリオ例では、マップ内で障害物を検出する距離センサーの読み取り値を指定して、障害物を回避するようにモバイル ロボットに学習させます。強化学習アルゴリズムの目的は、障害物との衝突を回避するためにロボットが使用するべき制御 (線形速度と角速度) について学習することです。この例では、既知の環境の占有マップを使用して、距離センサーの読み取り値の生成、障害物の検出、およびロボットに起こりうる衝突のチェックを行います。距離センサーの読み取り値は DDPG エージェントの観測値であり、線形速度と角速度の制御はアクションです。

マップの読み込み

ロボットの環境を表すマップ行列 simpleMap を読み込みます。

load exampleMaps simpleMap 
load exampleHelperOfficeAreaMap office_area_map
mapMatrix = simpleMap;
mapScale = 1;

距離センサーのパラメーター

次に、ノイズを含む距離センサーをシミュレートする rangeSensor オブジェクトを設定します。距離センサーの読み取り値は、エージェントによる観測値と見なされます。距離の読み取り値の角度位置、最大距離、およびノイズのパラメーターを定義します。

scanAngles = -3*pi/8:pi/8:3*pi/8;
maxRange = 12;
lidarNoiseVariance = 0.1^2;
lidarNoiseSeeds = randi(intmax,size(scanAngles));

ロボットのパラメーター

エージェントのアクションは 2 次元ベクトル a=[v,ω] です。ここで vω は、ロボットの線形速度と角速度です。DDPG エージェントは角速度と線形速度の両方に正規化された入力を使用します。つまり、エージェントのアクションは -1 から 1 までのスカラーであり、これを maxLinSpeed および maxAngSpeed のパラメーターで乗算して実際の制御を取得します。この線形速度および角速度の最大値を指定します。

また、ロボットの初期位置を [x y theta] として指定します。

% Max speed parameters
maxLinSpeed = 0.3;
maxAngSpeed = 0.3;

% Initial pose of the robot
initX = 17;
initY = 15;
initTheta = pi/2;

マップとロボットの位置の表示

ロボットのアクションを可視化するには、Figure を作成します。まず占有マップを表示して、ロボットの初期位置をプロットします。

fig = figure("Name","simpleMap");
set(fig, "Visible","on");
ax = axes(fig);

show(binaryOccupancyMap(mapMatrix),"Parent",ax);
hold on
plotTransforms([initX,initY,0],eul2quat([initTheta,0,0]),"MeshFilePath","groundvehicle.stl","View","2D");
light;
hold off

Figure simpleMap contains an axes object. The axes object with title Binary Occupancy Grid, xlabel X [meters], ylabel Y [meters] contains 5 objects of type patch, line, image.

環境インターフェイス

アクションを実行して観測信号と報酬信号を与える環境モデルを作成します。提供されているモデル例の名前 exampleHelperAvoidObstaclesMobileRobot、シミュレーション時間のパラメーター、およびエージェントのブロック名を指定します。

mdl = "exampleHelperAvoidObstaclesMobileRobot";
Tfinal = 100;
sampleTime = 0.1;

agentBlk = mdl + "/Agent";

モデルを開きます。

open_system(mdl)

モデルには Environment ブロックおよび Agent ブロックが含まれています。Agent ブロックはまだ定義されていません。

Environment Subsystem ブロック内には、ロボットとセンサーのデータをシミュレートするモデルが表示されます。サブシステムはアクションを受け入れ、距離センサーの読み取り値に基づいて観測信号を生成し、障害物からの距離およびアクション コマンドの出力に基づいて報酬を計算します。

open_system(mdl + "/Environment")

rlNumericSpec オブジェクトを使用し、距離センサーの角度位置ごとに十分な要素を使用して距離の読み取り値の下限と上限を指定することにより、観測パラメーター obsInfo を定義します。

obsInfo = rlNumericSpec([numel(scanAngles) 1],...
    "LowerLimit",zeros(numel(scanAngles),1),...
    "UpperLimit",ones(numel(scanAngles),1)*maxRange);
numObservations = obsInfo.Dimension(1);

アクション パラメーター actInfo を定義します。アクションは、制御コマンド ベクトル a=[v,ω][-1,1] に正規化したものです。

numActions = 2;
actInfo = rlNumericSpec([numActions 1],...
    "LowerLimit",-1,...
    "UpperLimit",1);

rlSimulinkEnv (Reinforcement Learning Toolbox)を使用して、環境インターフェイス オブジェクトを作成します。モデル、エージェント ブロック名、観測パラメーター、アクション パラメーターを指定します。exampleHelperRLAvoidObstaclesResetFcn を使用して、シミュレーションのリセット関数を設定します。この関数は、障害物の回避を開始するためにロボットを新しいランダムな位置に配置することにより、シミュレーションを再開します。

env = rlSimulinkEnv(mdl,agentBlk,obsInfo,actInfo);
env.ResetFcn = @(in)exampleHelperRLAvoidObstaclesResetFcn(in,scanAngles,maxRange,mapMatrix);
env.UseFastRestart = "Off";

学習用の Simulink® 環境を設定するもう 1 つの例については、Create Simulink Environment and Train Agent (Reinforcement Learning Toolbox)を参照してください。

DDPG エージェント

DDPG エージェントは、観測値とアクションを与えられると、クリティック値の関数表現を使用して長期の報酬を概算します。クリティックを作成するには、まず 2 つの入力 (観測値とアクション)、および 1 つの出力をもつ深層ニューラル ネットワークを作成します。深層ニューラル ネットワーク値の関数表現を作成する場合の詳細については、Create Policies and Value Functions (Reinforcement Learning Toolbox)を参照してください。

statePath = [
    featureInputLayer(numObservations, "Normalization","none","Name","State")
    fullyConnectedLayer(50,"Name","CriticStateFC1")
    reluLayer("Name","CriticRelu1")
    fullyConnectedLayer(25,"Name","CriticStateFC2")];
actionPath = [
    featureInputLayer(numActions,"Normalization","none","Name","Action")
    fullyConnectedLayer(25,"Name","CriticActionFC1")];
commonPath = [
    additionLayer(2,"Name","add")
    reluLayer("Name","CriticCommonRelu")
    fullyConnectedLayer(1,"Name","CriticOutput")];

criticNetwork = layerGraph();
criticNetwork = addLayers(criticNetwork,statePath);
criticNetwork = addLayers(criticNetwork,actionPath);
criticNetwork = addLayers(criticNetwork,commonPath);
criticNetwork = connectLayers(criticNetwork,"CriticStateFC2","add/in1");
criticNetwork = connectLayers(criticNetwork,"CriticActionFC1","add/in2");
criticNetwork = dlnetwork(criticNetwork);

次に、rlOptimizerOptions を使用してクリティック オプティマイザーのオプションを指定します。

最後に、指定した深層ニューラル ネットワークとオプションを使用してクリティック表現を作成します。クリティックに関するアクションと観測値の仕様も指定しなければなりません。これは環境インターフェイスから取得します。詳細については、rlQValueFunction (Reinforcement Learning Toolbox)を参照してください。

criticOptions = rlOptimizerOptions("LearnRate",1e-3,"L2RegularizationFactor",1e-4,"GradientThreshold",1);
critic = rlQValueFunction(criticNetwork,obsInfo,actInfo,"ObservationInputNames","State","ActionInputNames","Action");

DDPG エージェントは、観測値を与えられると、アクター表現を使用して、実行するアクションを決定します。アクターを作成するには、まず 1 つの入力 (観測値)、および 1 つの出力 (アクション) をもつ深層ニューラル ネットワークを作成します。

最後に、クリティックと同様の方法でアクターを作成します。詳細については、rlContinuousDeterministicActor (Reinforcement Learning Toolbox)を参照してください。

actorNetwork = [
    featureInputLayer(numObservations,"Normalization","none","Name","State")
    fullyConnectedLayer(50,"Name","actorFC1")
    reluLayer("Name","actorReLU1")
    fullyConnectedLayer(50, "Name","actorFC2")
    reluLayer("Name","actorReLU2")
    fullyConnectedLayer(2, "Name","actorFC3")
    tanhLayer("Name","Action")];
actorNetwork = dlnetwork(actorNetwork);

actorOptions = rlOptimizerOptions("LearnRate",1e-4,"L2RegularizationFactor",1e-4,"GradientThreshold",1);
actor = rlContinuousDeterministicActor(actorNetwork,obsInfo,actInfo);

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

エージェントのオプションを指定します。

agentOpts = rlDDPGAgentOptions(...
    "SampleTime",sampleTime,...
    "ActorOptimizerOptions",actorOptions,...
    "CriticOptimizerOptions",criticOptions,...
    "DiscountFactor",0.995, ...
    "MiniBatchSize",128, ...
    "ExperienceBufferLength",1e6); 

agentOpts.NoiseOptions.Variance = 0.1;
agentOpts.NoiseOptions.VarianceDecayRate = 1e-5;

rlDDPGAgent オブジェクトを作成します。変数 obstacleAvoidanceAgent は、Agent ブロック用のモデルで使用されます。

obstacleAvoidanceAgent = rlDDPGAgent(actor,critic,agentOpts);
open_system(mdl + "/Agent")

報酬

エージェントの報酬関数は以下のようにモデル化されます。

エージェントには最も近い障害物を回避するための報酬が与えられ、これによって最悪のシナリオが最小限に抑えられます。さらに、エージェントには、線形速度が高速の場合は正の報酬が与えられ、角速度が高速の場合は負の報酬が与えられます。この報酬手法により、エージェントが円を描くように移動する動作が抑制されます。報酬を調整することが、エージェントに適切に学習させる上で重要であるため、報酬はアプリケーションによって異なります。

エージェントの学習

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

  • 最大 10000 個のエピソードについて学習させ、各エピソードは最大 maxSteps タイム ステップ分継続します。

  • [Episode Manager] ダイアログ ボックスに学習の進行状況を表示し (Plots オプションを設定)、コマンド ライン表示を有効にします (Verbose オプションを true に設定)。

  • 50 個の連続するエピソードにわたってエージェントの受け取る平均累積報酬が 400 を超えた場合は、学習を停止します。

詳細については、rlTrainingOptions (Reinforcement Learning Toolbox)を参照してください。

maxEpisodes = 10000;
maxSteps = ceil(Tfinal/sampleTime);
trainOpts = rlTrainingOptions(...
    "MaxEpisodes",maxEpisodes, ...
    "MaxStepsPerEpisode",maxSteps, ...
    "ScoreAveragingWindowLength",50, ...
    "StopTrainingCriteria","AverageReward", ...
    "StopTrainingValue",400, ...
    "Verbose", true, ...
    "Plots","training-progress");

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

doTraining = false; % Toggle this to true for training. 

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

Reinforcement Learning Episode Manager を使用すると、学習の進行状況をエピソード単位で追跡できます。エピソード数の増加に伴って、報酬値の増加を確認する必要があります。

シミュレーション

学習済みのエージェントを使用して、障害物を回避しながらマップ内を走行するロボットを 200 秒間シミュレーションします。

set_param("exampleHelperAvoidObstaclesMobileRobot","StopTime","200");
out = sim("exampleHelperAvoidObstaclesMobileRobot.slx");

可視化

距離センサーの読み取り値を使用して、ロボットが環境内を走行するシミュレーションを可視化するには、補助関数 exampleHelperAvoidObstaclesPosePlot を使用します。

for i = 1:5:size(out.range,3)
    u = out.pose(i,:);
    r = out.range(:,:,i);
    exampleHelperAvoidObstaclesPosePlot(u,mapMatrix,mapScale,r,scanAngles,ax);
end

Figure simpleMap contains an axes object. The axes object with title Binary Occupancy Grid, xlabel X [meters], ylabel Y [meters] contains 6 objects of type patch, line, image. One or more of the lines displays its values using only markers

拡張性

このエージェントを使用して、別のマップでの走行をシミュレートすることができます。オフィス環境の LIDAR スキャンから生成された別のマップを、同じ学習済みモデルと共に使用します。このマップは、学習後に学習済みモデルを適用するという、より現実的なシナリオを表しています。

マップの変更

mapMatrix = office_area_map.occupancyMatrix > 0.5;
mapScale = 10;
initX = 20;
initY = 30;
initTheta = 0;
fig = figure("Name","office_area_map");
set(fig,"Visible","on");
ax = axes(fig);
show(binaryOccupancyMap(mapMatrix,mapScale),"Parent",ax);
hold on
plotTransforms([initX,initY,0],eul2quat([initTheta, 0, 0]),"MeshFilePath","groundvehicle.stl","View","2D");
light;
hold off

Figure office_area_map contains an axes object. The axes object with title Binary Occupancy Grid, xlabel X [meters], ylabel Y [meters] contains 5 objects of type patch, line, image.

シミュレーション

新しいマップ上でロボットの軌跡をシミュレーションします。後でエージェントを再学習させて再調整する必要がある場合に備えて、シミュレーション時間をリセットします。

out = sim("exampleHelperAvoidObstaclesMobileRobot.slx");
set_param("exampleHelperAvoidObstaclesMobileRobot","StopTime","inf");

可視化

for i = 1:5:size(out.range,3)
    u = out.pose(i,:);
    r = out.range(:,:,i);
    exampleHelperAvoidObstaclesPosePlot(u,mapMatrix,mapScale,r,scanAngles,ax);
end

Figure office_area_map contains an axes object. The axes object with title Binary Occupancy Grid, xlabel X [meters], ylabel Y [meters] contains 6 objects of type patch, line, image. One or more of the lines displays its values using only markers