この記事は私が金沢工業大学ロボティクス学科で担当している2020年度後学期に担当したロボットプログラミングⅡをROS2用に変更したものです。演習3では次のコンテンツを学びます。
コンテンツ
- ワークスペース
- パッケージ
参考サイト
ワークスペース
- 概要
- これからROS2でいろいろなプログラムを作っていきます。ROS2ではプログラムをパッケージ(package)とよばれる単位で作っていきます。まずは、パッケージを保存する作業用のディレクトリ(フォルダ)を作りましょう。ROS2ではこれをワークスペース(workspace)とよびます。1つのワークスペースに好きなだけパッケージを作ることができます。端末でパッケージを使うためには、設定ファイルを反映する必要があります。
- まず、既にインストールされているROS2の設定ファイルを反映します。これは、これから新規に作成するワークスペースのパッケージをビルドするために必要です。この環境のことをアンダーレイ(underlay)とよびます。一方、これから新規に作成するワークスペースの環境をオーバーレイ(overlay)とよびます。オーバーレイはアンダーレイをもとにした環境です。
- 設定ファイルの実行
- 次のsourceコマンドでアンダーレイの設定ファイル/opt/ros/foxy/setpu.bashを実行します。sourceはファイルに書かれたコマンドを現在のシェルで実行するコマンドです。
$ source /opt/ros/foxy/setup.bash
- 次のsourceコマンドでアンダーレイの設定ファイル/opt/ros/foxy/setpu.bashを実行します。sourceはファイルに書かれたコマンドを現在のシェルで実行するコマンドです。
- ワークスペース用ディレクトリの作成
- 次のコマンドで名前がworkspace_nameのワークスペースに使用するディレクトリを作成します。ディレクトリ名は何でもよい。先頭の$は入力を受け付けるコマンドプロンプトなので打つ必要はありません。
$ mkdir -p ~/workspace_name/src
- 次のコマンドで名前がworkspace_nameのワークスペースに使用するディレクトリを作成します。ディレクトリ名は何でもよい。先頭の$は入力を受け付けるコマンドプロンプトなので打つ必要はありません。
パッケージ
- 概要
- パッケージはあなたが作成したROS2コードの入れ物と考えることもできます。パッケージを使うことにより、あなたのROS2コードを簡単に公開したり、ビルドできるようになります。
- 種類
- ROS2ではビルドシステムとしてamentを使い、ビルドするツールとしてcolconを使います。パッケージの種類はCMakeとPythonがあります。CMakeはソフトウェアをビルド、テストするツールでCやC++のビルドに使われます。
- 構成
- CMake:次のファイルが必須
- CMakeLists.txt:パッケージのコードをビルドする方法が書かれたファイル
- package.xml:パッケージに関するメタ情報が書かれたファイル
- Python
- setup.py:パッケージのインストールする方法が書かれたファイル
- setup.cfg:パッケージに実行可能ファイルがある場合に必要なファイル。ros2 runコマンドが実行可能ファイルを見つけるのに使う。
- package.xml:パッケージに関するメタ情報が書かれたファイル
- /<package_name>:パッケージと同じ名前のディレクトリ。ROS2のツールがパッケージに
__init__.py
があるかを見つけるのに使う。
- CMake:次のファイルが必須
- 作成
- ディレクトリを移動する。
$ cd ~/colcon_ws/src
- 次のros2 pkg createコマンドで名前がpackage_nameのパッケージを作成する。
- CMake
$ ros2 pkg create --build-type ament_cmake <package_name>
- Python
$ ros2 pkg create --build-type ament_python <package_name>
- ROS2のプログラムを作成する。典型的なROS2プログラムは次の処理をしている。
- 初期化
- rclpy.init(): ROS2通信のための初期化。ROS2ノード作成する前に呼び出さなければならない。
- ROS2ノードの作成
- rclpy.create_node()関数を呼び出すか、Nodeクラスからインスタンスを作成するかどちらかの方法で作成する。通常はクラスを使ってプログラムを作成するので後者の方法を選ぶ。
- ノードの処理(コールバック関数を使う場合が多い)
- 次の関数でノードを処理を実行する。
- rclpy.spin():処理を実行して、ノードが終了するまでブロックする。
- rclpy.spin_once():処理を1回実行するか、タイムアウトの期限までウェイトする。
- 次の関数でノードを処理を実行する。
- 終了処理
- rclpy.destroy_node():ノードを破壊する。
- rclpy.shutdown():初期化コンテキストを終了する。
- 初期化
- なお、簡単に説明した初期化や終了処理のAPIは以下のリンクで詳細がわかる。
- CMake
- ディレクトリを移動する。
- ビルド
- ROS2ではビルドツールにcolconを使う。
- ビルドするためにworkspace_nameディレクトリに移動する。
$ cd ~/workspace_name
- 次のcolconコマンドでビルドする。このコマンドではワークスペースにある全てのパッケージをビルドする。
$ colcon build
- ワークスペースで初めてビルドすると~/workspace_nameディレクトリにbuild、install、logディレクトリが作成される。
- 次回以降、1つのパッケージmy_packageだけビルドしたいときは次のpackages-selectオプションをつけてビルドする。
$ colcon build --packages-select my_package
- ビルドするためにworkspace_nameディレクトリに移動する。
- ROS2ではビルドツールにcolconを使う。
- 設定ファイルの実行
- アンダーレイ設定ファイルの実行
$ source /opt/ros/foxy/setup.bash
- オーバーレイ設定ファイルの反映。作成したワークスペースの設定ファイルを実行する。これにより、あなたのワークスペースがパスに追加されるので、パッケージの実行可能ファイルを使うことができるようになる。
$ source ~/workspace_name/install/setup.bash
- アンダーレイ設定ファイルの実行
- パッケージの実行
- ros2 runコマンドで、パッケージ名my_package、ノード名my_nodeを実行する。
$ ros2 run my_package my_node
- ros2 runコマンドで、パッケージ名my_package、ノード名my_nodeを実行する。
ハンズオン
A. 一連の作業体験
では、ワークスペース作成からパッケージ作成と実行までの一連の流れを体験しましょう!なお、この例ではワークスペース名をcolcon_ws、Pythonパッケージとしています。
- ワークスペースの作成と移動
$ mkdir -p ~/colcon_ws/src
$ cd ~/colcon_ws/src
- アンダーレイ設定ファイルの実行
$ source /opt/ros/foxy/setup.bash
- パッケージとノード作成。
--node_name
オプションをつけるとプログラミングの最初の定番例hello worldと端末に出力するサンプルが作られる。ここではノード名をhello_node、パッケージ名をhelloにする。 - ビルド
$ cd ~/colcon_ws
$ colcon build
- オーバーレイ設定ファイルの実行
$ source ~/colcon_ws/install/setup.bash
- ノードの実行
$ ros2 run hello hello_node
- 問題がなければ次のように端末に表示される。
- Hi from hello.
- 少し幸せになる設定
- 毎回、アンダーレイとオーバーレイの設定ファイルを実行するのは面倒なので次のコマンドを実行して.bashrcに追記する。
$ echo "source /opt/ros/foxy/setup.bash" >> ~/.bashrc
$ echo "source ~/colcon_ws/install/setup.bash" >> ~/.bashrc
- 毎回、アンダーレイとオーバーレイの設定ファイルを実行するのは面倒なので次のコマンドを実行して.bashrcに追記する。
B. 初めてのROS2プログラム作成
次に、上で作成したhelloパッケージを改変して初めてのROS2のプログラムを作って行こう!
- ソースコードの作成
$ cd ~/colcon_ws/src/hello/hello
$ gedit hello_node.py
-
import rclpy # ROS2のPythonモジュールをインポートする import time # スリープに使用するtimeモジュールのインポート from rclpy.node import Node # rclpy.nodeからNodeモジュールをインポートする # 端末にhello worldと10回表示する関数 def print_hello(): i = 1 while i <= 10: print('%d: hello world' % i) i += 1 time.sleep(1) # 1秒間スリープする # main関数 def main(): rclpy.init() # ROS通信の初期化 node = Node('hello_node') # ノードの生成。引数はノード名。 print_hello() # 自作関数 rclpy.spin(node) # ノード終了まで待機 rclpy.destroy_node() # ノードの破壊 rclpy.shutdown() # ノードの終了処理 # このコードをモジュールとしてimportできるようにするおまじない。 if __name__ == '__main__': main()
- Package.xmlファイルの編集
- 自動作成されたPackage.xmlを次に示す。ここで、変更する必要があるのは次の5項目。現時点では必要ないが、自作パッケージを公開するときは変更しましょう。
- 4行目:name (パッケージ名)
- 5行目:version(パッケージのバージョン)
- 6行目:description (パッケージの説明)
- 7行目:maintainer email (保守者、メールアドレス)
- 8行目:license (パッケージのライセンス)
- 自動作成されたPackage.xmlを次に示す。ここで、変更する必要があるのは次の5項目。現時点では必要ないが、自作パッケージを公開するときは変更しましょう。
- Setup.pyファイルの編集
- 自動作成されたSetup.pyを次に示す。ここで、変更する必要があるのは次の6項目。この内容は、Package.xmlと同じにしなければならない。
- 3行目:package_name (パッケージ名)
- 7行目:version(パッケージのバージョン)
- 16行目:maintainer (保守者)
- 17行目:maintainer_email (保守者のメールアドレス)
- 18行目:description (パッケージの説明)
- 23行目
- ‘ノード名 = パッケージ名.ノード名:main’
- 自動作成されたSetup.pyを次に示す。ここで、変更する必要があるのは次の6項目。この内容は、Package.xmlと同じにしなければならない。
- ビルド
$ cd ~/colcon_ws
$ colcon build
- オーバーレイ設定ファイルの実行
$ source ~/colcon_ws/install/setup.bash
- ノードの実行
- 次のコマンドを実行して、下図のようにhello worldが表示されれば成功! 10: hello worldと表示されたらプログラムがブロックされるのでCtrl-Cでノードを終了させる。
$ ros2 run hello hello_node
- 次のコマンドを実行して、下図のようにhello worldが表示されれば成功! 10: hello worldと表示されたらプログラムがブロックされるのでCtrl-Cでノードを終了させる。
ホームワーク
- helloパッケージのhello_node.pyプログラムをクラス化した次のコードを使い、hello2パッケージを作成して実行しよう。
- 以下のノードを作成しよう!
- “I Love KIT”と表示するkitノードを作ろう。ただし、ダブルクォーテーションは表示しなくて良い。
- キーボードから打たれ文字列をそのまま表示するechoノードを作ろう。ただし、文字列に空白は含まないとものとします。
- キーボードから打たれた文字列を”I Love”の後につける、loveノードを作ろう。
終わり