[LiDAR 전체 프로세스 flow chart ]
크게 Offline과 Online으로 나누어 프로세스가 진행되며 Offline에서는 GPSLAM을 통해 lane, ground, nonground에 대한 PCD map을 만든다. 생성한 PCD map은 Online에서 실시간 LiDAR data에서 ROI영역을 설정에 활용된다. GPSLAM은 직접 구현한 것으로 이름만 SLAM이지 SLAM이라고 할 수도 없는 조잡한 코드이다. SLAM 알고리즘을 활용하여 PCD map을 만들지 않은 이유는 제작해보았을 때 불필요한 loop closure가 발동되어 부정확한 map이 만들어 졌으며(LeGO-LOAM, LIO-SAM, FAST-LIO를 사용해보았다.) 모라이 시뮬레이터에서 rate도 높고 노이즈가 없는 정확한 imu와 gps를 사용할 수 있기에 굳이 SLAM을 사용할 필요가 있나?라는 생각이 들어 직접 만들었다.
Online에 실행되는 프로세스는 Velodyne Driver에서 LiDAR data를 subscribe하여 Patchwork++를 거쳐 LiDAR data에서 Nonground와 Ground를 분류한다. 이후 Nonground만을 활용하여 기존에 만들었던 PCD map을 활용하여 ROI에 해당하는 point cloud만을 남겼다. 추출한 point cloud에서 object의 위치를 특정하기 위해 clustering을 수행하는데 해당 과정은 Object Detection에 포함된다. Object Detection단계에서 object의 중심 위치와 크기를 추정한다. 추정한 object 정보를 바탕으로 tracking을 수행하며 object의 위치 noise를 제거하고 id를 부여함을 통해 다음 몇 초 뒤의 object의 위치를 특정할 수 있다.
[PCD Map 생성::GPSLAM]
GPS와 IMU를 통해 차량의 pose를 계산하여 publish한다. Velodyne driver를 통해 LiDAR data를 받으면 이를 patchwork++를 거쳐 nonground와 ground pointcloud로 나뉘어 publish한다. GPSLAM에서는 ground 와 nonground pointcloud를 subscribe하고 ego pose를 기준으로 translation과 rotation을 수행한다. 이후 ground point cloud에서 차선 또는 노면 표시에 해당하는 point cloud를 segmentation한다. GPSLAM 결과 pcd 파일이 생성되는데 이를 rviz를 통해 시각화 하면 아래와 같다.
위의 PCD map을 활용하여 주차 영역을 설정하여 영역 안에 물체가 있는지 인지하여 주차 가능한 영역임을 파악한다. 또한, 실시간 LiDAR data 중 필요한 point cloud만을 추출하는 ROI 영역 설정에도 활용된다. 각각의 자세한 방법은 따로 정리하겠다.
[ROI SETTING (RCA)]
point clicker.py는 pcd_viewer로 pcd 파일을 시각화 하였을 때 마우스 커서로 점을 선택하면 txt파일에 점의 좌표를 작성한다. 이를 통해 ROI 영역을 직접 설정할 수 있다. (소스 코드는 github 링크에서 확인할 수 있다.)
ROI 영역을 설정하는 이유는 주행에 있어서 인식하는 것에 있어 불필요한 부분을 제외시키기 위함이다. 예를 들면 주차장에서 연석 위의 나무나 풀 혹은 건물이 있다. ROI 설정을 통해 불필요한 부분을 이후 프로세스에서 제외시키면 실시간성 확보에 도움을 준다.
ROI영역은 크게 유형으로 나누어 설정하였다. 성남 시청의 바깥 영역을 Outer, Outer 영역 안에 있는 연석을 경계로 한 영역을 Inner으로 한다. 해당 영역은 rviz로 아래와 같이 시각화 할 수 있다. (노란색 선으로 시각화)
Ray Casting Algorithm은 예전에 전공 강의 중 컴퓨터 그래픽 설계에서 배운 내용인데 설정한 Outer 영역 안에 존재하면서 Inner 영역 밖에 존재하는 점들을 실시간성을 확보하면서 정확하게 추출하기에 적합하다고 판단되어 이를 활용해 ROI Setting을 구현하였다.
Ray Casting Algorithm에 대한 설명을 간략히 하면 다음과 같다.
위의 그림과 같이 임의의 다각형 안에 2개의 다각형이 포함된 것을 볼 수 있다. 이를 위의 설명한 내용에 따르면 제일 큰 다각형을 Outer, 나머지 두 다각형을 Inner로 할 수 있다. 파란색으로 칠해진 영역이 ROI에 해당한다.
위의 임의의 점에서 시작한 수평선을 그었을 때 ROI와 만나는 교점의 개수를 적어둔 것인데 앞서 설명한 바와 같이 교점의 개수가 홀수이면 ROI 안에 위치한 점이고 짝수이면 ROI 밖에 위치한 점임을 확인할 수 있다.
아래 영상과 같이 실시간으로 LiDAR Pointcloud 중 ROI 영역 안에 존재하는 Point cloud만을 추출할 수 있다.
위의 두 영상을 비교해보았을 때 ROI를 설정한 경우 점의 개수가 줄어들었을 뿐만 아니라 주차 공간에 주차된 차량에 해당하는 Point Cloud만 존재하는 것을 확인할 수 있다. 이처럼 ROI를 설정하여 Point Cloud를 추출하는 경우 자율주행에 있어 필요한 Point Cloud만을 남겨 다음 프로세스에서 불필요한 연산을 할 필요가 없다.
[Object Detection]
추출한 ROI영역 내의 Point Cloud에서 물체의 정보를 파악하는 Object Detection에서는 Clustering을 수행한다. 대회에서 사용한 LiDAR는 HDL 32e로 채널 수가 많다고 할 수 없다. 만약 Hesai사의 LiDAR처럼 중간 부분에 laser channel간의 간격(수직 해상도)가 작은 경우에는 문제가 되지 않지만 HDL32e처럼 모든 channel의 간격이 거의 일정한 경우 물체와 센서 간의 거리가 멀어지는 경우 고정된 tolerance값만으로 정확하게 물체를 clustering할 수 없다.
따라서 이전에 개발한 adaptive clustering을 활용하였다. 이는 우선 큰 tolerance 값(1.0)으로 1차 clustering을 수행 하고 그 결과 로 추출된 pointcloud의 중심에서 센서까지의 거리를 계산하여 해당 pointcloud에 적용할 clustering parameter를 결정하는 계산과정에 활용한다.
clustering을 수행하였다면 물체의 중심 위치와 물체의 크기를 파악할 수 있다. 하지만 clustering에서 추정한 물체 중 제외 시켜야할 것이 존재한다. 그것은 지면인데 지면이 아니라고 예측한 것들이다. Patchwork++의 성능은 좋지만 100% 지면과 지면이 아닌 것들을 분류하지 않는다. 여러 오류가 존재하는데 이를 해결하기 위해 적용한 것이 PCA(주성분 분석)을 활용한 지면 FN 제거 이다.
주성분 분석에 대한 설명은 아래 링크를 참고하면 되겠다.
https://bottle-an00.tistory.com/28
주성분 분석을 통해 clustering된 Point Cloud의 주축을 구하고 Patchwork++에서 분류한 지면 Point Cloud들 중 clustering된 Point Cloud 중심 2M안의 지면 점들의 법선 벡터와 주축의 사잇각을 구하였을 때 80도 이상인 경우는 지면 FN이라고 판단하여 Object Detectino 이후 과정에서 제외한다.
이후 물체의 정보는 물체에 해당하는 Point Cloud 중심좌표와 Pointcloud의 크기 및 영역이 계산되어 저장된다.
[Tracking]
Object Detection 결과 저장한 Object Info를 input으로 하여 pcl 라이브러리의 radiusSearch()를 활용해 이전의 5개의 frame에서 인지한 object들 중 가장 가까운 물체 하나를 정한다. 이때 해당 물체까지의 거리가 range threshold 이하라면 IOU를 계산하여 iou threshold보다 큰 경우 해당 물체라고 matching하여 동일한 Id를 부여한다. iou는 물체의 point cloud의 min point와 Max point를 pcl의 getMinMax()를 활용해 얻어 이를 바탕으로 z값을 사용하지 않는 2D Bounding Box를 만들어 계산한다. (원래는 계획상 iou를 계산하여 object matching을 수행하려 했으나 센서의 위치에 따라 물체의 point cloud 형태가 크게 바뀌기 때문에 tracking 성능이 감소하는 결과가 있었다. 게다가 움직이는 물체의 경우 그러한 경향이 더 크기에 적합하지 않다고 판단하였다. 따라서, 위의 flow chart에서 IOU Threshold Check는 없다고 생각하면 된다. )
Object matching이 되었다면 EKF(확장 칼만 필터)를 활용해 물체의 위치와 속도 id등의 정보를 얻는다. 시스템 모델의 구성은 매우 간단하며 아래와 같다.
x = {x, y, vx, vy}
P = 1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 10, 0,
0, 0, 0, 10
A = 1, 0, dt, 0,
0, 1, 0, dt,
0, 0, 1, 0,
0, 0, 0, 1;
H = 1, 0, 0, 0,
0, 1, 0, 0;
Q_ = dt_4/4*noise_ax, 0, dt_3/2*noise_ax, 0,
0, dt_4/4*noise_ay, 0, dt_3/2*noise_ay,
dt_3/2*noise_ax, 0, dt_2*noise_ax, 0,
0, dt_3/2*noise_ay, 0, dt_2*noise_ay;
tracking을 한 이유는 물체의 정보를 더 정확하고 깔끔하게 전달하기 위함이다. 판단에 정보를 publish할 때 markerarray를 활용한다. markerarray는 duration을 설정할 수 있는데 이를 설정할 때 너무 빠르게 설정하면 판단 프로세스에서 장애물을 적절한 타이밍에 subscribe할 수 없다. 반면 너무 길게 설정하면 장애물이 여러개로 publish되어 빠르게 움직이는 물체의 경우 잔상처럼 여러개가 publish된다. 이때 동일한 id로 설정하면 duration에 상관없이 update되는데 이를 위해서 tracking을 사용한 것이다. tracking을 하면 물체의 고유의 id를 설정할 수 있기에 이를 markerarray의 id로 설정하여 publish하면 더욱 정확하게 물체의 정보를 전달해 줄 수 있다.
'플젝 > SHARK 대회' 카테고리의 다른 글
2024_SHARK 미션 별 구현 내용 정리 LiDAR 부분 정리 (0) | 2024.09.02 |
---|---|
2024 SHARK 자율 주행 대회 (1) | 2024.08.29 |