# ROS2 패키지의 표준 구조

#### 패키지의 기본 개념

ROS2 패키지는 특정 기능을 제공하는 독립적인 단위로, 노드(Node), 메시지(Message), 서비스(Service), 액션(Action) 등의 ROS2 요소를 포함할 수 있다. ROS2 패키지는 소스 코드, 실행 파일, 설정 파일, 메시지 정의, 서비스 정의 등의 파일로 구성되며, 특정 기능을 실행하거나 구현하기 위해 함께 배포된다.

ROS2의 패키지 구조는 CMake를 사용한 빌드 시스템과 `colcon`이라는 빌드 도구를 기반으로 구성되며, 모든 ROS2 패키지는 특정 디렉토리 구조를 따라야 한다. 이러한 구조는 패키지의 가독성, 유지 관리, 배포를 용이하게 하며, 빌드 및 종속성 관리를 표준화한다.

#### 패키지의 디렉토리 구조

ROS2 패키지는 다음과 같은 기본 디렉토리 및 파일 구조를 따른다.

```
my_package/
├── CMakeLists.txt
├── package.xml
├── include/
├── src/
├── launch/
├── msg/
├── srv/
├── action/
├── config/
└── scripts/
```

**CMakeLists.txt**

`CMakeLists.txt` 파일은 패키지의 빌드를 정의하는 핵심 파일이다. CMake는 ROS2 패키지의 빌드 시스템으로 사용되며, 이 파일에는 프로젝트 이름, 종속성, 빌드 타겟, 컴파일러 옵션 등이 포함된다. ROS2 패키지의 `CMakeLists.txt`는 여러 단계로 구성되며, 다음과 같은 주요 항목들을 포함한다.

1. 프로젝트 이름 설정:

   ```cmake
   project(my_package)
   ```
2. 필요한 ROS2 종속성 선언:

   ```cmake
   find_package(ament_cmake REQUIRED)
   find_package(rclcpp REQUIRED)
   ```
3. 실행 파일 생성 및 빌드 규칙 설정:

   ```cmake
   add_executable(my_node src/my_node.cpp)
   target_link_libraries(my_node rclcpp)
   ```

**package.xml**

`package.xml` 파일은 ROS2 패키지의 메타데이터를 정의하는 XML 파일이다. 이 파일은 패키지의 이름, 버전, 라이선스, 종속성 등을 기술한다. ROS2에서 패키지 관리는 이 파일을 통해 이루어지며, 이를 통해 `colcon`과 같은 빌드 도구가 패키지의 빌드 순서 및 종속성을 결정한다.

```xml
<package format="3">
  <name>my_package</name>
  <version>0.1.0</version>
  <description>A simple ROS2 package</description>
  <maintainer email="maintainer@example.com">Maintainer Name</maintainer>
  <license>Apache-2.0</license>
  <buildtool_depend>ament_cmake</buildtool_depend>
  <exec_depend>rclcpp</exec_depend>
</package>
```

이 외에도 패키지의 실행에 필요한 종속성(`exec_depend`), 개발에 필요한 종속성(`buildtool_depend`), 테스트에 필요한 종속성 등을 정의할 수 있다.

#### include/ 디렉토리

`include/` 디렉토리는 ROS2 패키지에서 사용할 헤더 파일을 저장하는 디렉토리이다. 일반적으로 패키지의 이름을 포함하는 하위 디렉토리를 만들어 그 안에 헤더 파일을 배치한다. 예를 들어, `my_package`라는 패키지가 있다면, 헤더 파일은 `include/my_package/` 안에 저장된다.

이 구조는 C++에서 라이브러리나 클래스의 선언을 중앙에서 관리할 수 있도록 하며, 여러 소스 파일에서 일관된 헤더 파일을 사용할 수 있게 해준다.

#### src/ 디렉토리

`src/` 디렉토리는 ROS2 패키지의 소스 코드 파일을 저장하는 디렉토리이다. 여기에는 C++ 또는 Python으로 작성된 노드 파일들이 위치하며, CMake를 사용해 빌드될 파일들이 포함된다.

#### launch/ 디렉토리

`launch/` 디렉토리는 ROS2 시스템을 실행하는 데 필요한 런치 파일을 저장하는 곳이다. 런치 파일은 여러 노드를 한 번에 실행하거나, 노드 간의 통신을 설정하고 다양한 파라미터를 지정하는 데 사용된다. ROS2에서는 XML 또는 Python 형식의 런치 파일을 사용할 수 있으며, 이 파일을 통해 복잡한 시스템을 한 번에 실행할 수 있다.

예시로 Python 기반의 런치 파일은 다음과 같이 작성된다:

```python
from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription([
        Node(
            package='my_package',
            executable='my_node',
            name='my_node',
            output='screen',
            parameters=[{'use_sim_time': False}]
        )
    ])
```

#### msg/ 디렉토리

`msg/` 디렉토리는 사용자 정의 메시지 타입을 정의하는 디렉토리이다. ROS2에서는 노드 간에 교환되는 데이터를 메시지(Message)라는 형태로 주고받으며, 기본 제공되는 메시지 타입 외에 사용자가 필요에 따라 새로운 메시지를 정의할 수 있다.

예를 들어, 위치 정보를 포함하는 메시지를 정의하려면 `Position.msg` 파일을 다음과 같이 작성할 수 있다:

```plaintext
float64 x
float64 y
float64 z
```

이렇게 정의된 메시지는 ROS2 빌드 시스템에서 자동으로 메시지 타입으로 변환되어, 노드 간 통신에서 사용할 수 있게 된다.

#### srv/ 디렉토리

`srv/` 디렉토리는 사용자 정의 서비스(Service) 타입을 정의하는 디렉토리이다. ROS2 서비스는 요청(Request)과 응답(Response) 패턴을 통해 통신하며, 서비스 정의 파일은 이 두 가지 정보를 모두 포함해야 한다.

예시로 `AddTwoInts.srv`라는 파일을 다음과 같이 작성할 수 있다:

```plaintext
int64 a
int64 b
---
int64 sum
```

이 서비스는 두 개의 정수를 입력으로 받아 그 합을 응답으로 반환하는 서비스이다.

#### action/ 디렉토리

`action/` 디렉토리는 사용자 정의 액션(Action) 타입을 정의하는 디렉토리이다. 액션은 서비스와 비슷하지만, 장시간에 걸친 작업을 처리할 수 있으며, 중간에 피드백을 제공할 수 있는 특징을 갖는다.

액션 파일은 목표(Goal), 피드백(Feedback), 결과(Result) 세 가지 섹션으로 나누어진다. 예를 들어, 로봇이 지정된 거리만큼 이동하는 액션을 정의할 수 있다.

```plaintext
# 목표
float64 distance
---
# 피드백
float64 current_distance
---
# 결과
bool success
```

#### config/ 디렉토리

`config/` 디렉토리는 ROS2 노드에서 사용할 설정 파일을 저장하는 곳이다. 주로 YAML 형식으로 작성된 파일들이 이 디렉토리에 포함되며, 노드 실행 시 파라미터 값을 지정할 수 있다. 이 디렉토리를 사용하면 동일한 코드를 다양한 환경에서 재사용할 수 있으며, 파라미터 변경을 통해 유연한 시스템 구성이 가능한다.

예시 YAML 파일:

```yaml
my_node:
  ros__parameters:
    param_name: param_value
```

#### scripts/ 디렉토리

`scripts/` 디렉토리는 ROS2 패키지에서 사용할 스크립트 파일들을 저장하는 곳이다. 주로 Python으로 작성된 스크립트 파일이 여기에 위치하며, CMake 빌드 과정에서 별도로 컴파일되지 않고 바로 실행할 수 있다.

Python 스크립트 예시:

```python
#!/usr/bin/env python3

import rclpy
from rclpy.node import Node

class MyNode(Node):
    def __init__(self):
        super().__init__('my_node')
        self.get_logger().info('Hello ROS2')

def main(args=None):
    rclpy.init(args=args)
    node = MyNode()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()
```

이와 같이 작성된 스크립트는 ROS2 환경에서 실행할 수 있으며, Python 기반 노드를 쉽게 실행할 수 있게 해준다.
