rclcpp (ROS Client Library for C++) を読み解く (3)
半年前の記事ですが、ROS 2のクライアントサイドの仕組みを理解するためにC++用クライアントrclcpp
に着目していました。
ROS 2が正式リリースされる際にこのソースコードにもかなり変更が入り、実装がより疎結合になるように改善されているため、本日はその部分を見ていきます。
rclcpp::node_interfaces::Node***Interface
ROSノードを表現する一番重要なクラスNodeの実装は、デザインパターン用語でいうDelegateパターンで実装されています。
- 名前空間関連
- トピック関連
- サービス関連
- パラメータ関連
- タイマー関連
というような単位でインタフェースのみを純粋仮想関数で提供するクラスを定義し、それを実際に実装するインスタンスをコンストラクタで与えることで、実行時にノードの特性を変更することができるようになっています。
Node::create_wall_timer
一つだけ、タイマー関連のインタフェースであるNodeTimersInterfaceを取り上げます。
ROS 1からROS 2で大きく実装パターンが変更された部分にタイマー実行処理があります。 これまではトピックのパブリッシャノードはmain関数などのstatic関数内でwhile文を作って独自に無限ループを回すことが常套手段だったと思います。
しかし、ROS 2ではその実装方法は推奨されない方法になりました。 その代わり、Nodeクラスに周期実行のためのタイマー機能が内蔵され、タイマーのコールバック関数にトピックの発行処理を書くスタイルが推奨されます。
そのためのメソッドがNode::create_wall_timer()
です。 callback
引数に周期実行したいコールバック関数を渡し、Nodeインスタンスがスピン状態になった後、period
引数の周期に従って周期実行されます。
11行目でNodeTimersInterface::add_timer()
が呼ばれています。 add_timer
の実装自体はrclcpp
の関数ではないrcl
ライブラリ関数(rcl_timer_***()
など)が呼び出されます。 これにより、タイマー実行の実装をその他のクライアントライブラリ(例えばPython用のrclpy
)との間で再利用しているようです。
ちなみに、タイマーのクロックには標準のWallTimer
ではstd::chrono::steady_clock
が用いられています。
https://cpprefjp.github.io/reference/chrono/steady_clock.html
steady_clockは、物理的な時間と同様、決して逆行することがない時間を表現するためのクロックである。
とのことです。処理系依存ですが、クロックの精度が非常に気になるところです。
Comments powered by Disqus.