1. roslaunch 기본 개념
ROS 2에서 여러 노드를 실행할 때 터미널을 여러 개 열고 하나씩 실행하면 불편합니다.
예를 들어 다음과 같은 명령을 각각 실행해야 한다고 가정해 보겠습니다.
ros2 run turtlesim turtlesim_node
ros2 run my_first_package my_publisher
이런 경우 launch 파일을 만들면 한 번에 실행할 수 있습니다.
ros2 launch my_first_package turtlesim_and_teleop.launch.py
ROS 2의 launch 파일은 Python으로 작성하는 방식이 일반적입니다.
기본 구조는 다음과 같습니다.
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
namespace='turtlesim',
package='turtlesim',
executable='turtlesim_node',
output='screen'
),
Node(
namespace='pub_cmd_vel',
package='my_first_package',
executable='my_publisher',
output='screen'
)
])
이 파일은 두 개의 노드를 동시에 실행합니다.
1. turtlesim 패키지의 turtlesim_node
2. my_first_package 패키지의 my_publisher
from launch import LaunchDescription
from launch_ros.actions import Node
LaunchDescription은 launch 파일에서 실행할 작업 목록을 담는 객체입니다.
즉, “어떤 노드들을 실행할 것인가?”를 정의하는 컨테이너 역할을 합니다.
Node는 ROS 2 노드를 launch 파일 안에서 실행하기 위한 액션입니다.
터미널에서 직접 실행하는 아래 명령과 비슷한 역할을 합니다.
def generate_launch_description():
ROS 2 launch 파일에서 반드시 사용되는 함수입니다.
ROS 2는 launch 파일을 실행할 때 이 함수를 찾아서 호출합니다.
그리고 이 함수가 반환하는 LaunchDescription 안의 내용을 기준으로 노드들을 실행합니다.
즉, 이 함수는 launch 파일의 시작점이라고 보면 됩니다.
return LaunchDescription([
LaunchDescription 객체를 반환합니다.
대괄호 [] 안에는 실행할 노드나 액션들이 들어갑니다.
현재 코드에서는 두 개의 Node가 등록되어 있습니다.
1) 첫 번째 Node 설명
Node(
namespace='turtlesim',
package='turtlesim',
executable='turtlesim_node',
output='screen'
),
이 부분은 turtlesim 패키지의 turtlesim_node를 실행합니다.
터미널 명령으로 표현하면 대략 아래와 같습니다.
ros2 run turtlesim turtlesim_node
하지만 여기서는 namespace='turtlesim'이 추가되어 있기 때문에 실제 노드와 토픽 이름 앞에 /turtlesim 네임스페이스가 붙습니다.
예를 들어 일반적으로 turtlesim 노드를 실행하면 토픽 이름이 다음처럼 나옵니다.
/turtle1/cmd_vel
/turtle1/pose
하지만 이 launch 파일에서는 네임스페이스가 적용되어 다음처럼 됩니다.
/turtlesim/turtle1/cmd_vel
/turtlesim/turtle1/pose
즉, namespace='turtlesim'은 이 노드가 사용하는 이름 공간을 /turtlesim 아래로 묶어주는 역할을 합니다.
2) 두 번째 Node 설명
Node(
namespace='pub_cmd_vel',
package='my_first_package',
executable='my_publisher',
output='screen'
)
이 부분은 사용자가 만든 패키지인 my_first_package 안의 my_publisher 실행 파일을 실행합니다.
터미널 명령으로 표현하면 대략 아래와 같습니다.
ros2 run my_first_package my_publisher
여기에도 네임스페이스가 지정되어 있습니다.
namespace='pub_cmd_vel'
따라서 이 노드는 /pub_cmd_vel 네임스페이스 안에서 실행됩니다.
예를 들어 my_publisher 노드가 cmd_vel이라는 토픽을 발행한다면, 실제 토픽 이름은 다음처럼 될 수 있습니다.
/pub_cmd_vel/cmd_vel
단, 이것은 my_publisher 코드 안에서 토픽 이름을 어떻게 작성했는지에 따라 달라집니다.
예를 들어 코드 안에서 상대 토픽 이름을 사용했다면:
self.create_publisher(Twist, 'cmd_vel', 10)
launch 파일의 네임스페이스가 적용되어 실제 토픽은 다음처럼 됩니다.
/pub_cmd_vel/cmd_vel
반대로 절대 토픽 이름을 사용했다면:
self.create_publisher(Twist, '/turtle1/cmd_vel', 10)
이 경우에는 네임스페이스의 영향을 받지 않고 그대로 /turtle1/cmd_vel이 됩니다.
3) package의 의미
package='turtlesim'
또는
package='my_first_package'
package는 실행할 노드가 들어 있는 ROS 2 패키지 이름입니다.
예를 들어:
package='turtlesim'
은 turtlesim 패키지 안에서 실행 파일을 찾겠다는 뜻입니다.
package='my_first_package'
은 사용자가 만든 my_first_package 패키지 안에서 실행 파일을 찾겠다는 뜻입니다.
4) executable의 의미
executable='turtlesim_node'
또는
executable='my_publisher'
executable은 실제 실행할 프로그램(노드) 이름입니다.
즉, 아래 명령에서 마지막 부분에 해당합니다.
ros2 run turtlesim turtlesim_node
여기서:
turtlesim
은 패키지 이름이고,
turtlesim_node
는 실행 파일 이름입니다.
5) namespace의 의미
namespace='turtlesim'
namespace='pub_cmd_vel'
namespace는 노드 이름과 토픽 이름 앞에 붙는 이름 공간입니다.
네임스페이스를 사용하는 이유는 여러 노드나 여러 로봇을 동시에 실행할 때 이름 충돌을 막기 위해서입니다.
예를 들어 로봇 두 대를 실행한다고 하면:
/robot1/cmd_vel
/robot2/cmd_vel
처럼 분리할 수 있습니다.
이 코드에서는 turtlesim 노드는 /turtlesim 아래에, publisher 노드는 /pub_cmd_vel 아래에 들어갑니다.
만약 namespace를 사용하지 않는다면 namespace=''로 정의가 가능한데 namespace를 생략하는 것이 정석입니다.
6) output='screen'의 의미
output='screen'
노드에서 출력하는 로그를 터미널 화면에 보여주겠다는 뜻입니다.
예를 들어 노드 코드 안에 다음과 같은 로그가 있다면:
self.get_logger().info('Publishing cmd_vel')
launch 실행 터미널에 출력됩니다.
만약 output='screen'이 없다면 로그가 화면에 바로 보이지 않거나 launch 시스템 내부 로그로만 저장될 수 있습니다.
개발 중에는 보통 output='screen'을 넣는 것이 좋습니다.
문제 찾기가 훨씬 쉽습니다.
2. launch 파일 폴더 만들기
패키지 안에 launch 파일을 넣기 위해 다음 구조를 사용합니다.
my_first_package/
├── launch/
│ └── turtlesim_and_teleop.launch.py
├── my_first_package/
│ ├── my_publisher.py
│ └── ...
├── package.xml
└── setup.py
launch 폴더를 만든 뒤 그 안에 .launch.py 파일을 작성합니다.
터미널을 실행하여 아래을 명령을 실행합니다.
cd ~/ros2_study/src/my_first_package/
mkdir launch
touch launch/turtlesim_and_teleop.launch.py

파일명 예시는 다음과 같습니다.
turtlesim_and_teleop.launch.py
dist_turtle_action.launch.py
code를 실행하고 turtlesim_and_teleop.launch.py 파일을 작성합니다.

3. setup.py에 launch 파일 등록하기
Python 기반 ROS 2 패키지에서는 launch 파일을 설치 대상에 포함해야 합니다.
setup.py에 다음 구문이 필요합니다.
import os
import glob
from setuptools import setup
package_name = 'my_first_package'
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']
),
(
'share/' + package_name + '/launch',
glob.glob(os.path.join('launch', '*.launch.py'))
),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='pw',
maintainer_email='pw@todo.todo',
description='TODO: Package description',
license='TODO: License declaration',
tests_require=['pytest'],
entry_points={
'console_scripts': [
'my_first_node = my_first_package.my_first_node:main',
'my_subscriber = my_first_package.my_subscriber:main',
'my_publisher = my_first_package.my_publisher:main',
'dist_turtle_action_server = my_first_package.dist_turtle_action_server:main',
],
},
)
아래의 부분이 핵심입니다.
먼저 glob를 import 합니다.
import os
import glob

(
'share/' + package_name + '/launch',
glob.glob(os.path.join('launch', '*.launch.py'))
),
위의 코드는 ROS 2 Python 패키지의 setup.py에서 launch 파일들을 설치 경로로 복사하도록 지정하는 부분입니다.
현재 패키지 폴더 안의 launch 디렉토리에 있는 모든 *.launch.py 파일을 찾아서, ROS 2 설치 공간의 share/패키지이름/launch 폴더에 복사하라는 의미입니다.
이 코드는 패키지를 빌드할 때,
launch/*.launch.py
형태의 파일들을 찾아서 ROS 2 설치 공간 안의 다음 경로( package_name = 'mobile_robot_bringup' )로 복사합니다.
install/mobile_robot_bringup/share/mobile_robot_bringup/launch/
즉, 패키지 안에 있는 launch 파일을 ROS 2가 실행할 수 있는 위치로 설치하는 역할입니다.
os.path.join('launch', '*.launch.py')
이 부분은 파일 검색 패턴을 만듭니다.
결과적으로 다음과 같은 문자열이 됩니다.
launch/*.launch.py
즉, launch 폴더 안에 있는 모든 .launch.py 파일을 의미합니다.
예를 들어 패키지 구조가 다음과 같다면:
mobile_robot_bringup/
├── setup.py
├── package.xml
├── mobile_robot_bringup/
│ └── __init__.py
└── launch/
├── robot_bringup.launch.py
├── navigation.launch.py
└── slam.launch.py
다음 파일들이 검색됩니다.
launch/robot_bringup.launch.py
launch/navigation.launch.py
launch/slam.launch.py
glob.glob()은 조건에 맞는 파일 목록을 리스트로 반환합니다.
예를 들어:
glob.glob(os.path.join('launch', '*.launch.py'))
의 결과는 다음처럼 됩니다.
[
'launch/robot_bringup.launch.py',
'launch/navigation.launch.py',
'launch/slam.launch.py'
]

이 설정이 없으면 빌드 후 ros2 launch에서 launch 파일을 찾지 못할 수 있습니다.
4. 빌드 및 실행
파일을 수정한 뒤에는 반드시 다시 빌드합니다.
cd ~/ros2_study
colcon build --packages-select my_first_package

만약에 ~/ros2_study/install/my_first_package/share/my_first_package/launch 위치에 turtlesim_and_teleop.launch.py 파일이 존재하지 않을 경우, 아래의 명령을 실행하여 다시 빌드합니다.
cd ~/ros2_study
colcon build --packages-select my_first_package --symlink-install
환경을 다시 적용합니다.
source install/setup.bash
새로운 터미널을 실행하여 launch 파일을 실행합니다.
ros2 launch my_first_package turtlesim_and_teleop.launch.py
정상적으로 실행되면 하나의 터미널에서 여러 노드의 로그가 함께 출력됩니다.

5. launch 파일에서 파라미터 지정하기
launch 파일에서는 노드 실행뿐 아니라 파라미터도 지정할 수 있습니다.
예를 들어 turtlesim 배경색을 바꾸고 싶다면 다음처럼 작성합니다.
turtlesim_node = Node(
package='turtlesim',
executable='turtlesim_node',
output='screen',
parameters=[
{'background_r': 255},
{'background_g': 192},
{'background_b': 203},
]
)
이 설정은 turtlesim 배경색을 RGB 값으로 지정하는 예시입니다.
background_r = 255
background_g = 192
background_b = 203
즉, launch 파일에서 노드를 실행하면서 동시에 초기 설정값까지 넣을 수 있습니다.
6. action Server까지 함께 실행하는 launch 파일
turtlesim_node와 사용자 정의 액션 서버를 함께 실행하고 싶다면 다음처럼 구성할 수 있습니다.
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
turtlesim_node = Node(
package='turtlesim',
executable='turtlesim_node',
output='screen',
parameters=[
{'background_r': 255},
{'background_g': 192},
{'background_b': 203},
]
)
dist_turtle_action_node = Node(
package='my_first_package',
executable='dist_turtle_action_server',
output='screen'
)
return LaunchDescription([
turtlesim_node,
dist_turtle_action_node
])
launch 파일을 만들었던 폴더로 이동하여 dist_turtle_action.launch.py 파일을 생성합니다.
cd ~/ros2_study/src/my_first_package/launch/
touch dist_turtle_action.launch.py

dist_turtle_action.launch.py 팡리을 열고 위의 소스 코드를 입력하고 저장합니다.

my_first_packge를 다시 빌드합니다.
cd ~/ros2_study
colcon build --packages-select my_first_package --symlink-install

환경을 다시 적용합니다.
source install/setup.bash
새로운 터미널을 실행하여 launch 파일을 실행합니다.
이렇게 하면 turtle 시뮬레이터와 액션 서버가 동시에 실행됩니다.
ros2 launch my_first_package dist_turtle_action.launch.py


/ros2_study/install/my_first_package/share/my_first_package/launch 위치에 2개의 launch 파일이 존재합니다.

7. launch가 필요한 이유
ROS 2 프로젝트가 커지면 노드가 하나만 있는 경우는 거의 없습니다.
예를 들어 이동로봇 시스템이라면 다음 노드들이 동시에 실행될 수 있습니다.
모터 제어 노드
거리 센서 입력 노드
IMU 필터 노드
경로 계획 노드
미션 제어 노드
카메라 인식 노드
그리퍼 제어 노드
상태 LED 노드
로그 기록 노드
이 노드들을 매번 터미널에서 하나씩 실행하는 것은 비효율적입니다.
launch 파일은 이런 노드 실행을 자동화하는 역할을 합니다.
그리고 여러 개의 launch 파일을 자동으로 실행해 주는 tmux도 유용하게 사용됩니다.
'강좌 > ROS2' 카테고리의 다른 글
| 서비스 정의 만들기 (0) | 2026.05.21 |
|---|---|
| launch 파일에서 실행 인자 사용하기 #1 (0) | 2026.05.15 |
| 소스에서 파라미터 사용하기 (0) | 2026.05.10 |
| ROS 2 MultiThreadedExecutor와 Action Server로 Turtlesim 거리 이동 구현하기 (0) | 2026.05.10 |
| ROS2 MultiThread 기초 (0) | 2026.05.10 |