본문으로 바로가기

ROS 2에서 package.xml은 패키지의 신분증입니다.

 

노드가 실제로 어떻게 빌드되는지는 C++ 패키지에서는 CMakeLists.txt, Python 패키지에서는 setup.py가 담당합니다.

하지만 이 패키지가 어떤 이름을 가지는지, 어떤 의존성을 사용하는지, 어떤 빌드 방식을 쓰는지는 package.xml이 설명합니다.

 

 

1. package.xml이 하는 일

package.xml은 ROS 2 패키지의 메타데이터를 담는 파일입니다.

 

주요 역할은 다음과 같습니다.

                     항목                                                              의미
패키지 이름 ROS 2에서 이 패키지를 부르는 이름
버전 패키지 버전
설명 패키지가 하는 일
관리자 유지보수 담당자
라이선스 사용 조건
의존성 빌드, 실행, 테스트에 필요한 패키지
빌드 타입 ament_cmake, ament_python 등

 

ROS 2 Humble에서 colcon build를 실행하면 colcon은 각 패키지의 package.xml을 읽고 패키지 의존 관계를 판단합니다.

즉, package.xml이 틀리면 패키지 빌드나 실행에서 바로 문제가 납니다.

 

 

 

 

2. package.xml 기본 구조

 

기본 구조는 다음과 같습니다.

 
<?xml version="1.0"?>
<package format="3">
  <name>패키지_이름</name>
  <version>0.0.0</version>
  <description>패키지 설명</description>

  <maintainer email="이메일">관리자 이름</maintainer>
  <license>라이선스</license>

  의존성 태그들...

  <export>
    <build_type>빌드_타입</build_type>
  </export>
</package>
 

 

ROS 2 Humble에서는 보통 다음 형식을 사용합니다.

 
<package format="3">
 

format="3"은 package.xml 문법 버전입니다. 실습에서는 그냥 ROS 2 Humble에서 일반적으로 사용하는 package.xml 형식이라고 이해하면 됩니다.

 

더보기

format="3"은 package.xml 문법 버전입니다.

 

쉽게 말하면 다음과 같습니다.

format="3" = package.xml을 3번 형식 규칙으로 작성했다는 뜻
 

 

ROS에는 과거부터 여러 manifest 형식이 있었습니다.

 

             형식                                                            주 사용 시기/용도

format 1 오래된 ROS 1 방식
format 2 개선된 ROS 1/ROS 2 호환 방식
format 3 ROS 2에서 일반적으로 사용하는 방

 

 

 

 

3. C++ 패키지: my_cpp_package

my_cpp_package는 C++ 패키지입니다.

 

따라서 빌드 타입은 다음과 같습니다.

 
<build_type>ament_cmake</build_type>
 

 

C++ 패키지에서는 보통 rclcpp를 사용합니다.

 

예를 들어 C++ 코드에서 다음 헤더를 사용한다면,

 
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
 

 

package.xml에는 최소한 다음 의존성이 필요합니다.

 
<depend>rclcpp</depend>
<depend>std_msgs</depend>
 

 

 

 

my_cpp_package/package.xml 예제

 
<?xml version="1.0"?>
<package format="3">
  <name>my_cpp_package</name>
  <version>0.0.0</version>
  <description>ROS 2 Humble C++ practice package</description>

  <maintainer email="dragon@example.com">dragon</maintainer>
  <license>Apache-2.0</license>

  <buildtool_depend>ament_cmake</buildtool_depend>

  <depend>rclcpp</depend>
  <depend>std_msgs</depend>

  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>

  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>
 
 
 
 

C++ 패키지에서 중요한 부분

 

1) 패키지 이름

 
<name>my_cpp_package</name>
 

 

이 이름은 패키지 폴더 이름과 같아야 합니다.

 
~/ros2_study/src/my_cpp_package
 

 

즉, 폴더 이름과 package.xml의 <name> 값이 다르면 안 됩니다.

 

 

 

2) 빌드 도구 의존성

 
<buildtool_depend>ament_cmake</buildtool_depend>
 

 

C++ 패키지는 CMake 기반으로 빌드합니다.

그래서 ament_cmake가 필요합니다.

 

 

 

3) C++ 클라이언트 라이브러리 의존성

 
<depend>rclcpp</depend>
 

 

rclcpp는 ROS 2 C++ 노드를 만들 때 사용하는 기본 라이브러리입니다.

C++ 노드에서 다음 코드를 사용하면 반드시 필요합니다.

 
#include "rclcpp/rclcpp.hpp"
 

 

 

 

4) 메시지 패키지 의존성

 
<depend>std_msgs</depend>
 

 

std_msgs/msg/String 같은 기본 메시지를 사용할 때 필요합니다.

 

예를 들어 C++ 코드에서 다음을 사용하면,

 
#include "std_msgs/msg/string.hpp"
 

 

package.xml에 다음이 있어야 합니다.

 
<depend>std_msgs</depend>
 
 
 
 

5) 빌드 타입

 
<export>
  <build_type>ament_cmake</build_type>
</export>
 

 

이 부분이 빠지면 ROS 2가 이 패키지를 어떤 방식으로 빌드해야 하는지 알 수 없습니다.

 

C++ 패키지는 반드시 다음 구조를 사용합니다.

 
<export>
  <build_type>ament_cmake</build_type>
</export>
 

 

이건 실무에서도 자주 터지는 포인트입니다.
빌드가 이상하게 안 되면 package.xml의 <build_type>부터 확인하는 게 맞습니다.

 

 

 

 

4. Python 패키지: my_first_package

my_first_package는 Python 패키지입니다.

 

따라서 빌드 타입은 다음과 같습니다.

 
<build_type>ament_python</build_type>
 

 

Python 패키지에서는 보통 rclpy를 사용합니다.

 

예를 들어 Python 코드에서 다음을 사용한다면,

 
import rclpy
from std_msgs.msg import String
 

 

package.xml에는 다음 의존성이 필요합니다.

 
<exec_depend>rclpy</exec_depend>
<exec_depend>std_msgs</exec_depend>
 
 
 
 

my_first_package/package.xml 예제

 
<?xml version="1.0"?>
<package format="3">
  <name>my_first_package</name>
  <version>0.0.0</version>
  <description>ROS 2 Humble Python practice package</description>

  <maintainer email="dragon@example.com">dragon</maintainer>
  <license>Apache-2.0</license>

  <exec_depend>rclpy</exec_depend>
  <exec_depend>std_msgs</exec_depend>

  <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>
 

 

 

 

Python 패키지에서 중요한 부분

1) 패키지 이름

 
<name>my_first_package</name>
 

 

이 이름은 다음 항목들과 맞아야 합니다.

 
~/ros2_study/src/my_first_package
 

 

그리고 setup.py 안의 package_name도 같아야 합니다.

 
package_name = 'my_first_package'
 

 

Python 패키지에서는 이름이 하나라도 어긋나면 ros2 run에서 실행 파일을 못 찾는 경우가 많습니다.

 

 

 

2) rclpy 실행 의존성

 
<exec_depend>rclpy</exec_depend>
 

 

rclpy는 ROS 2 Python 노드를 만들 때 사용하는 기본 라이브러리입니다.

Python 코드에서 다음을 사용하면 필요합니다.

 
import rclpy
 

 

더보기

Python 노드에서:

 
import rclpy
 

를 해도, 현재 환경에 이미 rclpy가 설치되어 있으면 실행됩니다.

예를 들어 Ubuntu에서 ROS 2를 설치하면 보통 다음 패키지가 이미 깔려 있습니다.

 
ros-${ROS_DISTRO}-rclpy
 

그래서 package.xml에 없어도 Python 인터프리터가 rclpy를 찾을 수 있습니다.

 

Python 코드에서 rclpy를 직접 사용한다면:

 
<exec_depend>rclpy</exec_depend>
 

를 넣는 게 맞습니다.

 

 

 

 

3) 메시지 패키지 실행 의존성

 
<exec_depend>std_msgs</exec_depend>
 

 

Python 코드에서 다음을 사용하면 필요합니다.

 
from std_msgs.msg import String
 

 

Python 패키지에서는 보통 실행 시점 의존성으로 작성합니다.

 
<exec_depend>std_msgs</exec_depend>
 
 
우리가 지금까지 실습한 내용을 기준으로 아래의 메세지 의존성을 추가해야 합니다.
 
  <exec_depend>rclpy</exec_depend>
  <exec_depend>geometry_msgs</exec_depend>
  <exec_depend>my_first_package_msgs</exec_depend>
  <exec_depend>turtlesim</exec_depend>
 
 
 
 

4) 빌드 타입

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

 

Python 패키지는 반드시 ament_python으로 지정해야 합니다.

C++ 패키지처럼 ament_cmake를 쓰면 안 됩니다.

 

 

 

 

5. C++ 패키지와 Python 패키지의 차이

핵심 차이는 빌드 타입입니다.

                             구분                                                                 C++ 패키지                                   Python 패키지
패키지 이름 my_cpp_package my_first_package
빌드 타입 ament_cmake ament_python
주요 파일 CMakeLists.txt setup.py, setup.cfg
ROS 클라이언트 라이브러리 rclcpp rclpy
대표 의존성 태그 <depend> <exec_depend>
export build_type ament_cmake ament_python

 

 

 

 

6. 인터페이스 패키지와 연결되는 경우

현재 실습환경에는 인터페이스 패키지도 있습니다.

 
my_first_package_msgs
 

 

이 패키지는 .msg, .srv, .action 파일을 정의하는 패키지입니다.

C++ 패키지나 Python 패키지에서 이 인터페이스를 사용한다면 각각의 package.xml에 의존성을 추가해야 합니다.

 

 

C++ 패키지에서 인터페이스 사용

my_cpp_packagesms의 C++ 코드에서 다음처럼 사용자 정의 메시지를 사용한다고 가정합니다.

 
#include "my_first_package_msgs/msg/my_message.hpp"
 

 

그러면 my_cpp_packagesms/package.xml에 다음을 추가합니다.

 
<depend>my_first_package_msgs</depend>
 

 

예:

 
<depend>rclcpp</depend>
<depend>std_msgs</depend>
<depend>my_first_package_msgs</depend>
 

 

 

 

Python 패키지에서 인터페이스 사용

my_first_package의 Python 코드에서 다음처럼 사용자 정의 메시지를 사용한다고 가정합니다.

 
from my_first_package_msgs.msg import MyMessage
 

 

그러면 my_first_package/package.xml에 다음을 추가합니다.

 
<exec_depend>my_first_package_msgs</exec_depend>
 

 

예:

 
<exec_depend>rclpy</exec_depend>
<exec_depend>std_msgs</exec_depend>
<exec_depend>my_first_package_msgs</exec_depend>
 
 
 
 
 

7. 의존성 태그 정리

package.xml에서 자주 사용하는 의존성 태그는 다음과 같습니다.

                    태그                                              의미
<buildtool_depend> 빌드 도구 의존성
<build_depend> 빌드할 때 필요한 의존성
<exec_depend> 실행할 때 필요한 의존성
<depend> 빌드와 실행 모두 필요한 의존성
<test_depend> 테스트할 때 필요한 의존성

 

실습에서는 이렇게 기억하면 됩니다.

 

C++ 패키지:

 
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend>
<depend>std_msgs</depend>
 

 

Python 패키지:

 
<exec_depend>rclpy</exec_depend>
<exec_depend>std_msgs</exec_depend>
 

 

인터페이스 패키지를 사용할 때:

 
<depend>my_first_package_msgs</depend>
 

 

또는 Python에서는:

 
<exec_depend>my_first_package_msgs</exec_depend>
 

 

 

 

 

8. 실습환경에서 빌드 확인

workspace는 ros2_study입니다.

 
cd ~/ros2_study
colcon build
 

 

특정 패키지만 빌드하려면 다음처럼 합니다.

 
colcon build --packages-select my_cpp_packagesms
 
 
colcon build --packages-select my_first_package
 

 

빌드 후에는 반드시 환경 설정을 합니다.

 
source install/setup.bash
 

 

패키지가 인식되는지 확인합니다.

 
ros2 pkg list | grep my_cpp_packagesms
ros2 pkg list | grep my_first_package
ros2 pkg list | grep my_first_package_msgs
 

 

 

 

 

10. 최종 정리

ROS 2 Humble에서 package.xml은 패키지의 기본 정보를 담는 핵심 파일입니다.

 

C++ 패키지 my_cpp_package는 다음이 핵심입니다.

 
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend>

<export>
  <build_type>ament_cmake</build_type>
</export>
 

 

Python 패키지 my_first_package는 다음이 핵심입니다.

 
<exec_depend>rclpy</exec_depend>

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

 

인터페이스 패키지 my_first_package_msgs를 C++ 또는 Python에서 사용한다면 각 패키지의 package.xml에 의존성을 추가해야 합니다.

 

C++ 패키지:

 
<depend>my_first_package_msgs</depend>
 

 

Python 패키지:

 
<exec_depend>my_first_package_msgs</exec_depend>
 

 

728x90
728x90