본문 바로가기

쓰기

ROS(Robot Operating System) 개념과 활용
2016.03.05 17:25

ROS(Robot Operating System) 개념과 활용 - 10. CMakeLists.txt 파헤치기

조회 수 8436
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

 CMakeLists.txt는 빌드 설정에 관련된 매우 중요한 파일이지만 주석의 압박과 익숙하지 않은 사용법 때문에 매번 대충 작성했던 경험이 있습니다. 관련 가이드를 찾아 보니 생각보다 간단한 규칙으로 되어 있어서 다른 내용을 진행하기 전에 미리 짚고 넘어가려고 합니다. ROS Wiki에 올라온 내용(http://wiki.ros.org/catkin/CMakeLists.txt)을 주로 참고했고, 개인적인 내용들을 추가하여 정리해 보았습니다. ROS패키지의 CMakeLists.txt는 기본적으로 CMake에 대한 설정 파일에 catkin 관련 매크로를 사용할 수 있도록 한 것이므로 CMake 관련 내용을 찾아 보시면 이해하기 더 좋습니다.


comments.jpg

CMakeLists.txt 파일의 초기 내용은 대부분 주석문으로 이루어져 있습니다.


 우선 어떤 패키지를 생성해서 CMakeLists.txt를 처음 보게 되면 주석의 압박에 놀라게 됩니다. 주석을 다 지우고 코드만 남겨 보면 괄호 빼고 딱 4줄만 남지만, 주석 처리된 부분에 필수 요소들이 들어 있어 사용자가 원하는 부분의 내용을 주석 해제하여 코드를 추가해야 합니다. 또한 주석 자체에도 상당한 내용의 정보가 들어 있으므로 파일 작성 시에도 참고할 수 있습니다. CMakeLists.txt를 구성하는 내용은 크게 아래와 같이 나누어지며, 내용의 순서는 CMakeLists.txt를 작성할 때 반드시 지켜져야 한다는 특징이 있습니다.


1. CMake 최소 버전 (cmake_minimum_required)

2. 패키지 이름 (project())

3. 빌드에 필요한 CMake, catkin 관련 패키지 탐색 (find_package())

4. ROS 메시지, 서비스, 액션 생성기 (add_message_files(), add_service_files(), add_action_files())

5. 메시지, 서비스, 액션 생성 (generate_messages())

6. catkin 관련 빌드 정보 지정 (catkin_package())

7. 라이브러리, 실행 파일 지정 (add_library(), add_executable(), target_link_libraries())

8. 유닛 테스트 (catkin_add_gtest())

9. 생성된 target에 대한 설치 옵션 지정 (install())


각각의 번호별로 나눠서 보도록 하겠습니다.


1. CMake 최소 버전 (cmake_minimum_required)

 catkin을 사용할 때 필요한 CMake의 최소 버전입니다. 현재는 2.8.3버전 이상으로 설정되어 있습니다.


cmake_minimum_required(VERSION 2.8.3)



2. 패키지 이름 (project())

 CMake의 project()를 이용해 패키지명을 지정합니다. catkin_create_pkg를 이용해서 패키지를 만든 경우 패키지 이름이 자동으로 입력되어 있습니다. 여기서 입력한 패키지 이름은 ${PROJECT_NAME}이라는 변수에 저장됩니다.


project(test_package)



3. 빌드에 필요한 CMake, catkin 관련 패키지 탐색 (find_package())

 CMake가 패키지를 빌드할 때 필요한 패키지를 추가합니다. catkin에 관련된 기본 패키지는 REQUIRED 옵션만 추가하시면 됩니다.


find_package(catkin REQUIRED)


만약 패키지 소스를 작성하면서 추가적인 패키지(roscpp나 rospy 같은)를 포함시켜야 한다면 catkin의 COMPONENTS 옵션으로 추가시킬 수 있습니다. 각각의 패키지를 find_package를 이용해 추가시킬 수도 있지만 COMPONENTS 옵션의 요소로서 추가할 경우 작성이 훨씬 간편합니다. 예를 들어


find_package(catkin REQUIRED)
find_package(roscpp REQUIRED)
find_package(rospy REQUIRED)

라고 작성하는 것 보다는


find_package(catkin REQUIRED COMPONENTS roscpp rospy)

라고 작성하는 것이 간편합니다.


또한 위 예시의 패키지들은 실제로 catkin의 하위 패키지는 아니지만 이런 식으로 작성함으로써 include 디렉토리나 라이브러리 같은 환경 변수들을 공유하게 되어 사용이 편리해진다는 장점이 있습니다. find_package()를 통해 패키지를 찾게 되면 패키지의 정보가 포함된 환경 변수들이 생성되는데, CMakelists.txt 예시에서 자주 볼 수 있는


${catkin_INCLUDE_DIRS}

같은 변수들이 COMPONENTS로 명시된 패키지들의 include 디렉토리까지 모두 대표하게 되는 것입니다. 이러한 환경 변수들은 네 가지가 제시되어 있습니다.


<PACKAGE_NAME>_FOUND
<PACKAGE_NAME>_INCLUDE_DIRS or <NAME>_INCLUDES
<PACKAGE_NAME>_LIBRARIES or <NAME>_LIBS
<PACKAGE_NAME>_DEFINITIONS


C++ Boost를 사용하는 경우 Boost와 해당 component를 추가해 주시면 됩니다. 예를 들어 Boost의 threads를 사용하고자 할 경우


find_package(Boost REQUIRED COMPONENTS thread)


그 밖의 내용으로 runtime dependencies는 find_package의 COMPONENTS로 추가하지 말라고 되어 있는데 runtime dependency가 정확히 무엇인지 확인한 뒤 내용을 추가하도록 하겠습니다.



4. ROS 메시지, 서비스, 액션 생성기 (add_message_files(), add_service_files(), add_action_files())

 패키지에서 사용하는 메시지, 서비스, 액션 파일을 포함시켜 줍니다. 각각의 경로(msg, srv, action 폴더)에 포함되어 있는 파일들의 확장자를 포함한 이름을 입력해 주시면 됩니다. 메시지를 사용하는 경우 반드시 package.xml에서 'message_generation'을 build dependency로, 'message_runtime'을 runtime dependency로 추가해 주셔야 합니다. 또한 후술할 catkin_package() 내에 message_runtime이 반드시 포함되어 있어야 합니다.


add_message_files(FILES
     Message1.msg
     Message2.msg
)


add_service_files(FILES
     Service1.srv
     Service2.srv
)


add_action_files(FILES
     Action1.action
     Action2.action
)



5. 메시지, 서비스, 액션 생성 (generate_messages())

 패키지에서 사용하고자 하는 메시지 타입을 전부 추가해 줍니다.


generate_messages(
     DEPENDENCIES
     std_msgs
     sensor_msgs
)



6. catkin 관련 빌드 정보 지정 (catkin_package())

 catkin에 관련된 CMake 매크로를 작성하는 부분입니다. catkin_package()는 아래와 같은 다섯 가지의 선택적인 인자를 가집니다.


INCLUDE_DIRS
LIBRARIES
CATKIN_DEPENDS
DEPENDS
CFG_EXTRAS


INCLUDE_DIRS는 C 또는 C++의 include에 대응되는 디렉토리입니다. 생성된 헤더 파일들이 위치하는 곳입니다. LIBRARIES는 프로젝트에 해당되는 라이브러리들이 위치할 곳입니다. CATKIN_DEPENDS는 패키지가 의존하는 다른 catkin project이며, 예시에서는 roscpp와 nodelet을 제시하고 있습니다. DEPENDS는 catkin이 아닌 CMake와 연관된 의존 프로젝트입니다. 예시에서는 eigen과 opencv를 제시하였습니다. CFG_EXTRAS는 추가적인 configuration 옵션에 관한 것이고, 자주 사용되지는 않는 것 같습니다.


catkin_package(
     INCLUDE_DIRS include
     LIBRARIES ${PROJECT_NAME}
     CATKIN_DEPENDS roscpp nodelet
     DEPENDS eigen opencv
)

catkin_package()의 사용 예는 위와 같습니다.



7. 라이브러리, 실행 파일 지정 (add_library(), add_executable(), target_link_libraries())

 이 과정에선 빌드 대상, 즉 target을 지정합니다. Target은 실행 파일이 될 수도 있고, 라이브러리가 될 수도 있습니다. 실행 파일은 지금까지 rosrun으로 구동시켰던 바로 그 실행 파일입니다. 라이브러리 target은 실행 파일이 빌드할 때 사용하거나, 실행 파일의 runtime 과정에서 활용할 수 있는 target입니다. 우선 target의 이름을 설정합니다. Target 이름은 폴더와 상관 없이 하나만 존재할 수 있는 고유한 이름입니다. Target 이름은 set_target_properties()를 이용해 바꿀 수 있습니다.


set_target_properties(original_target
                                   PROPERTIES OUTPUT_NAME target
                                   PREFIX "")

PREFIX는 target 앞에 위치하는 prefix(라이브러리 앞에 붙는 lib 등)를 대체합니다. 위 경우에는 prefix를 지워 버린다고 볼 수 있습니다.


Target의 기본 output 디렉토리 대신 커스텀 디렉토리를 지정하고 싶은 경우도 마찬가지로 set_target_properties()를 사용합니다.


set_target_properties(original_target
                                   PROPERTIES LIBRARY_OUTPUT_DIRECTORY target)


Target 이름 재지정과 커스텀 디렉토리 지정은 CMake 관련 기능이며 자주 쓰이지는 않는 것 같습니다. 그 다음 target을 지정하기 전에 target을 build할 때 필요한 include path와 library path를 설정해 줍니다. Include path는 target 빌드에 필요한 헤더가 포함된 경로이며, library path는 executable target 빌드에 사용되는 라이브러리 경로입니다. Include path 지정에 사용하는 include_directories()에 들어가는 인자는 find_package()에서 지정한 패키지에 '_INCLUDE_DIRS' 접미사를 붙여 만듭니다. find_package()에서 catkin을 포함시켰다면 아래와 같은 형식이 됩니다.


include_directories(include ${catkin_INCLUDE_DIRS})


Library path 지정에 사용하는 link_directories()는 사용을 권장하지 않고 target_link_libraries()를 대신 사용하라고 나와 있으므로 넘어갑니다. 이는 패키지들이 find_package() 내에 포함될 때 자동적으로 link information이 추가되기 때문입니다. 헤더 경로를 지정한 뒤에는 실제 target인 실행 파일과 라이브러리를 지정합니다. 실행 파일의 지정은 CMake 함수인 add_executable()을 사용합니다.


add_executable(target_name src/main.cpp src/source.cpp src/source2.cpp)


라이브러리 target을 생성하는 경우 CMake 함수인 add_library()를 사용합니다.


add_library(${PROJECT_NAME} ${${PROJECT_NAME}_SRCS})


그리고 실행 파일이 어떤 라이브러리에 link하는지 지정하기 위해 앞서 언급한 target_link_libraries()를 사용합니다.


target_link_libraries(<executable_target_name>, <lib1>, <lib2>, ......)

여기서 <executable_target_name>은 add_executable에서 추가한 target_name과 동일해야 한다는 것을 알 수 있습니다. 빌드 시에 ROS 관련 reference를 찾지 못하는 경우 라이브러리로 ${catkin_LIBRARIES}를 추가해 주시면 됩니다.


만약 빌드하려는 패키지가 메시지나 서비스, dynamic_reconfigure 파라미터를 생성하거나 이를 이용하는 실행 파일을 만드는 경우, add_dependencies()를 이용하여 자동 생성되는 메시지, 서비스, dynamic_reconfigure target에 대한 패키지의 의존성을 추가해야 합니다.


add_dependencies(target ${${PROJECT_NAME}_EXPORTED_TARGETS})



8. 유닛 테스트 (catkin_add_gtest())

 catkin에서 제공하는 gtest 기반의 unit test 매크로입니다. Unit test 기능을 지원한다는 정도 알아 두시면 될 것 같습니다.


catkin_add_gtest(unit_test test/utest.cpp)



9. 생성된 target에 대한 설치 옵션 지정 (install())

 빌드 이후 생성된 파일들은 catkin 작업 경로(catkin_ws)의 devel 폴더 아래에 위치하게 됩니다. 이렇게 생성된 target들을 원하는 시스템 경로에 설치하여 다른 프로그램들이 사용하거나, system-level의 설치 과정을 테스트하는 용도로 사용할 수 있습니다. 설치는 CMake의 install()을 이용하여 사용이 가능합니다. install()의 인자는 install할 target인 TARGETS와, ARCHIVE(static 라이브러리와 윈도우 DLL, .lib), LIBRARY(DLL 이외의 공유 라이브러리와 모듈), RUNTIME(실행 파일과 DLL 형식의 공유 라이브러리) 각각에 대한 설치 경로입니다.


install(TARGETS ${PROJECT_NAME}
     ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
     LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
     RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

${CATKIN_PACKAGE_LIB_DESTINATION}과 ${CATKIN_PACKAGE_BIN_DESTINATION}은 기본 경로이고, 라이브러리가 Python과 연관되어 Python 경로에 설치하고자 한다면 destination을 ${CATKIN_PACKAGE_PYTHON_DESTINATION}로 지정하시면 됩니다.


실행 가능한 Python 스크립트를 설치하는 경우 catkin_install_python()을 사용합니다.


catkin_install_python(PROGRAMS scripts/test_script
     DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})


헤더 파일을 설치(원하는 include 경로에 배치)하는 경우엔 앞서 사용한 install()을 이용합니다.


install(DIRECTORY include/${PROJECT_NAME}/
     DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
     PATTERN ".svn" EXCLUDE
)

'PATTERN ".svn" EXCLUDE'는 폴더명에 '.svn'이 포함된 include destination의 서브버전 폴더를 제외합니다. 서브버전 폴더명이 패키지와 불일치하는 경우에는 DESTINATION에 ${CATKIN_PACKAGE_INCLUDE_DESTINATION} 대신 ${CATKIN_GLOBAL_INCLUDE_DESTINATION}을 사용하시면 됩니다.


그 밖에 roslaunch 파일이나 다른 resource 설치의 경우에도 위와 동일한 방법을 사용합니다. launch 파일의 경우에는 아래와 같이 사용합니다.


install(DIRECTORY launch/
     DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
     PATTERN ".svn" EXCLUDE)

launch 디렉토리의 파일들을 패키지 공유 경로 아래의 launch 폴더에 설치합니다.



지금까지 CMakeLists.txt의 내용에 대하여 상당히 자세하게 알아 보았습니다. 앞으로는 좀 더 손쉽게 빌드를 하실 수 있길 바라며, 다음 강의인 rosserial로 찾아 뵙겠습니다.


  1. ROS(Robot Operating System) 개념과 활용 - 11. rosserial 알아보기

    ROS가 적용되는 시스템에선 연산을 위한 상위 제어기와 하드웨어 제어를 위한 하위 제어기가 각각의 역할을 수행하는 경우가 많습니다. 상위 제어기는 보통 PC나 OBC(One Board Computer)를 사용하게 되는데, 하위 제어기와 통신할 때 가장 흔하게 사용되는 ...
    Date2016.03.28 CategoryROS(Robot Operating System) 개념과 활용 By박정현 Views7539
    Read More
  2. ROS(Robot Operating System) 개념과 활용 - 10. CMakeLists.txt 파헤치기

    CMakeLists.txt는 빌드 설정에 관련된 매우 중요한 파일이지만 주석의 압박과 익숙하지 않은 사용법 때문에 매번 대충 작성했던 경험이 있습니다. 관련 가이드를 찾아 보니 생각보다 간단한 규칙으로 되어 있어서 다른 내용을 진행하기 전에 미리 짚고 넘어가...
    Date2016.03.05 CategoryROS(Robot Operating System) 개념과 활용 By박정현 Views8436
    Read More
  3. ROS(Robot Operating System) 개념과 활용 - 9. Dynamic reconfigure를 이용한 실시간 node parameter 업데이트

    오랜만의 ROS 강좌 업데이트입니다. 거의 반년 전 쯤에 해 보았던 내용이지만 이런 저런 바쁜 일들에 밀려 이제서야 업데이트를 하게 되었습니다. 본 코너인 ROS 개념과 활용에서는 나머지 기본적인 내용들을 다루고 최종적으로 간단한 제어 예제까지 수행할 ...
    Date2016.02.24 CategoryROS(Robot Operating System) 개념과 활용 By박정현 Views3852
    Read More
  4. 밸런싱 로봇 만들기 - 2. I2C로 IMU(MPU 6050)와 통신하기

    이번 포스팅은 밸런싱 로봇에서 사용하는 유일한 센서인 IMU(Inertial Measurement Unit) - MPU6050과의 통신에 대한 것입니다. 준비물 : 앞의 포스팅에서 만든 하드웨어, 컴퓨터와 UART통신을 하기 위한 UART통신모듈(테스트용), CodeVision AVR 센서와 통신...
    Date2015.08.16 Category밸런싱 로봇 By한종인 Views4087
    Read More
  5. ROS(Robot Operating System) 개념과 활용 - 8. roslaunch 사용과 launch 파일 작성하기

    저번에 USB 카메라를 이용하면서 usb_cam-test.launch 파일을 실행시켜 보았습니다. usb_cam-test.launch 파일을 실행시키면 USB 카메라와 직접적으로 상호작용하는 '/usb_cam' 노드와 '/usb_cam/image_raw' 토픽을 받아 화면에 출력하는 '/image_view' 노드...
    Date2015.08.13 CategoryROS(Robot Operating System) 개념과 활용 By박정현 Views17572
    Read More
  6. ROS(Robot Operating System) 개념과 활용 - 7. USB 카메라 사용하기

    ROS는 여러 가지 이미지 관련 패키지를 제공하고 있습니다. 특히 OpenCV 연동 기능을 제공하기 때문에 다양한 영상 처리 알고리즘을 적용할 수 있다는 장점이 있습니다. 이미지와 영상을 얻기 위해서는 이미지를 얻는 센서가 필요한데, ROS가 주로 PC나 SBC ...
    Date2015.08.09 CategoryROS(Robot Operating System) 개념과 활용 By박정현 Views6775
    Read More
  7. ROS(Robot Operating System) 개념과 활용 - 6. rqt를 이용한 데이터 모니터링

    ROS는 로봇으로부터 얻을 수 있는 데이터를 쉽게 확인하고 관리할 수 있도록 rqt라고 하는 모니터링 도구를 제공합니다. rqt는 GUI 개발에 쓰이는 Qt framework 기반의 ROS software framework입니다. rqt는 우리가 지금까지 노드간 관계를 확인할 때 써 오던...
    Date2015.08.08 CategoryROS(Robot Operating System) 개념과 활용 By박정현 Views7049
    Read More
  8. ROS(Robot Operating System) 개념과 활용 - 5. 바닥부터 node 작성하기

    지금까지는 기존에 있던 패키지 노드를 수정하여 사용해 왔습니다. 이번에는 노드를 아예 처음부터 새로 작성하는 법에 대해 알아보겠습니다. 또한 노드 내부에서 사용되는 ROS의 기본 구조에 대해서도 간략히 짚고 넘어가도록 하겠습니다. 노드 작성법을 간...
    Date2015.07.26 CategoryROS(Robot Operating System) 개념과 활용 By박정현 Views33231
    Read More
  9. ROS(Robot Operating System) 개념과 활용 - 4. ROS node를 이용하여 direct serial 통신하기

    ROS 노드들은 TCP/IP 프로토콜의 메시지 통신을 기반으로 데이터를 주고 받습니다. 하지만 대다수의 센서들과 MCU의 통신은 일반적인 serial 프로토콜을 이용해 통신을 하는 경우가 많습니다. 여러 용도로 편리하게 사용되는 UART 통신 또한 그러한 방식입니...
    Date2015.07.07 CategoryROS(Robot Operating System) 개념과 활용 By박정현 Views10403
    Read More
  10. 밸런싱 로봇 만들기 - 1. 하드웨어 구성

    안녕하세요? 오늘부터 "밸런싱로봇 만들기"를 포스팅할 P.M.한종인 입니다. 밸런싱 로봇 하드웨어를 제작하기 위해서는 다음과 같은 몇 가지 준비물이 필요합니다. 준비물 : 부품, 회로도, 인두, 땜납, 테프론 래핑 와이어(얇은 배선용 전선), 일반전선, 멀티...
    Date2015.07.03 Category밸런싱 로봇 By한종인 Views2692
    Read More
Board Pagination Prev 1 2 Next
/ 2