Knowhow/ROS2

[ROS2 Foxy Tutorial 한글 번역] 13. Creating a package

침닦는수건 2023. 2. 6. 11:26
반응형

Link

https://docs.ros.org/en/foxy/Tutorials/Beginner-Client-Libraries/Creating-Your-First-ROS2-Package.html

 

Creating a package — ROS 2 Documentation: Foxy documentation

Inside ros2_ws/src/my_package, you will see the files and folders that ros2 pkg create automatically generated: CMakePython CMakeLists.txt include package.xml src my_node.cpp is inside the src directory. This is where all your custom C++ nodes will go in t

docs.ros.org

 

Background

1. What is a ROS2 package?

패키지는 ROS2 에서 코드를 담는 컨테이너와 같다. 코드를 설치하거나 공유하기 위해선 패키지 형태로 만들 필요가 있다. 패키지로 만들면 ROS2 개발 결과를 release하고 다른 사람들이 쉽게 빌드해서 쓸 수 있게 된다. 

 

패키지를 만드는 방법은 ROS2 에서 빌드 시스템인 ament를 쓰거나 빌드 도구인 colcon을 이용하는 방법이다. 패키지는 CMake를 쓰거나 python으로도 만들 수 있다. 이 두 개도 공식적으로 지원되는 항목이다. 

 

2. What makes up a ROS2 package?

ROS2 Python과 CMake 패키지의 경우, 각각 약간의 필요 조건들이 있다. (이 글에서는 python만 다루도록 하겠다.)

 

python의 경우 다음과 같다.

  • package.xml : 패키지에 대한 메타 데이터를 담고 있는 파일
  • setup.py : 패키지를 어떻게 설치하는지 가이드 라인이 적힌 파일
  • setup.cfg : 패키지가 executable을 포함하고 있을 때 필요한 파일, ros2 run이 그래야 찾을 수 있다.
  • /<package_name> : 패키지 이름과 같은 폴더와 그 안에 __init__.py 파일이 존재해야 한다. 그래야 ROS2 tools가 패키지를 찾는다.

예시는 다음과 같다.

my_package/
      setup.py
      package.xml
      resource/my_package

 

3. Packages in a workspace

하나의 workspace 내에는 많은 패키지가 포함될 수 있으며 패키지마다 각각 폴더로 구분되어 있으면 된다. 이 때 패키지 별로 다른 빌드 타입이 달라도 문제가 되진 않는다. 단 nested 패키지 즉, 패키지 안에 또 다른 패키지가 있는 형태는 안된다.

 

가장 좋은 습관은 workspace 내 src 폴더가 있을 텐데 그 하위에 쭉 패키지를 나열하는 것이다. 

 

예시는 다음과 같다.

workspace_folder/
    src/
      package_1/
          CMakeLists.txt
          package.xml

      package_2/
          setup.py
          package.xml
          resource/package_2
      ...
      package_n/
          CMakeLists.txt
          package.xml

 

Prerequisites

2023.02.03 - [Development/ROS2] - [ROS2 Foxy tutorial 한글 번역] 12. Creating a workspace 내용을 참고하여 ROS2 workspace를 하나 만들어두면 된다.

 

Tasks

1. Create a package

첫번째로 ROS2 installation을 sourcing한다. 그리고 이전에 만들어둔 workspace/src로 이동한다. 

cd ~/ros2_ws/src

패키지를 생성하는 커맨드는 다음과 같다. 

ros2 pkg create --build-type ament_python <package_name>

이번 튜토리얼에서는 --node-name이라는 옵션을 추가해서 간단히 hello world executable을 패키지 내에 같이 만들어 볼 것이므로 다음 형식으로 입력하면 된다.

ros2 pkg create --build-type ament_python --node-name my_node my_package

이와 같이 입력하면 다음과 같은 출력 결과를 얻을 수 있다.

going to create a new package
package name: my_package
destination directory: /home/user/ros2_ws/src
package format: 3
version: 0.0.0
description: TODO: Package description
maintainer: ['<name> <email>']
licenses: ['TODO: License declaration']
build type: ament_python
dependencies: []
node_name: my_node
creating folder ./my_package
creating ./my_package/package.xml
creating source folder
creating folder ./my_package/my_package
creating ./my_package/setup.py
creating ./my_package/setup.cfg
creating folder ./my_package/resource
creating ./my_package/resource/my_package
creating ./my_package/my_package/__init__.py
creating folder ./my_package/test
creating ./my_package/test/test_copyright.py
creating ./my_package/test/test_flake8.py
creating ./my_package/test/test_pep257.py
creating ./my_package/my_package/my_node.py

 

2. Build a package

패키지를 workspace 내에 모아두는 구조는 colcon build를 이용해서 모든 패키지를 동시에 빌드할 수 있도록 하기 때문에 편의성이 높아진다. 그렇지 않으면 패키지 개별적으로 따로 빌드를 해주어야 한다.

( 패키지 별로 빌드 타입이 다를 경우, colcon이 빌드 시스템이 아닌 빌드 도구이기 때문에 알아서 맞는 시스템을 호출해서 처리해주는 듯하다.)

 

cd ~/ros2_ws
colcon build

이전 튜토리얼에서 ros2_ws에 ros_tutorials 패키지를 clone 받아 사용한 적이 있는데 그 때 colcon build를 사용해서 ros2_tutorials 내에 turtlesim 패키지를 빌드했었다. 이처럼 몇 개 안될 때는 금방 끝나지만 당연하게도 패키지 개수가 늘어나면 빌드 시간이 꽤 늘어난다.

 

특정 패키지만 선택적으로 빌드하고 싶을 땐 다음과 같이 할 수도 있다.

colcon build --packages-select my_package

 

3. Source the setup file

새로 만든 패키지와 executable을 사용하고 싶다면, 먼저 새 터미널을 열고 ROS2를 sourcing해서 준비해둔다. 

 

그리고 ros2_ws(workspace)내에서 다음 커맨드로 workspace를 sourcing한다.

. install/setup.bash

이렇게 하면 workspace가 경로에 추가되면서 패키지의 executable을 사용할 수 있게 된다.

 

4. Use the package

--node-name 옵션을 추가했기 때문에 생성된 패키지 executable은 알겠지만 다음 커맨드로 실행 가능하다.

ros2 run my_package my_node

다음과 같은 출력 결과를 얻을 수 있을 것이다. (python일 경우다.)

Hi from my_package.

 

5. Examine package contents

ros2_ws/src/my_package 내 ros2 pkg create 커맨드로 인해 생겨난 파일들이 다음과 같이 보일 것이다. 

my_package  package.xml  resource  setup.cfg  setup.py  test

 

6. Customize package.xml

패키지를 생성할 때 출력된 내용들은 살펴보면 description, license 항목 내에 TODO 라는 표시가 되어있는 것을 볼 수 있다. 이것은 패키지 description과 license 정의는 자동으로 되는 것이 아니라 필수적으로 개발자가 지정해줘야 하는 것이기 때문이다. maintainer 즉, 관리자가 누군지도 명시해야 한다.

 

ros2_ws/src/my_package 내 package.xml 파일을 열어서 보면 다음과 같다.

<?xml version="1.0"?>
<?xml-model
   href="http://download.ros.org/schema/package_format3.xsd"
   schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
 <name>my_package</name>
 <version>0.0.0</version>
 <description>TODO: Package description</description>
 <maintainer email="user@todo.todo">user</maintainer>
 <license>TODO: License declaration</license>

 <test_depend>ament_copyright</test_depend>
 <test_depend>ament_flake8</test_depend>
 <test_depend>ament_pep257</test_depend>
 <test_depend>python3-pytest</test_depend>

 <export>
   <build_type>ament_python</build_type>
 </export>
</package>

개발자의 이름과 e-mail을 maintainer에 기입하고 description에 짧은 패키지 소개글을 작성하면 된다.

<description>Beginner client libraries tutorials practice package</description>

이런 느낌이다.

 

그리고 license는 여러가지 종류가 있는데 그 중 사용하고자 하는 타입을 기재하면 된다. 이번 튜토리얼에서는 공부용이니 Apache License 2.0을 사용하겠다.

<license>Apache License 2.0</license>

license 태그 밑에 _depend로 끝나는 것들이 많이 있을텐데 이것은 다른 패키지와의 의존성이 기재된 것이다. 이걸 기반으로 colcon이 찾는다. 위 예제는 아무런 의존성도 갖고 있지 않은 간단한 형태이기 때문에 아무것도 없고 ament나 python 관련된 것들만 있는 것이고 실제로는 다양한 내용들이 있다.

 

python을 사용하는 경우, package.xml 외에 setup.py 파일도 만들어 줘야 하는데 그 코드는 package.xml 내용과 동일하다. 같은 내용을 형식만 바꾸어서 한 번 더 정리해주면 된다. 주의할 점은 xml 파일에 기재된 내용과 완전히 일치해야 한다는 것이다. 버전이나 패키지 이름도 당연히 같아야 한다. 

from setuptools import setup

package_name = 'my_py_pkg'

setup(
 name=package_name,
 version='0.0.0',
 packages=[package_name],
 data_files=[
     ('share/ament_index/resource_index/packages',
             ['resource/' + package_name]),
     ('share/' + package_name, ['package.xml']),
   ],
 install_requires=['setuptools'],
 zip_safe=True,
 maintainer='TODO',
 maintainer_email='TODO',
 description='TODO: Package description',
 license='TODO: License declaration',
 tests_require=['pytest'],
 entry_points={
     'console_scripts': [
             'my_node = my_py_pkg.my_node:main'
     ],
   },
)

 

Summary

작성한 코드를 패키지로 정리해서 사용이 쉬운 형태로 만들어 보았다. 

 

패키지는 필요한 파일들이 colcon에 의해서 알아서 엮여 만들어졌고 로컬 환경에서 실행해볼 수 있는 executable 파일도 포함되어 있다.

 

반응형