この記事の内容
ROS 2のQoS(Quality of Service)について、皆さんご存じでしょうか?
私はなんとなく、通信の品質に関するものであるとか、publishする側とsubscribeする側で指定して、その組み合わせによっていいとかダメとかあったなというレベルでしか考えていませんでしたので、一度初心に戻って調べてまとめてみようと思いました。
ROS 2のトピックのpub/subはわかってるけども、QoSについてはちょっと自信がないという方に見ていただけたら幸いです。
QoSとは
QoSとはQuality of Serviceの略で、ROS 2の通信システムにおけるデータの伝送品質を管理するための設定です。
ROS 2ではトピックを使ってノード間でやり取りを行います。QoSではノード間でメッセージの送受信を行う際に、メッセージの特性に応じて通信の信頼性をどのレベルにするのか、履歴をどれくらい保持しておくかなど設定を行うことができます。これらをQoSポリシーと呼びます。
QoSポリシーとして、履歴(History), 信頼性(Reliablity), 耐久性(Durability), デッドライン(Deadline), 寿命(Lifespan),生存性(Liveliness)などがあります。
信頼性(Reliablity)を1つ例にしてみます。信頼性はそれは高いほうが嬉しいですが、信頼性を高くするには応答確認や転送がうまくいかない場合の再送処理で速度や通信トラフィックとのトレードオフとなります。
そのためQoSの信頼性では、確実に届けるReliableという設定や、可能な限りベストを尽くすBest Effortという設定があります。
例えば企業側で顧客にDMのはがきを郵送で送付するケースを考えます。このケースでは、企業側は多くの人に安くDMを郵送したいというニーズがあります。このような場合は、1つのはがきが失われたとしてもあまり影響はありません。このようなケースはBest Errortを使用します。ROS 2でのケースに当てはめると、2DLiDARの点群やIMUなどのセンサデータであれば、大量のデータを処理するケースがあると思いますが、1つ1つのデータを確実に処理するというよりは、なるべくセンサからとったばかりの新鮮な(とってから時間があまりたっていない)ものを処理場合はこのようなBest Effortにするとよいでしょう。
対して、重要な契約書を顧客に送りたいケースを考えます。このケースでは、多少高くてもいいので確実に郵送して、届いたことをきちんと確認したいというニーズがあります。このようなケースはReliableを使用します。ROS 2でのケースに当てはめると、ナビゲーションのゴール位置の指令を行う場合などは、確実に届く必要があるので、信頼性は高い必要がありますので、このようなケースはReliableを使用するとよいでしょう。
信頼度(Reliable)についてイメージをお話して、なんとなくQoSの一部がどういうものなのかイメージできたかと思いますので、つぎは全体像について説明します。
ROS 2の QoSについての全体像
ROS 2におけるQoSの仕組みの全体像について以下に記載します。
大きくQoSの用語としてはQoSポリシーとQoSプロファイルというものがあります。
まず、QoSポリシーについて解説します。
QoSポリシー
QoSポリシーは、前述していますが、履歴(History), 信頼性(Reliablity), 耐久性(Durability), デッドライン(Deadline), 寿命(Lifespan),生存性(Liveliness)などのパラメータが存在しています。これらは、トピックを発行するパブリッシャ側と、サブスクライバ側にそれぞれ持っています。それぞれのQoSポリシーの組み合わせが適切でないとやり取りすることができません。
QoSポリシーは、パブリッシャ側は提供できる最大品質を要求します。サブスクライバ側はパブリッシャ側の品質以下にする必要があります。
例えば、パブリッシャ側は、信頼性をBest Effortにしているのに、サブスクライバ側がReliableにしている場合は、互換性がないためエラーとなります。逆は問題ありません。
信頼度(Reliablity)について例を挙げましたが、耐久性(Durability)においても同様です。
以下のページが参考になります。
QoSプロファイル
QoSポリシーは履歴(History), 信頼性(Reliablity), 耐久性(Durability), デッドライン(Deadline), 寿命(Lifespan),生存性(Liveliness)などが存在するということを記載しました。いろいろ設定できるのはうれしいのですが、用途ごとに設定を毎回決めるのはユーザ側として面倒なこともあります。ユースケースごとに、テンプレートを作っておいてそれを使うというのがQoSプロファイルというものです。
ROS 2側で用意してくれているQoSプロファイルがいくつかあり、例えばセンサーデータのプロファイルというものがあります。これは、センサーデータでは、信頼性はそこまで高くなくてよいのでBest Effortで、履歴に関してもそこまで覚えておく必要がないので5つまで保持しておくという設定をセンサーデータのQoSプロファイルとして用意されています。
このようにユースケースごとにQoSポリシーをまとめているものをQoSプロファイルと呼びます。
QoS ポリシー
QoSポリシーとしていくつか存在しますが、以下にまとめたものを記載します。
QoS ポリシーの互換性
QoSポリシーの互換性について、実際に実験してみます。ros2 topic pubコマンドとros2 topic echoコマンドにqosを指定できるのでこれを使って実験してみます。
パブリッシャ:Reliable, サブスクライバ: BestEffort
まずは、パブリッシャ側にReliableを指定して、サブスクライバ側でBest Effortを指定します。
このパターンではパブリッシャ側の指定より、サブスクライバ側の指定のほうが緩いため、問題なく通信が行えるはずです。通信としてはBest Effortで通信されます。
サブスクライバとして以下のコマンドを実行します。
ros2 topic echo --qos-reliability best_effort test_topic std_msgs/msg/Int32
パブリッシャとして以下のコマンドを実行します。
ros2 topic pub -1 --qos-reliability reliable test_topic std_msgs/msg/Int32 '{data: 100}'
実行した結果は、以下のようになります。パブリッシャ側でパブリッシュした内容が取得できていることがわかります。
パブリッシャ:BestEffort, サブスクライバ: Reliable
次はパブリッシャ側にBest Effortを指定して、サブスクライバ側でReliableを指定します。
このパターンではパブリッシャ側の指定より、サブスクライバ側の指定のほうがきついため、問題が発生するはずです。
サブスクライバとして以下のコマンドを実行します。
ros2 topic echo --qos-reliability reliable test_topic std_msgs/msg/Int32
パブリッシャとして以下のコマンドを実行します。
ros2 topic pub -1 --qos-reliability best_effort test_topic std_msgs/msg/Int32 '{data: 100}'
上記のコマンドを実行すると、サブスクライバ側で以下の表示がでています。QoSのpolicyに互換性がないとなってますね。
QoS プロファイル
ROS 2で定義されているQoSプロファイルとして、Services、Parameters, Sensor data, System defaultがあります。以下のような定義になっています。
以下は定義されているヘッダファイルになります。これらのユースケースで使用できる場合は活用するとよいでしょう。
コメント