아래는 Xiang Gao와 Tao Zhang의 <Introduction to Visual SLAM>을 읽고 번역정리+추가적인 코멘트를 단 내용이다.
말은 가능하면 간소화하고, 이론적으로 더 참고할만한 부분은 추가적인 코멘트를 넣었음.
저자에 의해 모든 자료가 무료 배포되었음. 아래 링크 참고
📘 영어판 도서 파일: https://github.com/gaoxiang12/slambook-en
📂 practice 코드: https://github.com/gaoxiang12/slambook2
🔎 학습 목표
1. Visual SLAM 프레임워크가 어떤 모듈들로 이루어지고, 각 모듈이 어떤 역할을 하는지 이해한다.
2. 프로그래밍 환경을 셋팅하고, 실험을 위한 준비를 완료한다.
3. 리눅스에서 프로그램을 어떻게 컴파일하고 실행하는지 이해한다. 만일 컴파일 단계에서 문제가 생긴다면 어떻게 디버깅하는지 배운다.
4. CMake의 기본 사용법을 배운다.
이번 강의에서는 따라오는 챕터에서 다룰 내용들의 개요를 잡는 느낌으로 visual SLAM 시스템의 구조를 요약 설명할 것이다. 실습 파트에서는 환경 설정과 프로그램 개발에 대한 기초를 설명한다. 깜찍한 "Hellow SLAM" 프로그램을 만들어보는 것으로 마무리!
위는 Little Carrot이라는 이름을 가진 귀여운 로봇이다.
이 친구가 방 안에서 자유롭게 돌아다닐 수 있도록 자율주행 기능을 탑재해보자.
바퀴만으로도 돌아다니는 것은 가능하지만, 적절한 네비게이션 시스템 없이는 여기저기 부딫혀 물건을 망가뜨릴 수도 있다. 머리에 카메라 두개를 달아주어 Little Carrot이 두 눈과 머리, 사지가 있는 사람의 형상을 갖추도록 디자인해보자. 이제 Little Carrot은 사람처럼 자유롭게 돌아다니면서 환경을 탐색할 수 있을까? 그러기 위해서는 Little Carrot은 최소한 아래 두 가지를 스스로 알 수 있어야 한다.
이 두 문제를 풀기 위해선 바닥에 가이드 레일을 깔아 그 위만 주행하도록 한다든가, QR 코드같은 마커를 벽에 덕지덕지 붙인다든가, radio localization 기기를 테이블에 부착한다든가 하는 여러가지 접근 방법들이 있을 수 있다. 실외환경이라면 Little Carrot의 머리에 휴대폰이나 차량에 부착하는 GNSS 수신기를 설치해줄 수도 있을 것이다.
위 그림에서 보이는 여러가지 센서들은 침입형(intrusive)/비침입형(non-intrusive) 두 가지 카테고리로 나뉜다. 비침입형 센서는 로봇 몸체에 부착하기만 하면 환경과는 관계없이 활용 할 수 있는 휠 인코더, 카메라, 레이저 센서, IMU 등을 의미한다. 침입형 센서는 로봇이 아닌 환경에 설치해야하는 가이드 레일이나 QR 코드 등을 말한다. 침입형의 경우 설치가 가능하기만 하다면 localization 문제를 매우 간단하고 정확하게 해결할 수 있지만 범용성이나 사용성의 한계로 인해 활용에 제약이 생길 수 밖에 없다. 만약 GPS 수신을 받을 수 없는 상황이라거나 가이드 레일을 깔 수 없는 상황이라면 어떡할 것인가?
반대로 비침입형 센서의 경우 직접적인 위치 파악이 불가하고 간접적인 물리적 측정치만을 얻을 수 있다. 예를 들어 휠 인코더는 휠 회전각을 측정하고, IMU는 각속도와 각가속도를 측정한다. 카메라나 레이저 스캐너는 점군이나 이미지와 같은 특정 형식으로 외부환경을 관측한다. 우리는 이러한 간접적인 관측치로부터 위치를 추정하기 위해 여러 복잡한 알고리즘들을 적용해야 한다. 이렇게만 들으면 침입형 센서를 이용한 방식에 비해 엄청 돌아가는 것처럼 보이지만, 이 방식의 분명한 이점은 환경에 대한 요구사항이 없기 때문에 어떤 미지의 환경에서도 적용이 가능하다는 것이다. 이런 특성으로 인해 여러 연구에서 이 비침입형 센서를 이용한 localization 방식을 self-localization이라고 명명하기도 한다.
다시 앞에서 얘기한 SLAM의 정의로 돌아가보면, 우리는 사전 정보가 없는 미지의 환경을 탐색하는 것이 SLAM의 핵심이라고 말한 바 있다. 이론적으로는, Little Carrot이 놓일 환경이 어떤 환경일지 미리 추정하지 않아야 하므로 (물론 실제로는 실외인지 실내인지 정도의 대략적인 범위는 주어질 것이다) 우리는 GPS 같은 외부 센서가 잘 작동할 것이라고 가정해서는 안된다. 따라서 이 책에서는 비침입형 센서를 사용해 SLAM을 수행하는 것에 초점을 맞추며, 그 중에서도 우리는 visual SLAM에 대해서 다루고 있으므로 Little Carrot의 두 눈으로 무엇을 할 수 있는지를 중점적으로 알아 볼 것이다.
SLAM에서 쓰이는 카메라는 보통의 SLR (single-lens reflex) 카메라와는 차이가 있다. 훨씬 저가이며, 비싼 렌즈를 사용하지 않는다. 또한 일정 속도(보통의 경우 30fps)로 연사하여 연속적인 비디오 스트림 형태의 데이터를 생성한다. 카메라는 아래 그림과 같이 크게 세 가지 카테고리로 나뉜다; monocular (단안), stereo (양안), RGB-D.
이름에서 직관적으로 알 수 있듯이, 단안 카메라는 하나의 카메라만을 가지고 있고, 양안 카메라는 카메라 두 개로 이루어져있다. RGB-D 카메라의 원리는 좀 더 복잡한데, 컬러 이미지를 찍는 것 뿐만 아니라 각 픽셀에 대해 씬과 카메라 사이의 거리를 측정해준다. 자세한 원리는 lecture 5에서 다룰 것이다. 이 외에도 파노라마 카메라, 이벤트 카메라 등의 특별한 카메라 타입이 사용되기도 한다. 여러분은 우리가 Little Carrot의 머리에 박아준 카메라가 바로 양안 카메라임을 눈치챘을 것이다. 그럼 각 카메라 타입의 장단점을 살펴보자.
이렇게 일반적인 카메라 타입들을 간단히 살펴보았다. 이제, 장면에서 움직이고 있는 카메라를 상상해보라. 우리는 카메라로부터 연속적으로 변화하는 일련의 이미지들을 얻을 것이다. Visual SLAM의 목표는 이 이미지들을 이용해 localization과 building map을 수행하는 것이다. 이건 꽤 복잡한 작업이기 때문에 하나의 알고리즘만으로 이미지를 입력받아 위치와 맵에 대한 정보를 연속적으로 출력하도록 만드는 것은 불가능하다. SLAM은 여러 알고리즘을 통합한 프레임워크를 통해 수행되는데, 수십년에 걸친 연구 끝에 아래와 같은 정형화된 형태가 확립되었다.
위 프레임워크는 몇십 년간의 시행착오 끝에 정착된 것으로, 사실 안정적인 조명 조건과 제한되고 고정된 환경과 사람의 특별한 방해가 없는 경우를 상정한다면 visual SLAM 문제는 이미 해결되었다고 봐도 된다. (문제는 현실에서는 이런 가정이 통하지 않는다는 것😂)
이제 각 모듈의 기능에 대해 자세히 알아볼 건데, 작동 원리를 더 깊이 이해하려면 여러 수학적 지식이 추가로 필요하며 이는 책의 part 2에서 자세히 다룰 것이다. 지금은 각 모듈에 대한 직관적이고 정성적인 이해에 집중해보자.
VO는 인접 이미지 프레임 사이의 카메라 움직임을 파악하는 작업으로 가장 간단한 경우로는 앞뒤 연속 이미지 사이의 움직임을 추정하는 일이 될 것이다. 아래 두 이미지를 보면 우리는 자연히 오른쪽 이미지를 왼쪽으로 살짝 회전하면 왼쪽의 이미지가 될 것이라는 것을 알아챌 수 있다 (비디오로 보았으면 좀 더 쉬웠을 것이다). 이때 여러분은 '왼쪽으로 살짝 돌린다'는 움직임을 어떻게 두 이미지를 통해 알아챘는가?
아마 자연스럽게 이런 생각을 했을 것이다. “보자, 바테이블은 지금 가깝고 벽이랑 블랙보드는 멀리 떨어져있지. 카메라가 왼쪽으로 돌면 바테이블의 가까운 부분이 나타나기 시작할거고, 오른쪽의 캐비닛은 이미지 밖으로 나가기 시작하겠지?” 이 정보들로 우리는 카메라가 왼쪽으로 돈다고 결론짓게 된다.
여기서 더 나아가서, 여러분은 카메라가 얼만큼 돌았는지 또는 이동했는지 각도나 센티미터 단위로 대답 할 수 있는가? 이는 인간에게도 어려운 문제이다. 왜냐하면 우리 직관은 숫자에는 약하기 때문이다. 하지만 컴퓨터에게는, 이런 움직임은 숫자로 설명되어야한다. 그렇다면 어떻게 컴퓨터가 이미지들만으로 카메라의 움직임을 계산하게 할 수 있을까? Visual SLAM에서 주어지는 것은 이미지 내 픽셀들의 값과 그들이 공간의 한 점을 카메라의 이미지 평면으로 투영한 결과라는 사실 뿐이다. 카메라의 움직임을 정량화하기 위해서는 첫째로 카메라와 공간상의 점들 간의 기하학적 관계를 이해해야 한다. 이 관계를 밝히기 위해서는 약간의 배경지식이 필요하지만, 여기서는 우선 직관적인 개념만을 이해해도 충분하다. 현재로서는 VO가 인접 프레임의 이미지들로부터 카메라 움직임을 추정하고 장면의 3D 구조를 복원할 수 있다는 내용만 가져가면 된다. 이름에 odometry가 들어가는 이유는, VO가 실제 휠 오도메트리 (휠 인코더를 이용한)와 유사하게 순간순간의 ego-motion만 계산하고 글로벌 맵이나 절대 포즈 (absolute pose)를 추정하지 않기 때문이다. VO는 금붕어같이 금방금방 까먹고 전체적인 구조정보를 사용하지 않는다.
이제 우리가 VO를 구현을 해놔서, 지금 모든 앞뒤 프레임 간 카메라 움직임을 추정할 수 있다고 가정해보자. 만약 우리가 인접한 움직임끼리 모두 연결한다면 이는 자연히 로봇의 전체 경로를 나타내게 될 것이고 그럼 localization 문제는 끝이다. 또, 우리는 각 시간의 카메라 위치에서의 모든 픽셀들의 3D 위치를 계산할 수 있게 되고, 이것을 통합하면 맵을 형성할 수 있다. 여기까지 보면 VO만으로 SLAM 문제가 거의 해결된 것 처럼 보인다. 정말 그럴까? VO는 visual SLAM 문제를 풀기 위한 핵심 기술이 맞다. 우리는 이 책에서 VO에 대한 자세한 설명을 제공하기 위해 꽤 많은 부분을 투자할 것이다. 하지만, VO 만을 사용해 경로를 추정하는 것은 필연적으로 드리프트의 축적을 수반한다. 각 추정에는 항상 일정 오차가 따라온다. odometry가 작동하는 방식 때문에 이전 순간의 오차는 다음 순간으로 그대로 전파되고, 일정 시간이 지나면 추정이 부정확해지게 된다. 예를 들어, 로봇이 처음에 왼쪽으로 90도 돌고 그 다음 오른쪽으로 90도 돌았다고 해보자. 오차로 인해 우리는 처음 90도의 회전을 89도로 추정했다. 그러면 로봇이 다시 오른쪽으로 회전했을 때 로봇의 추정된 위치가 원점이 아니라는 사실이 우리를 당황스럽게 만들 것이다. 더 기분 나쁜 사실은, 이후의 모든 추정이 완벽하게 정확하게 이루어져도 이 처음의 1도 실수는 지워지지 않고 모든 경로상에 반영될 것이라는 점이다!
축적되는 드리프트는 일관성있는 맵을 구축할 수 없도록 만든다. 일자 복도는 비스듬해지고, 직각 코너는 비뚤어지게 된다🤮
드리프트 문제를 해결하기 위해 우리는 두가지 요소가 추가로 필요한데, 바로 뒤에 나오는 백엔드 최적화와 루프 클로징이다. 루프 클로징은 로봇이 이전 위치로 돌아왔는지를 판별해주고, 백엔드 최적화는 이런 정보들을 바탕으로 전체 경로의 모양을 교정해주는 역할을 한다.
제너럴하게 말하자면, 백엔드 최적화는 SLAM 시스템에서 노이즈를 처리하는 부분을 맡고 있다고 할 수 있다.
모든 센서 데이터가 정확하면 정말 좋겠지만, 실제로는 가장 비싼 센서조차도 일정량의 노이즈를 항상 포함한다. 거기에 더해 많은 센서의 성능은 주변의 자기장이나 온도 등에 많은 영향을 받는다. 따라서 이미지로부터 카메라의 움직임을 추정하는 문제를 푸는것에 더해 우리는 이 추정이 어느정도의 노이즈를 포함하고 있는지, 이전 시간으로부터 다음 시간까지 이 노이즈가 어떻게 전파되어오는지, 현재 추정치를 어느정도 신뢰할 수 있는지를 추가적으로 고려해야한다. 백엔드 최적화는 노이즈를 포함한 인풋 데이터로부터 전체 시스템의 상태(state)를 추정하고 그들의 불확실성(uncertainty)을 계산한다. 여기서 말하는 상태는 로봇 자체의 경로와 환경에 대한 맵 둘 모두를 포함하는 개념이다.
SLAM 프레임워크에서 프론트엔드는 백엔드에 최적화할 데이터와 그 초기값을 전달한다. 백엔드는 넘겨받은 데이터의 최적화만을 진행하기 때문에, 이미지랑은 이제 관계가 없고 전달받은 숫자와 행렬들과만 관련이 있다. 따라서 visual SLAM에서 프론트엔드는 컴퓨터 비전의 영역과 맞닿아 있고- feature 추출과 매칭 등- 백엔드는 상태 추정 이론(state estimation theory)과 밀접한 관련이 있다고 할 수 있다. 역사적으로 오랫동안 백엔드의 최적화 파트 자체가 SLAM 연구의 동의어였다. 초기 SLAM 문제는 지금의 백엔드가 해결하려고 하는 것과 정확히 일치하는, 상태 추정에 대한 문제 그 자체로 설명되었다. 초기 논문에서 이는 “estimation of spatial uncertainty”로 명명되었으며, 이는 SLAM의 근본적인 특성- 자기 자신의 움직임과 주변 환경에 대한 uncertainty를 추정하는-을 직접적으로 설명하는 용어였다. 우리는 상태 추정 이론을 이용해 상태에 대한 mean과 covariance(=uncertainty)를 추정하기 위해 다양한 필터나 비선형 최적화 등을 사용한다. 자세한 이론적 내용은 5장, 8장 및 9장에서 설명한다.
loop closure detection으로도 알려진 루프 클로징 모듈은 주로 SLAM에서의 위치 추정에서 발생하는 드리프트 에러를 해결하는 역할을 한다. 로봇이 일정 시간 이동 후 원점으로 돌아왔다고 가정했을 때, 실제로 우리가 추정하는 마지막 위치는 드리프트로 인해 원점이 아닐 것이다. 이 오차를 어떻게 교정해줄 수 있을까? 만약 로봇에게 그것이 사실은 현재 원점으로 돌아왔다는 것을 알려줄 방법이 있다면, 우리는 현재 위치를 원점으로 끌어다 놓음으로써 드리프트를 제거할 수 있을 것이다. 이게 정확히 루프 클로징이 하는 일이다.
루프 클로징은 localization과 map building 둘 모두와 깊은 관계가 있다. 사실, 맵을 구축하는 주된 목적 중 하나가 로봇이 자신이 다녀온 장소를 알 수 있도록 하는 것이기도 하다. 루프 클로징을 가능케 하기 위해선 로봇이 이전에 방문한 장면을 식별할 수 있도록 해주어야 하는데, 예를 들자면 로봇이 출발하는 곳에 QR 코드와 같은 마커를 설치하는 식의 방법을 생각해 볼 수 있다. 만약 동일한 마커를 다시 목격한다면 우리는 로봇이 원점으로 돌아왔다는 것을 알 수 있다. 하지만 마커는 앞서 말했듯이 침입형 센서이다. 비침입형 센서만으로 로봇이 루프 클로징을 수행하려면 어떻게 해야 할까? 가능한 방법 중 하나는 이미지 간의 유사도를 측정하는 것이다. 사람은 비슷한 두 이미지를 보고 두 이미지가 같은 장소에서 찍힌 것인지 아닌지 쉽게 판별할 수 있다. 따라서 우리가 살펴볼 시각적 루프 탐지는 이미지 간 유사도를 측정하는 알고리즘이라고 봐도 된다.
루프가 탐지되고 나면, 우리는 백엔드 최적화 알고리즘에게 “자, A랑 B는 같은 점이야!”와 같은 정보를 전달하게 된다. 이 정보를 바탕으로 전체 경로와 맵은 A와 B를 한 점으로 잇도록 조정될 것이다. 이런 방식을 통해, 충분하고 신뢰할 수 있는 루프 탐지를 가지고 있다면 축적된 에러를 제거하고 전체적으로 일관성있는 경로와 맵을 얻을 수 있게 된다.
매핑은 맵을 구축하는 과정을 뜻하는데, 맵이라는건 아래 그림과 같이 환경에 대한 묘사를 의미하고 이 묘사는 정해져 있는 것이 아니라 실제 용도에 따라 어떤 형태든 될 수 있다.
로봇 청소기를 예로 들어보자. 로봇 청소기는 바닥에 붙어서 움직이기 때문에 네비게이션을 위해서는 single-line 레이저 스캐너를 이용해 만든 2D 맵이면 충분할 것이다. 카메라의 경우에는 카메라의 6-DoF(degree-of-freedom) 움직임을 커버할 수 있는 최소 3차원의 맵이 필요할 것이다. 가끔 우리는 단순한 점들의 집합이 아닌 부드럽고 아름다운 삼각면의 텍스쳐들로 이루어진 모델링 결과가 필요할 수도 있다. 또는, 생김새는 전혀 신경쓰지 않고 “점 A와 점 B는 연결되어있고, 점 B와 점 C는 연결되어있지 않군” 과 같은 위상적인(topological) 정보만을 필요로 할 수도 있다. 아니면 가끔은 맵 자체가 아예 필요하지 않을 수도 있다. 예를 들어 level 2 자율주행차는 차선에 상대적인 움직임만을 추정함으로써 차선을 따르며 주행할 수 있다. 이렇게 맵에 대한 요구조건이나 아이디어는 용도에 따라 다양한 모습을 띤다. 앞서 말한 VO나 루프 탐지, 백엔드 최적화와는 다르게 매핑은 특정 알고리즘을 가지고 있지 않다. 여러 형태가 될 수 있는 이 맵이라는 개념은 크게는 두가지 카테고리로 나뉜다.
Little Carrot이 몇가지 센서를 장착하고 미지의 환경에서 돌아다니는 상황을 수학적인 언어로는 어떻게 나타낼 수 있을까? 우선 센서들은 개별 time point에서 데이터들을 모으기 때문에, 우리는 그 순간순간의 맵과 위치만을 고려한다. 즉, 움직임이라는 연속적인 과정을 우리는 데이터 샘플링이 일어나는 불연속적인 time step () 상에서 해석한다는 말이다. 를 사용해 Little Carrot의 위치를 나타낸다면, 각 time step에서의 위치는 ,..., 와 같이 표현될 수 있을 것이고, 이들은 Little Carrot의 경로를 이루게 된다.
맵의 경우엔, 우리는 맵이 몇 개의 랜드마크들로 구성되어있다고 가정한다. 각 time step에서 센서들은 랜드마크들의 일부를 볼 수 있고, 그 관찰(observation)을 기록한다. ,..., 를 사용해 맵 상 존재하는 총 N개의 랜드마크를 표현하도록 하자.
이 설정 하에, 'Little Carrot이 몇가지 센서를 장착하고 미지의 환경에서 돌아다니는 상황'은 기본적으로 다음 두 부분으로 이루어져있다.
1. motion: time step -> 사이에 Little Carrot의 위치 가 어떻게 변하는지
2. observation: Little Carrot이 위치 에서 라는 랜드마크를 탐지하는 상황
로봇에게 "왼쪽으로 15도 돌아"와 같은 모션 명령을 전달하면 이 명령은 컨트롤러를 통해 여러 방식으로 수행된다. 우리는 로봇의 위치에 대한 명령을 내릴 수도 있고, 가속도나 각속도 등을 조종할 수도 있다. 어쨌든 이런 다양한 컨트롤의 종류에 관계 없이 우리는 다음의 보편적이고 추상적인 수학 모델을 이용해 로봇의 모션을 나타낼 수 있다.
여기서 는 인풋 명령을 의미하고, 는 노이즈를 의미한다. 여기서 우리는 특정 수식이 아닌 제너럴한 표현인 를 사용해 프로세스를 표현함으로써 어떤 모션 인풋이든 나타낼 수 있도록 하였다. 이 수식을 motion equation이라고 한다.
노이즈의 존재는 이 모델을 확률 모델(stochastic model)로 바꾼다. 즉, 우리가 “앞으로 1미터 직진”이라는 명령을 한다고 해도 그게 로봇이 실제로 정확히 1미터 갈 거라는걸 의미하진 않는다. 만약 모든 지시가 정확하게 수행된다면 사실 추정 작업 자체가 필요가 없지만, 로봇이 언제는 0.9미터를 가고 언제는 또 1.1미터를 가는게 현실이다. 따라서 각 움직임에서 노이즈는 랜덤하게 적용된다. 만일 우리가 노이즈를 무시한다면, 인풋 명령들로만 추정한 포지션은 불과 몇 분 뒤 실제 위치와 몇백 마일 떨어지게 될 수도 있다.
motion equation과 비슷하게 observation equation이라는 것이 있는데, 이 수식은 Little carrot이 위치 에서 랜드마크 를 보고 관측 데이터 를 생성하는 상황을 묘사한다. 이 관계 또한 일반성을 잃지 않도록 추상적인 함수 를 이용해 표현해보자.
여기서 는 observation의 노이즈이다. 여러 센서 종류에 따라 관측 데이터 와 observation eq. 는 다양한 형태가 될 수 있다.
여러분은 아마 "아니, 그래서 , 는 정확히 뭐고 , , 는 뭘 나타내는거야.."라며 모호한 표현에 혼란을 느끼고 있을 지 모른다.
실제 적용에서는 모션이나 센서의 종류에 따라 몇가지 종류의 특정한 매개변수화(parameterization) 방법이 존재한다. 매개변수화란 다음과 같은 것이다. 로봇이 평면 상에서 움직인다고 할 때 로봇의 포즈는 2차원의 좌표와 각도로 표현될 수 있다. 즉, 이 상황에서 로봇의 포즈 는 두 축 상에서의 위치 , 와 각도 를 통해 와 같이 나타내어질 수 있다. 이 때, 인풋 명령은 단위시간 사이에서 이 위치와 각도의 변화량()으로 해석될 수 있으므로, 와 같은 형태로 표현해보자. 그러면 motion equation은 다음과 같이 매개변수화된다.
여기서 는 앞에서 말했듯이 노이즈이다. 위 식은 간단한 선형관계를 나타낸다. 하지만 모든 인풋 명령이 이런식으로 위치와 각도의 변화량으로만 구성되어있진 않다. 예를 들어, 스로틀이나 조이스틱의 인풋은 속도나 가속도이므로 위와는 다른 형태의 조금 더 복잡한 motion equation을 갖게 된다. 그 때는 역학에 대한 추가적인 지식이 필요하다.
observation equation의 경우에는 예를 들어 로봇이 2차원의 레이저 센서를 사용한다고 해보자. 레이저는 로봇과 랜드마크 사이의 거리 과 각도 를 측정함으로써 2D 랜드마크를 관측한다. 랜드마크가 에 있고, 로봇의 포즈가 , 관측데이터를 로 놓으면 observation eq.는 다음과 같이 표현된다:
visual SLAM으로 한정해 생각해보면, 센서는 카메라이고 observation eq.는 '랜드마크에 대한 이미지의 픽셀을 가져오는' 과정으로 생각해 볼 수 있다. 이는 카메라 모델에 대한 수식과 관련되어있고, chapter4에서 자세히 다뤄볼 것이다.
확실히 motion/observation 이 두 식은 센서 별로 매우 다른 형태로 매개변수화된다는 것을 알 수 있는데, 만약 우리가 범용성을 유지하면서 이들을 일반적인 abstract form으로 표현해본다면 SLAM 프로세스는 다음의 두 기본식으로 요약 가능하다.
여기서 는 랜드마크를 관측했던 위치에 대한 정보를 담고있는 집합(모든 순간에 랜드마크 관측이 가능하진 않다- 보통 한 순간에 랜드마크의 작은 일부만을 관측할 수 있음)이다. 이 두 식은 동시에 SLAM의 기본적인 문제를 묘사한다: “어떻게 노이즈가 포함된 인풋 컨트롤 와 센서 관측값 를 가지고 (localization)와 (mapping)를 정확하게 추정할 수 있을까?”
지금 보이듯이 우리는 SLAM 문제를 상태 추정 문제로 모델링하였는데, 그럼 어떻게 노이즈가 포함된 측정값들을 통해 내부적인(숨겨진) 상태 변수들을 추정할 수 있을까?
해법은 두 식의 특정한 형태와 noise의 확률분포에 있다. motion / observation eq. 가 선형이거나/비선형이거나, 노이즈가 gaussian/non-gaussian 으로 가정된다면, 모델은 선형/비선형, gaussian/non-gaussian 시스템으로 분류된다. 선형-가우시안(LG system) 은 가장 간단하고, 이것의 편향되지않은 최적의 추정치는 칼만 필터 (KF)를 통해 구할 수 있다. 복잡한 nonlinear non-gaussian(NLNG system)의 경우엔 기본적으로 extended Kaman filter (EKF), nonlinear optimization 두 가지 방법에 의존한다. 21세기 초반까지는 SLAM에서 EKF기반 방식이 지배적이었다. 이에 따라, EKF의 단점(부분 선형화에 따른 오차라든가 noise를 가우시안 분포로 추정하는 것 등)을 극복하기 위해 사람들은 입자 필터와 같은 다른 필터들을 사용하기 시작했고, 비선형 최적화 방법도 쓰기 시작했다. 오늘날 visual SLAM은 SOTA 최적화 방식인 그래프 최적화를 사용하는 것이 주류가 되었다. 현재로서는 최적화 방법이 명백하게 필터 기반 방식보다 우월하다고 생각되며, 컴퓨팅 파워가 받쳐주는 한 최적화 방법이 보통 선호된다(챕터8, 9).
여기까지 왔으면 SLAM의 수학적 모델에 대한 전반적인 이해는 되었으리라 생각하지만, 여전히 분명하게 해야 할 이슈 몇가지가 있다.
첫째로, 우리는 포즈 가 무엇인지 엄밀하게 정의해야 한다. 포즈라는 단어는 조금 모호하다. 앞에서는 계속 2D의 예시를 들었지만 많은 로봇은 3차원의 공간 상에서 움직인다. 3차원 공간에서의 모션은 3개의 좌표축 상의 평행이동과 회전으로 표현되고, 이는 총 6개의 degree of freedom (DoF)을 가진다. 그럼 6차원의 벡터로 표현된다는건가 하면 그것보다는 살짝 더 복잡하다. 그럼 6DoF 포즈를 어떻게 표현해야 하고, 그걸 어떻게 최적화할 것인가? 이를 어떻게 수학적 성질을 이용해 표현할 것인가? 이 내용이 chapter 2,3에서 주요하게 다룰 내용이다.
다음으로, 우리는 visual SLAM에서 observation equation이 어떻게 매개변수화되는지를 다룰 것이다. 다른 말로, 어떤 과정을 통해 공간 상의 랜드마크 점이 사진에 투영되는지를 살펴볼 것이다. 이를 위해서는 카메라의 투영 모델과 왜곡에 대한 설명이 필요하며, 챕터 4에서 다룰 것이다. 마지막으로, 우리가 이 모든 정보를 알고있을 때 상태 추정 문제를 풀기 위해 필요한 비선형 최적화에 대한 지식을 챕터 5에서 다룰 것이다.
위의 내용이 이 책에서 수학적인 배경지식을 설명하는 부분인 파트1을 이루고, 나머지 파트에서는 visual odometry나 백엔드 최적화 등등에 대한 자세한 내용을 살펴본다.
이런건 생략..
리눅스에서 라이브러리 파일은 정적 라이브러리와 공유 라이브러리 두 개로 나뉜다.
정적 라이브러리는 “.a” 확장자를 가지고 있고, 공유 라이브러리는 “.so” 확장자를 가진다. 모든 라이브러리는 포장된 함수들의 콜렉션이다. 차이점은 정적 라이브러리는 그들이 불러질 때마다 카피를 생성하고, 공유 라이브러리는 하나의 카피만을 만든다는 것이다. 만약 정적 라이브러리 대신 공유 라이브러리를 생성하고싶으면 CMakeLists.txt에서 add_library를 할 때 SHARED 플래그를 추가해주면 된다.
IDE란 Integrated Development Environments의 약어로, 파이참이나 VS Code 등의 개발을 도와주는 툴을 말한다. 기본적인 text editor만 있어도 코딩은 가능하지만 각종 자동완성부터 시작해 디버깅까지 다양한 지원기능을 활용하며 효율적인 개발을 하기 위해서는 개발에 없으면 안되는 존재인데, 이 세상에는 굉장히 다양한 IDE가 존재한다. 이 책에서는 KDevelop, CLion을 추천하는데 사실 나는 처음 들어보는 IDE이고, 개인적으로는 그냥 VSCode 쓰는 것을 추천한다. Extension이 넘치기 때문에 저자들이 말하는 KDevelop, CLion의 특장점을 커버하고도 남을거라 생각한다.