MATLAB-Automated Driving Toolbox-Customizing Scenes

YUN·2025년 1월 19일

MATLAB/Simulink

목록 보기
3/20

SLAM에 사용할 Scene(=map) 을 Unreal Engine 을 통해 Customize 하는 방법에 대한 공부 기록이다.

MATLAB-Automated Driving Toolbox-Customizing Scenes-Step1

우선, Automated Driving Toolbox Interface for Unreal Engine Projects가 필요하다

적절한 환경 구축을 위한 SW, HW 요구 사항을 확인해보자. (중요❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗)

🍎 나는 이 부분을 보지 않고 Unreal Engine을 최신 버전으로 다운받았다가 계속 Simulink와 Unreal Engine이 연결되지 않는 오류가 발생했다.

오류 내용은 잘 기억안나는데 'Mathworks simulation'을 찾을 수 없다? 뭐 이런 오류였다.

애드온을 전부 밀고 재설치해봐도 안되고, Unreal Engine을 4.x.x 버전으로 바꿔봐도 해결되지 않았다. 그러다 위 문서를 보게되었고 Unreal Engine 버전을 5.3.x 를 다운받아 사용하니 해결되었다.

우선, Unreal Engine을 설치하자.

Epic Games Launcher을 다운받고 -> 회원가입 -> 라이브러리 -> 사용중인 MATLAB Release 버전과 호환되는 Unreal Engine 버전을 선택 해서 설치하면 된다.

정상적으로 설치됬다면

C:\Program FilesEpic Games가 생성되었을 것이다.

새로운 Scene을 Custom 하려면 Automated Driving Tool box interface for Unreal Engine Porjects 의 support package가 필요하다.

support package는 PluginsRoadRunner Project를 포함하고있다.

Plugins 안에는,,,,
🍎AutoVrtlEnv folder에는 Editableprebuilt scene들이 있다.
🍎MathWorkSimulationSimulinkUnreal Editor연결해주는 플러그인이다.

자세한 사항은 위를 읽어보면 된다.

우선, AutoVrtlEnv 프로젝트를 로컬 머신으로 가져와야한다.

경로는 C:\Program Files\EpicGames\UE_5.3\Engine\Plugins\Marketplace\MathWorks 이다.

localFolder = "C:\Program Files\Epic Games\UE_5.3\Engine\Plugins\Marketplace\MathWorks"
sim3d.utils.copyExampleSim3dProject(localFolder);

해주면 된다.

🍎 나는 Marketplace\MathWorks 가 없길래 새로 만들어줬다.


이건 Unreal Engine에 포함된 Unreal Editor 말고 MATLAB에서 제공하는 RoadRunner를 이용해 Scenen을 Edit 할 사람들만 선택적으로 수행해주면 된다.

*나는 Unreal Editor을 사용할 예정이지만 일단 설치해봤다.

이는 Linux 환경을 쓰는 사람들의 환경 구축 방법인데 나는 Windows를 쓰고있어서 그냥 건너뛰었다.

MATLAB-Automated Driving Toolbox-Customizing Scenes-Step3 로 이동.

🍎 Step-2 는 Unreal Engine과 Matlab 버전 호환성 관련 문제있는 경우 프로젝트 옮기고 ~~ 뭐 하는 단계인 것 같은데 일단 나는 문제없어서 그냥 건너뛰었다.

📌 코드 설명

openExample(examplename)exmaplename에 해당하는 예제를 현재 위치 하위의 Example 폴더에 설치한다. 이미 설치되어있는 경우 해당 예제코드를 열어준다.

이후 open_system 으로 해당 예제에 사용된 Simulink Model을 열어준다.


Simulation 3D Scene Configuration 블록톱니 바퀴를 눌러준다.


Scene source, Project를 위와같이 바꿔주고 Open Unreal Editor을 누른다.
*Project에는 내가 수정하고싶은 Scene 을 포함하는 Porject를 선택하면 된다.


Open Unreal Editor을 누르면 Unreal Editor가 열리고 내 프로젝트의 scene을 불러온다.


Content Drawer 누르고 AutoVrtlEnv 디렉토리 안에 Maps 를 찾는다. 그 안에는 Automated Driving Toolbox Interface for Unreal Engine Projects support package 에서 기본 제공하는 pre-built scene 들이 존재한다.


AutovtrlEnvRRScene(RoadRunner Scene) 이 기본 제공하는 맵들(pre-built scene들)을 그대로 사용한다면 이 단계를 건너뛰고, 기존의 pre-built scene 에 기반해서 새로운 scene을 만들어 쓰는 경우라면 이 단계를 수행해줘야한다.

1. Blueprint-Open Level Blueprint 누르기

2. File-reparent blueprint

3. Sim3DLevelScriptActor 선택 후 종료

설정이 끝났으면 다음 단계를 진행하자.

Unreal Editor 에서 Scene을 생성하거나 수정하는 방법에 대한 기술이다.
(위에 나타난 표는 Unreal Editor 에서 보여지는 맵의 이름과 그에 상응하는 3D Scene Configuration block의 파라미터 이름을 연결해놓은 표이다.)

🍎 Project 내부의 Scene들을 Unreal Editor에서는 Level 이라 부른다.

😀 Custom Scene 만들기

  1. 완전 새롭게 처음부터 Scene을 만들고 싶은 경우라면, 좌측 상단 File-New Level 을 해주면 된다.

  2. 기존에 support package에서 제공되는 Scene에 기반해서 맵을 만들고 싶은 경우는 기존의 Scene을 열고 수정한다음 File-Save Current As 로 저장해주면 된다.

나는 이렇게 사람과 Pick-up Truck 을 추가해줬다.

🍎Unreal Editor에서는 사람, Pick-up Truck 같은 prop? 들을 Actor라고 부른다.

🚗 차량의 이동 경로 설정하기

  1. 기존에 support package 에서 제공하는 pre-built Scene에 기반해서 새로운 Scene을 만들어 사용하는 경우 Select Waypoints for Unreal Engine Simulation 를 참조한다.

  2. 사용하고자 하는 Scene이 support package에서 제공하는 pre-built Scene에 기반한 것이 아닌, 완전히 새롭게 만든 Scene인 경우는 Create Top-Down Static Map of Unreal Engine Scene 를 수행해줘야한다.

나는 prebuilt-scene에 기반해서 Scene을 만들어서 Create Top-Down Static Map of Unreal Engine Scene 를 해야한다.

😄 Create Top-Down Static Map of Unreal Engine Scene

Unreal Editor 로 만든 3-D scene은 너무 크고 복잡해서 자율 주행 알고리즘을 테스트하는데 쓰기 어렵다. 테스트 알고리즘을 간단히하기위해 Unreal Editor을 이용해 2-D top-down map을 만들어 사용한다.

와 ❗❗❗❗❗❗❗ 여기가 정말 중요하다 ❗❗❗❗❗❗❗❗

나는 이 부분 별로 안중요하다 생각하고 대충 내 상황에 맞추어 따라했는데
시뮬레이션이 실행은 되나 내가 지정한 경로와 다른 경로로 시뮬레이션이 되어서 원인 계속 찾아보고 있었는데 여기가 문제였다;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;하;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

그러니까 잘 따라 해야한다 ❗

openExample('driving/VisualPerceptionIn3DSimulationExample')
open_system('straightRoadSim3D')

우선 , 아무 Simulink 모델이나 열어준다.
그리고
Simulation 3D Scene Configuration 블럭의 톱니바퀴
-> Unreal Editor 선택
-> C:\Program Files\Epic Games\UE_5.3\Engine\Plugins\Marketplace\MathWorks\AutoVrtlEnv 선택
-> Open Unreal Editor
-> Content Drawer
-> Custom Scene 선택

로 Unreal Editor에서 Custom Scene을 열어준다.

좌측 Place Actors에 Camera Actor을 나의 Scene으로 드래그앤 드랍 해준다.


그럼 일단 이렇게 이상한 카메라뷰가 뜰거다. (아직 로케이션, 로테이션 설정 안해줘서 그렇다)

🍏 로케이션 설정

우측의 Details 윈도우가 보일 것이다.

여기서 Transform-Location 의 x,y,z 파라미터로 Actor(여기선 Camera)의 x,y,z 값을 결정한다.

이렇게 액터를 드래그해서 자신이 비추고 싶은 구역으로 카메라를 이동시킨다. (우측 하단 CameraActor 의 view를 보면서 이동시키면 편할듯)

🍏 로테이션 설정

Transform-Rotation 의 x,y,z 파라미터로 Actor(여기선 Camera)의 회전을 결정한다. 우선 Example에 나와있듯이 x,y,z 를 각각 -90, -90, 0 으로 설정해주면 카메라가 아래를 바라보게 된다.

🍏 카메라 내부 파라미터 설정

이건 뭐하는 건지 모르겠다. 나중에 공부해야겠다.
일단은 그대로 따라하자❗

이제 이렇게 원하는 Camera View로 카메라를 셋팅했을 것이다.

그다음 과정 (Matlab 코드치기 전까지 screenshot 찍고,,하는 과정)은 그냥 진짜 그대로 따라하면 된다. 쉬우니 설명하지 않겠다.

Matlab 코드 쓰는 부분부터 설명하겠다.

🍎 코드 설명
high-resolution screenshot을 불러와서 sceneImage에 저장한다.
❗❗내가 지정한 ❗미터 단위❗의 xlims와 ylims에 기반해서❗❗
2-D 공간 참조객체를 sceneRef에 저장한다.

🍏 xlims와 ylims는 내가 high-resolution 으로 캡쳐한 사진의 원점 기준 x좌표 범위와 y좌표 범위를 각각 넣어주면 된다.


맵 중간의 원점 같이 생긴 액터들 클릭해보다보면 World Location (Relative Location과 다름)0,0,0 인 액터가 있다. 이 액터를 기준으로 x축,y축 거리를 계산하면 된다.

우선 점과 점 사이의 거리를 계산하기 위해 시점을 Top 으로 바꿔준다.

그후 원점과 CameraView(캡쳐본) 의 좌측 꼭짓점의 x 좌표를 구해준다. (마우스 휠을 꾹 눌러주면 된다)

4170cm -> 41.7m

Unreal Engine 에서 측정한 거리는 cm 단위이므로 m단위로 바꿔준다.


원점과 CameraView(캡쳐본) 의 좌측 꼭짓점의 y 좌표를 구해준다.

2360cm -> 23.6m

같은 방법으로 캡쳐본의 가로,세로도 구해준다 나는 7130, 4450 정도가 나왔다.

7130->71.3m
4450->44.5m

따라서 x값은 -41.7 ~ 29.6 (-41.7+71.3 으로 구함) 이고,
, y값은 23.6~68.1 (23.6+23.6+44.5 로 구함) 이다.

🍎imread 함수는 Matlab 경로에 포함된 이미지 파일의 경우 이름만 적으면되지만, Matlab 경로에 포함되지 않은 이미지 파일의 경우 절대 경로로 적어줘야한다. 그냥 캡쳐한 2D top-view 사진이 포함된 디렉토리를 Matlab 경로에 포함해주고 , myScene.png대신 내가 저장한 2D top-view 이미지의 이름을 적어주자.

🍎 scenenRef 는 2-D 공간 참조 객체로, 이미지(2-D)의 픽셀들과 Scene의 world 좌표계 (3-D) 사이의 관계가 정의되어있는 객체 이다.

sceneImage = imread("parking_youn.png");
imageSize = size(sceneImage);
xlims = [-41.7 29.6]; % in meters, 각자의 경우에 맞게 
					  %위에서 구한 x범위 넣어주세요
ylims = [23.6 68.1];  % in meters, 각자의 경우에 맞게 
					  %위에서 구한 y범위 넣어주세요

sceneRef = imref2d(imageSize,xlims,ylims);
imshow(flip(sceneImage,1), sceneRef) % Display and flip the image to keep correct image orientation after the next step
set(gca,YDir="normal",Visible="on")  % Correct Y axis for right-handed world Cartesian coordinate system
xlabel("X (m)") 
ylabel("Y (m)") 

나는 이렇게 해줬다.

xlims, ylims 는 내가 캡쳐한 2-D Top-view의 중심점을 기준으로 정하는
공간참조 객체의 x,y축 범위를 정하는 속성이다.

🚗 scene image와 spatial reference 를 이용해 waypoint를 select 할 수 있다.

🏄‍♀️Custom한 Scene에서 waypoint를 select 하기

helperGetSceneImage 함수를 까보면 내부적으로 sceneImagesceneRef 를 반환하는 함수이다. 우리는 앞에서 이미 custom scene의high resolution top-view 이미지를 이용해 sceneImagesceneRefworkspace에 저장해놨다.

따라서 위 코드를 칠 필요가 없다.

sceneName='scene의 이름'
hScene = figure;
helperShowSceneImage(sceneImage, sceneRef)
title(sceneName)

Scene의 이름은 아무렇게나 지어주면 된다. 원하는대로.


그럼 이렇게 sceneRef를 사용하는 sceneImage를 전시해준다.


🍎 코드 설명
waypoint를 select할 수 있게 해준다.

watpoint를 select 하고 'Export to workspace'- '확인'을 누른다.
그러면 나의 workspace차량의 waypoint는 wayPoints 변수에, 차량의 poses는 refPoses에 저장된다.

% Load variables to workspace if they do not exist
if exist('refPoses', 'var')==0 || exist('wayPoints', 'var')==0
    
    % Load MAT-file containing preselected waypoints
    data = load('waypointsLargeParkingLot');
    data = data.waypointsLargeParkingLot;
    
    % Assign to caller workspace
    assignin('caller', 'wayPoints', {data.waypoints});
    assignin('caller', 'refPoses', {data.refPoses});
end

MAT-file을 workspace에 로드하고, 내가 select한 waypoint와 poses로
MAT-file을 채워넣는다.

numPoses = size(refPoses{1}, 1);

refDirections  = ones(numPoses,1);   % Forward-only motion
numSmoothPoses = 20 * numPoses;      % Increase this to increase the number of returned poses

[smoothRefPoses,~,cumLengths] = smoothPathSpline(refPoses{1}, refDirections, numSmoothPoses);

Poses를 부드럽게 설정하여 waypoint를 부드럽게 (연속적으로)만든다.

if ismac
    error(['3D Simulation is supported only on Microsoft' char(174) ' Windows' char(174) ' and Linux' char(174) '.']);
end

modelName = 'VisualizeVehiclePathIn3DSimulation';
open_system(modelName);
snapnow;

Simulink model 'VisualizeVehiclePathIn3DSimulation'을 연다.

% Configure the model to stop simulation at 5 seconds.
% simStopTime 은 임의로 설정해도된다. 지금은 5초만에 simulation
% 이 끝나도록 되어있지만 10으로 바꾸면 차량 속도가 느려지고
% 10초만에 시뮬레이션이 끝나게된다.
simStopTime = 5;   
set_param(gcs, 'StopTime', num2str(simStopTime));

% Create a constant velocity profile by generating a time vector
% proportional to the cumulative path length.
timeVector = normalize(cumLengths, 'range', [0, simStopTime]);

% Create variables required by the Simulink model.
refPosesX = [timeVector, smoothRefPoses(:,1)];
refPosesY = [timeVector, smoothRefPoses(:,2)];
refPosesT = [timeVector, smoothRefPoses(:,3)];

🍎 코드 설명
simulation을 얼마동안 지속할지 설정하고,
smooth 하게 만든 posesworkspace의 변수에 저장한다.

sim(modelName);

modelName에 해당하는 modelsimulation 한다.

❗❗ 문제점
오른쪽에 Top-down view 보면 왜 Large Parkinglot으로 불러와질까,,,?
simulation model의 helper~sceneimage인가 그부분 함수 연구해봐야할듯 하다.

혹은 Simulink 예제 따라해보며 Simulink에 대한 공부가 필요할수도,,,,

아! Simulink-Simulate Simple Driving Scenario and Sensor in Unreal Engine Environment 예제
공부해보면 될듯!

profile
안녕하세요. 전자공학부 학부생의 공부 기록입니다.

0개의 댓글