TURTLEBOT이란 ROBOTIS에서 제공하는 모바일로봇 플랫폼이다.
ROS를 처음 배우는 입문단계에서 ROS의 흐름 및 구조를 파악하기에 유용한 플랫폼이라 생각된다.
TURTLEBOT을 동작시키고 다양한 작업을 해보는데에는 Robotis의 E-Manual을 포함하여 많은 예제들과 설명들이 즐비하므로
나는 조금 더 깊게 TURTLEBOT의 코드들에 대하여 분석해보겠다.
우선 ROBOTIS에서 제공하는 E-Manual을 따라해보며 Turtlebot으로 지도를 작성해보고 네비게이션까지 해보았다고 가정하고 이야기를 시작하겠다.
https://emanual.robotis.com/docs/en/platform/turtlebot3/navigation/
SLAM을 진행하고 마지막으로 작성한 지도를 저장하기 위해서 아래 명령어를 실행했을 것이다.
$ rosrun map_server map_saver -f ~/map
map_server 패키지의 map_saver 노드를 통해 지도를 저장하겠다는 명령어이고 이를 통해 지도를 나타내는 pgm파일 및 yaml파일이 생성된다.
pgm파일은 Portable Gray Map으로 GrayScale로 표현되는 이미지라고 보면 될 것이다.
그리고 yaml파일은 노드를 실행시킬때 필요한 파라미터들에 대한 정보를 담고 있다고 볼 수 있고 따라서 생성한 yaml 파일은 지도의 분해능(resolution)이라든지 여러 정보들이 포함되어 있다.
그럼 생성한 yaml은 어떠한 노드를 실행시키기 위한 파라미터들인가?
Robotis의 E-Manual에서는 map_server 를 통해 작성한 지도를 저장하고 난 후 Navigation chapter로 넘어가고 다음의 명령어가 나타난다.
$ roslaunch turtlebot3_navigation turtlebot3_navigation.launch map_file:=$HOME/map.yaml
turtlebot3_navigation.launch 파일을 실행시키는데 map_file의 파라미터로 yaml파일을 넣어주는 것이 보인다.
그래서 해당 launch파일을 살펴보았다.
line4 에서 map_file이라는 변수에 yaml이 할당되는 것을 볼 수 있다.
그리고 line14 에서 map_file 변수는 map_server 패키지의 map_server 노드의 파라미터로 지정되는 것을 확인할 수 있다.
그럼 map_server 노드는 yaml파일을 갖고 무엇을 하는걸까??
이를 확인하기 위해 map_server 라는 실행노드가 생성될때 필요한 source code를 살펴봐야 할 것이다.
이를 위해 map_server 패키지의 CMakeLists.txt를 살펴보자.
map_server라는 실행노드는 src/main.cpp를 통해 생성됨을 확인할 수 있다.
그리고 코드의 내용은 아래와 같다.
MapServer 클래스의 생성자에서 fname 이라는 문자열의 주소를 파라미터로 입력받는 것을 볼 수 있다.
저기서 문자열은 yaml파일의 경로 및 이름이 해당될 것이다.
그리고 fname이라는 변수는 line77의 std::ifstream fin(fname.c_str()) 에서 사용된다.
ifstream fin(xxx) 의 구조는 xxx를 읽어와 입력스트림을 생성한다는 의미이다.
그럼 fin에는 xxx의 내용들이 담기게 된다.
fin에 대한 설명은 아래 pdf 파일을 보며 이해하면 좋다.
따라서 fin에는 'fname'이라는 파일에 담긴 내용들이 들어가게 된다.
그리고 아래를 보면 YAML라이브러리의 Node클래스 객체 doc는 YAML라이브러리의 Load함수를 통해 fin의 내용을 불러오는 것을 확인할 수 있다.
(YAML::Node doc 의 구조에 대해 잘 모르겠다면 OpenCV 라이브러리를 생각해보자.
OpenCV라이브러리를 통해 객체를 생성하고 함수를 사용할땐 cv::Mat img, cv::imshow() 를 사용하게 된다.)
결과적으로 doc에는 fin의 내용들 즉, yaml파일의 내용들이 담기게 되고
doc에 순서대로 할당된 값들을 통해 res, negate, occ_th 등의 변수들에 값을 할당하게 된다.
즉 이 부분에서 yaml의 값들을 통해 변수들에 값을 할당하는 것을 볼 수 있다.
그리고 코드를 더 살펴보면 변수들을 통해 지도에 대한 메시지를 생성하고 map에 대한 정보(OccupancyGrid) 등을 publish하게 됨을 확인할 수 있다.
그럼 이 지도를 갖고 어떻게 주행을 하게 될까?
주행에 대한 부분은 다음 게시물에서 다루겠다.