📖

ROS2プログラミング入門 #7 再び振り返り

2022/05/22に公開

この記事では、ここまで学んだことを再び振り返りつつ、Launchファイルについて説明します。

メインループ

環境構築の後、さっそく ROS2プログラミング入門 #2 Hello worldHello world しましたが、このとき作ったコードにはメインループがありませんでした。

そこでコードにメインループを追加し Ctrl-C を押すまで終わらないノードを作ったわけです。

コードは次のようなものでしたね。

#include "rclcpp/rclcpp.hpp"

int main(int argc, char **argv)
{
  rclcpp::init(argc, argv);

  auto node = rclcpp::Node::make_shared("hello");
  RCLCPP_INFO(node->get_logger(), "Hello, ROS2 world!");

  rclcpp::WallRate loop(1);
  while (rclcpp::ok()) {
    loop.sleep();
  }

  rclcpp::shutdown();
  return 0;
}

また、ここでROS2アプリケーションにおける rclcpp ライブラリ等の重要性にも気付きました。

パブリッシャーとサブスクライバー

ROSでは複数のノードを協調させることでアプリケーションを実現します。

ノードがメッセージを送る時、そのノードはパブリッシャーとして働きます。また、ノードがメッセージを受ける時、そのノードはサブスクライバーとして働きます。

次の図は、トピックを介したメッセージのやり取りを表したものです。

パブリッシャーとサブスクライバー
https://docs.ros.org/en/foxy/Tutorials/Topics/Understanding-ROS2-Topics.html より

実際に my_publisher.cppmy_subscriber.cpp でシンプルなプログラムを作り、パブリッシャーおよびサブスクライバーとして動かしました。

ここまでで、下記に挙げるようなプログラムの流れが見えてきたように思います。

  1. ライブラリの初期化
  2. ノードの作成
  3. パブリッシャーの作成 / サブスクライバーの作成
  4. メインループの実行 / コールバック関数の待機
  5. ライブラリの終了処理

亀を制御する

そして次に試したのは、ここまでの知識を応用して、デモパッケージ turtlesim の亀を動かすノードを作ることです。

ターミナルを2つ起動して次のコマンドを実行し、

ros2 run turtlesim turtlesim_node
ros2 run my_first_package my_turtle_controller

亀がぐるぐる円を描くように動くのを見ました。

my_turtle_controllerを実行した様子
my_turtle_controllerを実行した様子

トピックを介してメッセージを送る時、それをどのようなデータ型で扱うかはとても重要です。

また、動かす対象が何であっても、適切なメッセージを適切なタイミングで送ってあげれば、その何かは(ハードウェア的なトラブルは別にして)きちんと動くはずです。

Launchファイル

ところで、これまで「複数のノードを一斉に同時起動する」ということはしていませんが、実はLaunchファイルを使うとそれができるようになります。

複数のノードが連携する実用的なアプリケーションを作るとき便利なので、試してみましょう。

作り方は Launch TutorialsCreating a launch file が参考になります。

準備

パッケージルートに launch ディレクトリを作り、そこにLaunchファイルを置きます。今回は my_publishermy_subscriber を起動する pubsub_launch.py を作ります。

コマンドとしては次のような感じです。

cd ~/dev_ws/src/my_first_package/
mkdir launch
touch launch/pubsub_launch.py

Launchファイルの作成

ファイルの拡張子が .py なので分かると思いますが、LaunchファイルはPythonで書きます。

ここでは中身を次のようにしました。

from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    node1 = Node(
        package='my_first_package',
        executable='my_publisher'
    )
    node2 = Node(
        package='my_first_package',
        executable='my_subscriber'
    )
    return LaunchDescription([
        node1,
        node2
    ])

実行

launch ディレクトリへ移動して ros2 launch で実行できます。

cd launch/
ros2 launch pubsub_launch.py

次のように表示されるはずです。

pubsub_launch.pyを実行した様子
pubsub_launch.pyを実行した様子

おわりに

今回は、ここまで学んだことを再び振り返りつつ、Launchファイルについて説明してみました。どなたかのお役に立てば幸いです。

Discussion