このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
Unreal Engine シミュレーションを使用した自動バレー パーキングの可視化
この例では、Epic Games® の Unreal Engine® を使用してレンダリングされた 3D シミュレーション環境で車両運動を可視化する方法について説明します。これはSimulink での自動バレー パーキングの例に忠実に従っています。
はじめに
Automated Driving Toolbox™ は Simulink® に Unreal Engine シミュレーション環境を統合します。この環境を使用して、あらかじめ用意されたシーンで車両の運動を可視化できます。この環境では、パス プランニングおよび車両制御アルゴリズムのパフォーマンスを直感的に解析できます。Simulink での自動バレー パーキングの例では、Simulink で自動バレー パーキング システムのためにパス プランニングおよび車両制御アルゴリズムを設計する方法について説明しています。この例では、モデルを拡張して、可視化エンジンを使用してシーン内の車両運動を可視化する方法について説明します。このワークフローの手順は、次のとおりです。
3D シーンからコストマップを作成する。
シーンからルート計画を作成する。
Simulink で 3D シーンと自車を構成する。
3D シーンで車両の運動をシミュレーションして可視化する。
この例で開かれたすべてのシステムを最後に閉じることができるように、現在開いているシステムのリストを取得します。
startingOpenSystems = find_system('MatchFilter', @Simulink.match.allVariants);
3D シーンからのコストマップの作成
可視化統合にはあらかじめ用意された多くのシーンが付属しています。各シーンには、シーンの探索に使用できる高解像度のイメージが含まれています。関数 helperShowSceneImage
を使用してイメージを表示します。この例では、Large Parking Lotシーンを使用します。
% Load and display the image of the parking lot sceneName = 'LargeParkingLot'; [sceneImage, sceneRef] = helperGetSceneImage(sceneName); % Visualize the scene image figure helperShowSceneImage(sceneImage, sceneRef)
このような高解像度のイメージは、ある程度の解像度まで環境を正確に描いたものです。このイメージを使用して、パス プランニングとナビゲーションのためのvehicleCostmap
を作成できます。
まず、イメージからフリー スペースを推定します。フリー スペースとは、車両が駐車中の車、コーン、道路の境界などの他の静的オブジェクトと衝突することなく、またマークが付けられた線を横切ることなく走行できる領域です。この例では、イメージの色に基づいてフリー スペースを推定できます。Image Processing Toolbox から色のしきい値アプリを使用してセグメンテーションを実行し、イメージからバイナリ イメージを生成します。例の最後に次のように補助関数 helperCreateCostmapFromImage
を使用してバイナリ イメージを生成することもできます。
sceneImageBinary = helperCreateCostmapFromImage(sceneImage);
あるいは、事前生成されたバイナリ イメージを読み込みます。
sceneImageBinary = imread('sim3d_LargeParkingLotBinary.bmp');
次に、バイナリ イメージからコストマップを作成します。バイナリ イメージを使用して、各セルでコスト値を指定します。
% Get the left-bottom corner location of the map mapLocation = [sceneRef.XWorldLimits(1), sceneRef.YWorldLimits(1)]; % [meters, meters] % Compute resolution mapWidth = sceneRef.XWorldLimits(2)-sceneRef.XWorldLimits(1); % meters cellSize = mapWidth/size(sceneImageBinary, 2); % Create the costmap costmap = vehicleCostmap(im2single(sceneImageBinary), 'CellSize', cellSize, 'MapLocation', mapLocation); figure plot(costmap, 'Inflation', 'off');
legend off
3D シーンで使用可能な車両に基づいて、自動的に駐車する車両の寸法を指定する必要もあります。この例では、Hatchbackの寸法を使用しています。これらの寸法は、コストマップと Simulink モデルで一貫している必要があります。
centerToFront = 1.104; % meters centerToRear = 1.343; % meters frontOverhang = 0.828; % meters rearOverhang = 0.589; % meters vehicleWidth = 1.653; % meters vehicleHeight = 1.513; % meters vehicleLength = centerToFront + centerToRear + frontOverhang + rearOverhang; vehicleDims = vehicleDimensions(vehicleLength, vehicleWidth, vehicleHeight,... 'FrontOverhang', frontOverhang, 'RearOverhang', rearOverhang); costmap.CollisionChecker.VehicleDimensions = vehicleDims;
車両を囲む円の数を指定して、インフレーション半径を設定します。
costmap.CollisionChecker.NumCircles = 5;
3D シーンからのルート計画の作成
グローバル ルート計画は、駐車スポットに到達するために移動する車線セグメントのシーケンスとして記述します。Unreal Engine シミュレーションのウェイポイントの選択で説明されているツールを使用して、シーン イメージから中間ゴール位置を対話的に選択することができます。この例では、ルート計画は作成済みで、table に格納されています。シミュレーションを行う前に、モデルのコールバック関数 PreLoadFcn
により、ルート計画を読み込みます。
data = load('routePlanUnreal.mat'); routePlan = data.routePlan %#ok<NOPTS>
routePlan=5×3 table
StartPose EndPose Attributes
_______________________ _______________________ __________
44.5 8 180 -33.5 8.5 180 1×1 struct
-33.5 8.5 180 -45.2 -0.7 250 1×1 struct
-45.2 -0.7 250 -33.5 -13.5 0 1×1 struct
-33.5 -13.5 0 -20.3 -13.5 -7 1×1 struct
-20.3 -13.5 -7 -13.5 -6.8 90 1×1 struct
% Plot vehicle at the starting pose startPose = routePlan.StartPose(1,:); hold on helperPlotVehicle(startPose, vehicleDims, 'DisplayName', 'Current Pose') legend for n = 1 : height(routePlan) % Extract the goal waypoint vehiclePose = routePlan{n, 'EndPose'}; % Plot the pose legendEntry = sprintf('Goal %i', n); helperPlotVehicle(vehiclePose, vehicleDims, 'DisplayName', legendEntry); hold on end hold off
3D シーンおよび自車の構成
図を閉じてモデルを開きます。
helperCloseFigures if ~ispc error(['3D Simulation is only supported on Microsoft', char(174), ' Windows', char(174), '.']); end modelName = 'APVWith3DSimulation'; open_system(modelName) snapnow
このモデルは、3D シーンで車両を可視化するための次の 2 つのブロックを追加することで、Simulink での自動バレー パーキングの例で使用されているモデルを拡張したものです。
Simulation 3D Scene Configuration:3D シミュレーション環境を実装します。[シーン名] パラメーターは
Large parking lot
に設定されています。Simulation 3D Vehicle with Ground Following:3D シーンで車両の位置と方向を変更するインターフェイスを提供します。車両の [タイプ] は、
costmap
の車両の寸法と整合したものになるように、Hatchback
に設定されています。このブロックへの入力は、車両の位置[X, Y]
(メートル) および向首角Yaw
(度) です。これらの値は、ワールド座標系のものです。
3D シーンでの車両運動の可視化
モデルをシミュレートし、車両がどのように走行して目的の駐車スポットに到達するのかを確認します。
sim(modelName)
シミュレーションの実行に伴い、Simulink 環境はSimulation 3D Vehicle with Ground Followingブロックを介して 3D 可視化エンジンで車両の位置と方向を更新します。3D 可視化エンジンの新しいウィンドウに自車が示されます。Automated Parking Valet
の図で、計画されたパスが青で表示され、車両の実際のパスが赤で表示されます。Parking Maneuver
の図は、最終的な駐車の操縦の探索で使用されたローカル コストマップを示しています。
拡張パス プランニング システムの探索
Path Planner ブロックは、最適な RRT* (Rapidly Exploring Random Tree) アルゴリズムを使用して環境マップで実行可能なパスを計画します。プランニング アルゴリズムのパフォーマンスを確保するために、パス プランニング モジュールを変更して次の 2 つの別個のモジュールを組み込みます。
Driving Mode:ナビゲーションに駐車場全体のコストマップを使用します。この実装は、Simulink での自動バレー パーキングの例でも使用されています。
Parking Mode:最終的な駐車の操縦のためのローカル コストマップを使用します。ローカル コストマップは、正方形のコストマップのサブマップです。このマップのサイズを指定するには、Path Planner ブロック ダイアログ ボックスの [Local costmap size (m)] パラメーターを使用します。コスト マップの寸法が小さいと、最終駐車スポットまでの実行可能なパスの探索における計算負荷が大幅に軽減されます。また、同じプランナー設定で、実行可能なパスが見つかる確率も高くなります。
Path Planner サブシステムを開きます。
open_system([modelName, '/Path Planner'], 'force')
2 つのパス プランナー モジュールがEnabled Subsystem (Simulink)ブロックとして実装されています。イネーブル信号は、Behavior Planner ブロックから送信された入力 Config
バスで IsParkingManeuver
信号から送られます。Parking Mode サブシステムが有効になると、車両の現在の位置を中心としてローカル コストマップが作成されます。
モデルと図を閉じます。
endingOpenSystems = find_system('MatchFilter', @Simulink.match.allVariants);
bdclose(setdiff(endingOpenSystems,startingOpenSystems))
helperCloseFigures
まとめ
この例では、3D シミュレーションを既存の Simulink での自動バレー パーキングの例に統合して、3D 駐車場シーンで車両の運動を可視化する方法を示しました。
サポート関数
helperCreateCostmapFromImage
function BW = helperCreateCostmapFromImage(sceneImage) %#ok<DEFNU> %helperCreateCostmapFromImage Create a costmap from an RGB image. % Flip the scene image sceneImage = flipud(sceneImage); % Call the autogenerated code from the Color Thresholder app BW = helperCreateMask(sceneImage); % Smooth the image BW = im2uint8(medfilt2(BW)); % Resize BW = imresize(BW, 0.5); % Compute complement BW = imcomplement(BW); end
helperCreateMask
function [BW,maskedRGBImage] = helperCreateMask(RGB) %createMask Threshold RGB image using auto-generated code from colorThresholder app. % [BW,MASKEDRGBIMAGE] = createMask(RGB) thresholds image RGB using % auto-generated code from the colorThresholder app. The colorspace and % range for each channel of the colorspace were set within the app. The % segmentation mask is returned in BW, and a composite of the mask and % original RGB images is returned in maskedRGBImage. % Auto-generated by colorThresholder app on 22-Oct-2021 %------------------------------------------------------ % Convert RGB image to chosen color space I = RGB; % Define thresholds for channel 1 based on histogram settings channel1Min = 42.000; channel1Max = 179.000; % Define thresholds for channel 2 based on histogram settings channel2Min = 66.000; channel2Max = 191.000; % Define thresholds for channel 3 based on histogram settings channel3Min = 67.000; channel3Max = 164.000; % Create mask based on chosen histogram thresholds sliderBW = (I(:,:,1) >= channel1Min ) & (I(:,:,1) <= channel1Max) & ... (I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ... (I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max); BW = sliderBW; % Initialize output masked image based on input image. maskedRGBImage = RGB; % Set background pixels where BW is false to zero. maskedRGBImage(repmat(~BW,[1 1 3])) = 0; end
helperCloseFigures
function helperCloseFigures() %helperCloseFigures Close all the figures except the simulation visualization % Find all the figure objects figHandles = findobj('Type', 'figure'); % Close the figures for i = 1: length(figHandles) close(figHandles(i)); end end