前回、以下の記事でROS2 Jazzy をRaspberry Pi 5 にインストールして、初心者(CLI)チュートリアルを行いました。今回は、自分のプロジェクトが作れるようにクライアントライブラリについて勉強します。
教科書は、公式ROSドキュメントサイトです。
では、早速初めていきます。
パッケージのビルドに「colcon」を使用する
これは、「colcon
」を使用して ROS 2 ワークスペースを作成および構築する方法に関する簡単なチュートリアルです。これは実践的なチュートリアルであり、コアドキュメントに代わるものではありません。
「colcon
」は、ROSビルドツールの「catkin_make
」、「catkin_make_isolated
」、「catkin_tools
」、「ament_tools
」を繰り返し実行します。設計の詳細については、このドキュメントを参照してください。
ソースは、以下にあります。
「colcon」をインストールする
$ sudo apt install python3-colcon-common-extensions
ROS2 Jazzy をソースからビルドしたので既にインストールされていました。
ワークスペースを作成する
まず、ワークスペースを格納するディレクトリ「ros2_ws
」を作成します。
ワークスペースの中には、複数のプロジェクトが格納できるように、プロジェクトディレクトリを作成します。
$ mkdir -p ~/ros2_ws/examples/src
$ cd ~/ros2_ws/examples
この時点で、ワークスペースには、1つの空の「src
」ディレクトリが含まれています。
ソースを追加する
サンプルリポジトリをワークスペースの「src
」ディレクトリにクローンしてみます。
$ git clone https://github.com/ros2/examples ./src/examples -b jazzy
これで、ワークスペースにROS2のサンプルのソースコードがダウンロードされます。
$ tree -L 3
.
└─ src
└─ examples
├─ CODEOWNERS
├─ CONTRIBUTING.md
├─ LICENSE
├─ README.md
├─ launch_testing
├─ rclcpp
└─ rclpy
6 directories, 4 files
アンダーレイの入手
サンプル パッケージに必要なビルド依存関係をワークスペースに提供する既存の ROS 2 インストールの環境をソース化しておくことが重要です。これは、バイナリ インストールまたはソース インストール (つまり、別の colcon ワークスペース) によって提供されるセットアップ スクリプトをソース化することによって実現されます。
ちょっと表現が分かり難いですが、インストール時に作成したワークスペースを「source
」しておくということです。
$ source ~/ros2_jazzy/install/setup.bash
自分の場合は、インストール後に既に「~/.bashrc
」に上記のコードを書いているので、自動的にアンダーレイが有効になっています。
ワークスペースを構築する
ワークスペースのルートで、 「colcon build
」を実行します。 「ament_cmake
」などのビルドタイプは「devel
」スペースの概念をサポートしておらず、パッケージをインストールする必要があるため、colcon は、「--symlink-install
」オプションをサポートしています。これにより、「source
」スペース内のファイル (Python ファイルやその他のコンパイルされていないリソースなど) を変更することで、インストールされたファイルを変更し、反映処理を高速化できます。
ここは、難解な一文ですが、次のコマンドを入力してビルドします。
$ colcon build --symlink-install
ビルドが完了すると「build」、「install」、「log」ディレクトリが表示されます。
$ tree -L 1
.
├─ build
├─ install
├─ log
└─ src
5 directories, 0 files
テストを実行する
先ほど作成したパッケージのテストを実行するには、次のコマンドを実行します。
$ colcon test
環境のソース
colcon が正常にビルドを完了すると、出力は、「install
」ディレクトリに保存されます。インストールされた実行可能ファイルまたはライブラリを使用する前に、それらをパスとライブラリ パスに追加する必要があります。colcon は、「install
」環境の設定に役立つ bash/bat ファイルをディレクトリに生成します。これらのファイルは、パスとライブラリ パスに必要なすべての要素を追加するとともに、パッケージによってエクスポートされた bash またはシェル コマンドを提供します。
$ source install/setup.bash
デモを試す
環境がソース化されると、colcon によってビルドされた実行ファイルを実行できます。サンプルからサブスクライバーノードを実行してみます。
$ ros2 run examples_rclcpp_minimal_subscriber subscriber_member_function
別のターミナルで、パブリッシャー ノードを実行してみましょう (セットアップ スクリプトをソースすることを忘れないでください)。
$ ros2 run examples_rclcpp_minimal_publisher publisher_member_function
パブリッシャーとサブスクライバーからのメッセージが表示され、数字が増加していきます。
以降の内容は、少し難しいので、あまり理解できませんでした。
実際にやってみないと分からないですね。
独自のパッケージを作成する方法
colcon は、「REP 149
」形式で定義された「pakage.xml
」の仕様を使用します。(「REP 140
」もサポートされています。)
colcon は複数のビルド タイプをサポートしています。推奨されるビルド タイプは、「ament_cmake
」と「ament_python
」です。純粋な「cmake
」パッケージもサポートされています。
「ament_python
」のビルド例としては、「ament_index_python
」パッケージがあります。ここでは、「setup.py
」がビルドの主なエントリ ポイントです。
「demo_nodes_cpp
」などのパッケージは、「ament_cmake
」のビルドタイプを司代油脂、ビルドツールとして「CMake
」を使用します。
「ros2 pkg create
」というツールを使用してテンプレートに基づいた新しいパッケージを作成することもできます。
※ここは、概要の説明のみです。後で実際のパッケージを作ってみることになります。
「colcon_cd」の設定
「colcon_cd
」コマンドを使用すると、シェルの現在の作業ディレクトリをパッケージのディレクトリにすばやく変更できます。例えば、「colcon_cd some_ros_package
」を入力すると、「~/ros2_ws/src/some_ros_package
」ディレクトリにすばやく移動できます。
$ echo "source /usr/share/colcon_cd/function/colcon.sh" >> ~/.bashrc
$ echo "export _colcon_cd_root=$HOME/ros2_jazzy/install" >> ~/.bashrc
インストール方法やワークスペースの場所によっては、上記の手順が異なる場合があります。これを元に戻すには、システムのシェル起動スクリプト(~/.bashrc
)を見つけて、追加されたソース コマンドとエクスポート コマンドを削除します。
補完機能を有効にする
「colcon
」をソースからビルドしてインストールした場合は、bashおよびbash-likeなシェルのコマンド補完をサポートします。これを使用するためには、「colcon_argcomplete
.bash」をソースしておく必要がありますが、自分の環境では、想定の場所(/usr/share/colcon_argcomplete/hook
)にインストールされていませんでした。
※補完機能の使用は断念しました。
その他のTips
- 特定のパッケージをビルドしたくない場合は、「
COLCON_IGNORE
」ディレクトリに名前の付いた空のファイルを置くと、インデックスが作成されません。 - CMake パッケージでテストの構成とビルドを避けたい場合は、「
--cmake-args -DBUILD_TESTING=0
」を渡すことができます。 - パッケージから特定のテストを 1 つだけ実行する場合:
colcon test --packages-select YOUR_PKG_NAME --ctest-args -R YOUR_TEST_IN_PKG
ワークスペースの作成
環境設定
メインのROS2をインストールした環境が、このチュートリアルのアンダーレイになります。(アンダーレイは必ずしもメインのROS2インストールである必要はないとのこと)
アンダーレイのシェルをソースする必要があります。
$ source ~/ros2_jazzy/install/setup.bash
自分は、既に「~/.bashrc」に埋め込んでいるので必要ないです。
新しいディレクトリを作成する
一番簡単なワークスペースの管理方法は、新しいワークスペースごとに新しいディレクトリを作成することです。ここではチュートリアル用のワークスペースを新たに作成します。
$ mkdir -p ~/ros2_ws/tutorials/src
$ cd ~/ros2_ws/tutorials/src
これで先に作成していた「exsamples
」ワークスペースと干渉せずに進めることが出来ます。
サンプルリポジトリをクローンする
チュートリアル用のリポジトリが用意されているのでクローンします。
$ git clone https://github.com/ros/ros_tutorials.git -b jazzy
以下の内容でクローンが作成されました。
$ tree -L 2
.
└─ ros_tutorials
├─ CODEOWNERS
└─ turtlesim
3 directories, 1 file
このチュートリアルは、「turtlesim
」が題材なんですね。
依存関係を解決する
ワークスペースでビルドする前に、パッケージの依存関係を解決する必要があります。既に全ての依存関係が解決されているかもしれませんが、長い待ち時間の挙句、ビルドが失敗するのは辛いので、クローンを作成するたびに依存関係を確認しておくことが望ましいです。
ワークスペースのルート「~/ros2_ws/tutorials/
」から、次のコマンドを実行します。
$ cd ..
$ rosdep install -i --from-paths src --rosdistro jazzy -y
既に全ての依存関係がある場合、コンソールは次を返します:
#All required rosdeps installed successfully
colcon でワークスペースを構築する
ワークスペースのルート「~/ros2_ws/tutorials/
」から、次のコマンドを使用してパッケージをビルドします。
$ colcon build
ビルドが完了したら、「exsamples
」と同じように4つのディレクトリが出来ています。
$ tree -L 1
.
├─ build
├─ install
├─ log
└─ src
5 directories, 0 files
オーバーレイのソース
オーバーレイをソースする前に、ワークスペースをビルドしたターミナルとは別の新しいターミナルを開く必要があります。ビルドしたのと同じターミナルでオーバーレイをソースしたり、オーバーレイがソースされた場所で同様にビルドしたりすると、複雑な問題が発生する可能性があります。
新しいターミナルで、メインのROS2 環境を「アンダーレイ」としてソースし、その「上に」オーバーレイを構築できるようにします。
なお、自分は、起動スクリプトでアンダーレイはソースしているので、オーバーレイのみソースします。
$ cd ~/ros2_ws/tutorials/
$ source ./install/local_setup.bash
これで、オーバーレイから「turtlesim
」パッケージを実行できます。
$ ros2 run turtlesim turtlesim_node
しかし、これがオーバーレイ turtlesim の実行であり、メインのインストールの turtlesim ではないことをどうやって確認できるでしょうか?
オーバーレイで turtlesim に変更を行って確認してみます。
オーバーレイを変更する
オーバーレイを変更するには、TurtleSim ウィンドウのタイトル バーを編集します。これを行うには、「~/ros2_ws/tutorials/src/ros_tutorials/turtlesim/src
」で「turtle_frame.cpp
」ファイルを見つけます。
関数「setWindowTitle("TurtleSim");
」を見つけて、値「"TurtleSim"
」を「"MyTurtleSim"
」に変更し、ファイルを保存します。
...
namespace turtlesim
{
TurtleFrame::TurtleFrame(rclcpp::Node::SharedPtr & node_handle, QWidget * parent, Qt::WindowFlags f)
: QFrame(parent, f)
, path_image_(500, 500, QImage::Format_ARGB32)
, path_painter_(&path_image_)
, frame_count_(0)
, id_counter_(0)
{
setFixedSize(500, 500);
setWindowTitle("MyTurtleSim");
srand(time(NULL));
...
C++先ほど実行した最初のターミナルに戻り、もう一度、「colcon build
」を実行します。
2番目のターミナル(オーバーレイのソース)に戻り、turtlesim を再度実行します。
$ ros2 run turtlesim turtlesim_node
ウィンドウのタイトルが修正した「MyTurtleSim
」に変わっています。
パッケージの作成
パッケージとは
パッケージは、ROS2コードのモジュール単位です。コードをインストールしたり、他の人と共有したりできるようにするには、パッケージに整理する必要があります。パッケージを使用すると、ROS 2 の作業をリリースし、他の人が簡単にビルドして使用できるようにすることができます。
ROS 2 でのパッケージ作成では、ビルド システムとして ament を使用し、ビルド ツールとして colcon を使用します。公式にサポートされている CMake または Python を使用してパッケージを作成できますが、他のビルド タイプも存在します。
パッケージの構成
ROS2 Python のパッケージの最低限必要なコンテンツは以下となります。
- 「
package.xml
」… パッケージに関するメタ情報を含むファイル - 「
resources/<package_name>
」 … パッケージのマーカーファイル - 「
setup.cfg
」 … パッケージに実行ファイルがある場合に必要となる。「ros2 run
」が、それらを見つけることができるようになる。 - 「
setup.py
」 … パッケージのインストール方法の説明を含む - 「
<package_name>
」 … ROS2ツールがパッケージを見つけるために使用する。パッケージと同じ名前のディレクトリには、「__init__.py
」が必要になる。
ROS2 CMake のパッケージの最低限必要なコンテンツは以下となります。
- 「
CMakeLists.txt
」 … パッケージ内のコードを構築する方法を記述したファイル - 「
include/<package_name>
」 … パッケージの公開ヘッダーを含むディレクトリ - 「
packege.xml
」 … パッケージに関するメタ情報を含むファイル - 「
src
」 … パッケージのソースコードを含むディレクトリ
それぞれ、最も単純なパッケージファイル構造は次のようになります。
CMake用
my_packages/
├─ CMakeLists.txt
├─ include/my_package/
├─ package.xml
└─ src/
Python用
my_packages/
├─ packages.xml
├─ resource/my_package
├─ setup.cfg
├─ setup.py
└─ my_package/
ワークスペース内の3つのパッケージ
1 つのワークスペースには、それぞれ独自のフォルダーに、必要な数のパッケージを含めることができます。また、1 つのワークスペースに異なるビルド タイプのパッケージ (CMake、Python など) を含めることもできます。ネストされたパッケージを含めることはできません。
一般的なのは、ワークスペース内に「src
」フォルダーを用意し、そこにパッケージを作成することです。これにより、ワークスペースの最上位レベルが「クリーン」に保たれます。
簡単なワークスペースは次のようになります。
workspace_folder/
src/
cpp_package_1/
CMakeLists.txt
include/cpp_package_1/
package.xml
src/
py_package_1/
package.xml
resource/py_package_1
setup.cfg
setup.py
py_package_1/
...
cpp_package_n/
CMakeLists.txt
include/cpp_package_n/
package.xml
src/
パッケージを作成する
まずは、ROS2 インストール(アンダーレイ)をソースします。
新しいワークスペース「~/ros2_ws/tutorial_ws
」を作ります。
パッケージ作成コマンドを使用する前に、「src」フォルダー内にいることを確認します。
$ mkdir -p ~/ros2_ws/tutorial_ws/src
$ cd ~/ros2_ws/tutorial_ws/src
ROS 2 で新しいパッケージを作成するためのコマンド構文は次のとおりです。
ros2 pkg create --build-type <build_type> --license Apache-2.0 <package_name>
<build_type>
には、以下の値を設定します。
- CMakeの場合:「
ament_cmake
」 - Pythonの場合:「
ament_python
」
ここでは、オプションの引数「--node-name
」と「--license
」を使用します。
「--node-name
」オプションは、パッケージ内に単純な Hello World タイプの実行可能ファイルを作成し、「--license
」オプションは、パッケージのライセンス情報を宣言します。
ターミナルに次のコマンドを入力します。
$ ros2 pkg create --build-type ament_cmake --license Apache-2.0 --node-name my_cpp_node my_cpp_package
これでワークスペースの「src
」ディレクトリ内に「my_cpp_package
」という新しいフォルダが作成されます。
コマンドを実行するとターミナルから次のメッセージが返されます。
going to create a new package
package name: my_cpp_package
destination directory: /home/chikuma/ros2_ws/tutorial_ws/src
package format: 3
version: 0.0.0
description: TODO: Package description
maintainer: ['chikuma <chikuma@todo.todo>']
licenses: ['Apache-2.0']
build type: ament_cmake
dependencies: []
node_name: my_cpp_node
creating folder ./my_cpp_package
creating ./my_cpp_package/package.xml
creating source and include folder
creating folder ./my_cpp_package/src
creating folder ./my_cpp_package/include/my_cpp_package
creating ./my_cpp_package/CMakeLists.txt
creating ./my_cpp_package/src/my_cpp_node.cpp
続けてPython用のパッケージも作成します。
ターミナルに次のコマンドを入力します。
$ ros2 pkg create --build-type ament_python --license Apache-2.0 --node-name my_py_node my_py_package
コマンドを実行するとターミナルから次のメッセージが返されます。
going to create a new package
package name: my_py_package
destination directory: /home/chikuma/ros2_ws/tutorial_ws/src
package format: 3
version: 0.0.0
description: TODO: Package description
maintainer: ['chikuma <chikuma@todo.todo>']
licenses: ['Apache-2.0']
build type: ament_python
dependencies: []
node_name: my_py_node
creating folder ./my_py_package
creating ./my_py_package/package.xml
creating source folder
creating folder ./my_py_package/my_py_package
creating ./my_py_package/setup.py
creating ./my_py_package/setup.cfg
creating folder ./my_py_package/resource
creating ./my_py_package/resource/my_py_package
creating ./my_py_package/my_py_package/__init__.py
creating folder ./my_py_package/test
creating ./my_py_package/test/test_copyright.py
creating ./my_py_package/test/test_flake8.py
creating ./my_py_package/test/test_pep257.py
creating ./my_py_package/my_py_package/my_py_node.py
パッケージをビルドする
ワークスペースにパッケージを配置すると、ワークスペース ルートで「colcon build
」を実行することでパッケージをビルドします。
ワークスペースルートに戻って、パッケージをビルドします。
$ cd ..
$ colcon build
ワークスペースに多数のパッケージがある場合は、時間がかかることがあります。
ビルドするパッケージを選択して実行する場合は、次のコマンドを実行します。
$ colcon build --packages-select my_py_package
セットアップファイルをソースする
新しいパッケージと実行可能ファイルを使用するには、まず、新しいターミナルを開き、「~/ros2_ws/tutorial_ws
」へ移動して次のコマンドを実行します。
なお、メインのROS2 インストールはソースされている必要があります。
$ cd ~/ros2_ws/tutorial_ws/
$ source install/local_setup.bash
ワークスペースがパスに追加されたので、新しいパッケージの実行可能ファイルを使用できるようになります。
パッケージを使用する
パッケージ作成中に引数「--node-name
」を使用して作成した実行可能ファイルを実行するには、次のコマンドを入力します。
$ ros2 run my_cpp_package my_cpp_node
端末に以下のメッセージが返されます:
hello world my_cpp_package package
続いてPython版も実行してみます。
$ ros2 run my_py_package my_py_node
端末に以下のメッセージが返されます:
Hi from my_py_package.
パッケージの内容を確認する
「~/ros2_ws/tutorial_ws/src/my_cpp_package
」と「~/ros2_ws/tutorial_ws/src/my_py_package
」の内部には、「ros2 pkg create
」で自動的に生成されたファイルとフォルダが表示されます。
$ cd ~/ros2_ws/tutorial_ws/src/
$ tree
.
├─ my_cpp_package
│ ├─ CMakeLists.txt
│ ├─ LICENSE
│ ├─ include
│ │ └─ my_cpp_package
│ ├─ package.xml
│ └─ src
│ └─ my_cpp_node.cpp
└─ my_py_package
├─ LICENSE
├─ my_py_package
│ ├─ __init__.py
│ └─ my_py_node.py
├─ package.xml
├─ resource
│ └─ my_py_package
├─ setup.cfg
├─ setup.py
└─ test
├─ test_copyright.py
├─ test_flake8.py
└─ test_pep257.py
9 directories, 14 files
package.xml をカスタマイズする
パッケージを作成した後の返信メッセージで、フィールド「description
」にメモ(TODO
)が含まれていることに気付いたかもしれません。これは、パッケージの説明が、パッケージをリリースする場合は必須となるためです。フィールド「maintainer
」も入力する必要がある場合があります。
「~/ros2_ws/tutorial_ws/src/my_cpp_package
」にある「package.xml
」エディターを使用して開きます。
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>my_cpp_package</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="chikuma@todo.todo">chikuma</maintainer>
<license>Apache-2.0</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
XMLpython版の「package.xml」も確認してみます。
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>my_py_package</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="chikuma@todo.todo">chikuma</maintainer>
<license>Apache-2.0</license>
<test_depend>ament_copyright</test_depend>
<test_depend>ament_flake8</test_depend>
<test_depend>ament_pep257</test_depend>
<test_depend>python3-pytest</test_depend>
<export>
<build_type>ament_python</build_type>
</export>
</package>
XML名前とメールアドレスが「maintainer
」に自動的に入力されていない場合は、その行に入力します。次に、「description
」の行を編集してパッケージの概要を入力します。
<description>Beginner client libraries tutorials practice package<description>
ライセンス タグの下に、「_depend
」で終わるタグ名がいくつかあります。これは、「package.xml
」が
他のパッケージへの依存関係をリストし、colcon が検索する場所です。
「my_package
」はシンプルで依存関係はありませんが、今後のチュートリアルでこのスペースが利用されることがわかります。
追加)Python版:「setup.py」の編集
Python版は、「package.xml」と同様のフィールドが「setup.py」にもあるため、そちらもメンテナンスする必要があります。
from setuptools import find_packages, setup
package_name = 'my_py_package'
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']),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='chikuma',
maintainer_email='chikuma@todo.todo',
description='TODO: Package description',
license='Apache-2.0',
tests_require=['pytest'],
entry_points={
'console_scripts': [
'my_py_node = my_py_package.my_py_node:main'
],
},
)
Pythonこの続きのチュートリアルも行いますが、ブログ記事はここまでとします。
以上です。
コメント