launchによる複数のノードの起動
launchによる複数のノードを同時に起動する方法について学びます.
目的
ros2 run
によりノードを起動できますが,幾つものノードを立ち上げる際には手間となります.
このような手間を解決するものとして予め定義したノード群を起動するlaunchと呼ばれる仕組みが用意されています.
今回はlaunchの使い方について学びます.
launch
ros2 run
にてノードを起動する方法を学びました.
実機を使う際には,たくさんのノードを起動しなければならず,かなり手間がかかるので非効率的です.
ROS2では効率化するための方法としてlaunch
が用意されています.
launch
を使うことで,パラメータを設定した複数のノードを一括して起動することができます.
便利なコマンドですので扱えるように学びましょう.
今回は,turtlesimパッケージに含まれるシミュレーターturtlesim_node
を2つ,そしてキーボードで操作できるturtle_teleop_key
をlaunchにより同時に起動します.
xtermのインストール
launchファイルの実行にxtermが必須ではありませんが,今回の演習で使用しますのでインストールしましょう.
1
|
$ sudo apt install xterm
|
launchファイルの作成
既に作成済みのワークスペースpractice_ws
の中にlaunch_practice
という名前のパッケージを作成します.
1
2
|
$ cd practice_ws/src
$ ros2 pkg create --build-type ament_python launch_practice
|
パッケージディレクトリの中にlaunch
ディレクトリを作成します.
1
2
3
|
$ cd launch_practice
$ mkdir launch
$ cd launch
|
launchディレクトリに移動したら,launch
ファイルを作成します.
launchファイルは,
今回はturtlesim_and_teleop_launch.py
という名前のlaunch
ファイルを作成します.
launch
ファイルをpython言語により作成しますが,他にもXMLやYAML等で記述することが可能です.
ファイル名の最後に_launch
が必要となるので注意してください.
1
|
$ vim turtlesim_and_teleop_launch.py
|
テキストエディタでturtlesim_and_teleop_launch.py
を開いたら,下記の内容を入力してください.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
package = 'turtlesim',
executable = 'turtlesim_node',
),
Node(
namespace="sim1",
package = 'turtlesim',
executable = 'turtlesim_node',
),
Node(
package = 'turtlesim',
executable = 'turtle_teleop_key',
prefix = 'xterm -e',
),
])
|
作成したプログラムを詳しくみていきます.
1
2
|
from launch import LaunchDescription
from launch_ros.actions import Node
|
launchファイルには,launch
とlaunch_ros
をインポートする必要があります.
4
5
|
def generate_launch_description():
return LaunchDescription([
|
LaunchDescription
オブジェクトをリターンするgenerate_launch_description
関数が必要です.
return文の中に起動するノードについて記述します.
6
7
8
9
|
Node(
package = 'turtlesim',
executable = 'turtlesim_node',
),
|
Node()にノードの設定を記述します.
package
にはパッケージ名,executable
にはノード名を記述します.
10
11
12
13
14
|
Node(
namespace="sim1",
package = 'turtlesim',
executable = 'turtlesim_node',
),
|
通常,同一の名前を持つノードを同時に起動すると警告が表示されます.
しかし,同じロボットやセンサを2個以上使いたいケースもあります.
そのような場合には,名前空間(namespace)を使用します.
上記の場合には,sim1
という名前空間の中に存在するturtlesim
ノードという意味となります.
異なる名前空間に属する同じノードの名前であれば,別々のノードとして認識できるため,警告は表示されません.
15
16
17
18
19
|
Node(
package = 'turtlesim',
executable = 'turtle_teleop_key',
prefix = 'xterm -e',
),
|
turtlesim
パッケージのturtle_teleop_key
を起動します.
prefix
としてxterm -e
を与えていますが,これはxtermという端末を起動するという意味です.
起動するノードからキーボード入力したい時に利用します.
Node()の中にpackage
とexecutable
は記述が必須となりますが,namespace
とprefix
はオプションとなります.
他にもパラメータの設定やリマップ等を行うことができます.
詳細を知りたい方は公式のドキュメントを参考にしてください.
次にsetup.pyファイルを編集します.
1
2
|
$ cd ../
$ vim setup.py
|
pythonでは,setup.pyファイルに依存するパッケージやエントリーポイントを記述します.
今回はハイライトの文を追加します.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
from setuptools import find_packages, setup
import os
from glob import glob
package_name = 'launch_practice'
setup(
name=package_name,
version='0.0.0',
packages=find_packages(exclude=['test']),
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
(os.path.join('share', package_name), glob('launch/*launch.[pxy][yma]*')),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='yuu',
maintainer_email='yuu@todo.todo',
description='TODO: Package description',
license='TODO: License declaration',
tests_require=['pytest'],
entry_points={
'console_scripts': [
],
},
)
|
2行目はOSモジュール,3行目はパスの取得に使います.
2つとも良く利用されるモジュールです.
15行目は,launchファイルが存在するパスを追加するために記述しています.
ここまでの作業が完了したらビルドしましょう.
1
2
|
$ cd ../../
$ colcon build
|
ビルド後には,以前と同様にsetup.bashをsourceにより実行します.
1
|
$ source install/setup.bash
|
最後にlaunchファイルを実行します.
まずはlaunchの使い方を学ぶためにヘルプを確認してみましょう.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
$ ros2 launch -h
usage: ros2 launch [-h] [-n] [-d] [-p | -s] [-a]
[--launch-prefix LAUNCH_PREFIX]
[--launch-prefix-filter LAUNCH_PREFIX_FILTER]
package_name [launch_file_name] [launch_arguments ...]
Run a launch file
positional arguments:
package_name Name of the ROS package which contains the launch
file
launch_file_name Name of the launch file
launch_arguments Arguments to the launch file; '<name>:=<value>' (for
duplicates, last one wins)
options:
-h, --help show this help message and exit
-n, --noninteractive Run the launch system non-interactively, with no
terminal associated
-d, --debug Put the launch system in debug mode, provides more
verbose output.
-p, --print, --print-description
Print the launch description to the console without
launching it.
-s, --show-args, --show-arguments
Show arguments that may be given to the launch file.
-a, --show-all-subprocesses-output
Show all launched subprocesses' output by overriding
their output configuration using the
OVERRIDE_LAUNCH_PROCESS_OUTPUT envvar.
--launch-prefix LAUNCH_PREFIX
Prefix command, which should go before all
executables. Command must be wrapped in quotes if it
contains spaces (e.g. --launch-prefix 'xterm -e gdb
-ex run --args').
--launch-prefix-filter LAUNCH_PREFIX_FILTER
Regex pattern for filtering which executables the
--launch-prefix is applied to by matching the
executable name.
|
今回はpackage_name
にはlaunch_practice
,launch_file_name
にはturtlesim_and_teleop_launch.py
となります.
今回は引数を必要としないためlaunch_arguments
は入力しません.
それでは実行してみましょう.
1
|
$ ros2 launch launch_practice turtlesim_and_teleop_launch.py
|
実行するとロボットシミュレータturtlesimの画面が2つ,ターミナルxtermが起動します.
試しにnode list
で起動しているノードを確認します.
1
2
3
4
|
ros2 node list
/sim1/turtlesim
/teleop_turtle
/turtlesim
|
以前と同様に/turtlesim
と/teleop_turtle
は確認できますが,新たに/sim1/turtlesim
が増えました.
これは名前空間を指定したturtlesimです.
名前空間(今回はsim1)の後に/ノード名
で実行されます.
最後にターミナルxtermを用いてロボットを操作してみましょう.
・turtlesim
しかロボットが動きません.
teleop_turtle
からは/turtle1/cmd_vel
しか送らないためです.
/sim1/turtlesim
を操作するには,/sim1/turtle1/cmd_vel
を送信する必要があります.