ROS2 Launchファイル リファレンス
(ROS1 → ROS2移行者・中級者向け)
概要
ROS2のlaunchシステムは、ROS1のroslaunchに比べて
宣言的・階層的・モジュール化された構成管理を目的として再設計されています。
このリファレンスでは、特にノード起動構文とIncludeLaunchDescriptionによる構成再利用を中心に、
ROS2開発の現場で必要となる仕組み・注意点・設計パターンを体系的に解説します。
1. 基本概念
1.1 LaunchConfiguration(設定値管理)
LaunchConfigurationは、launchファイル全体で共有される変数を管理します。
ROS1のargに相当しますが、ROS2ではグローバルスコープの設定変数として扱われます。
例:
config_type = LaunchConfiguration('config_type')
DeclareLaunchArgument(
'config_type',
default_value='default'
)
特徴:
- 定義は
DeclareLaunchArgumentによって宣言される - 同名変数が複数存在すると上書きされる
- スコープを限定するには
GroupAction(scoped=True)を使用する
1.2 DeclareLaunchArgument(外部引数)
DeclareLaunchArgumentは外部から指定できるパラメータを宣言します。
ROS1の<arg>タグに相当します。
例:
DeclareLaunchArgument(
'config_file',
default_value=[LaunchConfiguration('config_type'), '_config.yaml']
)
注意点:
- default値に数値文字列を指定すると型変換エラーが発生する
- 文字列結合はリスト形式(
[...])で記述する
1.3 スコープ制御
| クラス | 機能概要 |
|---|---|
PushLaunchConfigurations |
新しいスコープを作成(既存設定を一時保存) |
PopLaunchConfigurations |
スコープを破棄し、前の状態に戻す |
GroupAction(scoped=True) |
局所スコープを作成(ローカル変数のように扱える) |
PushROSNamespace |
ノードのnamespaceを設定する |
例:
GroupAction(
actions=[
PushROSNamespace('robot1'),
Node(package='my_pkg', executable='controller')
],
scoped=True
)
2. IncludeLaunchDescriptionによる構成管理
2.1 概要
IncludeLaunchDescriptionは、他のlaunchファイルを再利用・構成化するための仕組みです。
これにより、共通設定のテンプレート化や階層的launch構造を構築できます。
典型的な用途は次のとおりです:
- 共通設定ファイル(センサー初期化、RViz設定など)の再利用
- 複数ロボットインスタンスの動的生成
- 各モジュールのlaunch構成を独立・再利用可能にする
2.2 基本構文
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import PathJoinSubstitution, FindPackageShare, LaunchConfiguration
IncludeLaunchDescription(
PythonLaunchDescriptionSource(
PathJoinSubstitution([
FindPackageShare('my_robot_bringup'),
'launch',
'subsystem_launch.py'
])
),
launch_arguments={
'robot_ns': LaunchConfiguration('robot_ns'),
'param_file': LaunchConfiguration('param_file'),
}.items(),
)
ポイント:
-
.items()を必ず付ける(付け忘れると無効) -
launch_argumentsはLaunchConfiguration経由で子launchに引き渡される
2.3 変数スコープと継承
Includeで呼び出された子launchファイルは、
親launchのLaunchConfigurationスコープを共有します。
| 動作 | 説明 |
|---|---|
| 親→子の変数共有 | launch_argumentsで渡すと、子launchで使用可能 |
| 子→親の変更 | 上書きされる(同名変数は共有スコープ) |
| スコープを分離 |
GroupAction(scoped=True)またはPushLaunchConfigurations()を使用 |
例:スコープ分離
GroupAction(
actions=[
IncludeLaunchDescription(
PythonLaunchDescriptionSource('sub_launch.py'),
launch_arguments={'namespace': 'robot1'}.items()
)
],
scoped=True
)
2.4 再利用設計パターン
(1) テンプレート型設計
共通的なノードセット(例:SLAMやnavigation)を
パラメータ引数付きテンプレートlaunchとして定義する。
例:
# nav_template.launch.py
DeclareLaunchArgument('robot_ns')
DeclareLaunchArgument('map_yaml')
Node(
package='nav2_bringup',
executable='bringup_launch.py',
namespace=LaunchConfiguration('robot_ns'),
parameters=[LaunchConfiguration('map_yaml')],
)
再利用:
IncludeLaunchDescription(
PythonLaunchDescriptionSource('nav_template.launch.py'),
launch_arguments={
'robot_ns': 'robot1',
'map_yaml': '/maps/map1.yaml'
}.items()
)
(2) 多重Include構成
階層化したlaunch設計を行うことで、
**「トップレベル → サブシステム → ノード」**というモジュール構成を実現します。
構成例:
bringup/
├─ launch/
│ ├─ bringup.launch.py ← 全体構成
│ ├─ sensors.launch.py ← センサー群
│ ├─ navigation.launch.py ← 経路計画
│ └─ rviz.launch.py ← 可視化
bringup.launch.py
IncludeLaunchDescription(PythonLaunchDescriptionSource('sensors.launch.py'))
IncludeLaunchDescription(PythonLaunchDescriptionSource('navigation.launch.py'))
IncludeLaunchDescription(PythonLaunchDescriptionSource('rviz.launch.py'))
メリット:
- 各モジュールの独立性が高く、再利用しやすい
- チーム開発時に担当範囲を分離できる
(3) 共通引数・設定ファイル管理
複数のlaunchファイルで共通パラメータを扱う場合、
**共通定義ファイル(common_args.launch.py)**を設けると管理しやすくなります。
common_args.launch.py
def declare_common_arguments():
return [
DeclareLaunchArgument('use_sim_time', default_value='true'),
DeclareLaunchArgument('log_level', default_value='info')
]
各launchで再利用:
from common_args import declare_common_arguments
LaunchDescription([
*declare_common_arguments(),
Node(
package='my_pkg',
executable='node_main',
output='screen',
parameters=[{'use_sim_time': LaunchConfiguration('use_sim_time')}]
)
])
2.5 ベストプラクティスまとめ
| 分類 | 推奨方法 | 備考 |
|---|---|---|
| 共通設定 | 共通引数を共通関数化 | 重複防止・可読性向上 |
| 階層構成 | Includeで階層化 | 拡張に強い |
| スコープ制御 | GroupAction(scoped=True)でローカル化 | 変数衝突防止 |
| ファイル命名 | <機能>_launch.py |
モジュール明確化 |
| テンプレート化 | LaunchArgumentで汎用性を担保 | 引数明示で保守性向上 |
3. ノード起動構文
(※この章は既存①を維持・整理)
3.1 Nodeクラス(基本)
Node(
package='my_robot',
executable='controller',
name='controller_node',
namespace=LaunchConfiguration('robot_ns'),
parameters=[
PathJoinSubstitution([FindPackageShare('my_robot'), 'config', 'params.yaml'])
],
remappings=[('/cmd_vel', '/robot1/cmd_vel')],
output='screen'
)
注意:
- 同一namespace内で同名ノードは起動できない
- パラメータファイルは後方優先で上書きされる
3.2 ComposableNodeContainer(複合ノード)
ComposableNodeContainer(
name='image_container',
package='rclcpp_components',
executable='component_container_mt',
composable_node_descriptions=[
ComposableNode(
package='image_proc',
plugin='image_proc::ResizeNode',
name='resize_node'
),
ComposableNode(
package='image_proc',
plugin='image_proc::CropDecimateNode',
name='crop_node'
),
],
output='screen'
)
ポイント:
- 同一プロセス内で複数ノード実行
- 通信レイテンシを削減
- plugin名誤記は起動時例外の原因になる
4. トラブルシューティング
| 症状 | 原因 | 対応策 |
|---|---|---|
| 子launchの変数が親に影響 | スコープ共有 |
GroupAction(scoped=True)で隔離 |
| Includeの引数が反映されない |
.items()抜け |
必ずlaunch_arguments={...}.items()を指定 |
| 同名ノードが複数起動失敗 | namespace未指定 |
PushROSNamespaceで区別 |
| YAMLパラメータ未読込 | 階層不一致 | ノード名=YAML階層を一致させる |
5. まとめ
ROS2のLaunch設計では、
再利用性とスコープの明確化が最重要です。
-
IncludeLaunchDescriptionで階層化・再利用を行う -
GroupAction(scoped=True)で局所スコープを管理 -
DeclareLaunchArgumentでテンプレート化 -
ComposableNodeContainerで効率的な構成を構築
これにより、チーム開発でも安全・拡張性の高いlaunch構造を維持できます。
6. 参考資料
- ROS2公式ドキュメント
https://docs.ros.org/en/iron/Tutorials/Intermediate/Launch/ -
launchパッケージAPIリファレンス
https://docs.ros2.org/latest/api/launch/ -
launch_rosリファレンス
https://docs.ros2.org/latest/api/launch_ros/