본 포스팅은 아래의 MathWorks 김종헌 프로님의 Path Planning 시리즈 중 아래의 비디오를 정리한 것입니다.
이 비디오에서는 모바일 패스플래닝 시리즈 비디오의 두번째 파트로 MATLAB에서 제공하는 path planner를 사용함에 있어 기본이 되는 몇가지 요소들 대해서 설명한다. 그 두 번째 시간으로 Path Planning을 위한 주변 환경 모델링에 대해서 설명한다.
Collision Checking
먼저 충돌 검출에 대해 얘기해보자. 로봇을 위해 계획된 경로나 궤적이 환경 내에서 다른 장애물과 충돌을 할지 안할지를 확인시켜주는 것을 충돌 검출이라고 부른다.
그러면 충돌을 검출할 때 어떤 점들을 고려해야 할까?
-
일반적으로 주행 환경이 복잡한 형상을 가진 경우, 즉 환경을 구성하고 있는 어떤 여러 가지 장애물들이 있는데 이 장애물들의 형상이 굉장히 복잡해서 로봇의 형상까지 고려를 하게 되면 이게 부딪힐지 안 부딪힐지 좀 애매하다 혹은 안전을 위해 너무 충돌을 피해 멀리 돌아가면 비효율성이 커지는 현상이 있을 수 있다.
-
그리고 너무 자세하게 그 장애물을 표현하려고 그러면 그 장애물과 로봇 사이에 충돌이 어디서 어느 시점에 발생하는지를 충돌 확인 전에 충돌을 검색하는데 시간이 오래 걸릴 수 있다. 그래서 적당한 수준으로 환경을 압축해서 표현을 함으로써 효율성을 높여줄 필요가 있다. 결국 표현 방법에 있어서 계산 시간과 충돌 검출 사이에 상호 trade off가 존재하게 된다.
-
또, 환경을 표현하는 데 있어서 그림 1에서 보는 것처럼 3D 환경에서 점 하나 하나를 표현한다면 보기에는 멋지지만, 이 복잡한 환경을 너무 세밀하게 표현하다보니 정보를 저장하는데 너무 많은 메모리를 소비할 수 있다. 그래서 환경을 어떻게 추상화 할 거냐에 따라서 메모리 사이즈나 충돌 검출 속도에 영향을 주게 된다. 그렇다고 너무 많이 추상화 시키게 되면 존재할 충돌을 확인 못할 수도 있고, 충돌이 없는 공간에 충돌이 있다고 판단될 수도 있다.
-
마지막으로는 이동 물체에 대한 어려운 점도 있다. 이동 물체에 대해서 고려를 하는 게 생각보다 쉽지 않은 게 다른 물체의 이동 경로를 예측하기도 힘들지만, 안다고 하더라도 이 경로들이 어느 시점에 어디에서 충돌이 있을지를 보려면 예측이 필요한 시간 동안 내부적으로 시뮬레이션을 해서 각 시간대에서 일일히 충돌 검출을 해야한다. 그렇지 않으면 다른 타이밍에 지나가기 때문에 별 문제가 없는 상황에서도 충돌을 피하기 위해 로봇이 멈추거나 한참을 돌아갈수도 있기 때문이다.
결론적으로는 이렇게 환경을 표현하는 방식은 적당한 수준의 앱스트랙션을 필요로 하고 충돌 검출 알고리즘은 반복적으로 엄청나게 많은 수의 충돌을 체크해야 하므로 단순하면서도 굉장히 빨라야한다.
MATLAB의 환경 표현 방식
Recall from Planner Layout
그림 2. MATLAB의 planner 기본 구성
1편의 “Path Planning이란?” 편에서 언급한 것 처럼 MATLAB에서 제공하는 Path Planner는 State space, state validator, environment로 구성되어 있어서 path planner를 구성할 때 “내 주변 환경은 이렇게 구성돼 있어” 하고 환경 정보를 제공하고, 이를 근거로 state validator가 충돌 검사를 한다고 얘기한 바 있다.
그럼 이 때 사용할 수 있는 환경 정보의 형태는 어떤 것들이 있을까?
아래의 그림 3에서 볼 수 있는 것 처럼 Navigation Toolbox의 Path Planner는 여러가지 환경 표현 방식을 지원하고 있다. 크게 정적인 환경(Static Environments)과, 동적인 환경(Dynamic Environment)이 있다. 정적인 환경에서도, 그래프를 사용한 환경 표현 방식, 그리드를 이용해 환경을 이산화하는 방식 이것도 2차원에서 사용하는 맵, 3차원에서 사용하는 맵 등이 있다. 그리고 discrete geometry라고 해서 정해져 있는 특정한 형상으로 주변 물체를 표현을 할 수도 있는데 박스, 구, 실린더, 아니면 캐드 파일에서 메쉬 자체를 가져와 형상을 표현할수도 있다. 마지막으로는 이동 장애물을 표현하기 위한 dynamic capsule list도 있다.
Graph-based Environment Represenatation
그림 4. 그래프 기반 환경 표현 방식
첫 번째 환경 표현 방식으로서 그래프 방식이 있다. 그래프 방식이라는 건 노드와 엣지로 수학적 구조를 표현하는 방식이다. 주로 이동이 가능한 도로의 망을 표현하는 지도라던가, 커뮤니케이션 네트워크에서 연결성을 표현하는데 주로 사용되는 방법이다.
이렇게 그래프를 이용해서 환경을 표현하면 path planning을 하는데 상당히 효율적이다. Graph를 사용하면 갈 수 있는 곳이 노드로써 표현되고 이 노드들을 연결하는 길 혹은 통로가 엣지로 표현되기 때문에 로봇이 탐색해야되는 공간을 극단적으로 축소시킬 수 있다. 이로 인해 경로를 아주 효율적으로 검색할 수 있게 된다.
자율 주행차와 같은 모바일 플랫폼에서는 도로와 도로 내부의 차선들을 이렇게 graph로 표현함으로써 교차로에서 연결성을 표현할 수 있다. 그래서 이 위에서 글로벌 path planning을 하는 것을 보통 route planning이라고 하기도 한다. 휴대폰 내비게이션에서 주행 경로를 찾는 과정이 바로 이 방법을 사용한다.
navGraph
그래서 Navigation Toolbox에서는 이러한 그래프 형태의 환경을 표현하기 위해서 navGraph라는 object를 제공하며, 아래와 같이 여러 가지 메소드들을 가지고 있다.
methods | |
---|---|
Find IDs of links | |
Find IDs of states | |
Find state vectors of state indices | |
Find indices for queried state vectors | |
Find successive state indices and costs | |
Plot graph representation |
plannerAStar
나중에 설명하겠지만, 이렇게 graph로 표현된 환경에서 사용할 수 있는 plannerAStar를 이용해 최소 비용을 가진 경로를 계획할 수도 있다.
그림 4.1. plannerAStar를 이용한 최소 비용 경로 예시
Grid-based Environment Representation
그림 5. 레이저 스캐너를 이용해 만든 확률적 occupancy grid map 예시
다음은 occupancy grid 이다. Occupancy grid는 로봇 주변의 공간을 grid cell로 이산화하여 어떤 grid cell을 점유하는 물체가 존재하는지 안 하는지를 확률적으로 표현해주는 환경 표현 방식이다.
만약, 공간안에 센서를 위치해놓고, 장애물의 위치에 대한 거리 값을 받았다면 장애물이 존재하는 거리와 방위를 이용해 장애물이 있는 곳을 확인하여 그 거리까지는 장애물이 없었으니 장애물 앞쪽은 점유되어 있지 않다는 0에 가까운 확률적인 값을 해당 grid cell에 업데이트하고 장애물이 있는 위치에서는 이 공간이 장애물에 점유되어 있다는 1에 가까운 확률적인 값을 해당 grid cell에 업데이트하게 된다.
이 때 센서로부터의 거리에 따라 점유/비점유에 대한 확률을 떨어뜨려 측정거리에 대한 오차를 표현할 수도 있다. 또한, 센서와 가까운 영역은 하나의 grid cell이 더 많은 센서 값으로 확인이 될테니 더 높은 점유 혹은 비점유 확률을 가질 것이고, 센서와 먼 영역은 하나의 grid cell이 가까운쪽보다는 적은 수의 센서값으로 확인이 될테니 점유 혹은 비점유 확률을 가지게 되는 효과도 가지게 된다. 그리고, 시간에 따라 더 많은 측정값이 누적될 경우 공간에 대한 점유/비점유 확률이 점점 높아지는 특징도 있어 굉장히 현실적이다.
Occupancy grid는 점유와 비점유 정보만 가지고 1/0 값으로만 표현되는 binary occupancy grid도 있고, 그림 5에서와 같이 0과 1사이의 점유 확률 정보를 가지고 있는 probabilistic occupancy grid도 있다.
이런 occupancy grid를 사용했을 때 장점은 Bayesian filter를 이용해 공간 점유 확률을 계산함으로써 센서의 노이즈에 대응할 수도 있고, 거리에 대한 정확도 문제도 고려할 수 있다는 것이다. 그리고, 장애물의 위치만 확인할 수 있는 것이 아니라 주행이 가능한 free space도 찾을 수 있으며 장애물의 종류, 크기 방향 등을 검출하는 과정 없이 장애물의 점유한 공간을 확인할 수 있어 효과적이다. 거기에 더불어, 센서의 종류에 상관없이 센서의 위치와 센서 측정값 만을 사용하기 때문에, 센서들의 값을 융합하기 좋은 sensor fusion framework으로도 사용할 수 있다. 하지만, 단점은 정적인 환경에 적합하다는 점이다. 주변에 이동물체가 있는 경우, 장애물이 이미 이동하여 장애물이 그곳에 없을 때도 장애물이 위치하고 있다고 판단될 수 있기 때문이다.
2D Occupancy Grid: occupancyMap and binaryOccupancyMap
다시 한번, occupancy grid는 점유/비점유를 1과 0으로만 표현하는 binary occupancy grid와 0에서 1사이의 확률값을 가지는 probabilistic occupancy grid가 있다고 언급하였다. MATLAB의 Navigation toolbox는 두 종류를 모두 지원하고 있다.
예제를 한번 살펴보면, 이번에는 이미지를 사용해서 미리 만들어진 맵을 가져오도록 하자 (예제 링크).
% To open a shipped example folder
openExample('nav_robotics/ConvertPGMImageToMapExample')
% Import the image using imread
image = imread('playpen_map.pgm');
% Crop the image to the playpen area.
imageCropped = image(750:1250,750:1250);
% Normalize and subtract image values
% from 1 to get occupancy values.
imageNorm = double(imageCropped)/255;
imageOccupancy = 1 - imageNorm;
% Create the occupancyMap with
% 20 cells per meter resolution.
map = occupancyMap(imageOccupancy,20);
show(map);
% Inflate the map to add buffer around obstacles
robotSize = 0.3;
inflate(map,robotSize/2);
show(map);
그림 6. Map이미지로부터 occupancy grid를 만들고 이를 inflate하는 예시
딱 관심있는 영역만 맵으로 가져오기 위해 이미지를 cropping 했다. 그리고 이미지는 색깔을 표현하는 방식이 grey scale인 경우 0부터 255까지 값을 가지고 intensity를 표현하고 있는데 0이 검정, 255가 흰색이니 255로 나눈 다음에 1에서 이값을 빼주어야 이미지에서 검정색으로 표현된 장애물이 1의 값을 가지고, free space가 0의 값을 가지게 된다.
occupancy 값을 map에 넣고, 1m 안에 그리드 셀이 20개가 속하도록 resolution 값을 입력한다. 그럼 이제 occupancy map이 만들어 진다.
그리고 난 다음에는 패스 플래닝을 할 때 일반적으로 내 로봇의 상태를 한 지점에서의 위치와 방위로 표현하니 로봇의 크기가 반영되지 않기 때문에, 로봇의 크기가 반영되어 충돌 검출을 하기 위해 occupancy map에서 장애물에 오히려 로봇의 크기를 반영함으로써 Path planning을 하게 되면 충돌검출에 대한 컴퓨팅을 최소화할 수 있다.
그래서 그림 6의 마지막 장면에서 볼 수 있는 것 처럼 inflate라는 메소드를 이용해서 로봇 사이즈의 반지름 만큼 장애물에 반영한다.
Get/Set Occupancy Probability of Locations
앞에서는 이미 맵을 가지고 있다고 가정하고 occupancy map을 만들었다면 이번에는 센서에서 오는 정보를 이용해 점유를 표현하는 방법을 보자.
Occupancy map의 각 그리드 셀의 점유도를 업데이트하는 방법은 여러가지가 있는데 첫번째는 matrix 단위로 업데이트 하는 방식이다.
methods | |
---|---|
Convert occupancy map to matrix | |
Update occupancy probability at locations |
현재의 Occupancy 정보를 얻을 때도 occupancyMatrix라는 method를 이용해 전체 map을 matrix화 하여 받고, 정보를 update할 때도, 셀 하나 하나를 업데이트 하지 않고 전체 map을 가지고 있는 matrix로 업데이트 하는 방법이다.
이와는 반대로 getOccupancy와 setOccupancy의 경우는 맵상의 어떤 위치에 대해 해당 그리드 셀에 대해서만 점유도 정보를 가지고 오고 업데이트하는 방법이다.
methods | |
---|---|
Get occupancy probability of locations | |
Set occupancy probability of locations |
마지막 방식은 센서 데이터를 활용하는 방식이다. 일반적으로 센서 데이터를 가지고 온다는 것은 딱 하나의 셀에만 영향을 미치는 것이 아닌 장애물이 위치한 셀과 센서 위치 사이의 모든 셀이 영향을 받기 때문에 로봇의 위치에서 센서 측정값이 발생한 위치까지 ray casting이라는 기법을 이용해 직선으로 빛을 쏴준다고 가정하고 이 빛이 지나가는 모든 셀을 검색해서 중간에 위치한 셀들은 모두 freespace, 마지막에 위치한 cell은 장애물이 점유한 것으로 정해줄 수 있다.
methods | |
---|---|
Insert ray from laser scan observation | |
Compute cell indices along a ray | |
Find intersection points of rays and occupied map cells |
예제 코드를 보면,
% Create an empty occupancy grid map.
map = occupancyMap(10,10,20);
% Specify the pose of the vehicle, ranges, angles,
% and the maximum range of the laser scan.
pose = [5,5,0]; maxrange = 20;
ranges = 3*ones(100,1); angles = linspace(-pi/2,pi/2,100);
% Create a lidarScan object with the specified ranges and angles.
scan = lidarScan(ranges,angles);
% Insert the laser scan data into the occupancy map.
insertRay(map,pose,scan,maxrange); show(map);
getOccupancy(map,[8 5])
% Add a second reading to the occupancy values.
insertRay(map,pose,scan,maxrange); show(map);
getOccupancy(map,[8 5])
처음에 10미터 10미터 크기에 resolution이 20인 map을 만들고, 그리고 로봇의 pose가 5,5에 0도인 곳에서 20m 거리, -180도에서 180까지 커버리지를 갖는 센서를 사용해 센서 신호를 만든다. 만들어진 센서 신호는 3미터 거리에 모든 방향에서 장애물이 있다는 신호이다.
이 센서 신호는 scan이라는 변수에 입력되는데 insertRay 함수를 이용해 pose 위치에서 scan이라는 센서 신호가 발생했을 때 map을 업데이트한다.
그럼 아래와 같은 그림이 그려지고 이 때 가로 8, 세로 5 미터 지점(그림에서 가장 오른쪽인 호의 꼭지)에서 occupancy를 보면 0.7의 값이 나온다.
그림 7. occupancyMap으로부터 장애물의 위치와 확률을 도시한 예시
가로 8, 세로 5미터 지점(그림에서 가장 오른쪽인 호의 꼭지)은 위치는 로봇에서 3 미터 떨어진 정면에 위치한 점이다. 그럼 점유된 곳일 것이다. 그럼 같은 위치에서 같은 센서로 한번더 측정하면 이미 가지고 있던 확률에 확신이 더해지니 점유도가 더 높아진게 보인다.
Coordinate Conversion in Occupancy Grid Map
그림 8. grid, world, local 좌표계 간의 관계
Occupancy grid는 아무래도 공간을 표현하는 방법이다보니 좌표계가 존재할 수밖에 없다. 이 안에서는 세가지 좌표계가 존재한다.
우선, World Frame은 로봇이 동작하는 환경에 대한 절대적인 좌표계를 말한다. local 좌표계는 큰 맵이 있고, 이 occupancy grid는 로봇 주변 특정 영역에 대해서만 표현하는 맵인 경우에 로봇에 대한 자기 기준 좌표계이다. 마지막으로 grid 좌표계는 map을 표현하는 matrix에서 좌상단부터 인덱스를 갖다가 매겨서 전체 그리드에서 해당 grid cell의 위치를 표현하는 좌표계이다. 이 세 가지 좌표계는 서로 간의 상관관계를 가지고 있다. 그리고 이 상관 관계를 정의하는 property들이 있어 이 값을 어떻게 지정하느냐에 따라 각 coordinate system간의 변환식이 달라진다.
Occupancy grid object에서는 이런 좌표계 간의 변환에 대해 method를 제공하고 있다. 따라서, 한번 occupancy grid가 생성되면 각 좌표계 간의 변환은 복잡한 수학적 고민없이 method를 통해 수행할 수 있다.
Methods | |
---|---|
Convert grid indices to local coordinates | |
Convert grid indices to world coordinates | |
Convert local coordinates to grid indices | |
Convert local coordinates to world coordinates | |
Convert world coordinates to grid indices | |
Convert world coordinates to local coordinates |
vehicleCostmap for collision-checking
Occupancy grid의 또 다른 표현 방식중 하나인 vehicleCostmap은 map위에 장애물을 설정하여 path planning을 할 때, 이 장애물을 회피할 수 있도록 내 로봇의 크기를 효율적으로 표현하는 방법이다.
vehicle cost map을 생성할 때 처음에는 일반적인 occupancy grid와 동일하다. 차이가 있다면, 내 로봇의 크기를 장애물에 반영하기 위해 inflate를 해야 하는데 이때 Collision checker 라는 정보를 추가로 입력하는 것이다.
costmap = vehicleCostmap(occupancy_grid_map, 'CollisionChecker', collision_checker_config)
그림 9. vehicleCostmap을 활용해 map의 충돌 가능성을 확인하는 예시
collision checker 정보를 만들 때는 기존의 occupancy grid와 다르게 로봇의 가로-세로 길이비를 고려할 수 있다. 만약 로봇의 전체 크기를 아우르는 너무 큰 반지름을 사용하여 inflate했을 때, 로봇의 폭보다는 넓지만 길이보다는 좁은 통로에 대해 충돌이 발생한다고 잘못판단할 수 있기 때문에 inflation collision checker 함수는 몇 개의 원으로 입력된 차량의 형상을 커버할 수 있는 configuration을 생성하여 collision check를 수행하게 한다. 만약 하나의 큰 원 대신 3개의 작은 원으로 차량을 표현하면 폭과 길이방향으로 약간의 마진을 고려하여 차량을 표현할 수 있기 때문에, 장애물을 표현하는 영역의 크기가 작아져 탐색 공간을 훨씬 효율적으로 사용할 수 있게 된다.
vehicleDims = vehicleDimensions(vehicleLength, vehicleWidth);
collision_checker_config = inflationCollisionChecker(vehicleDims,numCircles)
그림 10. inflation을 통해 차량을 단순화하여 모델링하는 경우 여러개의 원으로 차량의 형상을 커버할 수도 있다.
Case Study: Creating the Occupancy Grid in Parking Lot
Path planning을 위해 주변 환경에 대한 occupancy grid를 만들려면 어떻게 해야 될까?
그림 11. 항공사진과 point cloud 맵을 이용해 occupancy grid를 만드는 방법
제안하고자 하는 아이디어는 두 개이다. 하나는 혹시 그곳의 항공사진이 있다면 semantic segmentation 같은 딥러닝 알고리즘을 이용해서 장애물과 장애물이 아닌 곳을 구분해서 이 정보를 이용해 occupancy grid를 만들수 있을 것이다. 다른 한 아이디어는 라이더 센서를 달고 SLAM을 이용해 주변 Map을 구성하고 포인트 클라우드 프로세싱을 이용해 맵을 만들 수도 있을 것이다. 첫 번째 방법은 MathWorks에서 제공하는 예제에도 있으니까 이걸 참고하도록 하고 여기서는 두 번째 방법을 어떻게 할수 있는지 알아보자.
Creating the Occupancy Grid from Point Cloud Map
우선 LIDAR를 이용한 3차원 SLAM을 통해 Map을 만들도록 하자. 지금은 SLAM에 대해 다루지 않기 때문에, 여기 예제 링크를 참고하여 point cloud를 이용해 SLAM을 하는 방법을 학습하자.
그리고는 이 포인트 클라우드를 ndtMap
변수에 저장해서 NDT 형태의 맵을 만들었다. NDT 방식의 맵에 대해 아는 사람도 있겠지만, 간단하게 설명하자면 전체 공간을 3차원 voxel로 나누어 voxel 안의 point 분포에 대한 확률적인 정보를 저장한 맵이다. 이를 이용하면 맵을 이용한 localization을 쉽게 할 수 있고, map을 저장하기 위한 메모리를 줄일 수 있다는 장점이 있다. 만약, 우리가 사용할 occupancy map의 resolution과 동일한 voxel 사이즈로 NDT 맵을 만들면 우리는 결국 2차원의 occupancy map에서 점유 정보를 이 voxel로 부터 얻을 수 있다.
그리고는 우선 비어 있는 vehicle cost map을 만들고, inflation 값을 지정한 다음 비어 있는 코스트 맵에 NDT 맵에서 추출한 점유 정보를 입력하면 맵이 최종적으로 만들어진다.
그림 13. point cloud 데이터로부터 얻은 NDT 맵과, 이를 통해 최종적으로 얻게되는 cost map
% Create NDT Map
voxelSize = 1;
ndtMap = pcmapndt(pointCloud,voxelSize);
% Visualize the NDT map.
Figure; show(ndtMap);
% Get the mean points of the NDT map.
pts = ndtMap.VoxelMean;
xyPoint = round([pts(:,1),pts(:,2)]);
% Create a costmap
mapWidth = 120; % width of costmap
mapLength = 100; % Length of costmap
costVal = 0; % Set the empty space value to zero.
cellSize = 1; % Side length of each square cell
costmap = vehicleCostmap(mapWidth, mapLength, …
costVal, CellSize=cellSize,MapLocation=[-80 -30]);
costmap.CollisionChecker.InflationRadius = 0.25; % inflation radius
% set the cost of each mean point to 1.
costVal = 1;
setCosts(costmap,xyPoint,costVal);
Figure; plot(costmap);
Multilayer Grid Maps
이런 occupancy grid는 또한 multi layer grid map이라는 형태로도 제공된다.
multi layer grid map이라는 것은 같은 영역에 대해 다른 정보를 가지고 있는 여러 개의 맵을 layer로 쌓아서 한꺼번에 저장을 해놓는 형태라고 볼 수 있다. 각각의 레이어들은 동기화가 돼 있어서 시간에 대해 map의 변화를 multilayer에 저장함으로써 map에 동적인 정보를 저장할 수도 있고, 그림 14처럼 로봇에 여러 개의 센서를 달았을 때 1번 센서의 값들만 보여주는 맵, 2번 센서의 값들만 보여주는 맵, 그리고, 이 값들을 모두 통합한 fusion map 등 각 맵들이 동기화되어 있다는 장점을 이용해 다양한 정보를 저장해둘수 있다.
3D map representation
MATLAB Navigation Toolbox는 3차원 occupancy grid도 제공한다. 아래 그림 15처럼 장애물들이 삼차원 형상을 가지고 있고, 이를 3차원 경로로 회피한다고 해보자.
이와 같은 상황에서 그림 16과 같은 3차원 occupancy grid가 사용될 수 있다. 만약, 이런 정보를 포인트 클라우드 형태로 가지고 있다면, 메모리도 많이 필요하고, 충돌 검출을 위한 알고리즘의 수행시간도 오래걸리겠지만, 3차원 occupancy grid에서는 Voxel 형태로 데이터를 최적화해서 갖고 있기 때문에 필요한 메모리 사이즈도 작다.
그림 16. Motion Planning with RRT for Fixed-Wing UAV (관련 링크)
또, 3차원 occupancy map도 그림 17에서와 같이 validator를 통해 충돌이 발생하는지 찾아낼 수 있다.
그림 17. Collision check in 3D occupancy map
dynamicCapsuleList
그림 18. 충돌 감지를 위한 캡슐 형태의 객체
dynamicCapsuleList는 이동 물체간 충돌 검출에 필요한 연산을 최소화 하기 위해 주변 이동 물체를 가로비가 큰 사각형 앞뒤에 특정 반지름 만큼의 반원을 붙이 캡슐 형태로 간단히 표현하는 방식이다. 다른 형상도 아니고 캡슐 형상을 사용하는 이유는 사각형 물체의 앞뒤에 버퍼가 되는 공간을 마련할 수 있다는 점과 하나의 원으로 물체를 표현하면 측면으로 너무 많은 버퍼를 두기 때문에 가로 길이가 큰 사각형으로 표현하여 planner의 효율성을 높일수 있다는 점, 그리고, 형상이 간단하여 두 캡슐 사이의 거리를 쉽게 계산할 수 있어 motion planning 중에 엄청난 수로 반복적인 계산이 필요한 충돌 체크에 대한 연산 부하를 줄일 수 있다는 점이다.
dynamicCapsuleList object를 이용해서 주변의 여러 이동 물체들의 미래 궤적을 정의하고 정해진 시간 간격대로 이 캡슐들이 점유하는 공간 사이의 겹침을 체크하는 checkCollision 함수를 사용하게 되면 손쉽게 복잡하고, 연산량이 많은 이동물체간의 충돌을 체크할 수 있다.
아래 그림 19의 영상을 보면 전체 캡슐리스트에서 특정 시간 구간내에서의 충돌을 검출하는 것을 볼 수 있다.
Examples of Finding Optimial Trajectory
예로써 자율주행을 위한 패스 플래닝을 구성해 보면, 지금 보시는 것처럼 각각의 오브젝트들이 미래 예측 궤적을 캡슐 리스트로 표현을 함으로써 가까운 미래에 주변 물체와 충돌하는지 확인할 수 있다.
그림에서 두개의 미래 궤적이 겹쳐져 있더라도 그 지역을 통과하는 타이밍이 다르면 충돌이 없고, 그래서 주행할 수 있게 된다. 따라서 해당 경로는 유효한 경로라는 것을 알 수 있는 것이다. 이런식으로 충돌을 고려한 패스 플래닝이 가능해진다.
Technical Resources
Path Planning 분야 외의 로봇 개발을 위한 다른 내용이 궁금하다면 아래의 매스웍스 코리아에서 제공하는 모바일 로봇틱스 그리고 자율주행 웹 포털을 통해 정보를 얻어갈 수 있으니 참고하기 바란다.
MATLAB Mobile Robotics Web Portal
그림 20. MATLAB을 이용한 육상 이동 로봇 개발 Web Portal (링크)
MATLAB ADAS Web Portal
그림 21. MATLAB을 이용한 자율주행/ADAS 개발 Web Portal (링크)
MATLAB Onramp Series
매트랩 기초 사용법을 학습하고 싶은 경우 MathWorks 홈페이지 내의 Onramp 라는 무료 트레이닝 코스를 활용할 수 있다. Onramp는 웹상으로 진행하는 온라인 무료 교육으로, 컴퓨터에 매트랩을 설치 할 필요 없이 온라인으로 매트랩 관련된 여러 기초 내용을 학습할 수 있다.
그림 22. MATLAB을 무료로 배울 수 있는 Onramp 시리즈 (링크)