5 분 소요


패키지(Package)란?

하나 이상의 노드 또는 노드 실행을 위한 정보 등을 묶어 놓은 것을 패키지(Package)라고 하며, 패키지의 묶음을 메타패키지(Metapackage)라 부른다.

이때 메타 패키지는 package.xml만을 포함하고 일반적인 패키지 내에 존재하는 폴더와 파일을 포함하지 않는다.

  • 파일 관점: 관련된 라이브러리, 모델링 파일들, 설정 파일들을 모아둔 폴더
  • 기능 관점: 시뮬레이션, 하드웨어 관련, 모델링, 원격 조종 등으로 분리시킨 모듈
    • _control: 원격 조종과 관련된 패키지
    • _description: 로봇의 외관과 관련 모델링과 관련된 패키지
    • _drive: 실질적인 하드웨어 드라이브와 상호작용과 관련된 패키지
  • 더불어 colcon build가 수행되는 빌드의 단위

이때 “_control, _description, _drive”과 같은 형식들은 암묵적인 형식이다. 한 폴더에 모두 넣고 패키지를 실행할 수도 있지만, 패키지를 분리하여 선택적으로 패키지를 실행함으로써 업무의 효율을 높일 수 있다.

ament를 사용하여 패키지를 만들 수 있다.

$ ros2 pkg create --build-type ament_cmake  <패키지이름> --dependencies rclcpp <종속성> 
$ ros2 pkg create --build-type ament_python <패키지이름> --dependencies rclpy <종속성> 
  • ’–build-type ament_cmake’ : 이 옵션은 패키지의 빌드 시스템을 지정. ROS 2에서는 Ament 빌드 시스템을 사용하며, ‘ament_cmake’는 그 중 하나. 따라서 패키지의 빌드를 위해 CMake를 사용하게 됨.
  • **‘<패키지이름>'** : 생성할 패키지의 이름을 지정. 이 부분에 원하는 패키지 이름을 입력.
  • ’–dependencies rclcpp’ : 이 옵션은 패키지가 의존하는 라이브러리나 패키지를 지정. 여기서는 rclcpp 라이브러리에 대한 의존성을 추가하고 있음. ‘rclcpp’는 ROS 2에서 사용되는 C++ 라이브러리로, ROS 클라이언트 라이브러리 중 하나.
  • **‘<종속성>'** : 추가적으로 패키지가 의존하는 다른 패키지들을 지정할 수 있음. 여러 종속성을 추가하려면 각 패키지를 공백으로 구분하여 나열하면 됨.

이 명령어를 실행하면 지정한 옵션과 종속성을 가진 ROS 2 패키지의 기본 구조가 생성. 생성된 패키지는 ‘src’, ‘include’, ‘launch’, ‘test’ 등의 디렉토리를 포함하며, 해당 디렉토리들에는 패키지의 소스 코드, 헤더 파일, 런치 파일, 테스트 코드 등이 위치. 이렇게 생성된 패키지를 기반으로 원하는 ROS 2 노드 및 기능을 개발할 수 있음.


패키지 생성

일단 오버레이 작업 공간을 다음과 같이 생성한 뒤에 src 폴더에 패키지를 생성했다. Cpp 패키지와 Python 패키지를 각각 하나씩 생성한다.

$ mkdir ~/ws/src
$ cd ~/ws/src

$ ros2 pkg create cmake_pkg --build-type ament_cmake
$ ros2 pkg create python_pkg --build-type ament_python

생성된 파일 및 폴더는 다음과 같음을 확인할 수 있다.

ws/
|-- src/
|   |-- cmake_pkg/
|   |-- python_pkg/

cmake_pkg

cmake_pkg/
|-- include/
|   `-- cmake_pkg/
|-- src/
|-- CMakeLists.txt
|-- package.xml
  • include/: 헤더 파일이 위치하는 폴더
  • src/: 소스 코드가 위치하는 폴더
  • CMakeLists.txt: CMake 설정 파일
  • package.xml: 패키지의 메타 정보를 담은 XML 파일

python_pkg

python_pkg/
|-- python_pkg/
|   `-- __init__.py
|-- resource
|   `-- python_pkg
|-- test
|   `-- test_copyright.py
|   `-- test_flake8.py
|   `-- test_pep257.py
|-- setup.py
|-- setup.cfg
|-- package.xml
  • python_pkg/: Python 패키지 모듈이 위치하는 폴더
  • setup.py: Python 패키지 설정 파일
  • setup.cfg: Python 패키지 설정 파일
  • package.xml: 패키지의 메타 정보를 담은 XML 파일

패키지 빌드

Workspace의 ‘src’ 폴더 안에 있는 ROS2 패키지들을 빌드할 때, colcon을 사용하여 빌드를 진행한다. 빌드가 완료되면, 빌드된 패키지들은 작업공간(workspace)의 디렉터리인 ’~/dev_ws/install’ 에 설치된다.

‘ament_python’을 사용하여 노드를 생성해보자.

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

이때 ’–node-name’ 옵션을 통해 노드를 생성하고, 패키지의 이름은 my_package, 노드 이름은 my_node 이다.

노드의 위치는 다음과 같다.

/home/jh/ws/src/my_package/my_package

image

이후에 작업공간 루트(ws)로 이동한 뒤에 colcon으로 노드 패키지를 빌드한 뒤에 오버레이 작업공간 환경설정을 한다.

$ colcon build --packages-select my_package
$ source ./install/setup.bash

이후 my_node를 실행하면 다음과 같음을 확인할 수 있다.

$ ros2 run my_package my_node

image

이때 ‘source install/setup.bash’ 명령어를 실행시키는 이유는 다음과 같다.

1. ROS 2 환경 변수 설정: setup.bash 파일은 빌드된 패키지의 실행 파일, 라이브러리 등이 위치한 디렉터리를 PATH, LD_LIBRARY_PATH, PYTHONPATH 등과 같은 환경 변수에 추가합니다. 이를 통해 빌드된 패키지를 사용할 수 있도록 환경을 설정합니다.

2. ROS 2 작업공간 활성화: source install/setup.bash 명령어를 통해 현재 쉘에서는 ROS 2 작업공간에 있는 패키지들을 활용할 수 있게 됩니다. 이는 빌드된 패키지들이 설치된 디렉터리를 현재 쉘의 환경 변수에 추가함으로써 구현됩니다.

이 명령어는 빌드된 ROS 2 패키지들의 실행 파일, 라이브러리, 리소스에 접근할 수 있도록 현재 쉘의 환경을 구성하는 데 사용됩니다. 만약 source install/setup.bash 명령어를 실행하지 않으면 빌드된 패키지를 사용할 수 없습니다.

빌드 시스템에 필요한 부가 기능

빌드 시스템에 필요한 부가 기능으로 ROS의 버전 시스템 툴인 vcstool, 의존성 관리 툴인 rosdep, 바이너리 패키지 관리 툴인 bloom이 있다.

1. vcstool(버전 컨트롤 시스템)

vcs는 Version Control System의 약자로 ROS 커뮤니티에서 사용하는 vcstool의 실행 명령어이다. 다양한 리포지터리와 혼재된 버전 관리 시스템을 사용하더라도 ROS를 사용함에 있어서 불편함이 없도록 만들어진 툴이다.

아래의 코드를 확인해보면, 우선 wget을 통하여 ros2.repos라는 파일을 받게 되는데 이 파일에는 vcs 타입, 리포지터리 주소, 설치해야 하는 브랜치에 대한 정보가 명시되어 있다. 이러한 정보가 기재된 *repos 파일을 이용하여 다양한 리포지터리, 다양한 vcs를 지원하며 패키지들을 관리할 수 있다.

$ wget https://raw.githubusercontent.com/ros2/ros2/foxy/ros2.repos
$ vcs import src < ros2.repos

2. rosdep(의존성 툴)

기본적으로 빌트 툴들은 각 패키지의 의존성을 고려해주기는 하지만 의존성 자체를 해결해 주지는 않는다. 이를 위해 ROS에서는 rosdep 이라는 툴을 사용하는데 이는 package.xml에 기술된 의존성 정보를 가지고 의존성 패키지들을 설치해 주는 역할을 한다.

3. bloom(바이너리 패키지 관리 툴)

bloom은 바이너리 패키지 관리 툴이다. 개발한 패키지를 사용자에게 전달하기 위해서는 쉽게 apt 명령어(sudo apt install ros-foxy-xxxxxx)를 통해 설치하고 이를 사용할 수 있도록 하는 것이 좋은데, 이러한 바이너리 패키지 배포 및 관리를 위한 툴이 bloom 이다. 이 툴을 사용하면 바이너리 패키지를 관리하기 위한 메타 데이터를 생성하고 dpkg-buildpackage와 같은 플랫폼 종속 도구가 바이너리 패키지를 빌드하는 데 사용된다.


실습

목표

새로운 작업공간을 생성 후 turtle_test 라는 패키지를 생성하고 해당 패키지의 launch 파일을 통해 turtlesim의 실행과 사각형을 그리는 두 작업이 동시에 시작할 수 있도록 해보자.

과정

1. 작업공간에 패키지 생성

$ cd ~/dev_ws/src
$ ros2 pkg create turtle_test --build-type ament_python

2. turtle_test 패키지에 launch 폴더 생성 후 turtle_launch.launch.py 파일 생성

$ cd ~/dev_ws/src/turtle_test
$ mkdir launch
$ touch ./launch/turtle_launch.launch.py

image

3. turtle_test 패키지 빌드

$ cd ~/dev_ws
$ colcon build --package-select turtle_test
$ source ./install/setup.bash

4. launch 파일 실행 (Error 발생)

$ ros2 launch turtle_test turtle_launch.launch.py

launch 명령어를 실행하니 아래와 같이 에러가 발생했다.

file 'turtle_launch.launch.py' was not found in the share directory of package 'turtle_test' which is at '/home/jh/dev_ws/install/turtle_test/share/turtle_test'

이 문제는 작업공간의 install 디렉터리에 설치된 turtle_test 패키지 폴더에 launch 폴더가 공유되지 않았기 때문에 발생한 문제이다. 그래서 turtle_test 패키지의 ‘setup.py’ 파일을 확인해 보니 다음과 같았다.

from setuptools import setup

package_name = 'turtle_test'

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='jh',
    maintainer_email='ahdtld54@korea.ac.kr',
    description='TODO: Package description',
    license='TODO: License declaration',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
        ],
    },
)

‘data_files’ 매개변수를 사용하여 ‘share’ 폴더를 설정할 수 있으므로, data_files 부분에 아래의 문장을 추가해주었다.

('share/' + package_name, ['launch/turtle_launch.launch.py']),

이후 빌드를 다시 진행하니 share 디렉터리에 아래와 같이 ‘turtle_launch.launch.py’ 파일이 생성되었다. 이후 launch 명령어를 실행하니 잘 작동하는 것을 확인할 수 있었다.

image

image


Reference