Note: This tutorial assumes that you have completed the previous tutorials: ROS 파일시스템의 탐색. |
Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags. |
ROS 패키지의 작성
Description: 이 자습서는 roscreate-pkg 또는 catkin을 이용해 새로운 패키지를 작성하는 방법에 대해 설명합니다. 또한 rospack을 이용해 패키지의 의존성을 확인하는 법도 알아봅니다.Tutorial Level: BEGINNER
Next Tutorial: ROS 패키지 빌드하기
roscreate 사용하기
본격적으로 패키지를 만들기 전에 roscreate-pkg 명령행 도구의 사용법을 알아봅시다. 모든 ROS 패키지들은 manifests, CMakeLists.txt, mainpage.dox, Makefiles 등 비슷한 파일들이 공통으로 들어 있습니다. 직접 손으로 위의 파일들을 만드는 것은 매우 수고로울 뿐 아니라, 빌드관련 파일과 매니패스트의 작성 시 사소한 실수때문에 에러가 생길 수 있습니다. roscreate-pkg는 이 과정을 자동화 해서 새로운 패키지를 만드는 데 도움을 줍니다.
현재 폴더 안에 새로운 패키지를 만드려면 아래와 같이 입력합니다.
# roscreate-pkg [package_name]
만들면서 패키지의 의존성을 정해줄 수 도 있습니다.
# roscreate-pkg [package_name] [depend1] [depend2] [depend3]
새로운 ROS Package 작성하기
이제 홈이나 프로젝트 폴더로 이동해 자습서에서 사용할 beginner_tutorials 패키지를 만들게 될 것입니다. 의존성이 있는 패키지로는 기본 ROS 패키지에 포함된 std_msgs, roscpp, rospy를 지정할 것입니다.
이제 ~/ros_workspace/sandbox 폴더로 이동합니다.
$ cd ~/ros_workspace/sandbox
또는 Fuerte나 그 이전의 버전을 사용하고 계신다면 간단히 아래의 방법을 사용할 수도 있습니다.
$ roscd $ cd sandbox
그 다음 새로운 패키지를 만들어 봅시다.
$ roscreate-pkg beginner_tutorials std_msgs rospy roscpp
명령이 실행되면 아래와 같은 화면이 출력될 것입니다.
Creating package directory ~/fuerte_workspace/sandbox/beginner_tutorials Creating include directory ~/fuerte_workspace/sandbox/beginner_tutorials/include/beginner_tutorials Creating cpp source directory ~/ros/ros_tutorials/beginner_tutorials/src Creating python source directory ~/fuerte_workspace/sandbox/beginner_tutorials/src/beginner_tutorials Creating package file ~/fuerte_workspace/sandbox/beginner_tutorials/Makefile Creating package file ~/fuerte_workspace/sandbox/beginner_tutorials/manifest.xml Creating package file ~/fuerte_workspace/sandbox/beginner_tutorials/CMakeLists.txt Creating package file ~/fuerte_workspace/sandbox/beginner_tutorials/mainpage.dox Please edit beginner_tutorials/manifest.xml and mainpage.dox to finish creating your package
우리는 beginner_tutorials/manifest.xml파일에 좀 더 관심을 가질 필요가 있습니다. manifests는 ROS에서 패키지의 빌드, 실행, 문서화 과정 모두에 영향을 미치기 때문에 링크를 통해 세부사항을 알아두시면 좋습니다.
이제 ROS가 새로 만들어진 패키지도 찾아낼 수 있는지 알아보겠습니다. 저장된 경로에 변경사항이 생겼을 때 새로고침을 해 주는 rospack profile을 사용해 새로운 패키지를 찾아낼 수 있게 해줍니다.
$ rospack profile $ rospack find beginner_tutorials
YOUR_PACKAGE_PATH/beginner_tutorials
만약 실패했다면, 이는 ROS가 새로 만들어진 패키지를 찾지 못했다는 것입니다. $ROS_PACKAGE_PATH와 관련이 깊은 문제이므로 자신이 설치한 방법(소스코드 또는 바이너리)의 설치 지침을 찾아 검토해 보시길 바랍니다. 만약 $ROS_PACKAGE_PATH 경로 밖의 폴더에 새 패키지를 만드셨을 경우는 새 경로를 $ROS_PACKAGE_PATH에 지정해 주시고 ros_workspace안의 setup.bash를 쉘에 다시 등록(re-source)시켜 주시기 바랍니다.
이제 패키지의 안으로 이동하겠습니다.
$ roscd beginner_tutorials $ pwd
YOUR_PACKAGE_PATH/beginner_tutorials
1차 패키지 의존성
앞서 roscreate-pkg를 사용할 때, 몇 가지 의존 패키지들을 같이 입력했었습니다. 이들을 1차 패키지 의존성(first-order dependencies)라 하고 rospack 도구를 이용해 다시 확인할 수 있습니다.
(Jan 9, 2013) There is a bug reported and already fixed in rospack in groovy; it may take some time to be reflected in the packages. If you see an issue similar to this with the next command, you can skip to the following command.
$ rospack depends1 beginner_tutorials
std_msgs rospy roscpp
보시다시피 rospack가 roscreate-pkg 명령을 쓸 때 입력한 의존성들을 모두 보여주는 것을 확인할 수 있습니다. 이 패키지 의존성은 매니페스트 파일에 기록되어 있습니다. 한번 매니페스트 파일을 살펴보겠습니다.
$ roscd beginner_tutorials $ cat manifest.xml
<package> ... <depend package="std_msgs"/> <depend package="rospy"/> <depend package="roscpp"/> </package>
간접 패키지 의존성
많은 경우에 한개의 의존성은 자기 나름대로의 의존성을 가지고 있습니다. 예를 들면, rospy는 두개의 의존성을 품고 있습니다.
(Jan 9, 2013) There is a bug reported and already fixed in rospack in groovy; it may take some time to be reflected in the packages. If you see an issue similar to this with the next command, you can skip to the following command.
$ rospack depends1 rospy
roslib roslang
rospack은 재귀적으로 이러한 내포된 의존성까지 알아낼 수 있습니다.
$ rospack depends beginner_tutorials
rospack roslib std_msgs rosgraph_msgs rosbuild roslang rospy cpp_common roscpp_traits rostime roscpp_serialization xmlrpcpp rosconsole roscpp
참고: Fuerte에서는 목록이 많이 짧아졌습니다.
std_msgs roslang rospy roscpp
ROS 클라이언트 라이브러리
혹시 이전 예제에서 보았던 rospy와 roscpp의 의존성에 대해 궁금해 하실 분들이 계실 지 모르겠습니다. rospy와 roscpp는 Client Libraries의 일종입니다. 클라이언트 라이브러리는 ROS상에서 서로 다른 프로그래밍 언어로 통신하는 것을 가능케 합니다. 각각 rospy는 python, roscpp는 C++에 대한 클라이언트 라이브러리입니다.
복습
이 자습서에서 소개한 명령어들을 적어보겠습니다.
- roscreate-pkg = ros+create-pkg : 새로운 ROS 패키지를 만드는 데 필요한 파일을 자동으로 만들어 줍니다.
- rospack = ros+pack(age) : ROS 패키지와 관련된 정보를 알려줍니다.
- rosstack = ros+stack : ROS 스택과 관련된 정보를 알려줍니다.
Contents
catkin 패키지는 어떻게 이루어져 있나요?
어떤 패키지를 catkin 패키지라 하기 위해서는 몇 가지 조건에 부합해야 합니다.
패키지는 반드시 catkin compliant package.xml 파일을 포함해야 한다.
- package.xml 파일은 패키지의 메타 정보를 제공하는 것입니다.
패키지는 반드시 catkin에서 쓰이는 CMakeLists.txt을 포함하고 있어야 한다.
이 규칙의 예외로는 CMakeLIsts.txt파일을 가지지 않는 catkin metapackages 가 있습니다.
- 한 폴더 당 한 개의 패키지만이 대응될 수 있습니다.
- 이는 내포된 패키지 또는 같은 폴더를 공유하는 복수의 패키지를 용납하지 않는다는 의미입니다.
가능한 패키지의 예시 중 가장 간단한 예시를 보겠습니다.
my_package/ CMakeLists.txt package.xml
catkin 작업공간 내의 패키지들
catkin패키지에 대한 작업을 할 때 추천하는 방법은 catkin 작업공간을 사용하는 것입니다. 그러나 단일(standalone)으로 catkin패키지를 빌드할 수도 있습니다 일반적인 작업공간의 예제는 아래와 같습니다.
workspace_folder/ -- 작업공간 src/ -- 소스 폴더 CMakeLists.txt -- catkin이 제공하는 '최상위'의 CMake 파일, package_1/ CMakeLists.txt -- package_1에 대한 CMakeLists.txt 파일 package.xml -- package_1에 대한 매니패스트 ... package_n/ CMakeLists.txt -- package_n에 대한 CMakeLists.txt 파일 package.xml -- package_n에 대한 매니패스트
이 자습서를 시작하기 전에 catkin에서 작업공간 만들기 자습서를 참고해 빈 catkin작업공간을 만들어 두세요.
catkin패키지 작성하기
이 자습서는 catkin_create_pkg를 어떻게 사용하는지, 만들고 난 뒤에 할 일에 대해 설명할 것입니다. catkin_create_pkg는 새로운 catkin 패키지를 만드는 스크립트입니다.
먼저 catkin에서 작업공간 만들기 자습서에서 만들어 둔 catkin 작업공간의 소스 폴더로 이동합니다.
#이 경로는 catkin에서 작업공간 만들기 자습서에서 만드셨을 것입니다. $ cd ~/catkin_ws/src
이제 std_msgs, roscpp, rospy에 대한 의존성을 가지는 'beginner_tutorials' 패키지를 만들기 위해catkin_create_pkg 스크립트를 사용해 보겠습니다.
$ catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
이를 수행하면 package.xml과 CMakeLists.txt가 들어있는 beginner_tutorials폴더가 만들어 집니다. 여러분이 catkin_create_pkg에 주어 준 정보로 package.xml과 CMakeLists.txt의 일부가 채워집니다.
catkin_create_pkg에는 기본적으로 패키지의 이름을 입력하고 선택사항으로, 의존성을 가질 패키지들을 입력할 수도 있습니다
# 이것은 예시입니다. 그대로 따라하지 마세요. # catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
catkin_create_pkg은 몇 가지 진보된 기능을 제공합니다. 이에 대한 정보는catkin/commands/catkin_create_pkg의 링크를 참고하세요.
패키지 의존성
1차 의존성
위에서 catkin_create_pkg를 사용했을 때 몇 가지 의존성 정보를 입력했었습니다. 이들을 1차 의존성이라 하고 rospack 도구를 이용해 다시 확인 할 수 있습니다.
(Jan 9, 2013) There is a bug reported and already fixed in rospack in groovy, which takes sometime until the change gets reflected on your computer. If you see a similar issue like this with the next command, you can skip to the next command.
$ rospack depends1 beginner_tutorials
std_msgs rospy roscpp
보시다시피 rospack은 우리가 catkin_create_pkg을 쓸 때 입력한 의존성 목록과 일치하는 결과를 보여줍니다. 패키지의 의존성은 package.xml파일에 등록되어 있습니다.
$ roscd beginner_tutorials $ cat package.xml
<package> ... <buildtool_depend>catkin</buildtool_depend> <build_depend>roscpp</build_depend> <build_depend>rospy</build_depend> <build_depend>std_msgs</build_depend> ... </package>
간접 의존성
많은 경우에 하나의 의존 패키지는 자체로도 의존 패키지를 가지고 있습니다. 일례로 rospy는 아래의 의존성을 가집니다.
(Jan 9, 2013) There is a bug reported and already fixed in rospack in groovy, which takes sometime until the change gets reflected on your computer. If you see a similar issue like this with the next command, you can skip to the next command.
$ rospack depends1 rospy
genpy rosgraph rosgraph_msgs roslib std_msgs
rospack은 재귀적으로 모든 간접 의존성을 알아낼 수 있습니다.
$ rospack depends beginner_tutorials cpp_common rostime roscpp_traits roscpp_serialization genmsg genpy message_runtime rosconsole std_msgs rosgraph_msgs xmlrpcpp roscpp rosgraph catkin rospack roslib rospy
패키지 사용자화
이 부분은 catkin_create_pkg명령이 생성한 각각의 파일들을 한줄한줄, 각각의 구성요소 별로 살펴보게 될 것입니다. 이 과정을 통해 어떻게 여러분의 패키지를 사용자화 하는지 알게 될 것입니다.
package.xml 사용자화
package.xml는 반드시 여러분이 새로 만든 패키지의 안에 있어야 합니다. 이제 package.xml안으로 들어가, 주의가 필요한 부분을 세세하게 짚어보도록 하겠습니다.
description tag
맨 먼저 description tag를 수정 해 보겠습니다.
5 <description>The beginner_tutorials package</description>
가능한 한줄로 요약한다는 전제를 가지고, 자유롭게 패키지에 대한 설명을 적어봅니다. 한 줄로는 설명이 어려운 경우 여러 줄로 입력하셔도 됩니다.
maintainer tags
다음은 maintainer tag에 대해 알아보겠습니다.
7 <!-- One maintainer tag required, multiple allowed, one person per tag -->
8 <!-- Example: -->
9 <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
10 <maintainer email="user@todo.todo">user</maintainer>
이 부분은 package.xml에서 가장 중요한 부분 중 하나입니다. 패키지의 관리자에 대한 정보가 기록 되는 부분이며 최소 한 명 이상의 정보가 입력되어야 합니다. 관리자의 이름은 태그의 몸체가 되고, 반드시 입력되어야 하는 웹메일 주소를 속성으로 가지고 있습니다.
7 <maintainer email="you@yourdomain.tld">Your Name</maintainer>
license tags
다음은 license tag입니다.
12 <!-- One license tag required, multiple allowed, one license per tag -->
13 <!-- Commonly used license strings: -->
14 <!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
15 <license>TODO</license>
여기서 라이센스에 대한 정보를 반드시 입력해야 합니다. 자주 쓰이는 라이센스로는 BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 등이 있습니다. Open Source Initiative에서 이들에 대한 내용을 찾아보실 수 있습니다. 이 자습서에서는 ROS의 핵심 부분에서 이미 사용되고 있는 BSD라이센스를 사용합니다.
8 <license>BSD</license>
dependencies tags
다음은 패키지의 의존성을 알려주는 태그의 모음들을 볼 수 있습니다. 의존성 목록들은 build_depend, buildtool_depend, run_depend, test_depend에 맞추어 나누어져 있습니다. 보다 상세한 설명을 원하시면 Catkin Dependencies의 링크를 참고하시길 바랍니다. 우리는 catkin_create_pkg에서 std_msgs, roscpp, rospy를 의존성으로 정하였으므로 여기서는 아래와 같이 보일 것입니다.
27 <!-- The *_depend tags are used to specify dependencies -->
28 <!-- Dependencies can be catkin packages or system dependencies -->
29 <!-- Examples: -->
30 <!-- Use build_depend for packages you need at compile time: -->
31 <!-- <build_depend>genmsg</build_depend> -->
32 <!-- Use buildtool_depend for build tool packages: -->
33 <!-- <buildtool_depend>catkin</buildtool_depend> -->
34 <!-- Use exec_depend for packages you need at runtime: -->
35 <!-- <exec_depend>python-yaml</exec_depend> -->
36 <!-- Use test_depend for packages you need only for testing: -->
37 <!-- <test_depend>gtest</test_depend> -->
38 <buildtool_depend>catkin</buildtool_depend>
39 <build_depend>roscpp</build_depend>
40 <build_depend>rospy</build_depend>
41 <build_depend>std_msgs</build_depend>
우리가 지정한 모든 의존성이 build_depend에 있고 기본 buildtool_depend에 catkin이 있음을 확인할 수 있습니다. 우리가 지정해 둔 의존성은 빌드할 때나 실행할 때도 필요한 패키지들이기 때문에 run_depend 태그로도 등록해 둡니다.
12 <buildtool_depend>catkin</buildtool_depend>
13
14 <build_depend>roscpp</build_depend>
15 <build_depend>rospy</build_depend>
16 <build_depend>std_msgs</build_depend>
17
18 <exec_depend>roscpp</exec_depend>
19 <exec_depend>rospy</exec_depend>
20 <exec_depend>std_msgs</exec_depend>
수정된 package.xml
위에서 수정한 부분을 주의하며 주석과 사용하지 않는 태그들을 정리하면 훨씬 간결해진 package.xml을 볼 수 있습니다.
1 <?xml version="1.0"?>
2 <package format="2">
3 <name>beginner_tutorials</name>
4 <version>0.1.0</version>
5 <description>The beginner_tutorials package</description>
6
7 <maintainer email="you@yourdomain.tld">Your Name</maintainer>
8 <license>BSD</license>
9 <url type="website">http://wiki.ros.org/beginner_tutorials</url>
10 <author email="you@yourdomain.tld">Jane Doe</author>
11
12 <buildtool_depend>catkin</buildtool_depend>
13
14 <build_depend>roscpp</build_depend>
15 <build_depend>rospy</build_depend>
16 <build_depend>std_msgs</build_depend>
17
18 <exec_depend>roscpp</exec_depend>
19 <exec_depend>rospy</exec_depend>
20 <exec_depend>std_msgs</exec_depend>
21
22 </package>
CMakeLists.txt의 사용자화
이제 메타 정보가 담긴 package.xml 파일이 패키지에 맞게 변형되었습니다. catkin_create_pkg 가 자동으로 만들어 낸 CMakeLists.txt를 수정하는 부분은 이후 ROS 코드를 빌드하는 자습서에서 다루게 될 것입니다.
이제 새로운 ROS패키지가 만들어 졌습니다. 다음 자습서로 이동합니다. ROS 패키지 빌드하기