ROS 2에서 Python 스크립트로 만든 노드가 많아지게 되면, 각 노드를 실행할 때마다 터미널을 하나씩 열어 ros2 run 명령어를 사용해야 한다. 예를 들어 노드가 5개라면 터미널을 5개 띄우고 각각 ros2 run으로 실행해야 하기 때문에 매우 비효율적이고 관리가 복잡해진다.
이러한 문제를 해결하기 위해 등장한 것이 바로 launch 파일이다. launch 파일을 사용하면 여러 노드를 한 번에 실행할 수 있어 훨씬 편리하다.
단, 주의할 점은 있다.
만약 특정 노드에서 출력하는 로그 메시지를 터미널에서 직접 확인해야 할 필요가 있다면, 그 노드는 launch 파일로 묶지 않고 별도로 ros2 run 명령어를 사용해 실행하는 것이 더 바람직하다.
Launch File : ROS2에서 여러 개의 노드들을 여러 개의 노드들을 한 번에 실행할 수 있도록 도와주는 파일
- launch file의 역할
- 여러 노드를 동시에 실행
- 각 노드의 실행 옵션(arguments, parameters 등) 설정
- 노드 간 관계 설정 ex) 네임스페이스 지정
- 조건부 실행, 반복 실행 등
- 파일 형식 : <런치 파일명>.launch.py
launch file을 만드는데 필요한 라이브러리들
import os
- 용도 : 파일 경로를 다를때 사용
- 파일 경로 연결해줄때 os.path.join() 사용
- 예를들어 패키지 내부의 특정 파일(params.yaml, rviz 파일 등) 경로를 얻을 때 필요
from ament_index_python.packages import get_packages_share_directory
- 용도 : 설치된 패키지의 share 디렉토리 경로를 가져옴(install 디렉토리 아래 위치)
- 왜 필요할까? 패키지 내부의 설정 파일, 파일 모델 등을 찾기 위해

- ydlidar_ros2_driver 패키지에 있는 런치 파일의 경로를 share 디렉토리로 부터 불러온다
from launch import LaunchDescription
- 용도 : 런치 파일의 뼈대로 LaunchDescription은 실행할 모든 액션(노드 실행, 파라미터 설정 등)을 담는 객체
- 필수 요소 : 항상 generate_launch_description() 함수에서 반환해야 한다.


from launch.actions import DeclareLaunchArgument
- 용도 : 런치 파일을 실행할 때 인자(argument)를 외부에서 입력 받을 수 있게 선언하는 기능
- param_file로부터 인자 값을 받아올 수 있다
- 예를 들어 노드 이름이나 파라미터 파일 경로를 런치 파일 실행 시 결정하고 싶을 때 필요

- 'use_sim_time' 이라는 이름의 인자 값이 입력되지 않았을 경우 default 값을 true로 설정한 것
- description : 이 인자에 대한 설명
from launch.substitutions import LaunchConfiguration
- 용도 : DeclareLaunchArgument로 받은 인자 값을 실제로 코드에서 읽을 때 사용
- 예를 들어 런치 인자로 받은 파라미터 파일 경로를 노드 실행 옵션에 넣을때
ex) LaunchConfiguration("param_file")

from launch_ros.actions import Node
- 용도 : ROS2 노드를 실행시키는 액션( 런치 파일에서 노드를 실행할 때 필수)
- 이걸로 패키지 이름, 실행 파일 이름, 파라미터 파일, 출력 설정 등을 할 수 있음

- package : 실행할 ROS2 프로그램 코드가 포함한 패키지 이름
- executable : 실행하려는 Python 실행 파일의 이름
-> 해당 파일 이름은 entry_points에서 입력해준 이름과 동일하게 작성한다. - output : 프로그램의 출력을 출력할 채널
from launch.launch_description_sources import PythonLaunchDescriptionSource
- 용도 : 포함할 launch 파일이 Python 파일일때 사용
-> 해당 파일을 include 해야함

- PythonLaunchDescriptionSource : 현재 패키지가 아닌 다른 패키지에서 launch 파일 경로를 불러오고 그 파일이 Python 형식의 launch 파일일때 실행 시킬 수 있도록하는것
from launch.actions import IncludeLaunchDescription
- 용도 : 다른 launch 파일을 포함할 때 사용
-> 복잡한 시스템에서 모듈별로 분리할 때 - PythonLaunchDescriptionSource가 안에 인자로 들어가는 경우가 대부분이다.

- IncludeLaunchDescription : PythonLaunchDescriptionSource 를 통해 다른 런치 파일을 불러오고 그 launch 파일 또한 현재의 launch 파일이 실행될때 실행될 수 있도록 하는 것
from launch.actions import ExecuteProcess
- 용도 : 터미널 창에서 치고싶은 명령어가 있을 때 사용하는 라이브러리

- cmd 를 통해 실행 시킬 각 명령어와 인자를 띄어쓰기 단위로 구분해서 '' 안에 넣고, 그것을 리스트 형태로 생성해줌
이제 Launch 파일을 만들어보자 launch 파일을 만드는 방법에는 2가지가 있다.
첫번째 방법 ) 아래의 그림처럼 LaunchConfiguration 클래스에 리스트 형태로 한번에 넣어주는 경우


- launch 파일이 생성될 때 한번에 등록
- 구조가 한눈에 보여서 깔끔하다.
두번째 경우) add_action() 함수로 하나하나 추가하는 경우

- launch 파일이 복잡해질때 쓰기 좋다.
두가지 경우 중 아무거나 개발자가 원하는 방법을 택해서 사용하면 된다.
이제 파일을 생성했다고 끝나는 것이 아니라 생성한 launch 파일을 인식할 수 있도록 setup.py에서 코드를 추가해줘야한다.
아래의 사진과 같이
# 아래 두가지 코드 중 하나를 입력해줘야한다.
# 첫번째 방법 : os 라이브러리를 이용해서 절대 경로 불러오는 방법
(os.path.join('share', package_name), glob('launch/*.launch.py'))
# 두번째 방법 : 상대경로를 직접 입력해주는 방법
('share/' + package_name + '/launch', glob.glob(os.path.join('launch', '*.launch.py'))),

action 노드를 만들었던 것으로 간단한 launch 파일 생성해보자


-> 따로따로 실행해줘야한다. 네임스페이스가 같기 때문에 바로 아래 그림과 같이기존 실행한 것과 충돌이 일어나서 제대로 실행이 안되기 때문이다.
-> namespace를 달리 해줘야한다.

<Namespace를 다르게 할당해준 경우>
-> 잘 작동하는 것을 볼 수 있다.

'ROS2 이론 정리' 카테고리의 다른 글
| ROS2 CLI (0) | 2025.05.05 |
|---|---|
| Hangman을 통한 통신 노드들 구현(Action, Topic, Service) (0) | 2025.04.30 |
| ROS2 스레드 (0) | 2025.04.26 |
| Action Client 구현(2) (0) | 2025.04.24 |
| Action Server 구현(1) (0) | 2025.04.24 |