全世界(展示会)がROS軍のロボットに支配されつつある世界にROS2なるなるものが舞い降りた。
ROS2軍は悪の化身ROSを打倒し世界に安寧をもたらす事ができるのか!?
The force be with you…
Contents
ROS2のはじめ方
公式サイトは使えない?
まずはROS2公式サイトのTutorialsを見たことがある方は知っていると思いますが、2019年9月現在、ROS2のチュートリアルは全く整備されていないと言ってもいいレベルで読めません。
よって、公式サイトだけで学習するのはちょっと無理があります。
参考書はどうか?
先日、日本で初めてのROS2参考書が発売されました。
しかし、残念ながらこちらの本は公式サイトをにある内容を翻訳・整理した程度に留まっており、ROS2パッケージの実用的な使い方などは身につきません。
この点については著者様本人の記事の「書いたこと、書かなかったこと」を参考にしたらいいと思います。
また、一部コマンドが動かなかった(私の不勉強のせいかも)ので、困ったら公式サイト…は整備されていないのでサンプルコードを見る等の努力が必要となります。
以下のような方たちは一冊くらい持っていても良いかもしれませんね。
- ROSを一度も触ったことがないけど、ROS1→ROS2の再学習コストを避けたい人
- 公式サイト及びdesign.ros2.orgを読んだことがない人
- setup.cfgやpackage.xml等の理解が曖昧であり、正しい書き方を一度確認したい人
- 死んでも英語が読みたくない人
最後の人は今すぐプログラミングやめなさい
で、どうすればいいのか?
有志の記事を参考にするのが良いと思います。
- ROS2導入&レクチャー
- ROSをROS2へ (有志によるMiguration Guideの翻訳)
ただし、インストール方法については必ず最新の環境に合わせるべきですので、公式サイトのInstallationに従ってインストールしましょう。
インストール・ros2コマンドの体系をある程度理解したら、公式のサンプルプログラムや実際のROS2パッケージのソースコードを頼りに実装していけばいいと思います。
私の場合は、以下のレポジトリ等を参考にしました。
- launchファイルの書き方の参考にnavigation2
- rqtライブラリを用いたGUI対応ノードの作成方法の参考にrqt_plot等
(rqt等はROS1用がmasterのブランチとなっているので、crystal-devel等のROS2用のブランチを参照するよう注意してください)
ROS2を使ってみてわかったこと
超個人的です。
Node
ROS1ではros::spin()等、Node一つ一つに依存せずに纏めて処理を行っていました。
しかし、この方式では1つのプログラム上で、マルチスレッドでNodeを動かす際に問題が発生します。
この問題を解決するために、ROS2ではNodeの運用は1つずつのクラスとして明確に分離されています。ros2/examplesのminimal_subscriber/member_function.cppを見ていただければわかりますが、spinの動作は以下のように実行する必要があります。
rclcpp::spin(SomeNode);
シングルスレッドで複数のノードを実行するにはrclcpp::executors::SingleThreadedExecutorを使用する必要があります。使い方はminimal_compositionを見てください。
ros2 param
ROS1ではroscoreに含まれているROS Parameter serverがパラメータを管理していました。
しかし、ROS2では単一障害点となりうるroscoreシステムを廃止し、ノード毎にパラメータサーバを持つようになりました。
よって、ROS2ではparameterを共有変数のように使うことはできません。
ただし、rclcpp::SyncParametersClient等を用いることで他ノードのパラメータを参照すること自体は可能です。
time周り
ROS2ではシステム上の時間かROS上の時間かを明確に分けるようになりました。これによりrosbagで動作がおかしくなるといった心配がなくなります(ほんまか?)
これにより、下記のコードは一見動きそうですが、実行時エラーとなります。
rclcpp::Time time_now = rclcpp::Clock().now(); double dt = (time_now - msg->header.stamp.nanoseconds();
これは、rclcpp::Clock()がデフォルトではRCL_SYSTEM_TIMEを参照するのに対し、msgのstampはRCL_ROS_TIMEとなっているためです。
よって以下のように対応すれば動作します。
rclcpp::Clock ros_clock(RCL_ROS_TIME); double dt = (ros_clock.now() - msg->header.stamp).nanoseconds();
しかしnanosecondsでしかデータ取得できないのめっちゃ不便なんですが…
丸め誤差とかあったとしても、double型の秒データで取得するメソッドも用意してほしいです…
最後に
ROS2、少しとっつきにくいですがみんなで勉強して盛り上げていきたいですね。
(2020年1月1日でPython2のサポート切れますから…)
ロボットと電子工作とプログラミング!
女の子は甘いもので出来てる?